diff options
author | Christoph Hellwig <hch@lst.de> | 2006-03-24 06:15:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-24 10:33:17 -0500 |
commit | 1107ccfbdef280fedc677af3bdbc405611ba554a (patch) | |
tree | a3588525dbe853d13e5f25fa496deecaa022ab3a | |
parent | 13c6204facb01d425320411c17febff666875518 (diff) |
[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: 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>
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 142 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 1 | ||||
-rw-r--r-- | drivers/s390/block/dasd_ioctl.c | 9 |
3 files changed, 55 insertions, 97 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 822e2a265578..ee09ef33d08d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1227,19 +1227,14 @@ dasd_eckd_fill_info(struct dasd_device * device, | |||
1227 | * (see dasd_eckd_reserve) device. | 1227 | * (see dasd_eckd_reserve) device. |
1228 | */ | 1228 | */ |
1229 | static int | 1229 | static int |
1230 | dasd_eckd_release(struct block_device *bdev, int no, long args) | 1230 | dasd_eckd_release(struct dasd_device *device) |
1231 | { | 1231 | { |
1232 | struct dasd_device *device; | ||
1233 | struct dasd_ccw_req *cqr; | 1232 | struct dasd_ccw_req *cqr; |
1234 | int rc; | 1233 | int rc; |
1235 | 1234 | ||
1236 | if (!capable(CAP_SYS_ADMIN)) | 1235 | if (!capable(CAP_SYS_ADMIN)) |
1237 | return -EACCES; | 1236 | return -EACCES; |
1238 | 1237 | ||
1239 | device = bdev->bd_disk->private_data; | ||
1240 | if (device == NULL) | ||
1241 | return -ENODEV; | ||
1242 | |||
1243 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 1238 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, |
1244 | 1, 32, device); | 1239 | 1, 32, device); |
1245 | if (IS_ERR(cqr)) { | 1240 | if (IS_ERR(cqr)) { |
@@ -1272,19 +1267,14 @@ dasd_eckd_release(struct block_device *bdev, int no, long args) | |||
1272 | * the interrupt is outstanding for a certain time. | 1267 | * the interrupt is outstanding for a certain time. |
1273 | */ | 1268 | */ |
1274 | static int | 1269 | static int |
1275 | dasd_eckd_reserve(struct block_device *bdev, int no, long args) | 1270 | dasd_eckd_reserve(struct dasd_device *device) |
1276 | { | 1271 | { |
1277 | struct dasd_device *device; | ||
1278 | struct dasd_ccw_req *cqr; | 1272 | struct dasd_ccw_req *cqr; |
1279 | int rc; | 1273 | int rc; |
1280 | 1274 | ||
1281 | if (!capable(CAP_SYS_ADMIN)) | 1275 | if (!capable(CAP_SYS_ADMIN)) |
1282 | return -EACCES; | 1276 | return -EACCES; |
1283 | 1277 | ||
1284 | device = bdev->bd_disk->private_data; | ||
1285 | if (device == NULL) | ||
1286 | return -ENODEV; | ||
1287 | |||
1288 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 1278 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, |
1289 | 1, 32, device); | 1279 | 1, 32, device); |
1290 | if (IS_ERR(cqr)) { | 1280 | if (IS_ERR(cqr)) { |
@@ -1316,19 +1306,14 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args) | |||
1316 | * (unconditional reserve) | 1306 | * (unconditional reserve) |
1317 | */ | 1307 | */ |
1318 | static int | 1308 | static int |
1319 | dasd_eckd_steal_lock(struct block_device *bdev, int no, long args) | 1309 | dasd_eckd_steal_lock(struct dasd_device *device) |
1320 | { | 1310 | { |
1321 | struct dasd_device *device; | ||
1322 | struct dasd_ccw_req *cqr; | 1311 | struct dasd_ccw_req *cqr; |
1323 | int rc; | 1312 | int rc; |
1324 | 1313 | ||
1325 | if (!capable(CAP_SYS_ADMIN)) | 1314 | if (!capable(CAP_SYS_ADMIN)) |
1326 | return -EACCES; | 1315 | return -EACCES; |
1327 | 1316 | ||
1328 | device = bdev->bd_disk->private_data; | ||
1329 | if (device == NULL) | ||
1330 | return -ENODEV; | ||
1331 | |||
1332 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 1317 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, |
1333 | 1, 32, device); | 1318 | 1, 32, device); |
1334 | if (IS_ERR(cqr)) { | 1319 | if (IS_ERR(cqr)) { |
@@ -1358,19 +1343,14 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args) | |||
1358 | * Read performance statistics | 1343 | * Read performance statistics |
1359 | */ | 1344 | */ |
1360 | static int | 1345 | static int |
1361 | dasd_eckd_performance(struct block_device *bdev, int no, long args) | 1346 | dasd_eckd_performance(struct dasd_device *device, void __user *argp) |
1362 | { | 1347 | { |
1363 | struct dasd_device *device; | ||
1364 | struct dasd_psf_prssd_data *prssdp; | 1348 | struct dasd_psf_prssd_data *prssdp; |
1365 | struct dasd_rssd_perf_stats_t *stats; | 1349 | struct dasd_rssd_perf_stats_t *stats; |
1366 | struct dasd_ccw_req *cqr; | 1350 | struct dasd_ccw_req *cqr; |
1367 | struct ccw1 *ccw; | 1351 | struct ccw1 *ccw; |
1368 | int rc; | 1352 | int rc; |
1369 | 1353 | ||
1370 | device = bdev->bd_disk->private_data; | ||
1371 | if (device == NULL) | ||
1372 | return -ENODEV; | ||
1373 | |||
1374 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 1354 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, |
1375 | 1 /* PSF */ + 1 /* RSSD */ , | 1355 | 1 /* PSF */ + 1 /* RSSD */ , |
1376 | (sizeof (struct dasd_psf_prssd_data) + | 1356 | (sizeof (struct dasd_psf_prssd_data) + |
@@ -1414,8 +1394,9 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args) | |||
1414 | /* Prepare for Read Subsystem Data */ | 1394 | /* Prepare for Read Subsystem Data */ |
1415 | prssdp = (struct dasd_psf_prssd_data *) cqr->data; | 1395 | prssdp = (struct dasd_psf_prssd_data *) cqr->data; |
1416 | stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1); | 1396 | stats = (struct dasd_rssd_perf_stats_t *) (prssdp + 1); |
1417 | rc = copy_to_user((long __user *) args, (long *) stats, | 1397 | if (copy_to_user(argp, stats, |
1418 | sizeof(struct dasd_rssd_perf_stats_t)); | 1398 | sizeof(struct dasd_rssd_perf_stats_t))) |
1399 | rc = -EFAULT; | ||
1419 | } | 1400 | } |
1420 | dasd_sfree_request(cqr, cqr->device); | 1401 | dasd_sfree_request(cqr, cqr->device); |
1421 | return rc; | 1402 | return rc; |
@@ -1426,27 +1407,22 @@ dasd_eckd_performance(struct block_device *bdev, int no, long args) | |||
1426 | * Returnes the cache attributes used in Define Extend (DE). | 1407 | * Returnes the cache attributes used in Define Extend (DE). |
1427 | */ | 1408 | */ |
1428 | static int | 1409 | static int |
1429 | dasd_eckd_get_attrib (struct block_device *bdev, int no, long args) | 1410 | dasd_eckd_get_attrib(struct dasd_device *device, void __user *argp) |
1430 | { | 1411 | { |
1431 | struct dasd_device *device; | 1412 | struct dasd_eckd_private *private = |
1432 | struct dasd_eckd_private *private; | 1413 | (struct dasd_eckd_private *)device->private; |
1433 | struct attrib_data_t attrib; | 1414 | struct attrib_data_t attrib = private->attrib; |
1434 | int rc; | 1415 | int rc; |
1435 | 1416 | ||
1436 | if (!capable(CAP_SYS_ADMIN)) | 1417 | if (!capable(CAP_SYS_ADMIN)) |
1437 | return -EACCES; | 1418 | return -EACCES; |
1438 | if (!args) | 1419 | if (!argp) |
1439 | return -EINVAL; | 1420 | return -EINVAL; |
1440 | 1421 | ||
1441 | device = bdev->bd_disk->private_data; | 1422 | rc = 0; |
1442 | if (device == NULL) | 1423 | if (copy_to_user(argp, (long *) &attrib, |
1443 | return -ENODEV; | 1424 | sizeof (struct attrib_data_t))) |
1444 | 1425 | rc = -EFAULT; | |
1445 | private = (struct dasd_eckd_private *) device->private; | ||
1446 | attrib = private->attrib; | ||
1447 | |||
1448 | rc = copy_to_user((long __user *) args, (long *) &attrib, | ||
1449 | sizeof (struct attrib_data_t)); | ||
1450 | 1426 | ||
1451 | return rc; | 1427 | return rc; |
1452 | } | 1428 | } |
@@ -1456,26 +1432,19 @@ dasd_eckd_get_attrib (struct block_device *bdev, int no, long args) | |||
1456 | * Stores the attributes for cache operation to be used in Define Extend (DE). | 1432 | * Stores the attributes for cache operation to be used in Define Extend (DE). |
1457 | */ | 1433 | */ |
1458 | static int | 1434 | static int |
1459 | dasd_eckd_set_attrib(struct block_device *bdev, int no, long args) | 1435 | dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp) |
1460 | { | 1436 | { |
1461 | struct dasd_device *device; | 1437 | struct dasd_eckd_private *private = |
1462 | struct dasd_eckd_private *private; | 1438 | (struct dasd_eckd_private *)device->private; |
1463 | struct attrib_data_t attrib; | 1439 | struct attrib_data_t attrib; |
1464 | 1440 | ||
1465 | if (!capable(CAP_SYS_ADMIN)) | 1441 | if (!capable(CAP_SYS_ADMIN)) |
1466 | return -EACCES; | 1442 | return -EACCES; |
1467 | if (!args) | 1443 | if (!argp) |
1468 | return -EINVAL; | 1444 | return -EINVAL; |
1469 | 1445 | ||
1470 | device = bdev->bd_disk->private_data; | 1446 | if (copy_from_user(&attrib, argp, sizeof(struct attrib_data_t))) |
1471 | if (device == NULL) | ||
1472 | return -ENODEV; | ||
1473 | |||
1474 | if (copy_from_user(&attrib, (void __user *) args, | ||
1475 | sizeof (struct attrib_data_t))) { | ||
1476 | return -EFAULT; | 1447 | return -EFAULT; |
1477 | } | ||
1478 | private = (struct dasd_eckd_private *) device->private; | ||
1479 | private->attrib = attrib; | 1448 | private->attrib = attrib; |
1480 | 1449 | ||
1481 | DEV_MESSAGE(KERN_INFO, device, | 1450 | DEV_MESSAGE(KERN_INFO, device, |
@@ -1484,6 +1453,27 @@ dasd_eckd_set_attrib(struct block_device *bdev, int no, long args) | |||
1484 | return 0; | 1453 | return 0; |
1485 | } | 1454 | } |
1486 | 1455 | ||
1456 | static int | ||
1457 | dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp) | ||
1458 | { | ||
1459 | switch (cmd) { | ||
1460 | case BIODASDGATTR: | ||
1461 | return dasd_eckd_get_attrib(device, argp); | ||
1462 | case BIODASDSATTR: | ||
1463 | return dasd_eckd_set_attrib(device, argp); | ||
1464 | case BIODASDPSRD: | ||
1465 | return dasd_eckd_performance(device, argp); | ||
1466 | case BIODASDRLSE: | ||
1467 | return dasd_eckd_release(device); | ||
1468 | case BIODASDRSRV: | ||
1469 | return dasd_eckd_reserve(device); | ||
1470 | case BIODASDSLCK: | ||
1471 | return dasd_eckd_steal_lock(device); | ||
1472 | default: | ||
1473 | return -ENOIOCTLCMD; | ||
1474 | } | ||
1475 | } | ||
1476 | |||
1487 | /* | 1477 | /* |
1488 | * Print sense data and related channel program. | 1478 | * Print sense data and related channel program. |
1489 | * Parts are printed because printk buffer is only 1024 bytes. | 1479 | * Parts are printed because printk buffer is only 1024 bytes. |
@@ -1642,6 +1632,7 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
1642 | .free_cp = dasd_eckd_free_cp, | 1632 | .free_cp = dasd_eckd_free_cp, |
1643 | .dump_sense = dasd_eckd_dump_sense, | 1633 | .dump_sense = dasd_eckd_dump_sense, |
1644 | .fill_info = dasd_eckd_fill_info, | 1634 | .fill_info = dasd_eckd_fill_info, |
1635 | .ioctl = dasd_eckd_ioctl, | ||
1645 | }; | 1636 | }; |
1646 | 1637 | ||
1647 | static int __init | 1638 | static int __init |
@@ -1649,59 +1640,18 @@ dasd_eckd_init(void) | |||
1649 | { | 1640 | { |
1650 | int ret; | 1641 | int ret; |
1651 | 1642 | ||
1652 | dasd_ioctl_no_register(THIS_MODULE, BIODASDGATTR, | ||
1653 | dasd_eckd_get_attrib); | ||
1654 | dasd_ioctl_no_register(THIS_MODULE, BIODASDSATTR, | ||
1655 | dasd_eckd_set_attrib); | ||
1656 | dasd_ioctl_no_register(THIS_MODULE, BIODASDPSRD, | ||
1657 | dasd_eckd_performance); | ||
1658 | dasd_ioctl_no_register(THIS_MODULE, BIODASDRLSE, | ||
1659 | dasd_eckd_release); | ||
1660 | dasd_ioctl_no_register(THIS_MODULE, BIODASDRSRV, | ||
1661 | dasd_eckd_reserve); | ||
1662 | dasd_ioctl_no_register(THIS_MODULE, BIODASDSLCK, | ||
1663 | dasd_eckd_steal_lock); | ||
1664 | |||
1665 | ASCEBC(dasd_eckd_discipline.ebcname, 4); | 1643 | ASCEBC(dasd_eckd_discipline.ebcname, 4); |
1666 | 1644 | ||
1667 | ret = ccw_driver_register(&dasd_eckd_driver); | 1645 | ret = ccw_driver_register(&dasd_eckd_driver); |
1668 | if (ret) { | 1646 | if (!ret) |
1669 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR, | 1647 | dasd_generic_auto_online(&dasd_eckd_driver); |
1670 | dasd_eckd_get_attrib); | 1648 | return ret; |
1671 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR, | ||
1672 | dasd_eckd_set_attrib); | ||
1673 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD, | ||
1674 | dasd_eckd_performance); | ||
1675 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE, | ||
1676 | dasd_eckd_release); | ||
1677 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV, | ||
1678 | dasd_eckd_reserve); | ||
1679 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK, | ||
1680 | dasd_eckd_steal_lock); | ||
1681 | return ret; | ||
1682 | } | ||
1683 | |||
1684 | dasd_generic_auto_online(&dasd_eckd_driver); | ||
1685 | return 0; | ||
1686 | } | 1649 | } |
1687 | 1650 | ||
1688 | static void __exit | 1651 | static void __exit |
1689 | dasd_eckd_cleanup(void) | 1652 | dasd_eckd_cleanup(void) |
1690 | { | 1653 | { |
1691 | ccw_driver_unregister(&dasd_eckd_driver); | 1654 | ccw_driver_unregister(&dasd_eckd_driver); |
1692 | |||
1693 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDGATTR, | ||
1694 | dasd_eckd_get_attrib); | ||
1695 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSATTR, | ||
1696 | dasd_eckd_set_attrib); | ||
1697 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDPSRD, | ||
1698 | dasd_eckd_performance); | ||
1699 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRLSE, | ||
1700 | dasd_eckd_release); | ||
1701 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDRSRV, | ||
1702 | dasd_eckd_reserve); | ||
1703 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDSLCK, | ||
1704 | dasd_eckd_steal_lock); | ||
1705 | } | 1655 | } |
1706 | 1656 | ||
1707 | module_init(dasd_eckd_init); | 1657 | module_init(dasd_eckd_init); |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 6010ecf76b4c..e9485559e22e 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -272,6 +272,7 @@ struct dasd_discipline { | |||
272 | /* i/o control functions. */ | 272 | /* i/o control functions. */ |
273 | int (*fill_geometry) (struct dasd_device *, struct hd_geometry *); | 273 | int (*fill_geometry) (struct dasd_device *, struct hd_geometry *); |
274 | int (*fill_info) (struct dasd_device *, struct dasd_information2_t *); | 274 | int (*fill_info) (struct dasd_device *, struct dasd_information2_t *); |
275 | int (*ioctl) (struct dasd_device *, unsigned int, void __user *); | ||
275 | }; | 276 | }; |
276 | 277 | ||
277 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | 278 | extern struct dasd_discipline *dasd_diag_discipline_pointer; |
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index e3ad34686444..bb6caf46bbd9 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
@@ -448,7 +448,14 @@ dasd_ioctl(struct inode *inode, struct file *file, | |||
448 | case DASDAPIVER: | 448 | case DASDAPIVER: |
449 | return dasd_ioctl_api_version(argp); | 449 | return dasd_ioctl_api_version(argp); |
450 | default: | 450 | default: |
451 | /* resort to the deprecated dynamic ioctl list */ | 451 | /* if the discipline has an ioctl method try it. */ |
452 | if (device->discipline->ioctl) { | ||
453 | int rval = device->discipline->ioctl(device, cmd, argp); | ||
454 | if (rval != -ENOIOCTLCMD) | ||
455 | return rval; | ||
456 | } | ||
457 | |||
458 | /* else resort to the deprecated dynamic ioctl list */ | ||
452 | list_for_each_entry(ioctl, &dasd_ioctl_list, list) { | 459 | list_for_each_entry(ioctl, &dasd_ioctl_list, list) { |
453 | if (ioctl->no == cmd) { | 460 | if (ioctl->no == cmd) { |
454 | /* Found a matching ioctl. Call it. */ | 461 | /* Found a matching ioctl. Call it. */ |