vdisk_nullio: Add "read_zero" attribute

Add an attribute called "read_zero" to vdisk_nullio devices that
controls whether or not READs from a vdisk_nullio device return
zeroed data buffers.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5539 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2014-05-23 02:20:35 +00:00
parent a3a3e76ce3
commit a3c9a05113
3 changed files with 102 additions and 7 deletions
+8 -1
View File
@@ -982,7 +982,7 @@ Intended to be used for performance measurements at the same way as
blocksize, read_only, removable, tst. See vdisk_fileio above for
description of those parameters.
vdisk_nullio also has extra attribute:
vdisk_nullio devices have the following two additional attributes:
- dummy - if this flag is set, LUNs corresponding to this device will
not appear at the initiator side. This is because SCST will set the
@@ -991,6 +991,13 @@ vdisk_nullio also has extra attribute:
See also SPC-4 for more information. It is designed to be used as a
"dummy" placeholder on LUN 0, if LUN 0 is not desired.
- read_zero - if this flag is set, reading from a vdisk_nullio device
returns a buffer filled with byte 0x00. If this flag is cleared
(which is the default behavior), the buffer returned to the
initiator is not cleared. Although this results in slightly faster
operation this is a security hole since any data that is present in
kernel memory can be returned to the initiator.
Handler vcdrom allows emulation of a virtual CDROM device using an ISO
file as backend. It has only single parameter: tst.
+8 -1
View File
@@ -840,7 +840,7 @@ Intended to be used for performance measurements at the same way as
blocksize, read_only, removable, tst. See vdisk_fileio above for
description of those parameters.
vdisk_nullio also has extra attribute:
vdisk_nullio devices have the following two additional attributes:
- dummy - if this flag is set, LUNs corresponding to this device will
not appear at the initiator side. This is because SCST will set the
@@ -849,6 +849,13 @@ vdisk_nullio also has extra attribute:
See also SPC-4 for more information. It is designed to be used as a
"dummy" placeholder on LUN 0, if LUN 0 is not desired.
- read_zero - if this flag is set, reading from a vdisk_nullio device
returns a buffer filled with byte 0x00. If this flag is cleared
(which is the default behavior), the buffer returned to the
initiator is not cleared. Although this results in slightly faster
operation this is a security hole since any data that is present in
kernel memory can be returned to the initiator.
Handler vcdrom allows emulation of a virtual CDROM device using an ISO
file as backend. It has only single parameter: tst.
+86 -5
View File
@@ -109,6 +109,7 @@ static struct scst_trace_log vdisk_local_trace_tbl[] = {
#define DEF_NV_CACHE 0
#define DEF_O_DIRECT 0
#define DEF_DUMMY 0
#define DEF_READ_ZERO 0
#define DEF_REMOVABLE 0
#define DEF_ROTATIONAL 1
#define DEF_THIN_PROVISIONED 0
@@ -160,6 +161,7 @@ struct scst_vdisk_dev {
unsigned int blockio:1;
unsigned int cdrom_empty:1;
unsigned int dummy:1;
unsigned int read_zero:1;
unsigned int removable:1;
unsigned int thin_provisioned:1;
unsigned int thin_provisioned_manually_set:1;
@@ -263,7 +265,8 @@ static int vcdrom_parse(struct scst_cmd *);
static int non_fileio_parse(struct scst_cmd *);
static int vdisk_exec(struct scst_cmd *cmd);
static int vcdrom_exec(struct scst_cmd *cmd);
static int non_fileio_exec(struct scst_cmd *cmd);
static int blockio_exec(struct scst_cmd *cmd);
static int nullio_exec(struct scst_cmd *cmd);
static void fileio_on_free_cmd(struct scst_cmd *cmd);
static enum compl_status_e nullio_exec_read(struct vdisk_cmd_params *p);
static enum compl_status_e blockio_exec_read(struct vdisk_cmd_params *p);
@@ -349,6 +352,10 @@ static ssize_t vdisk_sysfs_o_direct_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
static ssize_t vdev_sysfs_dummy_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
static ssize_t vdev_sysfs_rz_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
static ssize_t vdev_sysfs_rz_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count);
static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
@@ -421,6 +428,9 @@ static struct kobj_attribute vdisk_o_direct_attr =
__ATTR(o_direct, S_IRUGO, vdisk_sysfs_o_direct_show, NULL);
static struct kobj_attribute vdev_dummy_attr =
__ATTR(dummy, S_IRUGO, vdev_sysfs_dummy_show, NULL);
static struct kobj_attribute vdev_read_zero_attr =
__ATTR(read_zero, S_IWUSR|S_IRUGO, vdev_sysfs_rz_show,
vdev_sysfs_rz_store);
static struct kobj_attribute vdisk_removable_attr =
__ATTR(removable, S_IRUGO, vdisk_sysfs_removable_show, NULL);
static struct kobj_attribute vdisk_filename_attr =
@@ -516,6 +526,7 @@ static const struct attribute *vdisk_nullio_attrs[] = {
&vdisk_rd_only_attr.attr,
&vdisk_tst_attr.attr,
&vdev_dummy_attr.attr,
&vdev_read_zero_attr.attr,
&vdisk_removable_attr.attr,
&vdev_t10_vend_id_attr.attr,
&vdev_vend_specific_id_attr.attr,
@@ -634,7 +645,7 @@ static struct scst_dev_type vdisk_blk_devtype = {
.attach_tgt = vdisk_attach_tgt,
.detach_tgt = vdisk_detach_tgt,
.parse = non_fileio_parse,
.exec = non_fileio_exec,
.exec = blockio_exec,
.task_mgmt_fn_done = vdisk_task_mgmt_fn_done,
.get_supported_opcodes = vdisk_get_supported_opcodes,
.devt_priv = (void *)blockio_ops,
@@ -677,7 +688,7 @@ static struct scst_dev_type vdisk_null_devtype = {
.attach_tgt = vdisk_attach_tgt,
.detach_tgt = vdisk_detach_tgt,
.parse = non_fileio_parse,
.exec = non_fileio_exec,
.exec = nullio_exec,
.task_mgmt_fn_done = vdisk_task_mgmt_fn_done,
.devt_priv = (void *)nullio_ops,
.get_supported_opcodes = vdisk_get_supported_opcodes,
@@ -2847,8 +2858,7 @@ out:
return;
}
/* blockio and nullio */
static int non_fileio_exec(struct scst_cmd *cmd)
static int blockio_exec(struct scst_cmd *cmd)
{
struct scst_vdisk_dev *virt_dev = cmd->dev->dh_priv;
const vdisk_op_fn *ops = virt_dev->vdev_devt->devt_priv;
@@ -2875,6 +2885,31 @@ err:
goto out;
}
static int nullio_exec(struct scst_cmd *cmd)
{
struct scst_device *dev = cmd->dev;
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
if (unlikely(virt_dev->read_zero &&
(cmd->data_direction == SCST_DATA_READ ||
cmd->data_direction == SCST_DATA_BIDI))) {
struct scatterlist *sge;
int i;
void *p;
for_each_sg(cmd->sg, sge, cmd->sg_cnt, i) {
p = kmap(sg_page(sge));
if (sge->offset == 0 && sge->length == PAGE_SIZE)
clear_page(p);
else
memset(p + sge->offset, 0, sge->length);
kunmap(p);
}
}
return blockio_exec(cmd);
}
static int vcdrom_exec(struct scst_cmd *cmd)
{
int res = SCST_EXEC_COMPLETED;
@@ -5942,6 +5977,7 @@ static int vdev_create(struct scst_dev_type *devt,
virt_dev->rd_only = DEF_RD_ONLY;
virt_dev->dummy = DEF_DUMMY;
virt_dev->read_zero = DEF_READ_ZERO;
virt_dev->removable = DEF_REMOVABLE;
virt_dev->rotational = DEF_ROTATIONAL;
virt_dev->thin_provisioned = DEF_THIN_PROVISIONED;
@@ -7012,6 +7048,51 @@ static ssize_t vdev_sysfs_dummy_show(struct kobject *kobj,
virt_dev->dummy != DEF_DUMMY ? SCST_SYSFS_KEY_MARK "\n" : "");
}
static ssize_t vdev_sysfs_rz_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct scst_device *dev = container_of(kobj, struct scst_device,
dev_kobj);
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
bool read_zero = virt_dev->read_zero;
return sprintf(buf, "%d\n%s", read_zero, read_zero != DEF_READ_ZERO ?
SCST_SYSFS_KEY_MARK "\n" : "");
}
static ssize_t vdev_sysfs_rz_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf,
size_t count)
{
struct scst_device *dev = container_of(kobj, struct scst_device,
dev_kobj);
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
long read_zero;
int res;
char ch[16];
sprintf(ch, "%.*s", min_t(int, sizeof(ch) - 1, count), buf);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
res = kstrtol(ch, 0, &read_zero);
#else
res = strict_strtol(ch, 0, &read_zero);
#endif
if (res)
goto out;
res = -EINVAL;
if (read_zero != 0 && read_zero != 1)
goto out;
spin_lock(&virt_dev->flags_lock);
virt_dev->read_zero = read_zero;
spin_unlock(&virt_dev->flags_lock);
res = count;
out:
return res;
}
static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{