dasd_ioctl.c 18 KB

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