dasd_ioctl.c 17 KB

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