[PATCH] s390: use normal switch statement for ioctls in dasd_ioctlc
authorChristoph Hellwig <hch@lst.de>
Fri, 24 Mar 2006 11:15:20 +0000 (03:15 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 24 Mar 2006 15:33:17 +0000 (07:33 -0800)
Add an ->ioctl method to the dasd_discipline structure.  This allows to apply
the same kind of cleanups the last patch applied to dasd_ioctl.c to
dasd_eckd.c (the only dasd discipline with special ioctls) aswell.

Again lots of code removed.  During auditing the ioctls I found two fishy
return value propagations from copy_{from,to}_user, maintainers please check
those, I've marked them with XXX comments.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c

index 822e2a265578ca798afe71ee7279610de496ada2..ee09ef33d08d7e7f587b37438b76310b3e72c08f 100644 (file)
@@ -1227,19 +1227,14 @@ dasd_eckd_fill_info(struct dasd_device * device,
  * (see dasd_eckd_reserve) device.
  */
 static int
-dasd_eckd_release(struct block_device *bdev, int no, long args)
+dasd_eckd_release(struct dasd_device *device)
 {
-       struct dasd_device *device;
        struct dasd_ccw_req *cqr;
        int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       device = bdev->bd_disk->private_data;
-       if (device == NULL)
-               return -ENODEV;
-
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 32, device);
        if (IS_ERR(cqr)) {
@@ -1272,19 +1267,14 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
  * the interrupt is outstanding for a certain time. 
  */
 static int
-dasd_eckd_reserve(struct block_device *bdev, int no, long args)
+dasd_eckd_reserve(struct dasd_device *device)
 {
-       struct dasd_device *device;
        struct dasd_ccw_req *cqr;
        int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       device = bdev->bd_disk->private_data;
-       if (device == NULL)
-               return -ENODEV;
-
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 32, device);
        if (IS_ERR(cqr)) {
@@ -1316,19 +1306,14 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
  * (unconditional reserve)
  */
 static int
-dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
+dasd_eckd_steal_lock(struct dasd_device *device)
 {
-       struct dasd_device *device;
        struct dasd_ccw_req *cqr;
        int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       device = bdev->bd_disk->private_data;
-       if (device == NULL)
-               return -ENODEV;
-
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 32, device);
        if (IS_ERR(cqr)) {
@@ -1358,19 +1343,14 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
  * Read performance statistics
  */
 static int
-dasd_eckd_performance(struct block_device *bdev, int no, long args)
+dasd_eckd_performance(struct dasd_device *device, void __user *argp)
 {
-       struct dasd_device *device;
        struct dasd_psf_prssd_data *prssdp;
        struct dasd_rssd_perf_stats_t *stats;
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
        int rc;
 
-       device = bdev->bd_disk->private_data;
-       if (device == NULL)
-               return -ENODEV;
-
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1 /* PSF */  + 1 /* RSSD */ ,
                                   (sizeof (struct dasd_psf_prssd_data) +
@@ -1414,8 +1394,9 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
                /* Prepare for Read Subsystem Data */
                prssdp = (struct dasd_psf_prssd_data *) cqr->data;
                stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);
-               rc = copy_to_user((long __user *) args, (long *) stats,
-                                 sizeof(struct dasd_rssd_perf_stats_t));
+               if (copy_to_user(argp, stats,
+                                sizeof(struct dasd_rssd_perf_stats_t)))
+                       rc = -EFAULT;
        }
        dasd_sfree_request(cqr, cqr->device);
        return rc;
@@ -1426,27 +1407,22 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
  * Returnes the cache attributes used in Define Extend (DE).
  */
 static int
-dasd_eckd_get_attrib (struct block_device *bdev, int no, long args)
+dasd_eckd_get_attrib(struct dasd_device *device, void __user *argp)
 {
-       struct dasd_device *device;
-        struct dasd_eckd_private *private;
-        struct attrib_data_t attrib;
+       struct dasd_eckd_private *private =
+               (struct dasd_eckd_private *)device->private;
+       struct attrib_data_t attrib = private->attrib;
        int rc;
 
         if (!capable(CAP_SYS_ADMIN))
                 return -EACCES;
-        if (!args)
+       if (!argp)
                 return -EINVAL;
 
-        device = bdev->bd_disk->private_data;
-        if (device == NULL)
-                return -ENODEV;
-
-        private = (struct dasd_eckd_private *) device->private;
-        attrib = private->attrib;
-
-        rc = copy_to_user((long __user *) args, (long *) &attrib,
-                         sizeof (struct attrib_data_t));
+       rc = 0;
+       if (copy_to_user(argp, (long *) &attrib,
+                        sizeof (struct attrib_data_t)))
+               rc = -EFAULT;
 
        return rc;
 }
@@ -1456,26 +1432,19 @@ dasd_eckd_get_attrib (struct block_device *bdev, int no, long args)
  * Stores the attributes for cache operation to be used in Define Extend (DE).
  */
 static int
-dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
+dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp)
 {
-       struct dasd_device *device;
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private =
+               (struct dasd_eckd_private *)device->private;
        struct attrib_data_t attrib;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
-       if (!args)
+       if (!argp)
                return -EINVAL;
 
-       device = bdev->bd_disk->private_data;
-       if (device == NULL)
-               return -ENODEV;
-
-       if (copy_from_user(&attrib, (void __user *) args,
-                          sizeof (struct attrib_data_t))) {
+       if (copy_from_user(&attrib, argp, sizeof(struct attrib_data_t)))
                return -EFAULT;
-       }
-       private = (struct dasd_eckd_private *) device->private;
        private->attrib = attrib;
 
        DEV_MESSAGE(KERN_INFO, device,
@@ -1484,6 +1453,27 @@ dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
        return 0;
 }
 
+static int
+dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp)
+{
+       switch (cmd) {
+       case BIODASDGATTR:
+               return dasd_eckd_get_attrib(device, argp);
+       case BIODASDSATTR:
+               return dasd_eckd_set_attrib(device, argp);
+       case BIODASDPSRD:
+               return dasd_eckd_performance(device, argp);
+       case BIODASDRLSE:
+               return dasd_eckd_release(device);
+       case BIODASDRSRV:
+               return dasd_eckd_reserve(device);
+       case BIODASDSLCK:
+               return dasd_eckd_steal_lock(device);
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
 /*
  * Print sense data and related channel program.
  * Parts are printed because printk buffer is only 1024 bytes.
@@ -1642,6 +1632,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
        .free_cp = dasd_eckd_free_cp,
        .dump_sense = dasd_eckd_dump_sense,
        .fill_info = dasd_eckd_fill_info,
+       .ioctl = dasd_eckd_ioctl,
 };
 
 static int __init
@@ -1649,59 +1640,18 @@ dasd_eckd_init(void)
 {
        int ret;
 
-       dasd_ioctl_no_register(THIS_MODULE, BIODASDGATTR,
-                              dasd_eckd_get_attrib);
-       dasd_ioctl_no_register(THIS_MODULE, BIODASDSATTR,
-                              dasd_eckd_set_attrib);
-       dasd_ioctl_no_register(THIS_MODULE, BIODASDPSRD,
-                              dasd_eckd_performance);
-       dasd_ioctl_no_register(THIS_MODULE, BIODASDRLSE,
-                              dasd_eckd_release);
-       dasd_ioctl_no_register(THIS_MODULE, BIODASDRSRV,
-                              dasd_eckd_reserve);
-       dasd_ioctl_no_register(THIS_MODULE, BIODASDSLCK,
-                              dasd_eckd_steal_lock);
-
        ASCEBC(dasd_eckd_discipline.ebcname, 4);
 
        ret = ccw_driver_register(&dasd_eckd_driver);
-       if (ret) {
-               dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR,
-                                        dasd_eckd_get_attrib);
-               dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR,
-                                        dasd_eckd_set_attrib);
-               dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD,
-                                        dasd_eckd_performance);
-               dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE,
-                                        dasd_eckd_release);
-               dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV,
-                                        dasd_eckd_reserve);
-               dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK,
-                                        dasd_eckd_steal_lock);
-               return ret;
-       }
-
-       dasd_generic_auto_online(&dasd_eckd_driver);
-       return 0;
+       if (!ret)
+               dasd_generic_auto_online(&dasd_eckd_driver);
+       return ret;
 }
 
 static void __exit
 dasd_eckd_cleanup(void)
 {
        ccw_driver_unregister(&dasd_eckd_driver);
-
-       dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR,
-                                dasd_eckd_get_attrib);
-       dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR,
-                                dasd_eckd_set_attrib);
-       dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD,
-                                dasd_eckd_performance);
-       dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE,
-                                dasd_eckd_release);
-       dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV,
-                                dasd_eckd_reserve);
-       dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK,
-                                dasd_eckd_steal_lock);
 }
 
 module_init(dasd_eckd_init);
index 6010ecf76b4cfd1a440871f3bcb21c1894591b13..e9485559e22e775af94f5f56b9136492cc1e8575 100644 (file)
@@ -272,6 +272,7 @@ struct dasd_discipline {
         /* i/o control functions. */
        int (*fill_geometry) (struct dasd_device *, struct hd_geometry *);
        int (*fill_info) (struct dasd_device *, struct dasd_information2_t *);
+       int (*ioctl) (struct dasd_device *, unsigned int, void __user *);
 };
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
index e3ad34686444bec28e5f99b2cf4114a267cdee99..bb6caf46bbd9a0b403a66ab4d3ae2803411c70fd 100644 (file)
@@ -448,7 +448,14 @@ dasd_ioctl(struct inode *inode, struct file *file,
        case DASDAPIVER:
                return dasd_ioctl_api_version(argp);
        default:
-               /* resort to the deprecated dynamic ioctl list */
+               /* if the discipline has an ioctl method try it. */
+               if (device->discipline->ioctl) {
+                       int rval = device->discipline->ioctl(device, cmd, argp);
+                       if (rval != -ENOIOCTLCMD)
+                               return rval;
+               }
+
+               /* else resort to the deprecated dynamic ioctl list */
                list_for_each_entry(ioctl, &dasd_ioctl_list, list) {
                        if (ioctl->no == cmd) {
                                /* Found a matching ioctl. Call it. */