xref: /linux/drivers/s390/block/dasd_ioctl.c (revision bc46b7cbc58c4cb562b6a45a1fbc7b8e7b23df58)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
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  * Copyright IBM Corp. 1999, 2001
9  *
10  * i/o controls for the dasd driver.
11  */
12 
13 #include <linux/interrupt.h>
14 #include <linux/compat.h>
15 #include <linux/export.h>
16 #include <linux/major.h>
17 #include <linux/fs.h>
18 #include <linux/blkpg.h>
19 #include <linux/slab.h>
20 #include <asm/ccwdev.h>
21 #include <asm/schid.h>
22 #include <asm/cmb.h>
23 #include <linux/uaccess.h>
24 #include <linux/dasd_mod.h>
25 
26 #include "dasd_int.h"
27 
28 static int
dasd_ioctl_api_version(void __user * argp)29 dasd_ioctl_api_version(void __user *argp)
30 {
31 	int ver = DASD_API_VERSION;
32 	return put_user(ver, (int __user *)argp);
33 }
34 
35 /*
36  * Enable device.
37  * used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection
38  */
39 static int
dasd_ioctl_enable(struct block_device * bdev)40 dasd_ioctl_enable(struct block_device *bdev)
41 {
42 	struct dasd_device *base;
43 
44 	if (!capable(CAP_SYS_ADMIN))
45 		return -EACCES;
46 
47 	base = dasd_device_from_gendisk(bdev->bd_disk);
48 	if (!base)
49 		return -ENODEV;
50 
51 	dasd_enable_device(base);
52 	dasd_put_device(base);
53 	return 0;
54 }
55 
56 /*
57  * Disable device.
58  * Used by dasdfmt. Disable I/O operations but allow ioctls.
59  */
60 static int
dasd_ioctl_disable(struct block_device * bdev)61 dasd_ioctl_disable(struct block_device *bdev)
62 {
63 	struct dasd_device *base;
64 
65 	if (!capable(CAP_SYS_ADMIN))
66 		return -EACCES;
67 
68 	base = dasd_device_from_gendisk(bdev->bd_disk);
69 	if (!base)
70 		return -ENODEV;
71 	/*
72 	 * Man this is sick. We don't do a real disable but only downgrade
73 	 * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
74 	 * BIODASDDISABLE to disable accesses to the device via the block
75 	 * device layer but it still wants to do i/o on the device by
76 	 * using the BIODASDFMT ioctl. Therefore the correct state for the
77 	 * device is DASD_STATE_BASIC that allows to do basic i/o.
78 	 */
79 	dasd_set_target_state(base, DASD_STATE_BASIC);
80 	/*
81 	 * Set i_size to zero, since read, write, etc. check against this
82 	 * value.
83 	 */
84 	set_capacity(bdev->bd_disk, 0);
85 	dasd_put_device(base);
86 	return 0;
87 }
88 
89 /*
90  * Quiesce device.
91  */
dasd_ioctl_quiesce(struct dasd_block * block)92 static int dasd_ioctl_quiesce(struct dasd_block *block)
93 {
94 	unsigned long flags;
95 	struct dasd_device *base;
96 
97 	base = block->base;
98 	if (!capable (CAP_SYS_ADMIN))
99 		return -EACCES;
100 
101 	pr_info("%s: The DASD has been put in the quiesce "
102 		"state\n", dev_name(&base->cdev->dev));
103 	spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
104 	dasd_device_set_stop_bits(base, DASD_STOPPED_QUIESCE);
105 	spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
106 	return 0;
107 }
108 
109 
110 /*
111  * Resume device.
112  */
dasd_ioctl_resume(struct dasd_block * block)113 static int dasd_ioctl_resume(struct dasd_block *block)
114 {
115 	unsigned long flags;
116 	struct dasd_device *base;
117 
118 	base = block->base;
119 	if (!capable (CAP_SYS_ADMIN))
120 		return -EACCES;
121 
122 	pr_info("%s: I/O operations have been resumed "
123 		"on the DASD\n", dev_name(&base->cdev->dev));
124 	spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
125 	dasd_device_remove_stop_bits(base, DASD_STOPPED_QUIESCE);
126 	spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
127 
128 	dasd_schedule_block_bh(block);
129 	dasd_schedule_device_bh(base);
130 	return 0;
131 }
132 
133 /*
134  * Abort all failfast I/O on a device.
135  */
dasd_ioctl_abortio(struct dasd_block * block)136 static int dasd_ioctl_abortio(struct dasd_block *block)
137 {
138 	unsigned long flags;
139 	struct dasd_device *base;
140 	struct dasd_ccw_req *cqr, *n;
141 
142 	base = block->base;
143 	if (!capable(CAP_SYS_ADMIN))
144 		return -EACCES;
145 
146 	if (test_and_set_bit(DASD_FLAG_ABORTALL, &base->flags))
147 		return 0;
148 	DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag set");
149 
150 	spin_lock_irqsave(&block->request_queue_lock, flags);
151 	spin_lock(&block->queue_lock);
152 	list_for_each_entry_safe(cqr, n, &block->ccw_queue, blocklist) {
153 		if (test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
154 		    cqr->callback_data &&
155 		    cqr->callback_data != DASD_SLEEPON_START_TAG &&
156 		    cqr->callback_data != DASD_SLEEPON_END_TAG) {
157 			spin_unlock(&block->queue_lock);
158 			blk_abort_request(cqr->callback_data);
159 			spin_lock(&block->queue_lock);
160 		}
161 	}
162 	spin_unlock(&block->queue_lock);
163 	spin_unlock_irqrestore(&block->request_queue_lock, flags);
164 
165 	dasd_schedule_block_bh(block);
166 	return 0;
167 }
168 
169 /*
170  * Allow I/O on a device
171  */
dasd_ioctl_allowio(struct dasd_block * block)172 static int dasd_ioctl_allowio(struct dasd_block *block)
173 {
174 	struct dasd_device *base;
175 
176 	base = block->base;
177 	if (!capable(CAP_SYS_ADMIN))
178 		return -EACCES;
179 
180 	if (test_and_clear_bit(DASD_FLAG_ABORTALL, &base->flags))
181 		DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag unset");
182 
183 	return 0;
184 }
185 
186 /*
187  * performs formatting of _device_ according to _fdata_
188  * Note: The discipline's format_function is assumed to deliver formatting
189  * commands to format multiple units of the device. In terms of the ECKD
190  * devices this means CCWs are generated to format multiple tracks.
191  */
192 static int
dasd_format(struct dasd_block * block,struct format_data_t * fdata)193 dasd_format(struct dasd_block *block, struct format_data_t *fdata)
194 {
195 	struct dasd_device *base;
196 	int rc;
197 
198 	base = block->base;
199 	if (base->discipline->format_device == NULL)
200 		return -EPERM;
201 
202 	if (base->state != DASD_STATE_BASIC) {
203 		pr_warn("%s: The DASD cannot be formatted while it is enabled\n",
204 			dev_name(&base->cdev->dev));
205 		return -EBUSY;
206 	}
207 
208 	DBF_DEV_EVENT(DBF_NOTICE, base,
209 		      "formatting units %u to %u (%u B blocks) flags %u",
210 		      fdata->start_unit,
211 		      fdata->stop_unit, fdata->blksize, fdata->intensity);
212 
213 	/* Since dasdfmt keeps the device open after it was disabled,
214 	 * there still exists an inode for this device.
215 	 * We must update i_blkbits, otherwise we might get errors when
216 	 * enabling the device later.
217 	 */
218 	if (fdata->start_unit == 0) {
219 		block->gdp->part0->bd_mapping->host->i_blkbits =
220 			blksize_bits(fdata->blksize);
221 	}
222 
223 	rc = base->discipline->format_device(base, fdata, 1);
224 	if (rc == -EAGAIN)
225 		rc = base->discipline->format_device(base, fdata, 0);
226 
227 	return rc;
228 }
229 
dasd_check_format(struct dasd_block * block,struct format_check_t * cdata)230 static int dasd_check_format(struct dasd_block *block,
231 			     struct format_check_t *cdata)
232 {
233 	struct dasd_device *base;
234 	int rc;
235 
236 	base = block->base;
237 	if (!base->discipline->check_device_format)
238 		return -ENOTTY;
239 
240 	rc = base->discipline->check_device_format(base, cdata, 1);
241 	if (rc == -EAGAIN)
242 		rc = base->discipline->check_device_format(base, cdata, 0);
243 
244 	return rc;
245 }
246 
247 /*
248  * Format device.
249  */
250 static int
dasd_ioctl_format(struct block_device * bdev,void __user * argp)251 dasd_ioctl_format(struct block_device *bdev, void __user *argp)
252 {
253 	struct dasd_device *base;
254 	struct format_data_t fdata;
255 	int rc;
256 
257 	if (!capable(CAP_SYS_ADMIN))
258 		return -EACCES;
259 	if (!argp)
260 		return -EINVAL;
261 	base = dasd_device_from_gendisk(bdev->bd_disk);
262 	if (!base)
263 		return -ENODEV;
264 	if (base->features & DASD_FEATURE_READONLY ||
265 	    test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
266 		dasd_put_device(base);
267 		return -EROFS;
268 	}
269 	if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) {
270 		dasd_put_device(base);
271 		return -EFAULT;
272 	}
273 	if (bdev_is_partition(bdev)) {
274 		pr_warn("%s: The specified DASD is a partition and cannot be formatted\n",
275 			dev_name(&base->cdev->dev));
276 		dasd_put_device(base);
277 		return -EINVAL;
278 	}
279 	rc = dasd_format(base->block, &fdata);
280 	dasd_put_device(base);
281 
282 	return rc;
283 }
284 
285 /*
286  * Check device format
287  */
dasd_ioctl_check_format(struct block_device * bdev,void __user * argp)288 static int dasd_ioctl_check_format(struct block_device *bdev, void __user *argp)
289 {
290 	struct format_check_t cdata;
291 	struct dasd_device *base;
292 	int rc = 0;
293 
294 	if (!argp)
295 		return -EINVAL;
296 
297 	base = dasd_device_from_gendisk(bdev->bd_disk);
298 	if (!base)
299 		return -ENODEV;
300 	if (bdev_is_partition(bdev)) {
301 		pr_warn("%s: The specified DASD is a partition and cannot be checked\n",
302 			dev_name(&base->cdev->dev));
303 		rc = -EINVAL;
304 		goto out_err;
305 	}
306 
307 	if (copy_from_user(&cdata, argp, sizeof(cdata))) {
308 		rc = -EFAULT;
309 		goto out_err;
310 	}
311 
312 	rc = dasd_check_format(base->block, &cdata);
313 	if (rc)
314 		goto out_err;
315 
316 	if (copy_to_user(argp, &cdata, sizeof(cdata)))
317 		rc = -EFAULT;
318 
319 out_err:
320 	dasd_put_device(base);
321 
322 	return rc;
323 }
324 
dasd_release_space(struct dasd_device * device,struct format_data_t * rdata)325 static int dasd_release_space(struct dasd_device *device,
326 			      struct format_data_t *rdata)
327 {
328 	if (!device->discipline->is_ese && !device->discipline->is_ese(device))
329 		return -ENOTSUPP;
330 	if (!device->discipline->release_space)
331 		return -ENOTSUPP;
332 
333 	return device->discipline->release_space(device, rdata);
334 }
335 
336 /*
337  * Release allocated space
338  */
dasd_ioctl_release_space(struct block_device * bdev,void __user * argp)339 static int dasd_ioctl_release_space(struct block_device *bdev, void __user *argp)
340 {
341 	struct format_data_t rdata;
342 	struct dasd_device *base;
343 	int rc = 0;
344 
345 	if (!capable(CAP_SYS_ADMIN))
346 		return -EACCES;
347 	if (!argp)
348 		return -EINVAL;
349 
350 	base = dasd_device_from_gendisk(bdev->bd_disk);
351 	if (!base)
352 		return -ENODEV;
353 	if (base->features & DASD_FEATURE_READONLY ||
354 	    test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
355 		rc = -EROFS;
356 		goto out_err;
357 	}
358 	if (bdev_is_partition(bdev)) {
359 		pr_warn("%s: The specified DASD is a partition and tracks cannot be released\n",
360 			dev_name(&base->cdev->dev));
361 		rc = -EINVAL;
362 		goto out_err;
363 	}
364 
365 	if (copy_from_user(&rdata, argp, sizeof(rdata))) {
366 		rc = -EFAULT;
367 		goto out_err;
368 	}
369 
370 	rc = dasd_release_space(base, &rdata);
371 
372 out_err:
373 	dasd_put_device(base);
374 
375 	return rc;
376 }
377 
378 /*
379  * Swap driver iternal copy relation.
380  */
381 static int
dasd_ioctl_copy_pair_swap(struct block_device * bdev,void __user * argp)382 dasd_ioctl_copy_pair_swap(struct block_device *bdev, void __user *argp)
383 {
384 	struct dasd_copypair_swap_data_t data;
385 	struct dasd_device *device;
386 	int rc;
387 
388 	if (!capable(CAP_SYS_ADMIN))
389 		return -EACCES;
390 
391 	device = dasd_device_from_gendisk(bdev->bd_disk);
392 	if (!device)
393 		return -ENODEV;
394 
395 	if (copy_from_user(&data, argp, sizeof(struct dasd_copypair_swap_data_t))) {
396 		dasd_put_device(device);
397 		return -EFAULT;
398 	}
399 	if (memchr_inv(data.reserved, 0, sizeof(data.reserved))) {
400 		pr_warn("%s: Invalid swap data specified\n",
401 			dev_name(&device->cdev->dev));
402 		dasd_put_device(device);
403 		return DASD_COPYPAIRSWAP_INVALID;
404 	}
405 	if (bdev_is_partition(bdev)) {
406 		pr_warn("%s: The specified DASD is a partition and cannot be swapped\n",
407 			dev_name(&device->cdev->dev));
408 		dasd_put_device(device);
409 		return DASD_COPYPAIRSWAP_INVALID;
410 	}
411 	if (!device->copy) {
412 		pr_warn("%s: The specified DASD has no copy pair set up\n",
413 			dev_name(&device->cdev->dev));
414 		dasd_put_device(device);
415 		return -ENODEV;
416 	}
417 	if (!device->discipline->copy_pair_swap) {
418 		dasd_put_device(device);
419 		return -EOPNOTSUPP;
420 	}
421 	rc = device->discipline->copy_pair_swap(device, data.primary,
422 						data.secondary);
423 	dasd_put_device(device);
424 
425 	return rc;
426 }
427 
428 #ifdef CONFIG_DASD_PROFILE
429 /*
430  * Reset device profile information
431  */
dasd_ioctl_reset_profile(struct dasd_block * block)432 static int dasd_ioctl_reset_profile(struct dasd_block *block)
433 {
434 	dasd_profile_reset(&block->profile);
435 	return 0;
436 }
437 
438 /*
439  * Return device profile information
440  */
dasd_ioctl_read_profile(struct dasd_block * block,void __user * argp)441 static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
442 {
443 	struct dasd_profile_info_t *data;
444 	int rc = 0;
445 
446 	data = kmalloc(sizeof(*data), GFP_KERNEL);
447 	if (!data)
448 		return -ENOMEM;
449 
450 	spin_lock_bh(&block->profile.lock);
451 	if (block->profile.data) {
452 		data->dasd_io_reqs = block->profile.data->dasd_io_reqs;
453 		data->dasd_io_sects = block->profile.data->dasd_io_sects;
454 		memcpy(data->dasd_io_secs, block->profile.data->dasd_io_secs,
455 		       sizeof(data->dasd_io_secs));
456 		memcpy(data->dasd_io_times, block->profile.data->dasd_io_times,
457 		       sizeof(data->dasd_io_times));
458 		memcpy(data->dasd_io_timps, block->profile.data->dasd_io_timps,
459 		       sizeof(data->dasd_io_timps));
460 		memcpy(data->dasd_io_time1, block->profile.data->dasd_io_time1,
461 		       sizeof(data->dasd_io_time1));
462 		memcpy(data->dasd_io_time2, block->profile.data->dasd_io_time2,
463 		       sizeof(data->dasd_io_time2));
464 		memcpy(data->dasd_io_time2ps,
465 		       block->profile.data->dasd_io_time2ps,
466 		       sizeof(data->dasd_io_time2ps));
467 		memcpy(data->dasd_io_time3, block->profile.data->dasd_io_time3,
468 		       sizeof(data->dasd_io_time3));
469 		memcpy(data->dasd_io_nr_req,
470 		       block->profile.data->dasd_io_nr_req,
471 		       sizeof(data->dasd_io_nr_req));
472 		spin_unlock_bh(&block->profile.lock);
473 	} else {
474 		spin_unlock_bh(&block->profile.lock);
475 		rc = -EIO;
476 		goto out;
477 	}
478 	if (copy_to_user(argp, data, sizeof(*data)))
479 		rc = -EFAULT;
480 out:
481 	kfree(data);
482 	return rc;
483 }
484 #else
dasd_ioctl_reset_profile(struct dasd_block * block)485 static int dasd_ioctl_reset_profile(struct dasd_block *block)
486 {
487 	return -ENOTTY;
488 }
489 
dasd_ioctl_read_profile(struct dasd_block * block,void __user * argp)490 static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
491 {
492 	return -ENOTTY;
493 }
494 #endif
495 
496 /*
497  * Return dasd information. Used for BIODASDINFO and BIODASDINFO2.
498  */
__dasd_ioctl_information(struct dasd_block * block,struct dasd_information2_t * dasd_info)499 static int __dasd_ioctl_information(struct dasd_block *block,
500 		struct dasd_information2_t *dasd_info)
501 {
502 	struct subchannel_id sch_id;
503 	struct ccw_dev_id dev_id;
504 	struct dasd_device *base;
505 	struct ccw_device *cdev;
506 	struct list_head *l;
507 	unsigned long flags;
508 	int rc;
509 
510 	base = block->base;
511 	if (!base->discipline || !base->discipline->fill_info)
512 		return -EINVAL;
513 
514 	rc = base->discipline->fill_info(base, dasd_info);
515 	if (rc)
516 		return rc;
517 
518 	cdev = base->cdev;
519 	ccw_device_get_id(cdev, &dev_id);
520 	ccw_device_get_schid(cdev, &sch_id);
521 
522 	dasd_info->devno = dev_id.devno;
523 	dasd_info->schid = sch_id.sch_no;
524 	dasd_info->cu_type = cdev->id.cu_type;
525 	dasd_info->cu_model = cdev->id.cu_model;
526 	dasd_info->dev_type = cdev->id.dev_type;
527 	dasd_info->dev_model = cdev->id.dev_model;
528 	dasd_info->status = base->state;
529 	/*
530 	 * The open_count is increased for every opener, that includes
531 	 * the blkdev_get in dasd_scan_partitions.
532 	 * This must be hidden from user-space.
533 	 */
534 	dasd_info->open_count = atomic_read(&block->open_count);
535 	if (!block->bdev_file)
536 		dasd_info->open_count++;
537 
538 	/*
539 	 * check if device is really formatted
540 	 * LDL / CDL was returned by 'fill_info'
541 	 */
542 	if ((base->state < DASD_STATE_READY) ||
543 	    (dasd_check_blocksize(block->bp_block)))
544 		dasd_info->format = DASD_FORMAT_NONE;
545 
546 	dasd_info->features |=
547 		((base->features & DASD_FEATURE_READONLY) != 0);
548 
549 	memcpy(dasd_info->type, base->discipline->name, 4);
550 
551 	spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
552 	list_for_each(l, &base->ccw_queue)
553 		dasd_info->chanq_len++;
554 	spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
555 	return 0;
556 }
557 
dasd_ioctl_information(struct dasd_block * block,void __user * argp,size_t copy_size)558 static int dasd_ioctl_information(struct dasd_block *block, void __user *argp,
559 		size_t copy_size)
560 {
561 	struct dasd_information2_t *dasd_info;
562 	int error;
563 
564 	dasd_info = kzalloc(sizeof(*dasd_info), GFP_KERNEL);
565 	if (!dasd_info)
566 		return -ENOMEM;
567 
568 	error = __dasd_ioctl_information(block, dasd_info);
569 	if (!error && copy_to_user(argp, dasd_info, copy_size))
570 		error = -EFAULT;
571 	kfree(dasd_info);
572 	return error;
573 }
574 
575 /*
576  * Set read only
577  */
dasd_set_read_only(struct block_device * bdev,bool ro)578 int dasd_set_read_only(struct block_device *bdev, bool ro)
579 {
580 	struct dasd_device *base;
581 	int rc;
582 
583 	/* do not manipulate hardware state for partitions */
584 	if (bdev_is_partition(bdev))
585 		return 0;
586 
587 	base = dasd_device_from_gendisk(bdev->bd_disk);
588 	if (!base)
589 		return -ENODEV;
590 	if (!ro && test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
591 		rc = -EROFS;
592 	else
593 		rc = dasd_set_feature(base->cdev, DASD_FEATURE_READONLY, ro);
594 	dasd_put_device(base);
595 	return rc;
596 }
597 
dasd_ioctl_readall_cmb(struct dasd_block * block,unsigned int cmd,struct cmbdata __user * argp)598 static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
599 				  struct cmbdata __user *argp)
600 {
601 	size_t size = _IOC_SIZE(cmd);
602 	struct cmbdata data;
603 	int ret;
604 
605 	ret = cmf_readall(block->base->cdev, &data);
606 	if (!ret && copy_to_user(argp, &data, min(size, sizeof(*argp))))
607 		return -EFAULT;
608 	return ret;
609 }
610 
dasd_ioctl(struct block_device * bdev,blk_mode_t mode,unsigned int cmd,unsigned long arg)611 int dasd_ioctl(struct block_device *bdev, blk_mode_t mode,
612 	       unsigned int cmd, unsigned long arg)
613 {
614 	struct dasd_block *block;
615 	struct dasd_device *base;
616 	void __user *argp;
617 	int rc;
618 
619 	if (is_compat_task())
620 		argp = compat_ptr(arg);
621 	else
622 		argp = (void __user *)arg;
623 
624 	if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg)
625 		return -EINVAL;
626 
627 	base = dasd_device_from_gendisk(bdev->bd_disk);
628 	if (!base)
629 		return -ENODEV;
630 	block = base->block;
631 	rc = 0;
632 	switch (cmd) {
633 	case BIODASDDISABLE:
634 		rc = dasd_ioctl_disable(bdev);
635 		break;
636 	case BIODASDENABLE:
637 		rc = dasd_ioctl_enable(bdev);
638 		break;
639 	case BIODASDQUIESCE:
640 		rc = dasd_ioctl_quiesce(block);
641 		break;
642 	case BIODASDRESUME:
643 		rc = dasd_ioctl_resume(block);
644 		break;
645 	case BIODASDABORTIO:
646 		rc = dasd_ioctl_abortio(block);
647 		break;
648 	case BIODASDALLOWIO:
649 		rc = dasd_ioctl_allowio(block);
650 		break;
651 	case BIODASDFMT:
652 		rc = dasd_ioctl_format(bdev, argp);
653 		break;
654 	case BIODASDCHECKFMT:
655 		rc = dasd_ioctl_check_format(bdev, argp);
656 		break;
657 	case BIODASDINFO:
658 		rc = dasd_ioctl_information(block, argp,
659 				sizeof(struct dasd_information_t));
660 		break;
661 	case BIODASDINFO2:
662 		rc = dasd_ioctl_information(block, argp,
663 				sizeof(struct dasd_information2_t));
664 		break;
665 	case BIODASDPRRD:
666 		rc = dasd_ioctl_read_profile(block, argp);
667 		break;
668 	case BIODASDPRRST:
669 		rc = dasd_ioctl_reset_profile(block);
670 		break;
671 	case DASDAPIVER:
672 		rc = dasd_ioctl_api_version(argp);
673 		break;
674 	case BIODASDCMFENABLE:
675 		rc = enable_cmf(base->cdev);
676 		break;
677 	case BIODASDCMFDISABLE:
678 		rc = disable_cmf(base->cdev);
679 		break;
680 	case BIODASDREADALLCMB:
681 		rc = dasd_ioctl_readall_cmb(block, cmd, argp);
682 		break;
683 	case BIODASDRAS:
684 		rc = dasd_ioctl_release_space(bdev, argp);
685 		break;
686 	case BIODASDCOPYPAIRSWAP:
687 		rc = dasd_ioctl_copy_pair_swap(bdev, argp);
688 		break;
689 	default:
690 		/* if the discipline has an ioctl method try it. */
691 		rc = -ENOTTY;
692 		if (base->discipline->ioctl)
693 			rc = base->discipline->ioctl(block, cmd, argp);
694 	}
695 	dasd_put_device(base);
696 	return rc;
697 }
698 
699 
700 /**
701  * dasd_biodasdinfo() - fill out the dasd information structure
702  * @disk: [in] pointer to gendisk structure that references a DASD
703  * @info: [out] pointer to the dasd_information2_t structure
704  *
705  * Provide access to DASD specific information.
706  * The gendisk structure is checked if it belongs to the DASD driver by
707  * comparing the gendisk->fops pointer.
708  * If it does not belong to the DASD driver -EINVAL is returned.
709  * Otherwise the provided dasd_information2_t structure is filled out.
710  *
711  * Returns:
712  *   %0 on success and a negative error value on failure.
713  */
dasd_biodasdinfo(struct gendisk * disk,struct dasd_information2_t * info)714 int dasd_biodasdinfo(struct gendisk *disk, struct dasd_information2_t *info)
715 {
716 	struct dasd_device *base;
717 	int error;
718 
719 	if (disk->fops != &dasd_device_operations)
720 		return -EINVAL;
721 
722 	base = dasd_device_from_gendisk(disk);
723 	if (!base)
724 		return -ENODEV;
725 	error = __dasd_ioctl_information(base->block, info);
726 	dasd_put_device(base);
727 	return error;
728 }
729 /* export that symbol_get in partition detection is possible */
730 EXPORT_SYMBOL_GPL(dasd_biodasdinfo);
731