dasd_ioctl.c 16.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
L
Linus Torvalds 已提交
2 3 4 5 6 7
/*
 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
 *		    Horst Hummel <Horst.Hummel@de.ibm.com>
 *		    Carsten Otte <Cotte@de.ibm.com>
 *		    Martin Schwidefsky <schwidefsky@de.ibm.com>
 * Bugreports.to..: <Linux390@de.ibm.com>
8
 * Copyright IBM Corp. 1999, 2001
L
Linus Torvalds 已提交
9 10 11
 *
 * i/o controls for the dasd driver.
 */
S
Stefan Haberland 已提交
12 13 14

#define KMSG_COMPONENT "dasd"

L
Linus Torvalds 已提交
15
#include <linux/interrupt.h>
16
#include <linux/compat.h>
L
Linus Torvalds 已提交
17 18 19
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/blkpg.h>
20
#include <linux/slab.h>
L
Linus Torvalds 已提交
21
#include <asm/ccwdev.h>
S
Sebastian Ott 已提交
22
#include <asm/schid.h>
23
#include <asm/cmb.h>
24
#include <linux/uaccess.h>
25
#include <linux/dasd_mod.h>
L
Linus Torvalds 已提交
26 27 28 29 30 31 32 33

/* This is ugly... */
#define PRINTK_HEADER "dasd_ioctl:"

#include "dasd_int.h"


static int
34
dasd_ioctl_api_version(void __user *argp)
L
Linus Torvalds 已提交
35 36
{
	int ver = DASD_API_VERSION;
37
	return put_user(ver, (int __user *)argp);
L
Linus Torvalds 已提交
38 39 40 41 42 43 44
}

/*
 * Enable device.
 * used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection
 */
static int
45
dasd_ioctl_enable(struct block_device *bdev)
L
Linus Torvalds 已提交
46
{
47
	struct dasd_device *base;
L
Linus Torvalds 已提交
48 49 50

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
51

52 53 54 55 56
	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;

	dasd_enable_device(base);
L
Linus Torvalds 已提交
57
	/* Formatting the dasd device can change the capacity. */
58
	bd_set_nr_sectors(bdev, get_capacity(base->block->gdp));
59
	dasd_put_device(base);
L
Linus Torvalds 已提交
60 61 62 63 64 65 66 67
	return 0;
}

/*
 * Disable device.
 * Used by dasdfmt. Disable I/O operations but allow ioctls.
 */
static int
68
dasd_ioctl_disable(struct block_device *bdev)
L
Linus Torvalds 已提交
69
{
70
	struct dasd_device *base;
L
Linus Torvalds 已提交
71 72 73

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
74

75 76 77
	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
L
Linus Torvalds 已提交
78 79 80 81 82 83 84 85
	/*
	 * Man this is sick. We don't do a real disable but only downgrade
	 * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
	 * BIODASDDISABLE to disable accesses to the device via the block
	 * device layer but it still wants to do i/o on the device by
	 * using the BIODASDFMT ioctl. Therefore the correct state for the
	 * device is DASD_STATE_BASIC that allows to do basic i/o.
	 */
86
	dasd_set_target_state(base, DASD_STATE_BASIC);
L
Linus Torvalds 已提交
87 88 89 90
	/*
	 * Set i_size to zero, since read, write, etc. check against this
	 * value.
	 */
91
	bd_set_nr_sectors(bdev, 0);
92
	dasd_put_device(base);
L
Linus Torvalds 已提交
93 94 95 96 97 98
	return 0;
}

/*
 * Quiesce device.
 */
99
static int dasd_ioctl_quiesce(struct dasd_block *block)
L
Linus Torvalds 已提交
100 101
{
	unsigned long flags;
102
	struct dasd_device *base;
103

104
	base = block->base;
L
Linus Torvalds 已提交
105 106
	if (!capable (CAP_SYS_ADMIN))
		return -EACCES;
107

108 109
	pr_info("%s: The DASD has been put in the quiesce "
		"state\n", dev_name(&base->cdev->dev));
110
	spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
111
	dasd_device_set_stop_bits(base, DASD_STOPPED_QUIESCE);
112
	spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
L
Linus Torvalds 已提交
113 114 115 116 117
	return 0;
}


/*
S
Stefan Haberland 已提交
118
 * Resume device.
L
Linus Torvalds 已提交
119
 */
120
static int dasd_ioctl_resume(struct dasd_block *block)
L
Linus Torvalds 已提交
121 122
{
	unsigned long flags;
123
	struct dasd_device *base;
124

125
	base = block->base;
126
	if (!capable (CAP_SYS_ADMIN))
L
Linus Torvalds 已提交
127 128
		return -EACCES;

129 130
	pr_info("%s: I/O operations have been resumed "
		"on the DASD\n", dev_name(&base->cdev->dev));
131
	spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
132
	dasd_device_remove_stop_bits(base, DASD_STOPPED_QUIESCE);
133
	spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
L
Linus Torvalds 已提交
134

135
	dasd_schedule_block_bh(block);
L
Linus Torvalds 已提交
136 137 138
	return 0;
}

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
/*
 * Abort all failfast I/O on a device.
 */
static int dasd_ioctl_abortio(struct dasd_block *block)
{
	unsigned long flags;
	struct dasd_device *base;
	struct dasd_ccw_req *cqr, *n;

	base = block->base;
	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

	if (test_and_set_bit(DASD_FLAG_ABORTALL, &base->flags))
		return 0;
	DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag set");

	spin_lock_irqsave(&block->request_queue_lock, flags);
	spin_lock(&block->queue_lock);
	list_for_each_entry_safe(cqr, n, &block->ccw_queue, blocklist) {
		if (test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
		    cqr->callback_data &&
		    cqr->callback_data != DASD_SLEEPON_START_TAG &&
		    cqr->callback_data != DASD_SLEEPON_END_TAG) {
			spin_unlock(&block->queue_lock);
			blk_abort_request(cqr->callback_data);
			spin_lock(&block->queue_lock);
		}
	}
	spin_unlock(&block->queue_lock);
	spin_unlock_irqrestore(&block->request_queue_lock, flags);

	dasd_schedule_block_bh(block);
	return 0;
}

/*
 * Allow I/O on a device
 */
static int dasd_ioctl_allowio(struct dasd_block *block)
{
	struct dasd_device *base;

	base = block->base;
	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;

	if (test_and_clear_bit(DASD_FLAG_ABORTALL, &base->flags))
		DBF_DEV_EVENT(DBF_NOTICE, base, "%s", "abortall flag unset");

	return 0;
}

L
Linus Torvalds 已提交
192 193 194
/*
 * performs formatting of _device_ according to _fdata_
 * Note: The discipline's format_function is assumed to deliver formatting
195 196
 * commands to format multiple units of the device. In terms of the ECKD
 * devices this means CCWs are generated to format multiple tracks.
L
Linus Torvalds 已提交
197
 */
198 199
static int
dasd_format(struct dasd_block *block, struct format_data_t *fdata)
L
Linus Torvalds 已提交
200
{
201
	struct dasd_device *base;
202
	int rc;
L
Linus Torvalds 已提交
203

204 205
	base = block->base;
	if (base->discipline->format_device == NULL)
L
Linus Torvalds 已提交
206 207
		return -EPERM;

208
	if (base->state != DASD_STATE_BASIC) {
209 210
		pr_warn("%s: The DASD cannot be formatted while it is enabled\n",
			dev_name(&base->cdev->dev));
L
Linus Torvalds 已提交
211 212 213
		return -EBUSY;
	}

214
	DBF_DEV_EVENT(DBF_NOTICE, base,
215
		      "formatting units %u to %u (%u B blocks) flags %u",
L
Linus Torvalds 已提交
216 217 218 219 220 221 222 223 224
		      fdata->start_unit,
		      fdata->stop_unit, fdata->blksize, fdata->intensity);

	/* Since dasdfmt keeps the device open after it was disabled,
	 * there still exists an inode for this device.
	 * We must update i_blkbits, otherwise we might get errors when
	 * enabling the device later.
	 */
	if (fdata->start_unit == 0) {
225
		struct block_device *bdev = bdget_disk(block->gdp, 0);
L
Linus Torvalds 已提交
226 227 228 229
		bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
		bdput(bdev);
	}

230 231 232 233 234
	rc = base->discipline->format_device(base, fdata, 1);
	if (rc == -EAGAIN)
		rc = base->discipline->format_device(base, fdata, 0);

	return rc;
L
Linus Torvalds 已提交
235 236
}

237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
static int dasd_check_format(struct dasd_block *block,
			     struct format_check_t *cdata)
{
	struct dasd_device *base;
	int rc;

	base = block->base;
	if (!base->discipline->check_device_format)
		return -ENOTTY;

	rc = base->discipline->check_device_format(base, cdata, 1);
	if (rc == -EAGAIN)
		rc = base->discipline->check_device_format(base, cdata, 0);

	return rc;
}

L
Linus Torvalds 已提交
254 255 256 257
/*
 * Format device.
 */
static int
258
dasd_ioctl_format(struct block_device *bdev, void __user *argp)
L
Linus Torvalds 已提交
259
{
260
	struct dasd_device *base;
L
Linus Torvalds 已提交
261
	struct format_data_t fdata;
262
	int rc;
L
Linus Torvalds 已提交
263 264 265

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
266
	if (!argp)
L
Linus Torvalds 已提交
267
		return -EINVAL;
268 269 270 271 272 273
	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
	if (base->features & DASD_FEATURE_READONLY ||
	    test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
		dasd_put_device(base);
L
Linus Torvalds 已提交
274
		return -EROFS;
275 276 277
	}
	if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) {
		dasd_put_device(base);
L
Linus Torvalds 已提交
278
		return -EFAULT;
279
	}
280
	if (bdev_is_partition(bdev)) {
281 282
		pr_warn("%s: The specified DASD is a partition and cannot be formatted\n",
			dev_name(&base->cdev->dev));
283
		dasd_put_device(base);
L
Linus Torvalds 已提交
284 285
		return -EINVAL;
	}
286 287
	rc = dasd_format(base->block, &fdata);
	dasd_put_device(base);
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306

	return rc;
}

/*
 * Check device format
 */
static int dasd_ioctl_check_format(struct block_device *bdev, void __user *argp)
{
	struct format_check_t cdata;
	struct dasd_device *base;
	int rc = 0;

	if (!argp)
		return -EINVAL;

	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
307
	if (bdev_is_partition(bdev)) {
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
		pr_warn("%s: The specified DASD is a partition and cannot be checked\n",
			dev_name(&base->cdev->dev));
		rc = -EINVAL;
		goto out_err;
	}

	if (copy_from_user(&cdata, argp, sizeof(cdata))) {
		rc = -EFAULT;
		goto out_err;
	}

	rc = dasd_check_format(base->block, &cdata);
	if (rc)
		goto out_err;

	if (copy_to_user(argp, &cdata, sizeof(cdata)))
		rc = -EFAULT;

out_err:
	dasd_put_device(base);

329
	return rc;
L
Linus Torvalds 已提交
330 331
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
static int dasd_release_space(struct dasd_device *device,
			      struct format_data_t *rdata)
{
	if (!device->discipline->is_ese && !device->discipline->is_ese(device))
		return -ENOTSUPP;
	if (!device->discipline->release_space)
		return -ENOTSUPP;

	return device->discipline->release_space(device, rdata);
}

/*
 * Release allocated space
 */
static int dasd_ioctl_release_space(struct block_device *bdev, void __user *argp)
{
	struct format_data_t rdata;
	struct dasd_device *base;
	int rc = 0;

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
	if (!argp)
		return -EINVAL;

	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
	if (base->features & DASD_FEATURE_READONLY ||
	    test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
		rc = -EROFS;
		goto out_err;
	}
365
	if (bdev_is_partition(bdev)) {
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
		pr_warn("%s: The specified DASD is a partition and tracks cannot be released\n",
			dev_name(&base->cdev->dev));
		rc = -EINVAL;
		goto out_err;
	}

	if (copy_from_user(&rdata, argp, sizeof(rdata))) {
		rc = -EFAULT;
		goto out_err;
	}

	rc = dasd_release_space(base, &rdata);

out_err:
	dasd_put_device(base);

	return rc;
}

L
Linus Torvalds 已提交
385 386 387 388
#ifdef CONFIG_DASD_PROFILE
/*
 * Reset device profile information
 */
389
static int dasd_ioctl_reset_profile(struct dasd_block *block)
L
Linus Torvalds 已提交
390
{
391
	dasd_profile_reset(&block->profile);
L
Linus Torvalds 已提交
392 393 394 395 396 397
	return 0;
}

/*
 * Return device profile information
 */
398
static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
L
Linus Torvalds 已提交
399
{
400
	struct dasd_profile_info_t *data;
401
	int rc = 0;
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431

	data = kmalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	spin_lock_bh(&block->profile.lock);
	if (block->profile.data) {
		data->dasd_io_reqs = block->profile.data->dasd_io_reqs;
		data->dasd_io_sects = block->profile.data->dasd_io_sects;
		memcpy(data->dasd_io_secs, block->profile.data->dasd_io_secs,
		       sizeof(data->dasd_io_secs));
		memcpy(data->dasd_io_times, block->profile.data->dasd_io_times,
		       sizeof(data->dasd_io_times));
		memcpy(data->dasd_io_timps, block->profile.data->dasd_io_timps,
		       sizeof(data->dasd_io_timps));
		memcpy(data->dasd_io_time1, block->profile.data->dasd_io_time1,
		       sizeof(data->dasd_io_time1));
		memcpy(data->dasd_io_time2, block->profile.data->dasd_io_time2,
		       sizeof(data->dasd_io_time2));
		memcpy(data->dasd_io_time2ps,
		       block->profile.data->dasd_io_time2ps,
		       sizeof(data->dasd_io_time2ps));
		memcpy(data->dasd_io_time3, block->profile.data->dasd_io_time3,
		       sizeof(data->dasd_io_time3));
		memcpy(data->dasd_io_nr_req,
		       block->profile.data->dasd_io_nr_req,
		       sizeof(data->dasd_io_nr_req));
		spin_unlock_bh(&block->profile.lock);
	} else {
		spin_unlock_bh(&block->profile.lock);
432 433
		rc = -EIO;
		goto out;
434 435
	}
	if (copy_to_user(argp, data, sizeof(*data)))
436 437 438 439
		rc = -EFAULT;
out:
	kfree(data);
	return rc;
L
Linus Torvalds 已提交
440 441
}
#else
442
static int dasd_ioctl_reset_profile(struct dasd_block *block)
L
Linus Torvalds 已提交
443
{
444
	return -ENOTTY;
L
Linus Torvalds 已提交
445 446
}

447
static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
L
Linus Torvalds 已提交
448
{
449
	return -ENOTTY;
L
Linus Torvalds 已提交
450 451 452 453 454 455
}
#endif

/*
 * Return dasd information. Used for BIODASDINFO and BIODASDINFO2.
 */
456 457
static int __dasd_ioctl_information(struct dasd_block *block,
		struct dasd_information2_t *dasd_info)
L
Linus Torvalds 已提交
458
{
S
Sebastian Ott 已提交
459 460
	struct subchannel_id sch_id;
	struct ccw_dev_id dev_id;
461
	struct dasd_device *base;
L
Linus Torvalds 已提交
462
	struct ccw_device *cdev;
J
Jens Axboe 已提交
463
	struct list_head *l;
S
Sebastian Ott 已提交
464 465
	unsigned long flags;
	int rc;
L
Linus Torvalds 已提交
466

467
	base = block->base;
468
	if (!base->discipline || !base->discipline->fill_info)
L
Linus Torvalds 已提交
469 470
		return -EINVAL;

471
	rc = base->discipline->fill_info(base, dasd_info);
472
	if (rc)
L
Linus Torvalds 已提交
473 474
		return rc;

475
	cdev = base->cdev;
476
	ccw_device_get_id(cdev, &dev_id);
S
Sebastian Ott 已提交
477
	ccw_device_get_schid(cdev, &sch_id);
L
Linus Torvalds 已提交
478

479
	dasd_info->devno = dev_id.devno;
S
Sebastian Ott 已提交
480
	dasd_info->schid = sch_id.sch_no;
L
Linus Torvalds 已提交
481 482 483 484
	dasd_info->cu_type = cdev->id.cu_type;
	dasd_info->cu_model = cdev->id.cu_model;
	dasd_info->dev_type = cdev->id.dev_type;
	dasd_info->dev_model = cdev->id.dev_model;
485
	dasd_info->status = base->state;
H
Horst Hummel 已提交
486 487 488 489 490
	/*
	 * The open_count is increased for every opener, that includes
	 * the blkdev_get in dasd_scan_partitions.
	 * This must be hidden from user-space.
	 */
491 492
	dasd_info->open_count = atomic_read(&block->open_count);
	if (!block->bdev)
H
Horst Hummel 已提交
493
		dasd_info->open_count++;
494

L
Linus Torvalds 已提交
495 496 497 498
	/*
	 * check if device is really formatted
	 * LDL / CDL was returned by 'fill_info'
	 */
499 500
	if ((base->state < DASD_STATE_READY) ||
	    (dasd_check_blocksize(block->bp_block)))
L
Linus Torvalds 已提交
501
		dasd_info->format = DASD_FORMAT_NONE;
502

503
	dasd_info->features |=
504
		((base->features & DASD_FEATURE_READONLY) != 0);
L
Linus Torvalds 已提交
505

506
	memcpy(dasd_info->type, base->discipline->name, 4);
507

J
Jens Axboe 已提交
508 509 510 511
	spin_lock_irqsave(&block->queue_lock, flags);
	list_for_each(l, &base->ccw_queue)
		dasd_info->chanq_len++;
	spin_unlock_irqrestore(&block->queue_lock, flags);
512 513
	return 0;
}
L
Linus Torvalds 已提交
514

515 516 517 518 519 520 521 522 523 524 525 526 527
static int dasd_ioctl_information(struct dasd_block *block, void __user *argp,
		size_t copy_size)
{
	struct dasd_information2_t *dasd_info;
	int error;

	dasd_info = kzalloc(sizeof(*dasd_info), GFP_KERNEL);
	if (!dasd_info)
		return -ENOMEM;

	error = __dasd_ioctl_information(block, dasd_info);
	if (!error && copy_to_user(argp, dasd_info, copy_size))
		error = -EFAULT;
L
Linus Torvalds 已提交
528
	kfree(dasd_info);
529
	return error;
L
Linus Torvalds 已提交
530 531 532 533 534 535
}

/*
 * Set read only
 */
static int
536
dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
L
Linus Torvalds 已提交
537
{
538 539
	struct dasd_device *base;
	int intval, rc;
L
Linus Torvalds 已提交
540 541 542

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
543
	if (bdev_is_partition(bdev))
L
Linus Torvalds 已提交
544 545
		// ro setting is not allowed for partitions
		return -EINVAL;
H
Heiko Carstens 已提交
546
	if (get_user(intval, (int __user *)argp))
L
Linus Torvalds 已提交
547
		return -EFAULT;
548 549 550 551 552
	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
	if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
		dasd_put_device(base);
553
		return -EROFS;
554
	}
L
Linus Torvalds 已提交
555
	set_disk_ro(bdev->bd_disk, intval);
556 557 558
	rc = dasd_set_feature(base->cdev, DASD_FEATURE_READONLY, intval);
	dasd_put_device(base);
	return rc;
L
Linus Torvalds 已提交
559 560
}

561
static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
562
				  struct cmbdata __user *argp)
563 564 565 566 567
{
	size_t size = _IOC_SIZE(cmd);
	struct cmbdata data;
	int ret;

568
	ret = cmf_readall(block->base->cdev, &data);
569 570 571 572 573
	if (!ret && copy_to_user(argp, &data, min(size, sizeof(*argp))))
		return -EFAULT;
	return ret;
}

574 575
int dasd_ioctl(struct block_device *bdev, fmode_t mode,
	       unsigned int cmd, unsigned long arg)
L
Linus Torvalds 已提交
576
{
577 578
	struct dasd_block *block;
	struct dasd_device *base;
579
	void __user *argp;
580
	int rc;
581 582 583 584 585

	if (is_compat_task())
		argp = compat_ptr(arg);
	else
		argp = (void __user *)arg;
L
Linus Torvalds 已提交
586

587 588 589 590
	if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) {
		PRINT_DEBUG("empty data ptr");
		return -EINVAL;
	}
L
Linus Torvalds 已提交
591

592 593 594 595 596
	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
	block = base->block;
	rc = 0;
597 598
	switch (cmd) {
	case BIODASDDISABLE:
599 600
		rc = dasd_ioctl_disable(bdev);
		break;
601
	case BIODASDENABLE:
602 603
		rc = dasd_ioctl_enable(bdev);
		break;
604
	case BIODASDQUIESCE:
605 606
		rc = dasd_ioctl_quiesce(block);
		break;
607
	case BIODASDRESUME:
608 609
		rc = dasd_ioctl_resume(block);
		break;
610 611 612 613 614 615
	case BIODASDABORTIO:
		rc = dasd_ioctl_abortio(block);
		break;
	case BIODASDALLOWIO:
		rc = dasd_ioctl_allowio(block);
		break;
616
	case BIODASDFMT:
617 618
		rc = dasd_ioctl_format(bdev, argp);
		break;
619 620 621
	case BIODASDCHECKFMT:
		rc = dasd_ioctl_check_format(bdev, argp);
		break;
622
	case BIODASDINFO:
623 624
		rc = dasd_ioctl_information(block, argp,
				sizeof(struct dasd_information_t));
625
		break;
626
	case BIODASDINFO2:
627 628
		rc = dasd_ioctl_information(block, argp,
				sizeof(struct dasd_information2_t));
629
		break;
630
	case BIODASDPRRD:
631 632
		rc = dasd_ioctl_read_profile(block, argp);
		break;
633
	case BIODASDPRRST:
634 635
		rc = dasd_ioctl_reset_profile(block);
		break;
636
	case BLKROSET:
637 638
		rc = dasd_ioctl_set_ro(bdev, argp);
		break;
639
	case DASDAPIVER:
640 641
		rc = dasd_ioctl_api_version(argp);
		break;
642
	case BIODASDCMFENABLE:
643 644
		rc = enable_cmf(base->cdev);
		break;
645
	case BIODASDCMFDISABLE:
646 647
		rc = disable_cmf(base->cdev);
		break;
648
	case BIODASDREADALLCMB:
649 650
		rc = dasd_ioctl_readall_cmb(block, cmd, argp);
		break;
651 652 653
	case BIODASDRAS:
		rc = dasd_ioctl_release_space(bdev, argp);
		break;
654
	default:
655
		/* if the discipline has an ioctl method try it. */
656 657
		rc = -ENOTTY;
		if (base->discipline->ioctl)
658
			rc = base->discipline->ioctl(block, cmd, argp);
659
	}
660 661
	dasd_put_device(base);
	return rc;
L
Linus Torvalds 已提交
662
}
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695


/**
 * dasd_biodasdinfo() - fill out the dasd information structure
 * @disk [in]: pointer to gendisk structure that references a DASD
 * @info [out]: pointer to the dasd_information2_t structure
 *
 * Provide access to DASD specific information.
 * The gendisk structure is checked if it belongs to the DASD driver by
 * comparing the gendisk->fops pointer.
 * If it does not belong to the DASD driver -EINVAL is returned.
 * Otherwise the provided dasd_information2_t structure is filled out.
 *
 * Returns:
 *   %0 on success and a negative error value on failure.
 */
int dasd_biodasdinfo(struct gendisk *disk, struct dasd_information2_t *info)
{
	struct dasd_device *base;
	int error;

	if (disk->fops != &dasd_device_operations)
		return -EINVAL;

	base = dasd_device_from_gendisk(disk);
	if (!base)
		return -ENODEV;
	error = __dasd_ioctl_information(base->block, info);
	dasd_put_device(base);
	return error;
}
/* export that symbol_get in partition detection is possible */
EXPORT_SYMBOL_GPL(dasd_biodasdinfo);