mirror of
https://github.com/SCST-project/scst.git
synced 2026-09-20 15:04:19 +00:00
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:
+8
-1
@@ -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
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user