From e22a7f075226c51f3f71b922e9eeb4f99fac1475 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 5 Jul 2011 13:34:52 -0700 Subject: [PATCH] target: Implement Block Device Characteristics VPD page Implement page B1h, Block Device Characteristics, so that we can report a medium rotation rate of 1 (non-rotating / solid state) if the is_nonrot device attribute is set; we update the iblock backend to set this attribute if the underlying Linux block device has its nonrot flag set. Signed-off-by: Roland Dreier Reviewed-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_cdb.c | 17 +++++++++++++++++ drivers/target/target_core_configfs.c | 4 ++++ drivers/target/target_core_device.c | 13 +++++++++++++ drivers/target/target_core_iblock.c | 3 +++ include/target/target_core_base.h | 1 + include/target/target_core_device.h | 1 + include/target/target_core_transport.h | 2 ++ 7 files changed, 41 insertions(+) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 1157e0c6dba6..432253034de0 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -535,6 +535,22 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) return 0; } +/* Block Device Characteristics VPD page */ +static int +target_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) +{ + struct se_device *dev = cmd->se_dev; + + buf[0] = dev->transport->get_device_type(dev); + buf[3] = 0x3c; + + if (cmd->data_length >= 5 && + dev->se_sub_dev->se_dev_attrib.is_nonrot) + buf[5] = 1; + + return 0; +} + /* Thin Provisioning VPD */ static int target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) @@ -599,6 +615,7 @@ static struct { { .page = 0x83, .emulate = target_emulate_evpd_83 }, { .page = 0x86, .emulate = target_emulate_evpd_86 }, { .page = 0xb0, .emulate = target_emulate_evpd_b0 }, + { .page = 0xb1, .emulate = target_emulate_evpd_b1 }, { .page = 0xb2, .emulate = target_emulate_evpd_b2 }, }; diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 8d2aba51fc8b..6b00810b8dcb 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -698,6 +698,9 @@ SE_DEV_ATTR(emulate_tpws, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(enforce_pr_isids); SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(is_nonrot); +SE_DEV_ATTR(is_nonrot, S_IRUGO | S_IWUSR); + DEF_DEV_ATTRIB_RO(hw_block_size); SE_DEV_ATTR_RO(hw_block_size); @@ -746,6 +749,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { &target_core_dev_attrib_emulate_tpu.attr, &target_core_dev_attrib_emulate_tpws.attr, &target_core_dev_attrib_enforce_pr_isids.attr, + &target_core_dev_attrib_is_nonrot.attr, &target_core_dev_attrib_hw_block_size.attr, &target_core_dev_attrib_block_size.attr, &target_core_dev_attrib_hw_max_sectors.attr, diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index f13e2941936c..440e6b69d47b 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -853,6 +853,7 @@ void se_dev_set_default_attribs( dev->se_sub_dev->se_dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; dev->se_sub_dev->se_dev_attrib.emulate_alua = DA_EMULATE_ALUA; dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; + dev->se_sub_dev->se_dev_attrib.is_nonrot = DA_IS_NONROT; /* * The TPU=1 and TPWS=1 settings will be set in TCM/IBLOCK * iblock_create_virtdevice() from struct queue_limits values @@ -1117,6 +1118,18 @@ int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) return 0; } +int se_dev_set_is_nonrot(struct se_device *dev, int flag) +{ + if ((flag != 0) && (flag != 1)) { + printk(KERN_ERR "Illegal value %d\n", flag); + return -EINVAL; + } + dev->se_sub_dev->se_dev_attrib.is_nonrot = flag; + printk(KERN_INFO "dev[%p]: SE Device is_nonrot bit: %d\n", + dev, flag); + return 0; +} + /* * Note, this can only be called on unexported SE Device Object. */ diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 160c484fd3da..392e75fb1087 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -196,6 +196,9 @@ static struct se_device *iblock_create_virtdevice( " disabled by default\n"); } + if (blk_queue_nonrot(q)) + dev->se_sub_dev->se_dev_attrib.is_nonrot = 1; + return dev; failed: diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index cd163dd94cd4..81deb399bf6a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -661,6 +661,7 @@ struct se_dev_attrib { int emulate_reservations; int emulate_alua; int enforce_pr_isids; + int is_nonrot; u32 hw_block_size; u32 block_size; u32 hw_max_sectors; diff --git a/include/target/target_core_device.h b/include/target/target_core_device.h index 96586cc94984..f3b6ae655454 100644 --- a/include/target/target_core_device.h +++ b/include/target/target_core_device.h @@ -39,6 +39,7 @@ extern int se_dev_set_emulate_tas(struct se_device *, int); extern int se_dev_set_emulate_tpu(struct se_device *, int); extern int se_dev_set_emulate_tpws(struct se_device *, int); extern int se_dev_set_enforce_pr_isids(struct se_device *, int); +extern int se_dev_set_is_nonrot(struct se_device *, int); extern int se_dev_set_queue_depth(struct se_device *, u32); extern int se_dev_set_max_sectors(struct se_device *, u32); extern int se_dev_set_optimal_sectors(struct se_device *, u32); diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index 2aae76412377..b27ce1af698b 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h @@ -101,6 +101,8 @@ #define DA_ENFORCE_PR_ISIDS 1 #define DA_STATUS_MAX_SECTORS_MIN 16 #define DA_STATUS_MAX_SECTORS_MAX 8192 +/* By default don't report non-rotating (solid state) medium */ +#define DA_IS_NONROT 0 #define SE_MODE_PAGE_BUF 512 -- 2.34.1