aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_ioctl.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-03-24 06:15:19 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-24 10:33:16 -0500
commit13c6204facb01d425320411c17febff666875518 (patch)
treedf58981381da42532e0910694361eadb1c133ea9 /drivers/s390/block/dasd_ioctl.c
parent61d3ad0edf67e3baa66f124bc9ce964523d41809 (diff)
[PATCH] s390: use normal switch statement for ioctls in dasd_ioctlc
Handle ioctls implemented in dasd_ioctl through the normal switch statement that most drivers use instead of the awkward dasd_ioctl_no_register routine. This avoids searching a linear list on every call to dasd_ioctl(), and allows to give the various ioctl implementation functions sane prototypes, aswell as moving the check for bdev->bd_disk->private_data from the individual functions to dasd_ioctl. (I think it can't actually every be NULL, but let's keep that for later) 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>
Diffstat (limited to 'drivers/s390/block/dasd_ioctl.c')
-rw-r--r--drivers/s390/block/dasd_ioctl.c241
1 files changed, 86 insertions, 155 deletions
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index f9930552ab54..e3ad34686444 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -77,62 +77,11 @@ dasd_ioctl_no_unregister(struct module *owner, int no, dasd_ioctl_fn_t handler)
77 return 0; 77 return 0;
78} 78}
79 79
80int
81dasd_ioctl(struct inode *inp, struct file *filp,
82 unsigned int no, unsigned long data)
83{
84 struct block_device *bdev = inp->i_bdev;
85 struct dasd_device *device = bdev->bd_disk->private_data;
86 struct dasd_ioctl *ioctl;
87 const char *dir;
88 int rc;
89
90 if ((_IOC_DIR(no) != _IOC_NONE) && (data == 0)) {
91 PRINT_DEBUG("empty data ptr");
92 return -EINVAL;
93 }
94 dir = _IOC_DIR (no) == _IOC_NONE ? "0" :
95 _IOC_DIR (no) == _IOC_READ ? "r" :
96 _IOC_DIR (no) == _IOC_WRITE ? "w" :
97 _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u";
98 DBF_DEV_EVENT(DBF_DEBUG, device,
99 "ioctl 0x%08x %s'0x%x'%d(%d) with data %8lx", no,
100 dir, _IOC_TYPE(no), _IOC_NR(no), _IOC_SIZE(no), data);
101 /* Search for ioctl no in the ioctl list. */
102 list_for_each_entry(ioctl, &dasd_ioctl_list, list) {
103 if (ioctl->no == no) {
104 /* Found a matching ioctl. Call it. */
105 if (!try_module_get(ioctl->owner))
106 continue;
107 rc = ioctl->handler(bdev, no, data);
108 module_put(ioctl->owner);
109 return rc;
110 }
111 }
112 /* No ioctl with number no. */
113 DBF_DEV_EVENT(DBF_INFO, device,
114 "unknown ioctl 0x%08x=%s'0x%x'%d(%d) data %8lx", no,
115 dir, _IOC_TYPE(no), _IOC_NR(no), _IOC_SIZE(no), data);
116 return -EINVAL;
117}
118
119long
120dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
121{
122 int rval;
123
124 lock_kernel();
125 rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
126 unlock_kernel();
127
128 return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
129}
130
131static int 80static int
132dasd_ioctl_api_version(struct block_device *bdev, int no, long args) 81dasd_ioctl_api_version(void __user *argp)
133{ 82{
134 int ver = DASD_API_VERSION; 83 int ver = DASD_API_VERSION;
135 return put_user(ver, (int __user *) args); 84 return put_user(ver, (int *)argp);
136} 85}
137 86
138/* 87/*
@@ -140,15 +89,13 @@ dasd_ioctl_api_version(struct block_device *bdev, int no, long args)
140 * used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection 89 * used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection
141 */ 90 */
142static int 91static int
143dasd_ioctl_enable(struct block_device *bdev, int no, long args) 92dasd_ioctl_enable(struct block_device *bdev)
144{ 93{
145 struct dasd_device *device; 94 struct dasd_device *device = bdev->bd_disk->private_data;
146 95
147 if (!capable(CAP_SYS_ADMIN)) 96 if (!capable(CAP_SYS_ADMIN))
148 return -EACCES; 97 return -EACCES;
149 device = bdev->bd_disk->private_data; 98
150 if (device == NULL)
151 return -ENODEV;
152 dasd_enable_device(device); 99 dasd_enable_device(device);
153 /* Formatting the dasd device can change the capacity. */ 100 /* Formatting the dasd device can change the capacity. */
154 mutex_lock(&bdev->bd_mutex); 101 mutex_lock(&bdev->bd_mutex);
@@ -162,15 +109,13 @@ dasd_ioctl_enable(struct block_device *bdev, int no, long args)
162 * Used by dasdfmt. Disable I/O operations but allow ioctls. 109 * Used by dasdfmt. Disable I/O operations but allow ioctls.
163 */ 110 */
164static int 111static int
165dasd_ioctl_disable(struct block_device *bdev, int no, long args) 112dasd_ioctl_disable(struct block_device *bdev)
166{ 113{
167 struct dasd_device *device; 114 struct dasd_device *device = bdev->bd_disk->private_data;
168 115
169 if (!capable(CAP_SYS_ADMIN)) 116 if (!capable(CAP_SYS_ADMIN))
170 return -EACCES; 117 return -EACCES;
171 device = bdev->bd_disk->private_data; 118
172 if (device == NULL)
173 return -ENODEV;
174 /* 119 /*
175 * Man this is sick. We don't do a real disable but only downgrade 120 * Man this is sick. We don't do a real disable but only downgrade
176 * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses 121 * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
@@ -194,18 +139,13 @@ dasd_ioctl_disable(struct block_device *bdev, int no, long args)
194 * Quiesce device. 139 * Quiesce device.
195 */ 140 */
196static int 141static int
197dasd_ioctl_quiesce(struct block_device *bdev, int no, long args) 142dasd_ioctl_quiesce(struct dasd_device *device)
198{ 143{
199 struct dasd_device *device;
200 unsigned long flags; 144 unsigned long flags;
201 145
202 if (!capable (CAP_SYS_ADMIN)) 146 if (!capable (CAP_SYS_ADMIN))
203 return -EACCES; 147 return -EACCES;
204 148
205 device = bdev->bd_disk->private_data;
206 if (device == NULL)
207 return -ENODEV;
208
209 DEV_MESSAGE (KERN_DEBUG, device, "%s", 149 DEV_MESSAGE (KERN_DEBUG, device, "%s",
210 "Quiesce IO on device"); 150 "Quiesce IO on device");
211 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 151 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
@@ -219,18 +159,13 @@ dasd_ioctl_quiesce(struct block_device *bdev, int no, long args)
219 * Quiesce device. 159 * Quiesce device.
220 */ 160 */
221static int 161static int
222dasd_ioctl_resume(struct block_device *bdev, int no, long args) 162dasd_ioctl_resume(struct dasd_device *device)
223{ 163{
224 struct dasd_device *device;
225 unsigned long flags; 164 unsigned long flags;
226 165
227 if (!capable (CAP_SYS_ADMIN)) 166 if (!capable (CAP_SYS_ADMIN))
228 return -EACCES; 167 return -EACCES;
229 168
230 device = bdev->bd_disk->private_data;
231 if (device == NULL)
232 return -ENODEV;
233
234 DEV_MESSAGE (KERN_DEBUG, device, "%s", 169 DEV_MESSAGE (KERN_DEBUG, device, "%s",
235 "resume IO on device"); 170 "resume IO on device");
236 171
@@ -302,25 +237,19 @@ dasd_format(struct dasd_device * device, struct format_data_t * fdata)
302 * Format device. 237 * Format device.
303 */ 238 */
304static int 239static int
305dasd_ioctl_format(struct block_device *bdev, int no, long args) 240dasd_ioctl_format(struct block_device *bdev, void __user *argp)
306{ 241{
307 struct dasd_device *device; 242 struct dasd_device *device = bdev->bd_disk->private_data;
308 struct format_data_t fdata; 243 struct format_data_t fdata;
309 244
310 if (!capable(CAP_SYS_ADMIN)) 245 if (!capable(CAP_SYS_ADMIN))
311 return -EACCES; 246 return -EACCES;
312 if (!args) 247 if (!argp)
313 return -EINVAL; 248 return -EINVAL;
314 /* fdata == NULL is no longer a valid arg to dasd_format ! */
315 device = bdev->bd_disk->private_data;
316
317 if (device == NULL)
318 return -ENODEV;
319 249
320 if (device->features & DASD_FEATURE_READONLY) 250 if (device->features & DASD_FEATURE_READONLY)
321 return -EROFS; 251 return -EROFS;
322 if (copy_from_user(&fdata, (void __user *) args, 252 if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
323 sizeof (struct format_data_t)))
324 return -EFAULT; 253 return -EFAULT;
325 if (bdev != bdev->bd_contains) { 254 if (bdev != bdev->bd_contains) {
326 DEV_MESSAGE(KERN_WARNING, device, "%s", 255 DEV_MESSAGE(KERN_WARNING, device, "%s",
@@ -335,17 +264,8 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
335 * Reset device profile information 264 * Reset device profile information
336 */ 265 */
337static int 266static int
338dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args) 267dasd_ioctl_reset_profile(struct dasd_device *device)
339{ 268{
340 struct dasd_device *device;
341
342 if (!capable(CAP_SYS_ADMIN))
343 return -EACCES;
344
345 device = bdev->bd_disk->private_data;
346 if (device == NULL)
347 return -ENODEV;
348
349 memset(&device->profile, 0, sizeof (struct dasd_profile_info_t)); 269 memset(&device->profile, 0, sizeof (struct dasd_profile_info_t));
350 return 0; 270 return 0;
351} 271}
@@ -354,31 +274,24 @@ dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args)
354 * Return device profile information 274 * Return device profile information
355 */ 275 */
356static int 276static int
357dasd_ioctl_read_profile(struct block_device *bdev, int no, long args) 277dasd_ioctl_read_profile(struct dasd_device *device, void __user *argp)
358{ 278{
359 struct dasd_device *device;
360
361 device = bdev->bd_disk->private_data;
362 if (device == NULL)
363 return -ENODEV;
364
365 if (dasd_profile_level == DASD_PROFILE_OFF) 279 if (dasd_profile_level == DASD_PROFILE_OFF)
366 return -EIO; 280 return -EIO;
367 281 if (copy_to_user(argp, &device->profile,
368 if (copy_to_user((long __user *) args, (long *) &device->profile,
369 sizeof (struct dasd_profile_info_t))) 282 sizeof (struct dasd_profile_info_t)))
370 return -EFAULT; 283 return -EFAULT;
371 return 0; 284 return 0;
372} 285}
373#else 286#else
374static int 287static int
375dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args) 288dasd_ioctl_reset_profile(struct dasd_device *device)
376{ 289{
377 return -ENOSYS; 290 return -ENOSYS;
378} 291}
379 292
380static int 293static int
381dasd_ioctl_read_profile(struct block_device *bdev, int no, long args) 294dasd_ioctl_read_profile(struct dasd_device *device, void __user *argp)
382{ 295{
383 return -ENOSYS; 296 return -ENOSYS;
384} 297}
@@ -388,18 +301,14 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
388 * Return dasd information. Used for BIODASDINFO and BIODASDINFO2. 301 * Return dasd information. Used for BIODASDINFO and BIODASDINFO2.
389 */ 302 */
390static int 303static int
391dasd_ioctl_information(struct block_device *bdev, int no, long args) 304dasd_ioctl_information(struct dasd_device *device,
305 unsigned int cmd, void __user *argp)
392{ 306{
393 struct dasd_device *device;
394 struct dasd_information2_t *dasd_info; 307 struct dasd_information2_t *dasd_info;
395 unsigned long flags; 308 unsigned long flags;
396 int rc; 309 int rc;
397 struct ccw_device *cdev; 310 struct ccw_device *cdev;
398 311
399 device = bdev->bd_disk->private_data;
400 if (device == NULL)
401 return -ENODEV;
402
403 if (!device->discipline->fill_info) 312 if (!device->discipline->fill_info)
404 return -EINVAL; 313 return -EINVAL;
405 314
@@ -467,8 +376,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
467 } 376 }
468 377
469 rc = 0; 378 rc = 0;
470 if (copy_to_user((long __user *) args, (long *) dasd_info, 379 if (copy_to_user(argp, dasd_info,
471 ((no == (unsigned int) BIODASDINFO2) ? 380 ((cmd == (unsigned int) BIODASDINFO2) ?
472 sizeof (struct dasd_information2_t) : 381 sizeof (struct dasd_information2_t) :
473 sizeof (struct dasd_information_t)))) 382 sizeof (struct dasd_information_t))))
474 rc = -EFAULT; 383 rc = -EFAULT;
@@ -480,68 +389,90 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
480 * Set read only 389 * Set read only
481 */ 390 */
482static int 391static int
483dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) 392dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
484{ 393{
485 struct dasd_device *device; 394 struct dasd_device *device = bdev->bd_disk->private_data;
486 int intval, rc; 395 int intval;
487 396
488 if (!capable(CAP_SYS_ADMIN)) 397 if (!capable(CAP_SYS_ADMIN))
489 return -EACCES; 398 return -EACCES;
490 if (bdev != bdev->bd_contains) 399 if (bdev != bdev->bd_contains)
491 // ro setting is not allowed for partitions 400 // ro setting is not allowed for partitions
492 return -EINVAL; 401 return -EINVAL;
493 if (get_user(intval, (int __user *) args)) 402 if (get_user(intval, (int *)argp))
494 return -EFAULT; 403 return -EFAULT;
495 device = bdev->bd_disk->private_data;
496 if (device == NULL)
497 return -ENODEV;
498 404
499 set_disk_ro(bdev->bd_disk, intval); 405 set_disk_ro(bdev->bd_disk, intval);
500 rc = dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval); 406 return dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval);
501
502 return rc;
503} 407}
504 408
505/*
506 * List of static ioctls.
507 */
508static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
509{
510 { BIODASDDISABLE, dasd_ioctl_disable },
511 { BIODASDENABLE, dasd_ioctl_enable },
512 { BIODASDQUIESCE, dasd_ioctl_quiesce },
513 { BIODASDRESUME, dasd_ioctl_resume },
514 { BIODASDFMT, dasd_ioctl_format },
515 { BIODASDINFO, dasd_ioctl_information },
516 { BIODASDINFO2, dasd_ioctl_information },
517 { BIODASDPRRD, dasd_ioctl_read_profile },
518 { BIODASDPRRST, dasd_ioctl_reset_profile },
519 { BLKROSET, dasd_ioctl_set_ro },
520 { DASDAPIVER, dasd_ioctl_api_version },
521 { -1, NULL }
522};
523
524int 409int
525dasd_ioctl_init(void) 410dasd_ioctl(struct inode *inode, struct file *file,
411 unsigned int cmd, unsigned long arg)
526{ 412{
527 int i; 413 struct block_device *bdev = inode->i_bdev;
414 struct dasd_device *device = bdev->bd_disk->private_data;
415 void __user *argp = (void __user *)arg;
416 struct dasd_ioctl *ioctl;
417 int rc;
528 418
529 for (i = 0; dasd_ioctls[i].no != -1; i++) 419 if (!device)
530 dasd_ioctl_no_register(NULL, dasd_ioctls[i].no, 420 return -ENODEV;
531 dasd_ioctls[i].fn); 421
532 return 0; 422 if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) {
423 PRINT_DEBUG("empty data ptr");
424 return -EINVAL;
425 }
533 426
427 switch (cmd) {
428 case BIODASDDISABLE:
429 return dasd_ioctl_disable(bdev);
430 case BIODASDENABLE:
431 return dasd_ioctl_enable(bdev);
432 case BIODASDQUIESCE:
433 return dasd_ioctl_quiesce(device);
434 case BIODASDRESUME:
435 return dasd_ioctl_resume(device);
436 case BIODASDFMT:
437 return dasd_ioctl_format(bdev, argp);
438 case BIODASDINFO:
439 return dasd_ioctl_information(device, cmd, argp);
440 case BIODASDINFO2:
441 return dasd_ioctl_information(device, cmd, argp);
442 case BIODASDPRRD:
443 return dasd_ioctl_read_profile(device, argp);
444 case BIODASDPRRST:
445 return dasd_ioctl_reset_profile(device);
446 case BLKROSET:
447 return dasd_ioctl_set_ro(bdev, argp);
448 case DASDAPIVER:
449 return dasd_ioctl_api_version(argp);
450 default:
451 /* resort to the deprecated dynamic ioctl list */
452 list_for_each_entry(ioctl, &dasd_ioctl_list, list) {
453 if (ioctl->no == cmd) {
454 /* Found a matching ioctl. Call it. */
455 if (!try_module_get(ioctl->owner))
456 continue;
457 rc = ioctl->handler(bdev, cmd, arg);
458 module_put(ioctl->owner);
459 return rc;
460 }
461 }
462 return -EINVAL;
463 }
534} 464}
535 465
536void 466long
537dasd_ioctl_exit(void) 467dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
538{ 468{
539 int i; 469 int rval;
540 470
541 for (i = 0; dasd_ioctls[i].no != -1; i++) 471 lock_kernel();
542 dasd_ioctl_no_unregister(NULL, dasd_ioctls[i].no, 472 rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
543 dasd_ioctls[i].fn); 473 unlock_kernel();
544 474
475 return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
545} 476}
546 477
547EXPORT_SYMBOL(dasd_ioctl_no_register); 478EXPORT_SYMBOL(dasd_ioctl_no_register);