Merge branch 'origin'
[pandora-kernel.git] / drivers / s390 / block / dasd_ioctl.c
1 /*
2  * File...........: linux/drivers/s390/block/dasd_ioctl.c
3  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
4  *                  Horst Hummel <Horst.Hummel@de.ibm.com>
5  *                  Carsten Otte <Cotte@de.ibm.com>
6  *                  Martin Schwidefsky <schwidefsky@de.ibm.com>
7  * Bugreports.to..: <Linux390@de.ibm.com>
8  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9  *
10  * i/o controls for the dasd driver.
11  */
12 #include <linux/config.h>
13 #include <linux/interrupt.h>
14 #include <linux/major.h>
15 #include <linux/fs.h>
16 #include <linux/blkpg.h>
17
18 #include <asm/ccwdev.h>
19 #include <asm/uaccess.h>
20
21 /* This is ugly... */
22 #define PRINTK_HEADER "dasd_ioctl:"
23
24 #include "dasd_int.h"
25
26 /*
27  * SECTION: ioctl functions.
28  */
29 static struct list_head dasd_ioctl_list = LIST_HEAD_INIT(dasd_ioctl_list);
30
31 /*
32  * Find the ioctl with number no.
33  */
34 static struct dasd_ioctl *
35 dasd_find_ioctl(int no)
36 {
37         struct dasd_ioctl *ioctl;
38
39         list_for_each_entry (ioctl, &dasd_ioctl_list, list)
40                 if (ioctl->no == no)
41                         return ioctl;
42         return NULL;
43 }
44
45 /*
46  * Register ioctl with number no.
47  */
48 int
49 dasd_ioctl_no_register(struct module *owner, int no, dasd_ioctl_fn_t handler)
50 {
51         struct dasd_ioctl *new;
52         if (dasd_find_ioctl(no))
53                 return -EBUSY;
54         new = kmalloc(sizeof (struct dasd_ioctl), GFP_KERNEL);
55         if (new == NULL)
56                 return -ENOMEM;
57         new->owner = owner;
58         new->no = no;
59         new->handler = handler;
60         list_add(&new->list, &dasd_ioctl_list);
61         return 0;
62 }
63
64 /*
65  * Deregister ioctl with number no.
66  */
67 int
68 dasd_ioctl_no_unregister(struct module *owner, int no, dasd_ioctl_fn_t handler)
69 {
70         struct dasd_ioctl *old = dasd_find_ioctl(no);
71         if (old == NULL)
72                 return -ENOENT;
73         if (old->no != no || old->handler != handler || owner != old->owner)
74                 return -EINVAL;
75         list_del(&old->list);
76         kfree(old);
77         return 0;
78 }
79
80 int
81 dasd_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
119 long
120 dasd_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
131 static int
132 dasd_ioctl_api_version(struct block_device *bdev, int no, long args)
133 {
134         int ver = DASD_API_VERSION;
135         return put_user(ver, (int __user *) args);
136 }
137
138 /*
139  * Enable device.
140  * used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection
141  */
142 static int
143 dasd_ioctl_enable(struct block_device *bdev, int no, long args)
144 {
145         struct dasd_device *device;
146
147         if (!capable(CAP_SYS_ADMIN))
148                 return -EACCES;
149         device = bdev->bd_disk->private_data;
150         if (device == NULL)
151                 return -ENODEV;
152         dasd_enable_device(device);
153         /* Formatting the dasd device can change the capacity. */
154         down(&bdev->bd_sem);
155         i_size_write(bdev->bd_inode, (loff_t)get_capacity(device->gdp) << 9);
156         up(&bdev->bd_sem);
157         return 0;
158 }
159
160 /*
161  * Disable device.
162  * Used by dasdfmt. Disable I/O operations but allow ioctls.
163  */
164 static int
165 dasd_ioctl_disable(struct block_device *bdev, int no, long args)
166 {
167         struct dasd_device *device;
168
169         if (!capable(CAP_SYS_ADMIN))
170                 return -EACCES;
171         device = bdev->bd_disk->private_data;
172         if (device == NULL)
173                 return -ENODEV;
174         /*
175          * 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
177          * BIODASDDISABLE to disable accesses to the device via the block
178          * device layer but it still wants to do i/o on the device by
179          * using the BIODASDFMT ioctl. Therefore the correct state for the
180          * device is DASD_STATE_BASIC that allows to do basic i/o.
181          */
182         dasd_set_target_state(device, DASD_STATE_BASIC);
183         /*
184          * Set i_size to zero, since read, write, etc. check against this
185          * value.
186          */
187         down(&bdev->bd_sem);
188         i_size_write(bdev->bd_inode, 0);
189         up(&bdev->bd_sem);
190         return 0;
191 }
192
193 /*
194  * Quiesce device.
195  */
196 static int
197 dasd_ioctl_quiesce(struct block_device *bdev, int no, long args)
198 {
199         struct dasd_device *device;
200         unsigned long flags;
201         
202         if (!capable (CAP_SYS_ADMIN))
203                 return -EACCES;
204         
205         device = bdev->bd_disk->private_data;
206         if (device == NULL)
207                 return -ENODEV;
208         
209         DEV_MESSAGE (KERN_DEBUG, device, "%s",
210                      "Quiesce IO on device");
211         spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
212         device->stopped |= DASD_STOPPED_QUIESCE;
213         spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
214         return 0;
215 }
216
217
218 /*
219  * Quiesce device.
220  */
221 static int
222 dasd_ioctl_resume(struct block_device *bdev, int no, long args)
223 {
224         struct dasd_device *device;
225         unsigned long flags;
226         
227         if (!capable (CAP_SYS_ADMIN)) 
228                 return -EACCES;
229
230         device = bdev->bd_disk->private_data;
231         if (device == NULL)
232                 return -ENODEV;
233
234         DEV_MESSAGE (KERN_DEBUG, device, "%s",
235                      "resume IO on device");
236         
237         spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
238         device->stopped &= ~DASD_STOPPED_QUIESCE;
239         spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
240
241         dasd_schedule_bh (device);
242         return 0;
243 }
244
245 /*
246  * performs formatting of _device_ according to _fdata_
247  * Note: The discipline's format_function is assumed to deliver formatting
248  * commands to format a single unit of the device. In terms of the ECKD
249  * devices this means CCWs are generated to format a single track.
250  */
251 static int
252 dasd_format(struct dasd_device * device, struct format_data_t * fdata)
253 {
254         struct dasd_ccw_req *cqr;
255         int rc;
256
257         if (device->discipline->format_device == NULL)
258                 return -EPERM;
259
260         if (device->state != DASD_STATE_BASIC) {
261                 DEV_MESSAGE(KERN_WARNING, device, "%s",
262                             "dasd_format: device is not disabled! ");
263                 return -EBUSY;
264         }
265
266         DBF_DEV_EVENT(DBF_NOTICE, device,
267                       "formatting units %d to %d (%d B blocks) flags %d",
268                       fdata->start_unit,
269                       fdata->stop_unit, fdata->blksize, fdata->intensity);
270
271         /* Since dasdfmt keeps the device open after it was disabled,
272          * there still exists an inode for this device.
273          * We must update i_blkbits, otherwise we might get errors when
274          * enabling the device later.
275          */
276         if (fdata->start_unit == 0) {
277                 struct block_device *bdev = bdget_disk(device->gdp, 0);
278                 bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
279                 bdput(bdev);
280         }
281
282         while (fdata->start_unit <= fdata->stop_unit) {
283                 cqr = device->discipline->format_device(device, fdata);
284                 if (IS_ERR(cqr))
285                         return PTR_ERR(cqr);
286                 rc = dasd_sleep_on_interruptible(cqr);
287                 dasd_sfree_request(cqr, cqr->device);
288                 if (rc) {
289                         if (rc != -ERESTARTSYS)
290                                 DEV_MESSAGE(KERN_ERR, device,
291                                             " Formatting of unit %d failed "
292                                             "with rc = %d",
293                                             fdata->start_unit, rc);
294                         return rc;
295                 }
296                 fdata->start_unit++;
297         }
298         return 0;
299 }
300
301 /*
302  * Format device.
303  */
304 static int
305 dasd_ioctl_format(struct block_device *bdev, int no, long args)
306 {
307         struct dasd_device *device;
308         struct format_data_t fdata;
309
310         if (!capable(CAP_SYS_ADMIN))
311                 return -EACCES;
312         if (!args)
313                 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
320         if (device->features & DASD_FEATURE_READONLY)
321                 return -EROFS;
322         if (copy_from_user(&fdata, (void __user *) args,
323                            sizeof (struct format_data_t)))
324                 return -EFAULT;
325         if (bdev != bdev->bd_contains) {
326                 DEV_MESSAGE(KERN_WARNING, device, "%s",
327                             "Cannot low-level format a partition");
328                 return -EINVAL;
329         }
330         return dasd_format(device, &fdata);
331 }
332
333 #ifdef CONFIG_DASD_PROFILE
334 /*
335  * Reset device profile information
336  */
337 static int
338 dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args)
339 {
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));
350         return 0;
351 }
352
353 /*
354  * Return device profile information
355  */
356 static int
357 dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
358 {
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)
366                 return -EIO;
367
368         if (copy_to_user((long __user *) args, (long *) &device->profile,
369                          sizeof (struct dasd_profile_info_t)))
370                 return -EFAULT;
371         return 0;
372 }
373 #else
374 static int
375 dasd_ioctl_reset_profile(struct block_device *bdev, int no, long args)
376 {
377         return -ENOSYS;
378 }
379
380 static int
381 dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
382 {
383         return -ENOSYS;
384 }
385 #endif
386
387 /*
388  * Return dasd information. Used for BIODASDINFO and BIODASDINFO2.
389  */
390 static int
391 dasd_ioctl_information(struct block_device *bdev, int no, long args)
392 {
393         struct dasd_device *device;
394         struct dasd_information2_t *dasd_info;
395         unsigned long flags;
396         int rc;
397         struct ccw_device *cdev;
398
399         device = bdev->bd_disk->private_data;
400         if (device == NULL)
401                 return -ENODEV;
402
403         if (!device->discipline->fill_info)
404                 return -EINVAL;
405
406         dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
407         if (dasd_info == NULL)
408                 return -ENOMEM;
409
410         rc = device->discipline->fill_info(device, dasd_info);
411         if (rc) {
412                 kfree(dasd_info);
413                 return rc;
414         }
415
416         cdev = device->cdev;
417
418         dasd_info->devno = _ccw_device_get_device_number(device->cdev);
419         dasd_info->schid = _ccw_device_get_subchannel_number(device->cdev);
420         dasd_info->cu_type = cdev->id.cu_type;
421         dasd_info->cu_model = cdev->id.cu_model;
422         dasd_info->dev_type = cdev->id.dev_type;
423         dasd_info->dev_model = cdev->id.dev_model;
424         dasd_info->status = device->state;
425         /*
426          * The open_count is increased for every opener, that includes
427          * the blkdev_get in dasd_scan_partitions.
428          * This must be hidden from user-space.
429          */
430         dasd_info->open_count = atomic_read(&device->open_count);
431         if (!device->bdev)
432                 dasd_info->open_count++;
433         
434         /*
435          * check if device is really formatted
436          * LDL / CDL was returned by 'fill_info'
437          */
438         if ((device->state < DASD_STATE_READY) ||
439             (dasd_check_blocksize(device->bp_block)))
440                 dasd_info->format = DASD_FORMAT_NONE;
441
442         dasd_info->features |=
443                 ((device->features & DASD_FEATURE_READONLY) != 0);
444
445         if (device->discipline)
446                 memcpy(dasd_info->type, device->discipline->name, 4);
447         else
448                 memcpy(dasd_info->type, "none", 4);
449         dasd_info->req_queue_len = 0;
450         dasd_info->chanq_len = 0;
451         if (device->request_queue->request_fn) {
452                 struct list_head *l;
453 #ifdef DASD_EXTENDED_PROFILING
454                 {
455                         struct list_head *l;
456                         spin_lock_irqsave(&device->lock, flags);
457                         list_for_each(l, &device->request_queue->queue_head)
458                                 dasd_info->req_queue_len++;
459                         spin_unlock_irqrestore(&device->lock, flags);
460                 }
461 #endif                          /* DASD_EXTENDED_PROFILING */
462                 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
463                 list_for_each(l, &device->ccw_queue)
464                         dasd_info->chanq_len++;
465                 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
466                                        flags);
467         }
468
469         rc = 0;
470         if (copy_to_user((long __user *) args, (long *) dasd_info,
471                          ((no == (unsigned int) BIODASDINFO2) ?
472                           sizeof (struct dasd_information2_t) :
473                           sizeof (struct dasd_information_t))))
474                 rc = -EFAULT;
475         kfree(dasd_info);
476         return rc;
477 }
478
479 /*
480  * Set read only
481  */
482 static int
483 dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
484 {
485         struct dasd_device *device;
486         int intval, rc;
487
488         if (!capable(CAP_SYS_ADMIN))
489                 return -EACCES;
490         if (bdev != bdev->bd_contains)
491                 // ro setting is not allowed for partitions
492                 return -EINVAL;
493         if (get_user(intval, (int __user *) args))
494                 return -EFAULT;
495         device =  bdev->bd_disk->private_data;
496         if (device == NULL)
497                 return -ENODEV;
498
499         set_disk_ro(bdev->bd_disk, intval);
500         rc = dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval);
501
502         return rc;
503 }
504
505 /*
506  * List of static ioctls.
507  */
508 static 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
524 int
525 dasd_ioctl_init(void)
526 {
527         int i;
528
529         for (i = 0; dasd_ioctls[i].no != -1; i++)
530                 dasd_ioctl_no_register(NULL, dasd_ioctls[i].no,
531                                        dasd_ioctls[i].fn);
532         return 0;
533
534 }
535
536 void
537 dasd_ioctl_exit(void)
538 {
539         int i;
540
541         for (i = 0; dasd_ioctls[i].no != -1; i++)
542                 dasd_ioctl_no_unregister(NULL, dasd_ioctls[i].no,
543                                          dasd_ioctls[i].fn);
544
545 }
546
547 EXPORT_SYMBOL(dasd_ioctl_no_register);
548 EXPORT_SYMBOL(dasd_ioctl_no_unregister);