mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-20 14:16:31 +00:00
Patch from Witold Kowolik <witoldk1@open-e.com> implementing manual setting of SCSI ID on vdisk devices (with some changes)
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1365 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -652,6 +652,12 @@ subdirectories "vdisk" and "vcdrom". They have similar layout:
|
||||
|
||||
* "change NAME [PATH]" - changes a virtual CD in the VDISK CDROM.
|
||||
|
||||
* "set_scsiid NAME SCSI_ID" - sets T10 vendor specific identifier
|
||||
on Device Identification VPD page (0x83) of device "NAME" in
|
||||
INQUIRY data. By default VDISK handler always generates SCSI_ID
|
||||
for every new created device (at creation time). This parameter
|
||||
allows to overwrite generated by VDISK value of SCSI ID.
|
||||
|
||||
By default, if neither BLOCKIO, nor NULLIO option is supplied, FILEIO
|
||||
mode is used.
|
||||
|
||||
|
||||
@@ -569,6 +569,12 @@ subdirectories "vdisk" and "vcdrom". They have similar layout:
|
||||
|
||||
* "change NAME [PATH]" - changes a virtual CD in the VDISK CDROM.
|
||||
|
||||
* "set_scsiid NAME SCSI_ID" - sets T10 vendor specific identifier
|
||||
on Device Identification VPD page (0x83) of device "NAME" in
|
||||
INQUIRY data. By default VDISK handler always generates SCSI_ID
|
||||
for every new created device (at creation time). This parameter
|
||||
allows to overwrite generated by VDISK value of SCSI ID.
|
||||
|
||||
By default, if neither BLOCKIO, nor NULLIO option is supplied, FILEIO
|
||||
mode is used.
|
||||
|
||||
|
||||
@@ -214,6 +214,7 @@ struct scst_vdisk_dev {
|
||||
must be <= SCSI Model + 1 */
|
||||
char *file_name; /* File name, protected by
|
||||
scst_mutex and suspended activities */
|
||||
char scsi_id[16+8+2]; /* SCSI ID */
|
||||
char usn[MAX_USN_LEN];
|
||||
struct scst_device *dev;
|
||||
struct list_head vdisk_dev_list_entry;
|
||||
@@ -362,6 +363,7 @@ static int vcdrom_write_proc(char *buffer, char **start, off_t offset,
|
||||
#endif
|
||||
static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
|
||||
struct scst_tgt_dev *tgt_dev);
|
||||
static uint64_t vdisk_gen_dev_id_num(struct scst_vdisk_dev *virt_dev);
|
||||
|
||||
/** SYSFS **/
|
||||
|
||||
@@ -398,6 +400,10 @@ static ssize_t vdisk_sysfs_filename_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdisk_sysfs_scsi_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdisk_sysfs_scsi_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
|
||||
static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
@@ -420,6 +426,9 @@ static struct kobj_attribute vdisk_filename_attr =
|
||||
__ATTR(filename, S_IRUGO, vdisk_sysfs_filename_show, NULL);
|
||||
static struct kobj_attribute vdisk_resync_size_attr =
|
||||
__ATTR(resync_size, S_IWUSR, NULL, vdisk_sysfs_resync_size_store);
|
||||
static struct kobj_attribute vdisk_scsi_id_attr =
|
||||
__ATTR(scsi_id, S_IWUSR|S_IRUGO, vdisk_sysfs_scsi_id_show,
|
||||
vdisk_sysfs_scsi_id_store);
|
||||
|
||||
static struct kobj_attribute vcdrom_filename_attr =
|
||||
__ATTR(filename, S_IRUGO|S_IWUSR, vdisk_sysfs_filename_show,
|
||||
@@ -435,6 +444,7 @@ static const struct attribute *vdisk_fileio_attrs[] = {
|
||||
&vdisk_removable_attr.attr,
|
||||
&vdisk_filename_attr.attr,
|
||||
&vdisk_resync_size_attr.attr,
|
||||
&vdisk_scsi_id_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -445,6 +455,7 @@ static const struct attribute *vdisk_blockio_attrs[] = {
|
||||
&vdisk_removable_attr.attr,
|
||||
&vdisk_filename_attr.attr,
|
||||
&vdisk_resync_size_attr.attr,
|
||||
&vdisk_scsi_id_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -453,6 +464,7 @@ static const struct attribute *vdisk_nullio_attrs[] = {
|
||||
&vdisk_blocksize_attr.attr,
|
||||
&vdisk_rd_only_attr.attr,
|
||||
&vdisk_removable_attr.attr,
|
||||
&vdisk_scsi_id_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -460,6 +472,7 @@ static const struct attribute *vcdrom_attrs[] = {
|
||||
&vdisk_size_attr.attr,
|
||||
&vdisk_removable_attr.attr,
|
||||
&vcdrom_filename_attr.attr,
|
||||
&vdisk_scsi_id_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -467,6 +480,7 @@ static const struct attribute *vcdrom_attrs[] = {
|
||||
|
||||
/* Protects vdisks addition/deletion and related activities, like search */
|
||||
static DEFINE_MUTEX(scst_vdisk_mutex);
|
||||
static DEFINE_RWLOCK(vdisk_scsiid_rwlock);
|
||||
|
||||
/* Both protected by scst_vdisk_mutex */
|
||||
static LIST_HEAD(vdisk_dev_list);
|
||||
@@ -609,6 +623,8 @@ static struct scst_vdisk_thr nullio_thr_data;
|
||||
static char *vdisk_proc_help_string =
|
||||
"echo \"open|close|resync_size NAME [FILE_NAME [BLOCK_SIZE] "
|
||||
"[WRITE_THROUGH READ_ONLY O_DIRECT NULLIO NV_CACHE BLOCKIO]]\" "
|
||||
">/proc/scsi_tgt/vdisk/vdisk\n"
|
||||
"echo \"set_scsiid NAME SCSI_ID\" "
|
||||
">/proc/scsi_tgt/vdisk/vdisk\n";
|
||||
|
||||
static char *vcdrom_proc_help_string =
|
||||
@@ -723,6 +739,10 @@ static int vdisk_attach(struct scst_device *dev)
|
||||
loff_t err;
|
||||
struct scst_vdisk_dev *virt_dev = NULL, *vv;
|
||||
struct list_head *vd;
|
||||
uint64_t dev_id_num;
|
||||
int dev_id_len;
|
||||
char dev_id_str[17];
|
||||
int32_t i;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -804,6 +824,18 @@ static int vdisk_attach(struct scst_device *dev)
|
||||
dev->swp = DEF_SWP;
|
||||
dev->tas = DEF_TAS;
|
||||
|
||||
/* generate SCSI id */
|
||||
dev_id_num = vdisk_gen_dev_id_num(virt_dev);
|
||||
dev_id_len = scnprintf(dev_id_str, sizeof(dev_id_str), "%llx",
|
||||
dev_id_num);
|
||||
|
||||
write_lock(&vdisk_scsiid_rwlock);
|
||||
i = strlen(virt_dev->name) + 1; /* for ' ' */
|
||||
memset(virt_dev->scsi_id, ' ', i + dev_id_len);
|
||||
memcpy(virt_dev->scsi_id, virt_dev->name, i-1);
|
||||
memcpy(virt_dev->scsi_id + i, dev_id_str, dev_id_len);
|
||||
write_unlock(&vdisk_scsiid_rwlock);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return res;
|
||||
@@ -1415,15 +1447,6 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
|
||||
buf[1] = 0x80; /* removable */
|
||||
/* Vital Product */
|
||||
if (cmd->cdb[1] & EVPD) {
|
||||
uint64_t dev_id_num;
|
||||
int dev_id_len;
|
||||
char dev_id_str[17];
|
||||
|
||||
dev_id_num = vdisk_gen_dev_id_num(virt_dev);
|
||||
dev_id_len = scnprintf(dev_id_str, sizeof(dev_id_str), "%llx",
|
||||
dev_id_num);
|
||||
TRACE_DBG("dev_id num %lld, str %s, len %d", dev_id_num,
|
||||
dev_id_str, dev_id_len);
|
||||
if (0 == cmd->cdb[2]) {
|
||||
/* supported vital product data pages */
|
||||
buf[3] = 3;
|
||||
@@ -1451,11 +1474,12 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
|
||||
else
|
||||
memcpy(&buf[num + 4], SCST_FIO_VENDOR, 8);
|
||||
|
||||
i = strlen(virt_dev->name) + 1; /* for ' ' */
|
||||
memset(&buf[num + 12], ' ', i + dev_id_len);
|
||||
memcpy(&buf[num + 12], virt_dev->name, i-1);
|
||||
memcpy(&buf[num + 12 + i], dev_id_str, dev_id_len);
|
||||
buf[num + 3] = 8 + i + dev_id_len;
|
||||
read_lock(&vdisk_scsiid_rwlock);
|
||||
i = strlen(virt_dev->scsi_id);
|
||||
memcpy(&buf[num + 12], virt_dev->scsi_id, i);
|
||||
read_unlock(&vdisk_scsiid_rwlock);
|
||||
|
||||
buf[num + 3] = 8 + i;
|
||||
num += buf[num + 3];
|
||||
|
||||
#if 0 /* This isn't required and can be misleading, so let's disable it */
|
||||
@@ -3852,6 +3876,72 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdisk_sysfs_scsi_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int res, i;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
|
||||
write_lock(&vdisk_scsiid_rwlock);
|
||||
|
||||
if ((count > sizeof(virt_dev->scsi_id)) ||
|
||||
((count == sizeof(virt_dev->scsi_id)) &&
|
||||
(buf[count-1] != '\n'))) {
|
||||
PRINT_ERROR("SCSI ID is too long (max %zd "
|
||||
"characters)", sizeof(virt_dev->scsi_id)-1);
|
||||
res = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
memset(virt_dev->scsi_id, 0, sizeof(virt_dev->scsi_id));
|
||||
memcpy(virt_dev->scsi_id, buf, count);
|
||||
|
||||
i = 0;
|
||||
while (i < sizeof(virt_dev->scsi_id)) {
|
||||
if (virt_dev->scsi_id[i] == '\n') {
|
||||
virt_dev->scsi_id[i] = '\0';
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
res = count;
|
||||
|
||||
PRINT_INFO("SCSI ID for device %s changed to %s", virt_dev->name,
|
||||
virt_dev->scsi_id);
|
||||
|
||||
out_unlock:
|
||||
write_unlock(&vdisk_scsiid_rwlock);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdisk_sysfs_scsi_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int pos = 0;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_scsiid_rwlock);
|
||||
pos = sprintf(buf, "%s\n", virt_dev->scsi_id);
|
||||
read_unlock(&vdisk_scsiid_rwlock);
|
||||
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
#else /* CONFIG_SCST_PROC */
|
||||
|
||||
/*
|
||||
@@ -3873,8 +3963,9 @@ static int vdisk_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type)
|
||||
goto out;
|
||||
}
|
||||
|
||||
seq_printf(seq, "%-17s %-11s %-11s %-15s %s\n",
|
||||
"Name", "Size(MB)", "Block size", "Options", "File name");
|
||||
seq_printf(seq, "%-17s %-11s %-11s %-15s %-45s %-16s\n",
|
||||
"Name", "Size(MB)", "Block size", "Options", "File name",
|
||||
"SCSI id");
|
||||
|
||||
list_for_each_entry(virt_dev, &vdisk_dev_list, vdisk_dev_list_entry) {
|
||||
int c;
|
||||
@@ -3919,7 +4010,10 @@ static int vdisk_read_proc(struct seq_file *seq, struct scst_dev_type *dev_type)
|
||||
seq_printf(seq, " ");
|
||||
c++;
|
||||
}
|
||||
seq_printf(seq, "%s\n", virt_dev->file_name);
|
||||
read_lock(&vdisk_scsiid_rwlock);
|
||||
seq_printf(seq, "%-45s %-16s\n", virt_dev->file_name,
|
||||
virt_dev->scsi_id);
|
||||
read_unlock(&vdisk_scsiid_rwlock);
|
||||
}
|
||||
mutex_unlock(&scst_vdisk_mutex);
|
||||
out:
|
||||
@@ -3931,11 +4025,11 @@ static int vdisk_proc_mgmt_cmd(const char *buffer, int length,
|
||||
struct scst_dev_type *dev_type)
|
||||
{
|
||||
int res = 0, action;
|
||||
char *p, *name, *file_name, *i_buf;
|
||||
char *p, *name, *file_name, *i_buf, *scsi_id;
|
||||
struct scst_vdisk_dev *virt_dev, *vv;
|
||||
uint32_t block_size = DEF_DISK_BLOCKSIZE;
|
||||
int block_shift = DEF_DISK_BLOCKSIZE_SHIFT;
|
||||
size_t len;
|
||||
size_t len, slen;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -3970,6 +4064,9 @@ static int vdisk_proc_mgmt_cmd(const char *buffer, int length,
|
||||
} else if (!strncmp("resync_size ", p, 12)) {
|
||||
p += 12;
|
||||
action = 2;
|
||||
} else if (!strncmp("set_scsiid ", p, 11)) {
|
||||
p += 11;
|
||||
action = 3;
|
||||
} else {
|
||||
PRINT_ERROR("Unknown action \"%s\"", p);
|
||||
res = -EINVAL;
|
||||
@@ -4165,7 +4262,7 @@ static int vdisk_proc_mgmt_cmd(const char *buffer, int length,
|
||||
|
||||
kfree(virt_dev->file_name);
|
||||
kfree(virt_dev);
|
||||
} else { /* resync_size */
|
||||
} else if (action == 2) { /* resync_size */
|
||||
virt_dev = NULL;
|
||||
list_for_each_entry(vv, &vdisk_dev_list,
|
||||
vdisk_dev_list_entry) {
|
||||
@@ -4183,6 +4280,46 @@ static int vdisk_proc_mgmt_cmd(const char *buffer, int length,
|
||||
res = vdisk_resync_size(virt_dev);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
} else if (action == 3) { /* set scsi id */
|
||||
virt_dev = NULL;
|
||||
list_for_each_entry(vv, &vdisk_dev_list,
|
||||
vdisk_dev_list_entry) {
|
||||
if (strcmp(vv->name, name) == 0) {
|
||||
virt_dev = vv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (virt_dev == NULL) {
|
||||
PRINT_ERROR("Device %s not found", name);
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
scsi_id = p;
|
||||
while (!isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
*p++ = '\0';
|
||||
if (*scsi_id == '\0') {
|
||||
PRINT_ERROR("%s", "SCSI ID required");
|
||||
res = -EINVAL;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
write_lock(&vdisk_scsiid_rwlock);
|
||||
|
||||
slen = (strlen(scsi_id) <= (sizeof(virt_dev->scsi_id)-1) ?
|
||||
strlen(scsi_id) :
|
||||
(sizeof(virt_dev->scsi_id)-1));
|
||||
|
||||
memset(virt_dev->scsi_id, 0, sizeof(virt_dev->scsi_id));
|
||||
memcpy(virt_dev->scsi_id, scsi_id, slen);
|
||||
|
||||
PRINT_INFO("SCSI ID for device %s changed to %s",
|
||||
virt_dev->name, virt_dev->scsi_id);
|
||||
|
||||
write_unlock(&vdisk_scsiid_rwlock);
|
||||
}
|
||||
res = length;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user