dasd_ioctl.c 18 KB

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