diff options
author | Roland Dreier <roland@purestorage.com> | 2011-07-05 16:34:52 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-07-22 05:37:47 -0400 |
commit | e22a7f075226c51f3f71b922e9eeb4f99fac1475 (patch) | |
tree | e0a04f974153136eafe13793ee59be58c37c5ffc | |
parent | b2eb705e00a9b9a9b3122192a7ab3e9058f0c48a (diff) |
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 <roland@purestorage.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_cdb.c | 17 | ||||
-rw-r--r-- | drivers/target/target_core_configfs.c | 4 | ||||
-rw-r--r-- | drivers/target/target_core_device.c | 13 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.c | 3 | ||||
-rw-r--r-- | include/target/target_core_base.h | 1 | ||||
-rw-r--r-- | include/target/target_core_device.h | 1 | ||||
-rw-r--r-- | include/target/target_core_transport.h | 2 |
7 files changed, 41 insertions, 0 deletions
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) | |||
535 | return 0; | 535 | return 0; |
536 | } | 536 | } |
537 | 537 | ||
538 | /* Block Device Characteristics VPD page */ | ||
539 | static int | ||
540 | target_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) | ||
541 | { | ||
542 | struct se_device *dev = cmd->se_dev; | ||
543 | |||
544 | buf[0] = dev->transport->get_device_type(dev); | ||
545 | buf[3] = 0x3c; | ||
546 | |||
547 | if (cmd->data_length >= 5 && | ||
548 | dev->se_sub_dev->se_dev_attrib.is_nonrot) | ||
549 | buf[5] = 1; | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
538 | /* Thin Provisioning VPD */ | 554 | /* Thin Provisioning VPD */ |
539 | static int | 555 | static int |
540 | target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) | 556 | target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) |
@@ -599,6 +615,7 @@ static struct { | |||
599 | { .page = 0x83, .emulate = target_emulate_evpd_83 }, | 615 | { .page = 0x83, .emulate = target_emulate_evpd_83 }, |
600 | { .page = 0x86, .emulate = target_emulate_evpd_86 }, | 616 | { .page = 0x86, .emulate = target_emulate_evpd_86 }, |
601 | { .page = 0xb0, .emulate = target_emulate_evpd_b0 }, | 617 | { .page = 0xb0, .emulate = target_emulate_evpd_b0 }, |
618 | { .page = 0xb1, .emulate = target_emulate_evpd_b1 }, | ||
602 | { .page = 0xb2, .emulate = target_emulate_evpd_b2 }, | 619 | { .page = 0xb2, .emulate = target_emulate_evpd_b2 }, |
603 | }; | 620 | }; |
604 | 621 | ||
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); | |||
698 | DEF_DEV_ATTRIB(enforce_pr_isids); | 698 | DEF_DEV_ATTRIB(enforce_pr_isids); |
699 | SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); | 699 | SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); |
700 | 700 | ||
701 | DEF_DEV_ATTRIB(is_nonrot); | ||
702 | SE_DEV_ATTR(is_nonrot, S_IRUGO | S_IWUSR); | ||
703 | |||
701 | DEF_DEV_ATTRIB_RO(hw_block_size); | 704 | DEF_DEV_ATTRIB_RO(hw_block_size); |
702 | SE_DEV_ATTR_RO(hw_block_size); | 705 | SE_DEV_ATTR_RO(hw_block_size); |
703 | 706 | ||
@@ -746,6 +749,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { | |||
746 | &target_core_dev_attrib_emulate_tpu.attr, | 749 | &target_core_dev_attrib_emulate_tpu.attr, |
747 | &target_core_dev_attrib_emulate_tpws.attr, | 750 | &target_core_dev_attrib_emulate_tpws.attr, |
748 | &target_core_dev_attrib_enforce_pr_isids.attr, | 751 | &target_core_dev_attrib_enforce_pr_isids.attr, |
752 | &target_core_dev_attrib_is_nonrot.attr, | ||
749 | &target_core_dev_attrib_hw_block_size.attr, | 753 | &target_core_dev_attrib_hw_block_size.attr, |
750 | &target_core_dev_attrib_block_size.attr, | 754 | &target_core_dev_attrib_block_size.attr, |
751 | &target_core_dev_attrib_hw_max_sectors.attr, | 755 | &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( | |||
853 | dev->se_sub_dev->se_dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; | 853 | dev->se_sub_dev->se_dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; |
854 | dev->se_sub_dev->se_dev_attrib.emulate_alua = DA_EMULATE_ALUA; | 854 | dev->se_sub_dev->se_dev_attrib.emulate_alua = DA_EMULATE_ALUA; |
855 | dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; | 855 | dev->se_sub_dev->se_dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; |
856 | dev->se_sub_dev->se_dev_attrib.is_nonrot = DA_IS_NONROT; | ||
856 | /* | 857 | /* |
857 | * The TPU=1 and TPWS=1 settings will be set in TCM/IBLOCK | 858 | * The TPU=1 and TPWS=1 settings will be set in TCM/IBLOCK |
858 | * iblock_create_virtdevice() from struct queue_limits values | 859 | * 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) | |||
1117 | return 0; | 1118 | return 0; |
1118 | } | 1119 | } |
1119 | 1120 | ||
1121 | int se_dev_set_is_nonrot(struct se_device *dev, int flag) | ||
1122 | { | ||
1123 | if ((flag != 0) && (flag != 1)) { | ||
1124 | printk(KERN_ERR "Illegal value %d\n", flag); | ||
1125 | return -EINVAL; | ||
1126 | } | ||
1127 | dev->se_sub_dev->se_dev_attrib.is_nonrot = flag; | ||
1128 | printk(KERN_INFO "dev[%p]: SE Device is_nonrot bit: %d\n", | ||
1129 | dev, flag); | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1120 | /* | 1133 | /* |
1121 | * Note, this can only be called on unexported SE Device Object. | 1134 | * Note, this can only be called on unexported SE Device Object. |
1122 | */ | 1135 | */ |
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( | |||
196 | " disabled by default\n"); | 196 | " disabled by default\n"); |
197 | } | 197 | } |
198 | 198 | ||
199 | if (blk_queue_nonrot(q)) | ||
200 | dev->se_sub_dev->se_dev_attrib.is_nonrot = 1; | ||
201 | |||
199 | return dev; | 202 | return dev; |
200 | 203 | ||
201 | failed: | 204 | 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 { | |||
661 | int emulate_reservations; | 661 | int emulate_reservations; |
662 | int emulate_alua; | 662 | int emulate_alua; |
663 | int enforce_pr_isids; | 663 | int enforce_pr_isids; |
664 | int is_nonrot; | ||
664 | u32 hw_block_size; | 665 | u32 hw_block_size; |
665 | u32 block_size; | 666 | u32 block_size; |
666 | u32 hw_max_sectors; | 667 | 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); | |||
39 | extern int se_dev_set_emulate_tpu(struct se_device *, int); | 39 | extern int se_dev_set_emulate_tpu(struct se_device *, int); |
40 | extern int se_dev_set_emulate_tpws(struct se_device *, int); | 40 | extern int se_dev_set_emulate_tpws(struct se_device *, int); |
41 | extern int se_dev_set_enforce_pr_isids(struct se_device *, int); | 41 | extern int se_dev_set_enforce_pr_isids(struct se_device *, int); |
42 | extern int se_dev_set_is_nonrot(struct se_device *, int); | ||
42 | extern int se_dev_set_queue_depth(struct se_device *, u32); | 43 | extern int se_dev_set_queue_depth(struct se_device *, u32); |
43 | extern int se_dev_set_max_sectors(struct se_device *, u32); | 44 | extern int se_dev_set_max_sectors(struct se_device *, u32); |
44 | extern int se_dev_set_optimal_sectors(struct se_device *, u32); | 45 | 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 @@ | |||
101 | #define DA_ENFORCE_PR_ISIDS 1 | 101 | #define DA_ENFORCE_PR_ISIDS 1 |
102 | #define DA_STATUS_MAX_SECTORS_MIN 16 | 102 | #define DA_STATUS_MAX_SECTORS_MIN 16 |
103 | #define DA_STATUS_MAX_SECTORS_MAX 8192 | 103 | #define DA_STATUS_MAX_SECTORS_MAX 8192 |
104 | /* By default don't report non-rotating (solid state) medium */ | ||
105 | #define DA_IS_NONROT 0 | ||
104 | 106 | ||
105 | #define SE_MODE_PAGE_BUF 512 | 107 | #define SE_MODE_PAGE_BUF 512 |
106 | 108 | ||