dasd_ioctl.c 14.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6
/*
 * 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>
7
 * Copyright IBM Corp. 1999, 2001
L
Linus Torvalds 已提交
8 9 10
 *
 * i/o controls for the dasd driver.
 */
S
Stefan Haberland 已提交
11 12 13

#define KMSG_COMPONENT "dasd"

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

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

#include "dasd_int.h"


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

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

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

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

	dasd_enable_device(base);
L
Linus Torvalds 已提交
56
	/* Formatting the dasd device can change the capacity. */
57
	mutex_lock(&bdev->bd_mutex);
58 59
	i_size_write(bdev->bd_inode,
		     (loff_t)get_capacity(base->block->gdp) << 9);
60
	mutex_unlock(&bdev->bd_mutex);
61
	dasd_put_device(base);
L
Linus Torvalds 已提交
62 63 64 65 66 67 68 69
	return 0;
}

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

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

77 78 79
	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
L
Linus Torvalds 已提交
80 81 82 83 84 85 86 87
	/*
	 * 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.
	 */
88
	dasd_set_target_state(base, DASD_STATE_BASIC);
L
Linus Torvalds 已提交
89 90 91 92
	/*
	 * Set i_size to zero, since read, write, etc. check against this
	 * value.
	 */
93
	mutex_lock(&bdev->bd_mutex);
L
Linus Torvalds 已提交
94
	i_size_write(bdev->bd_inode, 0);
95
	mutex_unlock(&bdev->bd_mutex);
96
	dasd_put_device(base);
L
Linus Torvalds 已提交
97 98 99 100 101 102
	return 0;
}

/*
 * Quiesce device.
 */
103
static int dasd_ioctl_quiesce(struct dasd_block *block)
L
Linus Torvalds 已提交
104 105
{
	unsigned long flags;
106
	struct dasd_device *base;
107

108
	base = block->base;
L
Linus Torvalds 已提交
109 110
	if (!capable (CAP_SYS_ADMIN))
		return -EACCES;
111

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


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

129
	base = block->base;
130
	if (!capable (CAP_SYS_ADMIN))
L
Linus Torvalds 已提交
131 132
		return -EACCES;

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

139
	dasd_schedule_block_bh(block);
L
Linus Torvalds 已提交
140 141 142
	return 0;
}

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 192 193 194 195
/*
 * 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 已提交
196 197 198
/*
 * performs formatting of _device_ according to _fdata_
 * Note: The discipline's format_function is assumed to deliver formatting
199 200
 * 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 已提交
201
 */
202 203
static int
dasd_format(struct dasd_block *block, struct format_data_t *fdata)
L
Linus Torvalds 已提交
204
{
205
	struct dasd_device *base;
206
	int rc;
L
Linus Torvalds 已提交
207

208 209
	base = block->base;
	if (base->discipline->format_device == NULL)
L
Linus Torvalds 已提交
210 211
		return -EPERM;

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

218
	DBF_DEV_EVENT(DBF_NOTICE, base,
219
		      "formatting units %u to %u (%u B blocks) flags %u",
L
Linus Torvalds 已提交
220 221 222 223 224 225 226 227 228
		      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) {
229
		struct block_device *bdev = bdget_disk(block->gdp, 0);
L
Linus Torvalds 已提交
230 231 232 233
		bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize);
		bdput(bdev);
	}

234 235 236 237 238
	rc = base->discipline->format_device(base, fdata, 1);
	if (rc == -EAGAIN)
		rc = base->discipline->format_device(base, fdata, 0);

	return rc;
L
Linus Torvalds 已提交
239 240
}

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
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 已提交
258 259 260 261
/*
 * Format device.
 */
static int
262
dasd_ioctl_format(struct block_device *bdev, void __user *argp)
L
Linus Torvalds 已提交
263
{
264
	struct dasd_device *base;
L
Linus Torvalds 已提交
265
	struct format_data_t fdata;
266
	int rc;
L
Linus Torvalds 已提交
267 268 269

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
270
	if (!argp)
L
Linus Torvalds 已提交
271
		return -EINVAL;
272 273 274 275 276 277
	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 已提交
278
		return -EROFS;
279 280 281
	}
	if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) {
		dasd_put_device(base);
L
Linus Torvalds 已提交
282
		return -EFAULT;
283
	}
L
Linus Torvalds 已提交
284
	if (bdev != bdev->bd_contains) {
285 286
		pr_warn("%s: The specified DASD is a partition and cannot be formatted\n",
			dev_name(&base->cdev->dev));
287
		dasd_put_device(base);
L
Linus Torvalds 已提交
288 289
		return -EINVAL;
	}
290 291
	rc = dasd_format(base->block, &fdata);
	dasd_put_device(base);
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332

	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;
	if (bdev != bdev->bd_contains) {
		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);

333
	return rc;
L
Linus Torvalds 已提交
334 335 336 337 338 339
}

#ifdef CONFIG_DASD_PROFILE
/*
 * Reset device profile information
 */
340
static int dasd_ioctl_reset_profile(struct dasd_block *block)
L
Linus Torvalds 已提交
341
{
342
	dasd_profile_reset(&block->profile);
L
Linus Torvalds 已提交
343 344 345 346 347 348
	return 0;
}

/*
 * Return device profile information
 */
349
static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
L
Linus Torvalds 已提交
350
{
351
	struct dasd_profile_info_t *data;
352
	int rc = 0;
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382

	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);
383 384
		rc = -EIO;
		goto out;
385 386
	}
	if (copy_to_user(argp, data, sizeof(*data)))
387 388 389 390
		rc = -EFAULT;
out:
	kfree(data);
	return rc;
L
Linus Torvalds 已提交
391 392
}
#else
393
static int dasd_ioctl_reset_profile(struct dasd_block *block)
L
Linus Torvalds 已提交
394
{
395
	return -ENOTTY;
L
Linus Torvalds 已提交
396 397
}

398
static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
L
Linus Torvalds 已提交
399
{
400
	return -ENOTTY;
L
Linus Torvalds 已提交
401 402 403 404 405 406
}
#endif

/*
 * Return dasd information. Used for BIODASDINFO and BIODASDINFO2.
 */
407 408
static int dasd_ioctl_information(struct dasd_block *block,
				  unsigned int cmd, void __user *argp)
L
Linus Torvalds 已提交
409 410
{
	struct dasd_information2_t *dasd_info;
S
Sebastian Ott 已提交
411 412
	struct subchannel_id sch_id;
	struct ccw_dev_id dev_id;
413
	struct dasd_device *base;
L
Linus Torvalds 已提交
414
	struct ccw_device *cdev;
S
Sebastian Ott 已提交
415 416
	unsigned long flags;
	int rc;
L
Linus Torvalds 已提交
417

418
	base = block->base;
419
	if (!base->discipline || !base->discipline->fill_info)
L
Linus Torvalds 已提交
420 421
		return -EINVAL;

422
	dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
L
Linus Torvalds 已提交
423 424 425
	if (dasd_info == NULL)
		return -ENOMEM;

426
	rc = base->discipline->fill_info(base, dasd_info);
L
Linus Torvalds 已提交
427 428 429 430 431
	if (rc) {
		kfree(dasd_info);
		return rc;
	}

432
	cdev = base->cdev;
433
	ccw_device_get_id(cdev, &dev_id);
S
Sebastian Ott 已提交
434
	ccw_device_get_schid(cdev, &sch_id);
L
Linus Torvalds 已提交
435

436
	dasd_info->devno = dev_id.devno;
S
Sebastian Ott 已提交
437
	dasd_info->schid = sch_id.sch_no;
L
Linus Torvalds 已提交
438 439 440 441
	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;
442
	dasd_info->status = base->state;
H
Horst Hummel 已提交
443 444 445 446 447
	/*
	 * The open_count is increased for every opener, that includes
	 * the blkdev_get in dasd_scan_partitions.
	 * This must be hidden from user-space.
	 */
448 449
	dasd_info->open_count = atomic_read(&block->open_count);
	if (!block->bdev)
H
Horst Hummel 已提交
450
		dasd_info->open_count++;
451

L
Linus Torvalds 已提交
452 453 454 455
	/*
	 * check if device is really formatted
	 * LDL / CDL was returned by 'fill_info'
	 */
456 457
	if ((base->state < DASD_STATE_READY) ||
	    (dasd_check_blocksize(block->bp_block)))
L
Linus Torvalds 已提交
458
		dasd_info->format = DASD_FORMAT_NONE;
459

460
	dasd_info->features |=
461
		((base->features & DASD_FEATURE_READONLY) != 0);
L
Linus Torvalds 已提交
462

463
	memcpy(dasd_info->type, base->discipline->name, 4);
464

465
	if (block->request_queue->request_fn) {
L
Linus Torvalds 已提交
466 467 468 469
		struct list_head *l;
#ifdef DASD_EXTENDED_PROFILING
		{
			struct list_head *l;
470 471
			spin_lock_irqsave(&block->lock, flags);
			list_for_each(l, &block->request_queue->queue_head)
L
Linus Torvalds 已提交
472
				dasd_info->req_queue_len++;
473
			spin_unlock_irqrestore(&block->lock, flags);
L
Linus Torvalds 已提交
474 475
		}
#endif				/* DASD_EXTENDED_PROFILING */
476 477
		spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
		list_for_each(l, &base->ccw_queue)
L
Linus Torvalds 已提交
478
			dasd_info->chanq_len++;
479
		spin_unlock_irqrestore(get_ccwdev_lock(base->cdev),
L
Linus Torvalds 已提交
480 481 482 483
				       flags);
	}

	rc = 0;
484 485
	if (copy_to_user(argp, dasd_info,
			 ((cmd == (unsigned int) BIODASDINFO2) ?
486 487
			  sizeof(struct dasd_information2_t) :
			  sizeof(struct dasd_information_t))))
L
Linus Torvalds 已提交
488 489 490 491 492 493 494 495 496
		rc = -EFAULT;
	kfree(dasd_info);
	return rc;
}

/*
 * Set read only
 */
static int
497
dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
L
Linus Torvalds 已提交
498
{
499 500
	struct dasd_device *base;
	int intval, rc;
L
Linus Torvalds 已提交
501 502 503 504 505 506

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
	if (bdev != bdev->bd_contains)
		// ro setting is not allowed for partitions
		return -EINVAL;
H
Heiko Carstens 已提交
507
	if (get_user(intval, (int __user *)argp))
L
Linus Torvalds 已提交
508
		return -EFAULT;
509 510 511 512 513
	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);
514
		return -EROFS;
515
	}
L
Linus Torvalds 已提交
516
	set_disk_ro(bdev->bd_disk, intval);
517 518 519
	rc = dasd_set_feature(base->cdev, DASD_FEATURE_READONLY, intval);
	dasd_put_device(base);
	return rc;
L
Linus Torvalds 已提交
520 521
}

522
static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
523
				  struct cmbdata __user *argp)
524 525 526 527 528
{
	size_t size = _IOC_SIZE(cmd);
	struct cmbdata data;
	int ret;

529
	ret = cmf_readall(block->base->cdev, &data);
530 531 532 533 534
	if (!ret && copy_to_user(argp, &data, min(size, sizeof(*argp))))
		return -EFAULT;
	return ret;
}

535 536
int dasd_ioctl(struct block_device *bdev, fmode_t mode,
	       unsigned int cmd, unsigned long arg)
L
Linus Torvalds 已提交
537
{
538 539
	struct dasd_block *block;
	struct dasd_device *base;
540
	void __user *argp;
541
	int rc;
542 543 544 545 546

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

548 549 550 551
	if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) {
		PRINT_DEBUG("empty data ptr");
		return -EINVAL;
	}
L
Linus Torvalds 已提交
552

553 554 555 556 557
	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
	block = base->block;
	rc = 0;
558 559
	switch (cmd) {
	case BIODASDDISABLE:
560 561
		rc = dasd_ioctl_disable(bdev);
		break;
562
	case BIODASDENABLE:
563 564
		rc = dasd_ioctl_enable(bdev);
		break;
565
	case BIODASDQUIESCE:
566 567
		rc = dasd_ioctl_quiesce(block);
		break;
568
	case BIODASDRESUME:
569 570
		rc = dasd_ioctl_resume(block);
		break;
571 572 573 574 575 576
	case BIODASDABORTIO:
		rc = dasd_ioctl_abortio(block);
		break;
	case BIODASDALLOWIO:
		rc = dasd_ioctl_allowio(block);
		break;
577
	case BIODASDFMT:
578 579
		rc = dasd_ioctl_format(bdev, argp);
		break;
580 581 582
	case BIODASDCHECKFMT:
		rc = dasd_ioctl_check_format(bdev, argp);
		break;
583
	case BIODASDINFO:
584 585
		rc = dasd_ioctl_information(block, cmd, argp);
		break;
586
	case BIODASDINFO2:
587 588
		rc = dasd_ioctl_information(block, cmd, argp);
		break;
589
	case BIODASDPRRD:
590 591
		rc = dasd_ioctl_read_profile(block, argp);
		break;
592
	case BIODASDPRRST:
593 594
		rc = dasd_ioctl_reset_profile(block);
		break;
595
	case BLKROSET:
596 597
		rc = dasd_ioctl_set_ro(bdev, argp);
		break;
598
	case DASDAPIVER:
599 600
		rc = dasd_ioctl_api_version(argp);
		break;
601
	case BIODASDCMFENABLE:
602 603
		rc = enable_cmf(base->cdev);
		break;
604
	case BIODASDCMFDISABLE:
605 606
		rc = disable_cmf(base->cdev);
		break;
607
	case BIODASDREADALLCMB:
608 609
		rc = dasd_ioctl_readall_cmb(block, cmd, argp);
		break;
610
	default:
611
		/* if the discipline has an ioctl method try it. */
612 613
		rc = -ENOTTY;
		if (base->discipline->ioctl)
614
			rc = base->discipline->ioctl(block, cmd, argp);
615
	}
616 617
	dasd_put_device(base);
	return rc;
L
Linus Torvalds 已提交
618
}