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