Пример #1
0
int
blktap_control_destroy_device(struct blktap *tap)
{
	int err;
	unsigned long inuse;

	if (!tap)
		return 0;

	set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);

	for (;;) {
		inuse = tap->dev_inuse;
		err   = blktap_device_destroy(tap);
		if (err)
			goto wait;

		inuse = tap->dev_inuse;
		err   = blktap_ring_destroy(tap);
		if (err)
			goto wait;

		inuse = tap->dev_inuse;
		err   = blktap_sysfs_destroy(tap);
		if (err)
			goto wait;

		break;

	wait:
		BTDBG("inuse: 0x%lx, dev_inuse: 0x%lx\n",
		      inuse, tap->dev_inuse);
		if (wait_event_interruptible(tap->wq, tap->dev_inuse != inuse))
			break;
	}

	clear_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);

	if (tap->dev_inuse == (1UL << BLKTAP_CONTROL)) {
		err = 0;
		clear_bit(BLKTAP_CONTROL, &tap->dev_inuse);
	}

	return err;
}
Пример #2
0
static long
blktap_ring_ioctl(struct file *filp,
		  unsigned int cmd, unsigned long arg)
{
	struct blktap *tap = filp->private_data;
	struct blktap_ring *ring = &tap->ring;
	void __user *ptr = (void *)arg;
	int err;

	BTDBG("%d: cmd: %u, arg: %lu\n", tap->minor, cmd, arg);

	if (!ring->vma || ring->vma->vm_mm != current->mm)
		return -EACCES;

	switch(cmd) {
	case BLKTAP_IOCTL_RESPOND:

		blktap_read_ring(tap);
		return 0;

	case BLKTAP_IOCTL_CREATE_DEVICE_COMPAT: {
		struct blktap_device_info info;
		struct blktap2_params params;

		if (copy_from_user(&params, ptr, sizeof(params)))
			return -EFAULT;

		info.capacity             = params.capacity;
		info.sector_size          = params.sector_size;
		info.flags                = 0;

		err = blktap_device_create(tap, &info);
		if (err)
			return err;

		if (params.name[0]) {
			strncpy(tap->name, params.name, sizeof(params.name));
			tap->name[sizeof(tap->name)-1] = 0;
		}

		return 0;
	}

	case BLKTAP_IOCTL_CREATE_DEVICE: {
		struct blktap_device_info __user *ptr = (void *)arg;
		struct blktap_device_info info;
		unsigned long mask;
		size_t base_sz, sz;

		mask  = BLKTAP_DEVICE_FLAG_RO;
		mask |= BLKTAP_DEVICE_FLAG_PSZ;
		mask |= BLKTAP_DEVICE_FLAG_FLUSH;
		mask |= BLKTAP_DEVICE_FLAG_TRIM;
		mask |= BLKTAP_DEVICE_FLAG_TRIM_RZ;

		memset(&info, 0, sizeof(info));
		sz = base_sz = BLKTAP_INFO_SIZE_AT(flags);

		if (copy_from_user(&info, ptr, sz))
			return -EFAULT;

		if ((info.flags & BLKTAP_DEVICE_FLAG_PSZ) != 0)
			sz = BLKTAP_INFO_SIZE_AT(phys_block_offset);

		if (info.flags & BLKTAP_DEVICE_FLAG_TRIM)
			sz = BLKTAP_INFO_SIZE_AT(trim_block_offset);

		if (sz > base_sz)
			if (copy_from_user(&info, ptr, sz))
				return -EFAULT;

		if (put_user(info.flags & mask, &ptr->flags))
			return -EFAULT;

		return blktap_device_create(tap, &info);
	}

	case BLKTAP_IOCTL_REMOVE_DEVICE:

		return blktap_device_destroy(tap);
	}

	return -ENOTTY;
}