diff options
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r-- | drivers/char/mem.c | 133 |
1 files changed, 53 insertions, 80 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 65e12bca657..0491cdf63f2 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -694,9 +694,8 @@ static ssize_t read_zero(struct file * file, char __user * buf, written += chunk - unwritten; if (unwritten) break; - /* Consider changing this to just 'signal_pending()' with lots of testing */ - if (fatal_signal_pending(current)) - return written ? written : -EINTR; + if (signal_pending(current)) + return written ? written : -ERESTARTSYS; buf += chunk; count -= chunk; cond_resched(); @@ -823,6 +822,7 @@ static const struct file_operations zero_fops = { * - permits private mappings, "copies" are taken of the source of zeros */ static struct backing_dev_info zero_bdi = { + .name = "char/mem", .capabilities = BDI_CAP_MAP_COPY, }; @@ -864,96 +864,67 @@ static const struct file_operations kmsg_fops = { .write = kmsg_write, }; -static int memory_open(struct inode * inode, struct file * filp) -{ - int ret = 0; - - lock_kernel(); - switch (iminor(inode)) { - case 1: - filp->f_op = &mem_fops; - filp->f_mapping->backing_dev_info = - &directly_mappable_cdev_bdi; - break; +static const struct memdev { + const char *name; + const struct file_operations *fops; + struct backing_dev_info *dev_info; +} devlist[] = { + [ 1] = { "mem", &mem_fops, &directly_mappable_cdev_bdi }, #ifdef CONFIG_DEVKMEM - case 2: - filp->f_op = &kmem_fops; - filp->f_mapping->backing_dev_info = - &directly_mappable_cdev_bdi; - break; + [ 2] = { "kmem", &kmem_fops, &directly_mappable_cdev_bdi }, #endif - case 3: - filp->f_op = &null_fops; - break; + [ 3] = {"null", &null_fops, NULL }, #ifdef CONFIG_DEVPORT - case 4: - filp->f_op = &port_fops; - break; + [ 4] = { "port", &port_fops, NULL }, #endif - case 5: - filp->f_mapping->backing_dev_info = &zero_bdi; - filp->f_op = &zero_fops; - break; - case 7: - filp->f_op = &full_fops; - break; - case 8: - filp->f_op = &random_fops; - break; - case 9: - filp->f_op = &urandom_fops; - break; - case 11: - filp->f_op = &kmsg_fops; - break; + [ 5] = { "zero", &zero_fops, &zero_bdi }, + [ 7] = { "full", &full_fops, NULL }, + [ 8] = { "random", &random_fops, NULL }, + [ 9] = { "urandom", &urandom_fops, NULL }, + [11] = { "kmsg", &kmsg_fops, NULL }, #ifdef CONFIG_CRASH_DUMP - case 12: - filp->f_op = &oldmem_fops; - break; + [12] = { "oldmem", &oldmem_fops, NULL }, #endif - default: - unlock_kernel(); - return -ENXIO; - } - if (filp->f_op && filp->f_op->open) - ret = filp->f_op->open(inode,filp); +}; + +static int memory_open(struct inode *inode, struct file *filp) +{ + int minor; + const struct memdev *dev; + int ret = -ENXIO; + + lock_kernel(); + + minor = iminor(inode); + if (minor >= ARRAY_SIZE(devlist)) + goto out; + + dev = &devlist[minor]; + if (!dev->fops) + goto out; + + filp->f_op = dev->fops; + if (dev->dev_info) + filp->f_mapping->backing_dev_info = dev->dev_info; + + if (dev->fops->open) + ret = dev->fops->open(inode, filp); + else + ret = 0; +out: unlock_kernel(); return ret; } static const struct file_operations memory_fops = { - .open = memory_open, /* just a selector for the real open */ -}; - -static const struct { - unsigned int minor; - char *name; - umode_t mode; - const struct file_operations *fops; -} devlist[] = { /* list of minor devices */ - {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, -#ifdef CONFIG_DEVKMEM - {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, -#endif - {3, "null", S_IRUGO | S_IWUGO, &null_fops}, -#ifdef CONFIG_DEVPORT - {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, -#endif - {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, - {7, "full", S_IRUGO | S_IWUGO, &full_fops}, - {8, "random", S_IRUGO | S_IWUSR, &random_fops}, - {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, - {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, -#ifdef CONFIG_CRASH_DUMP - {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops}, -#endif + .open = memory_open, }; static struct class *mem_class; static int __init chr_dev_init(void) { - int i; + int minor; int err; err = bdi_init(&zero_bdi); @@ -964,10 +935,12 @@ static int __init chr_dev_init(void) printk("unable to get major %d for memory devs\n", MEM_MAJOR); mem_class = class_create(THIS_MODULE, "mem"); - for (i = 0; i < ARRAY_SIZE(devlist); i++) - device_create(mem_class, NULL, - MKDEV(MEM_MAJOR, devlist[i].minor), NULL, - devlist[i].name); + for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { + if (!devlist[minor].name) + continue; + device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor), + NULL, devlist[minor].name); + } return 0; } |