Commit 1107ccfb authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

[PATCH] s390: use normal switch statement for ioctls in dasd_ioctlc

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 13c6204f
...@@ -1227,19 +1227,14 @@ dasd_eckd_fill_info(struct dasd_device * device, ...@@ -1227,19 +1227,14 @@ dasd_eckd_fill_info(struct dasd_device * device,
* (see dasd_eckd_reserve) device. * (see dasd_eckd_reserve) device.
*/ */
static int 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; struct dasd_ccw_req *cqr;
int rc; int rc;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
cqr = dasd_smalloc_request(dasd_eckd_discipline.name, cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1, 32, device); 1, 32, device);
if (IS_ERR(cqr)) { if (IS_ERR(cqr)) {
...@@ -1272,19 +1267,14 @@ dasd_eckd_release(struct block_device *bdev, int no, long args) ...@@ -1272,19 +1267,14 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
* the interrupt is outstanding for a certain time. * the interrupt is outstanding for a certain time.
*/ */
static int 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; struct dasd_ccw_req *cqr;
int rc; int rc;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
cqr = dasd_smalloc_request(dasd_eckd_discipline.name, cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1, 32, device); 1, 32, device);
if (IS_ERR(cqr)) { if (IS_ERR(cqr)) {
...@@ -1316,19 +1306,14 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args) ...@@ -1316,19 +1306,14 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
* (unconditional reserve) * (unconditional reserve)
*/ */
static int 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; struct dasd_ccw_req *cqr;
int rc; int rc;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
cqr = dasd_smalloc_request(dasd_eckd_discipline.name, cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1, 32, device); 1, 32, device);
if (IS_ERR(cqr)) { if (IS_ERR(cqr)) {
...@@ -1358,19 +1343,14 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args) ...@@ -1358,19 +1343,14 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
* Read performance statistics * Read performance statistics
*/ */
static int 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_psf_prssd_data *prssdp;
struct dasd_rssd_perf_stats_t *stats; struct dasd_rssd_perf_stats_t *stats;
struct dasd_ccw_req *cqr; struct dasd_ccw_req *cqr;
struct ccw1 *ccw; struct ccw1 *ccw;
int rc; int rc;
device = bdev->bd_disk->private_data;
if (device == NULL)
return -ENODEV;
cqr = dasd_smalloc_request(dasd_eckd_discipline.name, cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
1 /* PSF */ + 1 /* RSSD */ , 1 /* PSF */ + 1 /* RSSD */ ,
(sizeof (struct dasd_psf_prssd_data) + (sizeof (struct dasd_psf_prssd_data) +
...@@ -1414,8 +1394,9 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args) ...@@ -1414,8 +1394,9 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
/* Prepare for Read Subsystem Data */ /* Prepare for Read Subsystem Data */
prssdp = (struct dasd_psf_prssd_data *) cqr->data; prssdp = (struct dasd_psf_prssd_data *) cqr->data;
stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1); stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1);
rc = copy_to_user((long __user *) args, (long *) stats, if (copy_to_user(argp, stats,
sizeof(struct dasd_rssd_perf_stats_t)); sizeof(struct dasd_rssd_perf_stats_t)))
rc = -EFAULT;
} }
dasd_sfree_request(cqr, cqr->device); dasd_sfree_request(cqr, cqr->device);
return rc; return rc;
...@@ -1426,27 +1407,22 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args) ...@@ -1426,27 +1407,22 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args)
* Returnes the cache attributes used in Define Extend (DE). * Returnes the cache attributes used in Define Extend (DE).
*/ */
static int 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 dasd_eckd_private *private; (struct dasd_eckd_private *)device->private;
struct attrib_data_t attrib; struct attrib_data_t attrib = private->attrib;
int rc; int rc;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
if (!args) if (!argp)
return -EINVAL; return -EINVAL;
device = bdev->bd_disk->private_data; rc = 0;
if (device == NULL) if (copy_to_user(argp, (long *) &attrib,
return -ENODEV; sizeof (struct attrib_data_t)))
rc = -EFAULT;
private = (struct dasd_eckd_private *) device->private;
attrib = private->attrib;
rc = copy_to_user((long __user *) args, (long *) &attrib,
sizeof (struct attrib_data_t));
return rc; return rc;
} }
...@@ -1456,26 +1432,19 @@ dasd_eckd_get_attrib (struct block_device *bdev, int no, long args) ...@@ -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). * Stores the attributes for cache operation to be used in Define Extend (DE).
*/ */
static int 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; struct attrib_data_t attrib;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
if (!args) if (!argp)
return -EINVAL; return -EINVAL;
device = bdev->bd_disk->private_data; if (copy_from_user(&attrib, argp, sizeof(struct attrib_data_t)))
if (device == NULL)
return -ENODEV;
if (copy_from_user(&attrib, (void __user *) args,
sizeof (struct attrib_data_t))) {
return -EFAULT; return -EFAULT;
}
private = (struct dasd_eckd_private *) device->private;
private->attrib = attrib; private->attrib = attrib;
DEV_MESSAGE(KERN_INFO, device, DEV_MESSAGE(KERN_INFO, device,
...@@ -1484,6 +1453,27 @@ dasd_eckd_set_attrib(struct block_device *bdev, int no, long args) ...@@ -1484,6 +1453,27 @@ dasd_eckd_set_attrib(struct block_device *bdev, int no, long args)
return 0; 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. * Print sense data and related channel program.
* Parts are printed because printk buffer is only 1024 bytes. * Parts are printed because printk buffer is only 1024 bytes.
...@@ -1642,6 +1632,7 @@ static struct dasd_discipline dasd_eckd_discipline = { ...@@ -1642,6 +1632,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
.free_cp = dasd_eckd_free_cp, .free_cp = dasd_eckd_free_cp,
.dump_sense = dasd_eckd_dump_sense, .dump_sense = dasd_eckd_dump_sense,
.fill_info = dasd_eckd_fill_info, .fill_info = dasd_eckd_fill_info,
.ioctl = dasd_eckd_ioctl,
}; };
static int __init static int __init
...@@ -1649,59 +1640,18 @@ dasd_eckd_init(void) ...@@ -1649,59 +1640,18 @@ dasd_eckd_init(void)
{ {
int ret; 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); ASCEBC(dasd_eckd_discipline.ebcname, 4);
ret = ccw_driver_register(&dasd_eckd_driver); ret = ccw_driver_register(&dasd_eckd_driver);
if (ret) { if (!ret)
dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR, dasd_generic_auto_online(&dasd_eckd_driver);
dasd_eckd_get_attrib); return ret;
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;
} }
static void __exit static void __exit
dasd_eckd_cleanup(void) dasd_eckd_cleanup(void)
{ {
ccw_driver_unregister(&dasd_eckd_driver); 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); module_init(dasd_eckd_init);
......
...@@ -272,6 +272,7 @@ struct dasd_discipline { ...@@ -272,6 +272,7 @@ struct dasd_discipline {
/* i/o control functions. */ /* i/o control functions. */
int (*fill_geometry) (struct dasd_device *, struct hd_geometry *); int (*fill_geometry) (struct dasd_device *, struct hd_geometry *);
int (*fill_info) (struct dasd_device *, struct dasd_information2_t *); 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; extern struct dasd_discipline *dasd_diag_discipline_pointer;
......
...@@ -448,7 +448,14 @@ dasd_ioctl(struct inode *inode, struct file *file, ...@@ -448,7 +448,14 @@ dasd_ioctl(struct inode *inode, struct file *file,
case DASDAPIVER: case DASDAPIVER:
return dasd_ioctl_api_version(argp); return dasd_ioctl_api_version(argp);
default: 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) { list_for_each_entry(ioctl, &dasd_ioctl_list, list) {
if (ioctl->no == cmd) { if (ioctl->no == cmd) {
/* Found a matching ioctl. Call it. */ /* Found a matching ioctl. Call it. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment