Ejemplo n.º 1
0
/*
 * Set read only
 */
static int
dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
{
	struct dasd_device *base;
	int intval, rc;

	if (!capable(CAP_SYS_ADMIN))
		return -EACCES;
	if (bdev != bdev->bd_contains)
		// ro setting is not allowed for partitions
		return -EINVAL;
	if (get_user(intval, (int __user *)argp))
		return -EFAULT;
	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);
		return -EROFS;
	}
	set_disk_ro(bdev->bd_disk, intval);
	rc = dasd_set_feature(base->cdev, DASD_FEATURE_READONLY, intval);
	dasd_put_device(base);
	return rc;
}
Ejemplo n.º 2
0
/*
 * Format device.
 */
static int
dasd_ioctl_format(struct block_device *bdev, void __user *argp)
{
	struct dasd_device *base;
	struct format_data_t fdata;
	int rc;

	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)) {
		dasd_put_device(base);
		return -EROFS;
	}
	if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) {
		dasd_put_device(base);
		return -EFAULT;
	}
	if (bdev != bdev->bd_contains) {
		pr_warning("%s: The specified DASD is a partition and cannot "
			   "be formatted\n",
			   dev_name(&base->cdev->dev));
		dasd_put_device(base);
		return -EINVAL;
	}
	rc = dasd_format(base->block, &fdata);
	dasd_put_device(base);
	return rc;
}
Ejemplo n.º 3
0
/*
 * Disable device.
 * Used by dasdfmt. Disable I/O operations but allow ioctls.
 */
static int
dasd_ioctl_disable(struct block_device *bdev)
{
	struct dasd_device *base;

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

	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
	/*
	 * 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.
	 */
	dasd_set_target_state(base, DASD_STATE_BASIC);
	/*
	 * Set i_size to zero, since read, write, etc. check against this
	 * value.
	 */
	mutex_lock(&bdev->bd_mutex);
	i_size_write(bdev->bd_inode, 0);
	mutex_unlock(&bdev->bd_mutex);
	dasd_put_device(base);
	return 0;
}
Ejemplo n.º 4
0
static void dasd_stats_all_block_reset(void)
{
	int i;
	struct dasd_device *device;

	for (i = 0; i < dasd_max_devindex; ++i) {
		device = dasd_device_from_devindex(i);
		if (IS_ERR(device))
			continue;
		if (device->block)
			dasd_profile_reset(&device->block->profile);
		dasd_put_device(device);
	}
}
Ejemplo n.º 5
0
static int dasd_stats_all_block_on(void)
{
	int i, rc;
	struct dasd_device *device;

	rc = 0;
	for (i = 0; i < dasd_max_devindex; ++i) {
		device = dasd_device_from_devindex(i);
		if (IS_ERR(device))
			continue;
		if (device->block)
			rc = dasd_profile_on(&device->block->profile);
		dasd_put_device(device);
		if (rc)
			return rc;
	}
	return 0;
}
Ejemplo n.º 6
0
/*
 * Enable device.
 * used by dasdfmt after BIODASDDISABLE to retrigger blocksize detection
 */
static int
dasd_ioctl_enable(struct block_device *bdev)
{
	struct dasd_device *base;

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

	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;

	dasd_enable_device(base);
	/* Formatting the dasd device can change the capacity. */
	mutex_lock(&bdev->bd_mutex);
	i_size_write(bdev->bd_inode,
		     (loff_t)get_capacity(base->block->gdp) << 9);
	mutex_unlock(&bdev->bd_mutex);
	dasd_put_device(base);
	return 0;
}
Ejemplo n.º 7
0
static int
dasd_devices_show(struct seq_file *m, void *v)
{
    struct dasd_device *device;
    struct dasd_block *block;
    char *substr;

    device = dasd_device_from_devindex((unsigned long) v - 1);
    if (IS_ERR(device))
        return 0;
    if (device->block)
        block = device->block;
    else {
        dasd_put_device(device);
        return 0;
    }
    /* Print device number. */
    seq_printf(m, "%s", dev_name(&device->cdev->dev));
    /* Print discipline string. */
    if (device != NULL && device->discipline != NULL)
        seq_printf(m, "(%s)", device->discipline->name);
    else
        seq_printf(m, "(none)");
    /* Print kdev. */
    if (block->gdp)
        seq_printf(m, " at (%3d:%6d)",
                   MAJOR(disk_devt(block->gdp)),
                   MINOR(disk_devt(block->gdp)));
    else
        seq_printf(m, "  at (???:??????)");
    /* Print device name. */
    if (block->gdp)
        seq_printf(m, " is %-8s", block->gdp->disk_name);
    else
        seq_printf(m, " is ????????");
    /* Print devices features. */
    substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
    seq_printf(m, "%4s: ", substr);
    /* Print device status information. */
    switch ((device != NULL) ? device->state : -1) {
    case -1:
        seq_printf(m, "unknown");
        break;
    case DASD_STATE_NEW:
        seq_printf(m, "new");
        break;
    case DASD_STATE_KNOWN:
        seq_printf(m, "detected");
        break;
    case DASD_STATE_BASIC:
        seq_printf(m, "basic");
        break;
    case DASD_STATE_UNFMT:
        seq_printf(m, "unformatted");
        break;
    case DASD_STATE_READY:
    case DASD_STATE_ONLINE:
        seq_printf(m, "active ");
        if (dasd_check_blocksize(block->bp_block))
            seq_printf(m, "n/f	 ");
        else
            seq_printf(m,
                       "at blocksize: %d, %ld blocks, %ld MB",
                       block->bp_block, block->blocks,
                       ((block->bp_block >> 9) *
                        block->blocks) >> 11);
        break;
    default:
        seq_printf(m, "no stat");
        break;
    }
    dasd_put_device(device);
    if (dasd_probeonly)
        seq_printf(m, "(probeonly)");
    seq_printf(m, "\n");
    return 0;
}
Ejemplo n.º 8
0
int dasd_ioctl(struct block_device *bdev, fmode_t mode,
	       unsigned int cmd, unsigned long arg)
{
	struct dasd_block *block;
	struct dasd_device *base;
	void __user *argp;
	int rc;

	if (is_compat_task())
		argp = compat_ptr(arg);
	else
		argp = (void __user *)arg;

	if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) {
		PRINT_DEBUG("empty data ptr");
		return -EINVAL;
	}

	base = dasd_device_from_gendisk(bdev->bd_disk);
	if (!base)
		return -ENODEV;
	block = base->block;
	rc = 0;
	switch (cmd) {
	case BIODASDDISABLE:
		rc = dasd_ioctl_disable(bdev);
		break;
	case BIODASDENABLE:
		rc = dasd_ioctl_enable(bdev);
		break;
	case BIODASDQUIESCE:
		rc = dasd_ioctl_quiesce(block);
		break;
	case BIODASDRESUME:
		rc = dasd_ioctl_resume(block);
		break;
	case BIODASDFMT:
		rc = dasd_ioctl_format(bdev, argp);
		break;
	case BIODASDINFO:
		rc = dasd_ioctl_information(block, cmd, argp);
		break;
	case BIODASDINFO2:
		rc = dasd_ioctl_information(block, cmd, argp);
		break;
	case BIODASDPRRD:
		rc = dasd_ioctl_read_profile(block, argp);
		break;
	case BIODASDPRRST:
		rc = dasd_ioctl_reset_profile(block);
		break;
	case BLKROSET:
		rc = dasd_ioctl_set_ro(bdev, argp);
		break;
	case DASDAPIVER:
		rc = dasd_ioctl_api_version(argp);
		break;
	case BIODASDCMFENABLE:
		rc = enable_cmf(base->cdev);
		break;
	case BIODASDCMFDISABLE:
		rc = disable_cmf(base->cdev);
		break;
	case BIODASDREADALLCMB:
		rc = dasd_ioctl_readall_cmb(block, cmd, argp);
		break;
	default:
		/* if the discipline has an ioctl method try it. */
		if (base->discipline->ioctl) {
			rc = base->discipline->ioctl(block, cmd, argp);
			if (rc == -ENOIOCTLCMD)
				rc = -EINVAL;
		} else
			rc = -EINVAL;
	}
	dasd_put_device(base);
	return rc;
}
Ejemplo n.º 9
0
static int
dasd_devices_show(struct seq_file *m, void *v)
{
	struct dasd_device *device;
	char *substr;

	device = dasd_device_from_devindex((unsigned long) v - 1);
	if (IS_ERR(device))
		return 0;
	/* Print device number. */
	seq_printf(m, "%s", device->cdev->dev.bus_id);
	/* Print discipline string. */
	if (device != NULL && device->discipline != NULL)
		seq_printf(m, "(%s)", device->discipline->name);
	else
		seq_printf(m, "(none)");
	/* Print kdev. */
	if (device->gdp)
		seq_printf(m, " at (%3d:%6d)",
			   device->gdp->major, device->gdp->first_minor);
	else
		seq_printf(m, "  at (???:??????)");
	/* Print device name. */
	if (device->gdp)
		seq_printf(m, " is %-8s", device->gdp->disk_name);
	else
		seq_printf(m, " is ????????");
	/* Print devices features. */
	substr = test_bit(DASD_FLAG_RO, &device->flags) ? "(ro)" : " ";
	seq_printf(m, "%4s: ", substr);
	/* Print device status information. */
	switch ((device != NULL) ? device->state : -1) {
	case -1:
		seq_printf(m, "unknown");
		break;
	case DASD_STATE_NEW:
		seq_printf(m, "new");
		break;
	case DASD_STATE_KNOWN:
		seq_printf(m, "detected");
		break;
	case DASD_STATE_BASIC:
		seq_printf(m, "basic");
		break;
	case DASD_STATE_READY:
	case DASD_STATE_ONLINE:
		seq_printf(m, "active ");
		if (dasd_check_blocksize(device->bp_block))
			seq_printf(m, "n/f	 ");
		else
			seq_printf(m,
				   "at blocksize: %d, %ld blocks, %ld MB",
				   device->bp_block, device->blocks,
				   ((device->bp_block >> 9) *
				    device->blocks) >> 11);
		break;
	default:
		seq_printf(m, "no stat");
		break;
	}
	dasd_put_device(device);
	if (dasd_probeonly)
		seq_printf(m, "(probeonly)");
	seq_printf(m, "\n");
	return 0;
}