xref: /linux/drivers/s390/block/dasd_ioctl.c (revision 99b3738fbf17208ac474420fa6b7e4b0c0c2b9ed)
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);
549