[Devel] [PATCH rh7] target/sbc: Add LBPRZ attribute + control CDB emulation
Andrei Vagin
avagin at openvz.org
Thu Feb 15 05:00:57 MSK 2018
[This sender failed our fraud detection checks and may not be who they appear to be. Learn about spoofing at http://aka.ms/LearnAboutSpoofing]
From: Jamie Pocas <jamie.pocas at emc.com>
This patch is back-ported from the upstream kernel:
ML e6f41633cb79b55ead84b023c02035322c7827e7
We need it to support the WRITE_SAME UNMAP command.
This change sets the LBPRZ flag in EVPD page b2h and READ CAPACITY (16)
based on a new unmap_zeroes_data device attribute. This flag is set
automatically for iblock based on underlying block device queue's
discard_zeroes_data flag.
Signed-off-by: Jamie Pocas <jamie.pocas at emc.com>
Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org>
Signed-off-by: Andrei Vagin <avagin at openvz.org>
---
drivers/target/target_core_device.c | 34 +++++++++++++++++++++++++++
drivers/target/target_core_file.c | 1 +
drivers/target/target_core_iblock.c | 1 +
drivers/target/target_core_rd.c | 1 +
drivers/target/target_core_sbc.c | 11 ++++++++-
drivers/target/target_core_spc.c | 12 ++++++++++
include/target/target_core_backend.h | 1 +
include/target/target_core_backend_configfs.h | 2 ++
include/target/target_core_base.h | 3 +++
9 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index c928bd1..e561823 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -708,6 +708,38 @@ int se_dev_set_unmap_granularity_alignment(
}
EXPORT_SYMBOL(se_dev_set_unmap_granularity_alignment);
+int se_dev_set_unmap_zeroes_data(
+ struct se_device *dev,
+ u32 flag)
+{
+ struct se_dev_attrib *da = &dev->dev_attrib;
+
+ if (flag > 1)
+ return -EINVAL;
+
+ if (da->da_dev->export_count) {
+ pr_err("dev[%p]: Unable to change SE Device"
+ " unmap_zeroes_data while export_count is %d\n",
+ da->da_dev, da->da_dev->export_count);
+ return -EINVAL;
+ }
+ /*
+ * We expect this value to be non-zero when generic Block Layer
+ * Discard supported is detected iblock_configure_device().
+ */
+ if (flag && !da->max_unmap_block_desc_count) {
+ pr_err("dev[%p]: Thin Provisioning LBPRZ will not be set"
+ " because max_unmap_block_desc_count is zero\n",
+ da->da_dev);
+ return -ENOSYS;
+ }
+ da->unmap_zeroes_data = flag;
+ pr_debug("dev[%p]: SE Device Thin Provisioning LBPRZ bit: %d\n",
+ da->da_dev, flag);
+ return 0;
+}
+EXPORT_SYMBOL(se_dev_set_unmap_zeroes_data);
+
int se_dev_set_max_write_same_len(
struct se_device *dev,
u32 max_write_same_len)
@@ -1534,6 +1566,8 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
dev->dev_attrib.unmap_granularity_alignment =
DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT;
+ dev->dev_attrib.unmap_zeroes_data =
+ DA_UNMAP_ZEROES_DATA_DEFAULT;
dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
xcopy_lun = &dev->xcopy_lun;
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 350a3b6..de165f5 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -1008,6 +1008,7 @@ static struct configfs_attribute *fileio_backend_dev_attrs[] = {
&fileio_dev_attrib_max_unmap_block_desc_count.attr,
&fileio_dev_attrib_unmap_granularity.attr,
&fileio_dev_attrib_unmap_granularity_alignment.attr,
+ &fileio_dev_attrib_unmap_zeroes_data.attr,
&fileio_dev_attrib_max_write_same_len.attr,
NULL,
};
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 60ff434..b451916 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -895,6 +895,7 @@ static struct configfs_attribute *iblock_backend_dev_attrs[] = {
&iblock_dev_attrib_max_unmap_block_desc_count.attr,
&iblock_dev_attrib_unmap_granularity.attr,
&iblock_dev_attrib_unmap_granularity_alignment.attr,
+ &iblock_dev_attrib_unmap_zeroes_data.attr,
&iblock_dev_attrib_max_write_same_len.attr,
NULL,
};
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index d27d588..fa35bcf 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -664,6 +664,7 @@ static struct configfs_attribute *rd_mcp_backend_dev_attrs[] = {
&rd_mcp_dev_attrib_max_unmap_block_desc_count.attr,
&rd_mcp_dev_attrib_unmap_granularity.attr,
&rd_mcp_dev_attrib_unmap_granularity_alignment.attr,
+ &rd_mcp_dev_attrib_unmap_zeroes_data.attr,
&rd_mcp_dev_attrib_max_write_same_len.attr,
NULL,
};
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 99fb25f..009385f 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -131,9 +131,18 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
* Set Thin Provisioning Enable bit following sbc3r22 in section
* READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
*/
- if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws)
+ if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) {
buf[14] |= 0x80;
+
+ /*
+ * LBPRZ signifies that zeroes will be read back from an LBA after
+ * an UNMAP or WRITE SAME w/ unmap bit (sbc3r36 5.16.2)
+ */
+ if (dev->dev_attrib.unmap_zeroes_data)
+ buf[14] |= 0x40;
+ }
+
rbuf = transport_kmap_data_sg(cmd);
if (rbuf) {
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 6c8bd6b..2dd2887 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -636,6 +636,18 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
if (dev->dev_attrib.emulate_tpws != 0)
buf[5] |= 0x40 | 0x20;
+ /*
+ * The unmap_zeroes_data set means that the underlying device supports
+ * REQ_DISCARD and has the discard_zeroes_data bit set. This satisfies
+ * the SBC requirements for LBPRZ, meaning that a subsequent read
+ * will return zeroes after an UNMAP or WRITE SAME (16) to an LBA
+ * See sbc4r36 6.6.4.
+ */
+ if (((dev->dev_attrib.emulate_tpu != 0) ||
+ (dev->dev_attrib.emulate_tpws != 0)) &&
+ (dev->dev_attrib.unmap_zeroes_data != 0))
+ buf[5] |= 0x04;
+
return 0;
}
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index f5f1f8d..4d5c23a 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -119,6 +119,7 @@ int se_dev_set_max_unmap_lba_count(struct se_device *, u32);
int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
int se_dev_set_unmap_granularity(struct se_device *, u32);
int se_dev_set_unmap_granularity_alignment(struct se_device *, u32);
+int se_dev_set_unmap_zeroes_data(struct se_device *dev, u32 flag);
int se_dev_set_max_write_same_len(struct se_device *, u32);
int se_dev_set_emulate_model_alias(struct se_device *, int);
int se_dev_set_emulate_dpo(struct se_device *, int);
diff --git a/include/target/target_core_backend_configfs.h b/include/target/target_core_backend_configfs.h
index 186f7a9..ea9252a 100644
--- a/include/target/target_core_backend_configfs.h
+++ b/include/target/target_core_backend_configfs.h
@@ -112,6 +112,8 @@ static struct target_backend_dev_attrib_attribute _backend##_dev_attrib_##_name
TB_DEV_ATTR(_backend, unmap_granularity, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, unmap_granularity_alignment); \
TB_DEV_ATTR(_backend, unmap_granularity_alignment, S_IRUGO | S_IWUSR); \
+ DEF_TB_DEV_ATTRIB(_backend, unmap_zeroes_data); \
+ TB_DEV_ATTR(_backend, unmap_zeroes_data, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, max_write_same_len); \
TB_DEV_ATTR(_backend, max_write_same_len, S_IRUGO | S_IWUSR);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index e94b784..47f7bf5 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -75,6 +75,8 @@
#define DA_UNMAP_GRANULARITY_DEFAULT 0
/* Default unmap_granularity_alignment */
#define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0
+/* Default unmap_zeroes_data */
+#define DA_UNMAP_ZEROES_DATA_DEFAULT 0
/* Default max_write_same_len, disabled by default */
#define DA_MAX_WRITE_SAME_LEN 0
/* Use a model alias based on the configfs backend device name */
@@ -678,6 +680,7 @@ struct se_dev_attrib {
int emulate_tas;
int emulate_tpu;
int emulate_tpws;
+ int unmap_zeroes_data;
int emulate_caw;
int emulate_3pc;
int pi_prot_format;
--
1.8.3.1
More information about the Devel
mailing list