mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-17 12:46:27 +00:00
scst_vdisk: Make vendor, product ID and related fields configurable via sysfs
Signed-off-by: Bart Van Assche <bvanassche@acm.org> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5316 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -32,6 +32,17 @@ more information):
|
||||
2:0:0:0 ram000 ram001 ram002 ram003 ram004 ram005 ram006 ram007
|
||||
ram008 ram009 ram010 ram011 ram012 ram013 ram014 ram015
|
||||
|
||||
Next, set the vendor ID, product ID etc. fields via sysfs. These fields
|
||||
must be set to the following values to allow AIX initiators to recognize
|
||||
SCST devices:
|
||||
* The Vendor ID (t10_vend_id) must be set to "IBM".
|
||||
* The Product ID (prod_id) must be set either to "VDASD blkdev" for SCSI disks
|
||||
or "VOPTA blkdev" for a SCSI CD-ROM.
|
||||
* The Product Revision Level (prod_rev_lvl) must be set to "0001".
|
||||
* The Vendor Specific Information in the INQUIRY response (inq_vend_specific)
|
||||
must be set to the serial number. The serial number is available in the
|
||||
"usn" sysfs attribute.
|
||||
|
||||
After this step a LUN has to be assigned to each exported SCSI device. Some
|
||||
non-Linux initiator operating systems only accept LUN numbes that are
|
||||
multiples of 256 and require that the LUN addressing method is used.
|
||||
|
||||
@@ -1069,28 +1069,6 @@ static void handle_crq(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
static void ibmvstgt_get_product_id(const struct scst_tgt_dev *tgt_dev,
|
||||
char *buf, const int size)
|
||||
{
|
||||
WARN_ON(size != 16);
|
||||
|
||||
/*
|
||||
* AIX uses hardcoded device names. The AIX SCSI initiator even won't
|
||||
* work unless we use the names VDASD and VOPTA.
|
||||
*/
|
||||
switch (tgt_dev->dev->type) {
|
||||
case TYPE_DISK:
|
||||
memcpy(buf, "VDASD blkdev ", 16);
|
||||
break;
|
||||
case TYPE_ROM:
|
||||
memcpy(buf, "VOPTA blkdev ", 16);
|
||||
break;
|
||||
default:
|
||||
snprintf(buf, size, "(devtype %d) ", tgt_dev->dev->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract target, bus and LUN information from a 64-bit LUN in CPU-order.
|
||||
*/
|
||||
@@ -1236,12 +1214,8 @@ static struct scst_tgt_template ibmvstgt_template = {
|
||||
#else
|
||||
.sg_tablesize = SCSI_MAX_SG_SEGMENTS,
|
||||
#endif
|
||||
.vendor = "IBM ",
|
||||
.revision = "0001",
|
||||
.fake_aca = true,
|
||||
.get_product_id = ibmvstgt_get_product_id,
|
||||
.get_serial = ibmvstgt_get_serial,
|
||||
.get_vend_specific = ibmvstgt_get_serial,
|
||||
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
.default_trace_flags = DEFAULT_IBMVSTGT_TRACE_FLAGS,
|
||||
|
||||
+18
@@ -953,8 +953,18 @@ Each vdisk_fileio's device has the following attributes in
|
||||
|
||||
- o_direct - contains O_DIRECT status of this virtual device.
|
||||
|
||||
- inq_vend_specific - Vendor specific data that will be reported via
|
||||
either bytes 36..55 or bytes 96..256 of the INQUIRY response, depending
|
||||
on whether this field is <= 20 or > 20 bytes long.
|
||||
|
||||
- nv_cache - contains NV_CACHE status of this virtual device.
|
||||
|
||||
- prod_id - PRODUCT IDENTIFICATION as reported via the INQUIRY response.
|
||||
The default value for this field is the SCST device name.
|
||||
|
||||
- prod_rev_lvl - PRODUCT REVISION LEVEL as reported via the INQUIRY
|
||||
response. The default value for this field is " 300".
|
||||
|
||||
- thin_provisioned - contains thin provisioning status of this virtual
|
||||
device.
|
||||
|
||||
@@ -975,6 +985,10 @@ Each vdisk_fileio's device has the following attributes in
|
||||
that these first eight characters are unique or VMware will consider
|
||||
these devices as identical.
|
||||
|
||||
- t10_vend_id - Contents of the T10 VENDOR IDENTIFICATION field of the
|
||||
INQUIRY response. The default value for this field is "SCST_BIO" for
|
||||
vdisk_block devices and "SCST_FIO" for vdisk_fileio devices.
|
||||
|
||||
- usn - contains the virtual device's serial number of INQUIRY data. It
|
||||
is created at the device creation time based on the device name and
|
||||
scst_vdisk_ID scst_vdisk.ko module parameter for procfs (see below)
|
||||
@@ -986,6 +1000,10 @@ Each vdisk_fileio's device has the following attributes in
|
||||
rescan size of the backend file. It is useful if you changed it, for
|
||||
instance, if you resized it.
|
||||
|
||||
- vend_specific_id - Vendor specific ID as reported via the Device
|
||||
Identification VPD page (83h). The default value for this attribute
|
||||
is the value of the t10_dev_id attribute.
|
||||
|
||||
For example:
|
||||
|
||||
/sys/kernel/scst_tgt/devices/disk1
|
||||
|
||||
@@ -811,8 +811,18 @@ Each vdisk_fileio's device has the following attributes in
|
||||
|
||||
- o_direct - contains O_DIRECT status of this virtual device.
|
||||
|
||||
- inq_vend_specific - Vendor specific data that will be reported via
|
||||
either bytes 36..55 or bytes 96..256 of the INQUIRY response, depending
|
||||
on whether this field is <= 20 or > 20 bytes long.
|
||||
|
||||
- nv_cache - contains NV_CACHE status of this virtual device.
|
||||
|
||||
- prod_id - PRODUCT IDENTIFICATION as reported via the INQUIRY response.
|
||||
The default value for this field is the SCST device name.
|
||||
|
||||
- prod_rev_lvl - PRODUCT REVISION LEVEL as reported via the INQUIRY
|
||||
response. The default value for this field is " 300".
|
||||
|
||||
- thin_provisioned - contains thin provisioning status of this virtual
|
||||
device.
|
||||
|
||||
@@ -828,6 +838,10 @@ Each vdisk_fileio's device has the following attributes in
|
||||
created device at creation time based on the device name and
|
||||
scst_vdisk_ID scst_vdisk.ko module parameter (see below).
|
||||
|
||||
- t10_vend_id - Contents of the T10 VENDOR IDENTIFICATION field of the
|
||||
INQUIRY response. The default value for this field is "SCST_BIO" for
|
||||
vdisk_block devices and "SCST_FIO" for vdisk_fileio devices.
|
||||
|
||||
- usn - contains the virtual device's serial number of INQUIRY data. It
|
||||
is created at the device creation time based on the device name and
|
||||
scst_vdisk_ID scst_vdisk.ko module parameter (see below).
|
||||
@@ -838,6 +852,10 @@ Each vdisk_fileio's device has the following attributes in
|
||||
rescan size of the backend file. It is useful if you changed it, for
|
||||
instance, if you resized it.
|
||||
|
||||
- vend_specific_id - Vendor specific ID as reported via the Device
|
||||
Identification VPD page (83h). The default value for this attribute
|
||||
is the value of the t10_dev_id attribute.
|
||||
|
||||
For example:
|
||||
|
||||
/sys/kernel/scst_tgt/devices/disk1
|
||||
|
||||
@@ -1156,29 +1156,6 @@ struct scst_tgt_template {
|
||||
struct completion *tgtt_kobj_release_cmpl;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Optional vendor to be reported via the SCSI inquiry data. If NULL,
|
||||
* an SCST device handler specific default value will be used, e.g.
|
||||
* "SCST_FIO" for scst_vdisk file I/O.
|
||||
*/
|
||||
const char *vendor;
|
||||
|
||||
/*
|
||||
* Optional method that sets the product ID in [buf, buf+size) based
|
||||
* on the device type (byte 0 of the SCSI inquiry data, which contains
|
||||
* the peripheral qualifier in the highest three bits and the
|
||||
* peripheral device type in the lower five bits).
|
||||
*/
|
||||
void (*get_product_id)(const struct scst_tgt_dev *tgt_dev,
|
||||
char *buf, int size);
|
||||
|
||||
/*
|
||||
* Optional revision to be reported in the SCSI inquiry response. If
|
||||
* NULL, an SCST device handler specific default value will be used,
|
||||
* e.g. " 210" for scst_vdisk file I/O.
|
||||
*/
|
||||
const char *revision;
|
||||
|
||||
/*
|
||||
* Optional method that writes the serial number of a target device in
|
||||
* [buf, buf+size) and returns the number of bytes written.
|
||||
@@ -1192,13 +1169,6 @@ struct scst_tgt_template {
|
||||
*/
|
||||
int (*get_serial)(const struct scst_tgt_dev *tgt_dev, char *buf,
|
||||
int size);
|
||||
|
||||
/*
|
||||
* Optional method that writes the SCSI inquiry vendor-specific data in
|
||||
* [buf, buf+size) and returns the number of bytes written.
|
||||
*/
|
||||
int (*get_vend_specific)(const struct scst_tgt_dev *tgt_dev, char *buf,
|
||||
int size);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -82,6 +82,7 @@ static struct scst_trace_log vdisk_local_trace_tbl[] = {
|
||||
#define SCST_FIO_REV " 300"
|
||||
|
||||
#define MAX_USN_LEN (20+1) /* For '\0' */
|
||||
#define MAX_INQ_VEND_SPECIFIC_LEN (INQ_BUF_SZ - 96)
|
||||
|
||||
#define INQ_BUF_SZ 256
|
||||
#define EVPD 0x01
|
||||
@@ -175,11 +176,22 @@ struct scst_vdisk_dev {
|
||||
scst_mutex and suspended activities */
|
||||
uint16_t command_set_version;
|
||||
|
||||
/* All 4 protected by vdisk_serial_rwlock */
|
||||
/* All 14 protected by vdisk_serial_rwlock */
|
||||
unsigned int t10_vend_id_set:1; /* true if t10_vend_id manually set */
|
||||
/* true if vend_specific_id manually set */
|
||||
unsigned int vend_specific_id_set:1;
|
||||
unsigned int prod_id_set:1; /* true if prod_id manually set */
|
||||
unsigned int prod_rev_lvl_set:1; /* true if prod_rev_lvl manually set */
|
||||
unsigned int t10_dev_id_set:1; /* true if t10_dev_id manually set */
|
||||
unsigned int usn_set:1; /* true if usn manually set */
|
||||
char t10_vend_id[8 + 1];
|
||||
char vend_specific_id[32 + 1];
|
||||
char prod_id[16 + 1];
|
||||
char prod_rev_lvl[4 + 1];
|
||||
char t10_dev_id[16+8+2]; /* T10 device ID */
|
||||
char usn[MAX_USN_LEN];
|
||||
uint8_t inq_vend_specific[MAX_INQ_VEND_SPECIFIC_LEN];
|
||||
int inq_vend_specific_len;
|
||||
|
||||
struct scst_device *dev;
|
||||
struct list_head vdev_list_entry;
|
||||
@@ -319,6 +331,22 @@ static ssize_t vdev_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 vdev_sysfs_t10_vend_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_t10_vend_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_vend_specific_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_vend_specific_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_prod_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_prod_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_prod_rev_lvl_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_prod_rev_lvl_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_t10_dev_id_show(struct kobject *kobj,
|
||||
@@ -327,6 +355,10 @@ static ssize_t vdev_sysfs_usn_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_usn_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_inq_vend_specific_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_inq_vend_specific_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_zero_copy_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
|
||||
@@ -357,11 +389,28 @@ static struct kobj_attribute vdisk_filename_attr =
|
||||
__ATTR(filename, S_IRUGO, vdev_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 vdev_t10_vend_id_attr =
|
||||
__ATTR(t10_vend_id, S_IWUSR|S_IRUGO, vdev_sysfs_t10_vend_id_show,
|
||||
vdev_sysfs_t10_vend_id_store);
|
||||
static struct kobj_attribute vdev_vend_specific_id_attr =
|
||||
__ATTR(vend_specific_id, S_IWUSR|S_IRUGO,
|
||||
vdev_sysfs_vend_specific_id_show,
|
||||
vdev_sysfs_vend_specific_id_store);
|
||||
static struct kobj_attribute vdev_prod_id_attr =
|
||||
__ATTR(prod_id, S_IWUSR|S_IRUGO, vdev_sysfs_prod_id_show,
|
||||
vdev_sysfs_prod_id_store);
|
||||
static struct kobj_attribute vdev_prod_rev_lvl_attr =
|
||||
__ATTR(prod_rev_lvl, S_IWUSR|S_IRUGO, vdev_sysfs_prod_rev_lvl_show,
|
||||
vdev_sysfs_prod_rev_lvl_store);
|
||||
static struct kobj_attribute vdev_t10_dev_id_attr =
|
||||
__ATTR(t10_dev_id, S_IWUSR|S_IRUGO, vdev_sysfs_t10_dev_id_show,
|
||||
vdev_sysfs_t10_dev_id_store);
|
||||
static struct kobj_attribute vdev_usn_attr =
|
||||
__ATTR(usn, S_IWUSR|S_IRUGO, vdev_sysfs_usn_show, vdev_sysfs_usn_store);
|
||||
static struct kobj_attribute vdev_inq_vend_specific_attr =
|
||||
__ATTR(inq_vend_specific, S_IWUSR|S_IRUGO,
|
||||
vdev_sysfs_inq_vend_specific_show,
|
||||
vdev_sysfs_inq_vend_specific_store);
|
||||
static struct kobj_attribute vdev_zero_copy_attr =
|
||||
__ATTR(zero_copy, S_IRUGO, vdev_zero_copy_show, NULL);
|
||||
|
||||
@@ -381,8 +430,13 @@ static const struct attribute *vdisk_fileio_attrs[] = {
|
||||
&vdisk_removable_attr.attr,
|
||||
&vdisk_filename_attr.attr,
|
||||
&vdisk_resync_size_attr.attr,
|
||||
&vdev_t10_vend_id_attr.attr,
|
||||
&vdev_vend_specific_id_attr.attr,
|
||||
&vdev_prod_id_attr.attr,
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
&vdev_zero_copy_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
@@ -397,8 +451,13 @@ static const struct attribute *vdisk_blockio_attrs[] = {
|
||||
&vdisk_rotational_attr.attr,
|
||||
&vdisk_filename_attr.attr,
|
||||
&vdisk_resync_size_attr.attr,
|
||||
&vdev_t10_vend_id_attr.attr,
|
||||
&vdev_vend_specific_id_attr.attr,
|
||||
&vdev_prod_id_attr.attr,
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
&vdisk_tp_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
@@ -409,8 +468,13 @@ static const struct attribute *vdisk_nullio_attrs[] = {
|
||||
&vdisk_rd_only_attr.attr,
|
||||
&vdev_dummy_attr.attr,
|
||||
&vdisk_removable_attr.attr,
|
||||
&vdev_t10_vend_id_attr.attr,
|
||||
&vdev_vend_specific_id_attr.attr,
|
||||
&vdev_prod_id_attr.attr,
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
&vdisk_rotational_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
@@ -418,8 +482,13 @@ static const struct attribute *vdisk_nullio_attrs[] = {
|
||||
static const struct attribute *vcdrom_attrs[] = {
|
||||
&vdev_size_attr.attr,
|
||||
&vcdrom_filename_attr.attr,
|
||||
&vdev_t10_vend_id_attr.attr,
|
||||
&vdev_vend_specific_id_attr.attr,
|
||||
&vdev_prod_id_attr.attr,
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -428,7 +497,10 @@ static const struct attribute *vcdrom_attrs[] = {
|
||||
/* Protects vdisks addition/deletion and related activities, like search */
|
||||
static DEFINE_MUTEX(scst_vdisk_mutex);
|
||||
|
||||
/* Protects devices t10_dev_id and usn */
|
||||
/*
|
||||
* Protects the device attributes t10_vend_id, vend_specific_id, prod_id,
|
||||
* prod_rev_lvl, t10_dev_id, usn and inq_vend_specific.
|
||||
*/
|
||||
static DEFINE_RWLOCK(vdisk_serial_rwlock);
|
||||
|
||||
/* Protected by scst_vdisk_mutex */
|
||||
@@ -2235,6 +2307,28 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a zero-terminated string into a fixed-size byte array and fill the
|
||||
* trailing bytes with @fill_byte.
|
||||
*/
|
||||
static void scst_copy_and_fill_b(char *dst, const char *src, int len,
|
||||
uint8_t fill_byte)
|
||||
{
|
||||
int cpy_len = min_t(int, strlen(src), len);
|
||||
|
||||
memcpy(dst, src, cpy_len);
|
||||
memset(dst + cpy_len, fill_byte, len - cpy_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a zero-terminated string into a fixed-size char array and fill the
|
||||
* trailing characters with spaces.
|
||||
*/
|
||||
static void scst_copy_and_fill(char *dst, const char *src, int len)
|
||||
{
|
||||
scst_copy_and_fill_b(dst, src, len, ' ');
|
||||
}
|
||||
|
||||
static enum compl_status_e vdisk_exec_write_same(struct vdisk_cmd_params *p)
|
||||
{
|
||||
struct scst_cmd *cmd = p->cmd;
|
||||
@@ -2445,16 +2539,10 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
|
||||
/* T10 vendor identifier field format (faked) */
|
||||
buf[num + 0] = 0x2; /* ASCII */
|
||||
buf[num + 1] = 0x1; /* Vendor ID */
|
||||
if (cmd->tgtt->vendor)
|
||||
memcpy(&buf[num + 4], cmd->tgtt->vendor, 8);
|
||||
else if (virt_dev->blockio)
|
||||
memcpy(&buf[num + 4], SCST_BIO_VENDOR, 8);
|
||||
else
|
||||
memcpy(&buf[num + 4], SCST_FIO_VENDOR, 8);
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
i = strlen(virt_dev->t10_dev_id);
|
||||
memcpy(&buf[num + 12], virt_dev->t10_dev_id, i);
|
||||
scst_copy_and_fill(&buf[num + 4], virt_dev->t10_vend_id, 8);
|
||||
i = strlen(virt_dev->vend_specific_id);
|
||||
memcpy(&buf[num + 12], virt_dev->vend_specific_id, i);
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
buf[num + 3] = 8 + i;
|
||||
@@ -2608,7 +2696,7 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
|
||||
goto out_put;
|
||||
}
|
||||
} else {
|
||||
int len, num;
|
||||
int num;
|
||||
|
||||
if (cmd->cdb[2] != 0) {
|
||||
TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
|
||||
@@ -2628,37 +2716,30 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
|
||||
buf[6] = 0x10; /* MultiP 1 */
|
||||
buf[7] = 2; /* CMDQUE 1, BQue 0 => commands queuing supported */
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
|
||||
/*
|
||||
* 8 byte ASCII Vendor Identification of the target
|
||||
* - left aligned.
|
||||
*/
|
||||
if (cmd->tgtt->vendor)
|
||||
memcpy(&buf[8], cmd->tgtt->vendor, 8);
|
||||
else if (virt_dev->blockio)
|
||||
memcpy(&buf[8], SCST_BIO_VENDOR, 8);
|
||||
else
|
||||
memcpy(&buf[8], SCST_FIO_VENDOR, 8);
|
||||
scst_copy_and_fill(&buf[8], virt_dev->t10_vend_id, 8);
|
||||
|
||||
/*
|
||||
* 16 byte ASCII Product Identification of the target - left
|
||||
* aligned.
|
||||
*/
|
||||
memset(&buf[16], ' ', 16);
|
||||
if (cmd->tgtt->get_product_id)
|
||||
cmd->tgtt->get_product_id(cmd->tgt_dev, &buf[16], 16);
|
||||
else {
|
||||
len = min_t(size_t, strlen(virt_dev->name), 16);
|
||||
memcpy(&buf[16], virt_dev->name, len);
|
||||
}
|
||||
scst_copy_and_fill(&buf[16], virt_dev->prod_id, 16);
|
||||
|
||||
/*
|
||||
* 4 byte ASCII Product Revision Level of the target - left
|
||||
* aligned.
|
||||
*/
|
||||
if (cmd->tgtt->revision)
|
||||
memcpy(&buf[32], cmd->tgtt->revision, 4);
|
||||
else
|
||||
memcpy(&buf[32], SCST_FIO_REV, 4);
|
||||
scst_copy_and_fill(&buf[32], virt_dev->prod_rev_lvl, 4);
|
||||
|
||||
/* Vendor specific information. */
|
||||
if (virt_dev->inq_vend_specific_len <= 20)
|
||||
memcpy(&buf[36], virt_dev->inq_vend_specific,
|
||||
virt_dev->inq_vend_specific_len);
|
||||
|
||||
/** Version descriptors **/
|
||||
|
||||
@@ -2699,13 +2780,14 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
|
||||
}
|
||||
|
||||
/* Vendor specific information. */
|
||||
if (cmd->tgtt->get_vend_specific) {
|
||||
/* Skip to byte 96. */
|
||||
num = 96 - 58;
|
||||
num += cmd->tgtt->get_vend_specific(cmd->tgt_dev,
|
||||
&buf[96], INQ_BUF_SZ - 96);
|
||||
if (virt_dev->inq_vend_specific_len > 20) {
|
||||
memcpy(&buf[96], virt_dev->inq_vend_specific,
|
||||
virt_dev->inq_vend_specific_len);
|
||||
num = 96 - 58 + virt_dev->inq_vend_specific_len;
|
||||
}
|
||||
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
buf[4] += num;
|
||||
resp_len = buf[4] + 5;
|
||||
}
|
||||
@@ -4640,6 +4722,20 @@ static int vdev_create(struct scst_dev_type *devt,
|
||||
"%llx-%s", dev_id_num, virt_dev->name);
|
||||
TRACE_DBG("t10_dev_id %s", virt_dev->t10_dev_id);
|
||||
|
||||
sprintf(virt_dev->t10_vend_id, "%.*s",
|
||||
(int)(sizeof(virt_dev->t10_vend_id) - 1),
|
||||
virt_dev->blockio ? SCST_BIO_VENDOR : SCST_FIO_VENDOR);
|
||||
|
||||
sprintf(virt_dev->vend_specific_id, "%.*s",
|
||||
(int)(sizeof(virt_dev->vend_specific_id) - 1),
|
||||
virt_dev->t10_dev_id);
|
||||
|
||||
sprintf(virt_dev->prod_id, "%.*s", (int)(sizeof(virt_dev->prod_id) - 1),
|
||||
virt_dev->name);
|
||||
|
||||
sprintf(virt_dev->prod_rev_lvl, "%.*s",
|
||||
(int)(sizeof(virt_dev->prod_rev_lvl) - 1), SCST_FIO_REV);
|
||||
|
||||
scnprintf(virt_dev->usn, sizeof(virt_dev->usn), "%llx", dev_id_num);
|
||||
TRACE_DBG("usn %s", virt_dev->usn);
|
||||
|
||||
@@ -5739,6 +5835,239 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_t10_vend_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
char *p;
|
||||
int res, len;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
p = memchr(buf, '\n', count);
|
||||
len = p ? p - buf : count;
|
||||
|
||||
if (len >= sizeof(virt_dev->t10_vend_id)) {
|
||||
PRINT_ERROR("T10 vendor id is too long (max %zd characters)",
|
||||
sizeof(virt_dev->t10_vend_id));
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_lock(&vdisk_serial_rwlock);
|
||||
sprintf(virt_dev->t10_vend_id, "%.*s", len, buf);
|
||||
virt_dev->t10_vend_id_set = 1;
|
||||
write_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_t10_vend_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int pos;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
pos = sprintf(buf, "%s\n%s", virt_dev->t10_vend_id,
|
||||
virt_dev->t10_vend_id_set ? SCST_SYSFS_KEY_MARK "\n" :
|
||||
"");
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_vend_specific_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
char *p;
|
||||
int res, len;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
p = memchr(buf, '\n', count);
|
||||
len = p ? p - buf : count;
|
||||
|
||||
if (len >= sizeof(virt_dev->vend_specific_id)) {
|
||||
PRINT_ERROR("Vendor specific id is too long (max %zd"
|
||||
" characters)",
|
||||
sizeof(virt_dev->vend_specific_id) - 1);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_lock(&vdisk_serial_rwlock);
|
||||
sprintf(virt_dev->vend_specific_id, "%.*s", len, buf);
|
||||
virt_dev->vend_specific_id_set = 1;
|
||||
write_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_vend_specific_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int pos;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
pos = sprintf(buf, "%s\n%s", virt_dev->vend_specific_id,
|
||||
virt_dev->vend_specific_id_set ?
|
||||
SCST_SYSFS_KEY_MARK "\n" : "");
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_prod_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
char *p;
|
||||
int res, len;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
p = memchr(buf, '\n', count);
|
||||
len = p ? p - buf : count;
|
||||
|
||||
if (len >= sizeof(virt_dev->prod_id)) {
|
||||
PRINT_ERROR("Product id is too long (max %zd characters)",
|
||||
sizeof(virt_dev->prod_id));
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_lock(&vdisk_serial_rwlock);
|
||||
sprintf(virt_dev->prod_id, "%.*s", len, buf);
|
||||
virt_dev->prod_id_set = 1;
|
||||
write_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_prod_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int pos;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
pos = sprintf(buf, "%s\n%s", virt_dev->prod_id,
|
||||
virt_dev->prod_id_set ? SCST_SYSFS_KEY_MARK "\n" : "");
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_prod_rev_lvl_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
char *p;
|
||||
int res, len;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
p = memchr(buf, '\n', count);
|
||||
len = p ? p - buf : count;
|
||||
|
||||
if (len >= sizeof(virt_dev->prod_rev_lvl)) {
|
||||
PRINT_ERROR("Product revision level is too long (max %zd"
|
||||
" characters)",
|
||||
sizeof(virt_dev->prod_rev_lvl));
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_lock(&vdisk_serial_rwlock);
|
||||
sprintf(virt_dev->prod_rev_lvl, "%.*s", len, buf);
|
||||
virt_dev->prod_rev_lvl_set = 1;
|
||||
write_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_prod_rev_lvl_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int pos;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
pos = sprintf(buf, "%s\n%s", virt_dev->prod_rev_lvl,
|
||||
virt_dev->prod_rev_lvl_set ? SCST_SYSFS_KEY_MARK "\n" :
|
||||
"");
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
@@ -5879,6 +6208,55 @@ static ssize_t vdev_sysfs_usn_show(struct kobject *kobj,
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_inq_vend_specific_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
char *p;
|
||||
int res = -EINVAL, len;
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
p = memchr(buf, '\n', count);
|
||||
len = p ? p - buf : count;
|
||||
if (len > MAX_INQ_VEND_SPECIFIC_LEN)
|
||||
goto out;
|
||||
|
||||
write_lock(&vdisk_serial_rwlock);
|
||||
memcpy(virt_dev->inq_vend_specific, buf, len);
|
||||
virt_dev->inq_vend_specific_len = len;
|
||||
write_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_inq_vend_specific_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int pos;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
pos = snprintf(buf, PAGE_SIZE, "%.*s\n%s",
|
||||
virt_dev->inq_vend_specific_len,
|
||||
virt_dev->inq_vend_specific,
|
||||
virt_dev->inq_vend_specific_len ?
|
||||
SCST_SYSFS_KEY_MARK "\n" : "");
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_zero_copy_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user