mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-21 06:36:27 +00:00
scst_vdisk: Make vdisk_nullio size configurable
Keep the default size of vdisk_nullio devices at VDISK_NULLIO_SIZE. Add a sysfs attribute 'size' which is the size of a vdisk device in bytes. Make the size of vdisk_nullio devices configurable. Accept "size" and "size_mb" as creation parameters for vdisk_nullio devices. Generate a CAPACITY DATA HAS CHANGED unit attention after size changes. Refuse any attempt to change the size into a number that is not a multiple of the block size. Signed-off-by: Bart Van Assche <bvanassche@acm.org> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5322 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -307,8 +307,14 @@ static int vdisk_unmap_range(struct scst_cmd *cmd,
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
|
||||
static ssize_t vdev_sysfs_size_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_size_mb_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_size_mb_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdisk_sysfs_blocksize_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdisk_sysfs_rd_only_show(struct kobject *kobj,
|
||||
@@ -365,8 +371,16 @@ static ssize_t vdev_zero_copy_show(struct kobject *kobj,
|
||||
static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
|
||||
static struct kobj_attribute vdev_size_attr =
|
||||
__ATTR(size_mb, S_IRUGO, vdev_sysfs_size_show, NULL);
|
||||
static struct kobj_attribute vdev_size_ro_attr =
|
||||
__ATTR(size, S_IRUGO, vdev_sysfs_size_show, NULL);
|
||||
static struct kobj_attribute vdev_size_rw_attr =
|
||||
__ATTR(size, S_IWUSR|S_IRUGO, vdev_sysfs_size_show,
|
||||
vdev_sysfs_size_store);
|
||||
static struct kobj_attribute vdev_size_mb_ro_attr =
|
||||
__ATTR(size_mb, S_IRUGO, vdev_sysfs_size_mb_show, NULL);
|
||||
static struct kobj_attribute vdev_size_mb_rw_attr =
|
||||
__ATTR(size_mb, S_IWUSR|S_IRUGO, vdev_sysfs_size_mb_show,
|
||||
vdev_sysfs_size_mb_store);
|
||||
static struct kobj_attribute vdisk_blocksize_attr =
|
||||
__ATTR(blocksize, S_IRUGO, vdisk_sysfs_blocksize_show, NULL);
|
||||
static struct kobj_attribute vdisk_rd_only_attr =
|
||||
@@ -419,7 +433,8 @@ static struct kobj_attribute vcdrom_filename_attr =
|
||||
vcdrom_sysfs_filename_store);
|
||||
|
||||
static const struct attribute *vdisk_fileio_attrs[] = {
|
||||
&vdev_size_attr.attr,
|
||||
&vdev_size_ro_attr.attr,
|
||||
&vdev_size_mb_ro_attr.attr,
|
||||
&vdisk_blocksize_attr.attr,
|
||||
&vdisk_rd_only_attr.attr,
|
||||
&vdisk_wt_attr.attr,
|
||||
@@ -442,7 +457,8 @@ static const struct attribute *vdisk_fileio_attrs[] = {
|
||||
};
|
||||
|
||||
static const struct attribute *vdisk_blockio_attrs[] = {
|
||||
&vdev_size_attr.attr,
|
||||
&vdev_size_ro_attr.attr,
|
||||
&vdev_size_mb_ro_attr.attr,
|
||||
&vdisk_blocksize_attr.attr,
|
||||
&vdisk_rd_only_attr.attr,
|
||||
&vdisk_wt_attr.attr,
|
||||
@@ -463,7 +479,8 @@ static const struct attribute *vdisk_blockio_attrs[] = {
|
||||
};
|
||||
|
||||
static const struct attribute *vdisk_nullio_attrs[] = {
|
||||
&vdev_size_attr.attr,
|
||||
&vdev_size_rw_attr.attr,
|
||||
&vdev_size_mb_rw_attr.attr,
|
||||
&vdisk_blocksize_attr.attr,
|
||||
&vdisk_rd_only_attr.attr,
|
||||
&vdev_dummy_attr.attr,
|
||||
@@ -480,7 +497,8 @@ static const struct attribute *vdisk_nullio_attrs[] = {
|
||||
};
|
||||
|
||||
static const struct attribute *vcdrom_attrs[] = {
|
||||
&vdev_size_attr.attr,
|
||||
&vdev_size_ro_attr.attr,
|
||||
&vdev_size_mb_ro_attr.attr,
|
||||
&vcdrom_filename_attr.attr,
|
||||
&vdev_t10_vend_id_attr.attr,
|
||||
&vdev_vend_specific_id_attr.attr,
|
||||
@@ -632,7 +650,9 @@ static struct scst_dev_type vdisk_null_devtype = {
|
||||
"dummy, "
|
||||
"read_only, "
|
||||
"removable, "
|
||||
"rotational",
|
||||
"rotational, "
|
||||
"size, "
|
||||
"size_mb",
|
||||
#endif
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
.default_trace_flags = SCST_DEFAULT_DEV_LOG_FLAGS,
|
||||
@@ -942,17 +962,15 @@ static int vdisk_attach(struct scst_device *dev)
|
||||
dev->dev_rd_only = virt_dev->rd_only;
|
||||
|
||||
if (!virt_dev->cdrom_empty) {
|
||||
if (virt_dev->nullio)
|
||||
err = VDISK_NULLIO_SIZE;
|
||||
else {
|
||||
if (!virt_dev->nullio) {
|
||||
res = vdisk_get_file_size(virt_dev->filename,
|
||||
virt_dev->blockio, &err);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
}
|
||||
virt_dev->file_size = err;
|
||||
virt_dev->file_size = err;
|
||||
|
||||
TRACE_DBG("size of file: %lld", (long long unsigned int)err);
|
||||
TRACE_DBG("size of file: %lld", err);
|
||||
}
|
||||
|
||||
vdisk_blockio_check_flush_support(virt_dev);
|
||||
vdisk_check_tp_support(virt_dev);
|
||||
@@ -4898,6 +4916,10 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
|
||||
virt_dev->thin_provisioned);
|
||||
} else if (!strcasecmp("zero_copy", p)) {
|
||||
virt_dev->zero_copy = !!val;
|
||||
} else if (!strcasecmp("size", p)) {
|
||||
virt_dev->file_size = val;
|
||||
} else if (!strcasecmp("size_mb", p)) {
|
||||
virt_dev->file_size = val * 1024 * 1024;
|
||||
} else if (!strcasecmp("blocksize", p)) {
|
||||
virt_dev->blk_shift = scst_calc_block_shift(val);
|
||||
if (virt_dev->blk_shift < 9) {
|
||||
@@ -4914,6 +4936,12 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev,
|
||||
}
|
||||
}
|
||||
|
||||
if (virt_dev->file_size % (1 << virt_dev->blk_shift) != 0) {
|
||||
PRINT_ERROR("Device size %lld is not a multiple of the block"
|
||||
" size %d", virt_dev->file_size,
|
||||
1 << virt_dev->blk_shift);
|
||||
res = -EINVAL;
|
||||
}
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
@@ -5042,7 +5070,7 @@ static int vdev_nullio_add_device(const char *device_name, char *params)
|
||||
int res = 0;
|
||||
static const char *const allowed_params[] = {
|
||||
"read_only", "dummy", "removable", "blocksize", "rotational",
|
||||
NULL
|
||||
"size", "size_mb", NULL
|
||||
};
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
@@ -5055,6 +5083,7 @@ static int vdev_nullio_add_device(const char *device_name, char *params)
|
||||
virt_dev->command_set_version = 0x04C0; /* SBC-3 */
|
||||
|
||||
virt_dev->nullio = 1;
|
||||
virt_dev->file_size = VDISK_NULLIO_SIZE;
|
||||
|
||||
res = vdev_parse_add_dev_params(virt_dev, params, allowed_params);
|
||||
if (res != 0)
|
||||
@@ -5492,22 +5521,128 @@ out_free:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
static int vdev_size_process_store(struct scst_sysfs_work_item *work)
|
||||
{
|
||||
struct scst_device *dev = work->dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
unsigned long long new_size;
|
||||
int size_shift, res = -EINVAL;
|
||||
|
||||
if (sscanf(work->buf, "%d %lld", &size_shift, &new_size) != 2 ||
|
||||
new_size > (ULONG_MAX >> size_shift))
|
||||
goto put;
|
||||
|
||||
new_size <<= size_shift;
|
||||
|
||||
res = scst_suspend_activity(SCST_SUSPEND_TIMEOUT_USER);
|
||||
if (res)
|
||||
goto put;
|
||||
|
||||
/* To sync with detach*() functions */
|
||||
res = mutex_lock_interruptible(&scst_mutex);
|
||||
if (res)
|
||||
goto resume;
|
||||
|
||||
virt_dev = dev->dh_priv;
|
||||
if (!virt_dev->nullio) {
|
||||
sBUG();
|
||||
res = -EPERM;
|
||||
} else if (new_size % (1 << virt_dev->blk_shift) == 0) {
|
||||
virt_dev->file_size = new_size;
|
||||
virt_dev->nblocks = virt_dev->file_size >> dev->block_shift;
|
||||
} else {
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
if (res == 0)
|
||||
scst_capacity_data_changed(dev);
|
||||
|
||||
resume:
|
||||
scst_resume_activity();
|
||||
|
||||
put:
|
||||
kobject_put(&dev->dev_kobj);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_size_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf,
|
||||
size_t count, int size_shift)
|
||||
{
|
||||
struct scst_device *dev = container_of(kobj, struct scst_device,
|
||||
dev_kobj);
|
||||
struct scst_sysfs_work_item *work;
|
||||
char *new_size;
|
||||
int res = -ENOMEM;
|
||||
|
||||
|
||||
new_size = kasprintf(GFP_KERNEL, "%d %.*s", size_shift, (int)count,
|
||||
buf);
|
||||
if (!new_size)
|
||||
goto out;
|
||||
|
||||
res = scst_alloc_sysfs_work(vdev_size_process_store, false, &work);
|
||||
if (res)
|
||||
goto out_free;
|
||||
|
||||
work->buf = new_size;
|
||||
work->dev = dev;
|
||||
|
||||
SCST_SET_DEP_MAP(work, &scst_dev_dep_map);
|
||||
kobject_get(&dev->dev_kobj);
|
||||
|
||||
res = scst_sysfs_queue_wait_work(work);
|
||||
if (res == 0)
|
||||
res = count;
|
||||
|
||||
out:
|
||||
return res;
|
||||
|
||||
out_free:
|
||||
kfree(buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_size_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
return vdev_size_store(kobj, attr, buf, count, 0);
|
||||
}
|
||||
|
||||
static ssize_t vdev_size_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
char *buf, int size_shift)
|
||||
{
|
||||
int pos = 0;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
unsigned long long size;
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
size = ACCESS_ONCE(virt_dev->file_size);
|
||||
|
||||
pos = sprintf(buf, "%lld\n", virt_dev->file_size / 1024 / 1024);
|
||||
return sprintf(buf, "%llu\n%s", size >> size_shift,
|
||||
virt_dev->nullio && size != VDISK_NULLIO_SIZE ?
|
||||
SCST_SYSFS_KEY_MARK "\n" : "");
|
||||
}
|
||||
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return vdev_size_show(kobj, attr, buf, 0);
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_size_mb_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
return vdev_size_store(kobj, attr, buf, count, 20);
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_size_mb_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return vdev_size_show(kobj, attr, buf, 20);
|
||||
}
|
||||
|
||||
static ssize_t vdisk_sysfs_blocksize_show(struct kobject *kobj,
|
||||
|
||||
Reference in New Issue
Block a user