* [PATCH-v2 0/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation
@ 2012-11-15 20:13 Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 1/3] target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops Nicholas A. Bellinger
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 20:13 UTC (permalink / raw)
To: target-devel; +Cc: linux-scsi, linux-kernel, Nicholas Bellinger
From: Nicholas Bellinger <nab@linux-iscsi.org>
Hi folks,
This -v2 series for-3.8 adds support for proper WRITE_SAME w/ UNMAP=0 emulation
for IBLOCK device backends to follow MKP's WRITE_SAME client patches that have
been merged in v3.7-rc1.
Currently it uses a bio_add_page() call for each sector in order to allow
scatterlist w/ page offsets to work, as blkdev_issue_write_same() currently
assumes underlying hw support + zero page offset.
This -v2 includes the following changes requested by hch to v1:
- Drop the SCF_WRITE_SAME_DISCARD flag
- Add sbc_ops handler specific to WRITE_SAME w/ UNMAP=1
- Move max_write_same_len sanity check from IBLOCK into sbc code
- Add SGL check for single sector in iblock_execute_write_same()
I'm testing these changes now against iscsi-target + tcm_loop ports on
target-pending/for-next. Please review.
Thanks!
--nab
Nicholas Bellinger (3):
target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops
target: Add/check max_write_same_len device attribute + update block
limits VPD
target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support
drivers/target/target_core_configfs.c | 4 ++
drivers/target/target_core_device.c | 11 ++++
drivers/target/target_core_iblock.c | 91 ++++++++++++++++++++++++++++++---
drivers/target/target_core_internal.h | 1 +
drivers/target/target_core_sbc.c | 59 +++++++++++----------
drivers/target/target_core_spc.c | 8 +++-
include/target/target_core_backend.h | 1 +
include/target/target_core_base.h | 3 +
8 files changed, 142 insertions(+), 36 deletions(-)
--
1.7.2.5
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH-v2 1/3] target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops
2012-11-15 20:13 [PATCH-v2 0/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation Nicholas A. Bellinger
@ 2012-11-15 20:13 ` Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 2/3] target: Add/check max_write_same_len device attribute + update block limits VPD Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 3/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support Nicholas A. Bellinger
2 siblings, 0 replies; 6+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 20:13 UTC (permalink / raw)
To: target-devel
Cc: linux-scsi, linux-kernel, Nicholas Bellinger, Martin K. Petersen
From: Nicholas Bellinger <nab@linux-iscsi.org>
This patch adds a new sbc_ops->execute_write_same_unmap() caller for use
with WRITE_SAME w/ UNMAP=1, and performs the ->execute_cmd() setup based
this bit within sbc_setup_write_same() code.
Also, makes the changes in sbc_parse_cdb() to handle a sense_reason_t
return from sbc_setup_write_same() on error.
Reported-by: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
drivers/target/target_core_sbc.c | 51 +++++++++++++++------------------
include/target/target_core_backend.h | 1 +
2 files changed, 24 insertions(+), 28 deletions(-)
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index b802421..a5a8f46 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -235,26 +235,30 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
}
-static int sbc_write_same_supported(struct se_device *dev,
- unsigned char *flags)
+static sense_reason_t
+sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
{
if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
pr_err("WRITE_SAME PBDATA and LBDATA"
" bits not supported for Block Discard"
" Emulation\n");
- return -ENOSYS;
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
}
-
/*
- * Currently for the emulated case we only accept
- * tpws with the UNMAP=1 bit set.
+ * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
+ * translated into block discard requests within backend code.
*/
- if (!(flags[0] & 0x08)) {
- pr_err("WRITE_SAME w/o UNMAP bit not"
- " supported for Block Discard Emulation\n");
- return -ENOSYS;
+ if (flags[0] & 0x08) {
+ if (!ops->execute_write_same_unmap)
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+
+ cmd->execute_cmd = ops->execute_write_same_unmap;
+ return 0;
}
+ if (!ops->execute_write_same)
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ cmd->execute_cmd = ops->execute_write_same;
return 0;
}
@@ -418,9 +422,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
cmd->se_cmd_flags |= SCF_FUA;
break;
case WRITE_SAME_32:
- if (!ops->execute_write_same)
- return TCM_UNSUPPORTED_SCSI_OPCODE;
-
sectors = transport_get_sectors_32(cdb);
if (!sectors) {
pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
@@ -431,9 +432,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
- if (sbc_write_same_supported(dev, &cdb[10]) < 0)
- return TCM_UNSUPPORTED_SCSI_OPCODE;
- cmd->execute_cmd = ops->execute_write_same;
+ ret = sbc_setup_write_same(cmd, &cdb[10], ops);
+ if (ret < 0)
+ return ret;
break;
default:
pr_err("VARIABLE_LENGTH_CMD service action"
@@ -495,9 +496,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
cmd->execute_cmd = ops->execute_unmap;
break;
case WRITE_SAME_16:
- if (!ops->execute_write_same)
- return TCM_UNSUPPORTED_SCSI_OPCODE;
-
sectors = transport_get_sectors_16(cdb);
if (!sectors) {
pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
@@ -507,14 +505,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
- if (sbc_write_same_supported(dev, &cdb[1]) < 0)
- return TCM_UNSUPPORTED_SCSI_OPCODE;
- cmd->execute_cmd = ops->execute_write_same;
+ ret = sbc_setup_write_same(cmd, &cdb[1], ops);
+ if (ret < 0)
+ return ret;
break;
case WRITE_SAME:
- if (!ops->execute_write_same)
- return TCM_UNSUPPORTED_SCSI_OPCODE;
-
sectors = transport_get_sectors_10(cdb);
if (!sectors) {
pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
@@ -528,9 +523,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
* Follow sbcr26 with WRITE_SAME (10) and check for the existence
* of byte 1 bit 3 UNMAP instead of original reserved field
*/
- if (sbc_write_same_supported(dev, &cdb[1]) < 0)
- return TCM_UNSUPPORTED_SCSI_OPCODE;
- cmd->execute_cmd = ops->execute_write_same;
+ ret = sbc_setup_write_same(cmd, &cdb[1], ops);
+ if (ret < 0)
+ return ret;
break;
case VERIFY:
size = 0;
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index aa86809..3393ab1 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -41,6 +41,7 @@ struct sbc_ops {
sense_reason_t (*execute_rw)(struct se_cmd *cmd);
sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd);
sense_reason_t (*execute_write_same)(struct se_cmd *cmd);
+ sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd);
sense_reason_t (*execute_unmap)(struct se_cmd *cmd);
};
--
1.7.2.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH-v2 2/3] target: Add/check max_write_same_len device attribute + update block limits VPD
2012-11-15 20:13 [PATCH-v2 0/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 1/3] target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops Nicholas A. Bellinger
@ 2012-11-15 20:13 ` Nicholas A. Bellinger
2012-11-15 20:38 ` Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 3/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support Nicholas A. Bellinger
2 siblings, 1 reply; 6+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 20:13 UTC (permalink / raw)
To: target-devel
Cc: linux-scsi, linux-kernel, Nicholas Bellinger, Christoph Hellwig,
Martin K. Petersen
From: Nicholas Bellinger <nab@linux-iscsi.org>
This patch adds a new max_write_same_len device attribute for use with
WRITE_SAME w/ UNMAP=0 backend emulation. This can be useful for
lowering the default backend value (IBLOCK uses 0xFFFF).
Also, update block limits VPD emulation code in spc_emulate_evpd_b0() to
report MAXIMUM WRITE SAME LENGTH, and enforce max_write_same_len during
sbc_parse() -> sbc_setup_write_same() CDB sanity checking for all emulated
WRITE_SAME w/ UNMAP=0 cases.
Cc: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
drivers/target/target_core_configfs.c | 4 ++++
drivers/target/target_core_device.c | 11 +++++++++++
drivers/target/target_core_internal.h | 1 +
drivers/target/target_core_sbc.c | 8 ++++++++
drivers/target/target_core_spc.c | 8 +++++++-
include/target/target_core_base.h | 3 +++
6 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 7b473b6..2b14164 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -676,6 +676,9 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR);
DEF_DEV_ATTRIB(unmap_granularity_alignment);
SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR);
+DEF_DEV_ATTRIB(max_write_same_len);
+SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR);
+
CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);
static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
@@ -701,6 +704,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
&target_core_dev_attrib_max_unmap_block_desc_count.attr,
&target_core_dev_attrib_unmap_granularity.attr,
&target_core_dev_attrib_unmap_granularity_alignment.attr,
+ &target_core_dev_attrib_max_write_same_len.attr,
NULL,
};
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 599374e..54439bc 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -706,6 +706,16 @@ int se_dev_set_unmap_granularity_alignment(
return 0;
}
+int se_dev_set_max_write_same_len(
+ struct se_device *dev,
+ u32 max_write_same_len)
+{
+ dev->dev_attrib.max_write_same_len = max_write_same_len;
+ pr_debug("dev[%p]: Set max_write_same_len: %u\n",
+ dev, dev->dev_attrib.max_write_same_len);
+ return 0;
+}
+
int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
{
if (flag != 0 && flag != 1) {
@@ -1393,6 +1403,7 @@ 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.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS;
dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS;
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index bc9c522..93e9c1f 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -24,6 +24,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_max_write_same_len(struct se_device *, u32);
int se_dev_set_emulate_dpo(struct se_device *, int);
int se_dev_set_emulate_fua_write(struct se_device *, int);
int se_dev_set_emulate_fua_read(struct se_device *, int);
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index a5a8f46..8dd8a802 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -238,6 +238,8 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
static sense_reason_t
sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
{
+ unsigned int sectors = spc_get_write_same_sectors(cmd);
+
if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
pr_err("WRITE_SAME PBDATA and LBDATA"
" bits not supported for Block Discard"
@@ -258,6 +260,12 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
if (!ops->execute_write_same)
return TCM_UNSUPPORTED_SCSI_OPCODE;
+ if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
+ pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",
+ sectors, cmd->se_dev->dev_attrib.max_write_same_len);
+ return TCM_INVALID_CDB_FIELD;
+ }
+
cmd->execute_cmd = ops->execute_write_same;
return 0;
}
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 4b3c183..cf1b8bb 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -465,7 +465,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
* Exit now if we don't support TP.
*/
if (!have_tp)
- return 0;
+ goto max_write_same;
/*
* Set MAXIMUM UNMAP LBA COUNT
@@ -491,6 +491,12 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
if (dev->dev_attrib.unmap_granularity_alignment != 0)
buf[32] |= 0x80; /* Set the UGAVALID bit */
+ /*
+ * MAXIMUM WRITE SAME LENGTH
+ */
+max_write_same:
+ put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]);
+
return 0;
}
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 5350f6e..645d90a 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -71,6 +71,8 @@
#define DA_UNMAP_GRANULARITY_DEFAULT 0
/* Default unmap_granularity_alignment */
#define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0
+/* Default max_write_same_len, disabled by default */
+#define DA_MAX_WRITE_SAME_LEN 0
/* Default max transfer length */
#define DA_FABRIC_MAX_SECTORS 8192
/* Emulation for Direct Page Out */
@@ -609,6 +611,7 @@ struct se_dev_attrib {
u32 max_unmap_block_desc_count;
u32 unmap_granularity;
u32 unmap_granularity_alignment;
+ u32 max_write_same_len;
struct se_device *da_dev;
struct config_group da_group;
};
--
1.7.2.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH-v2 3/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support
2012-11-15 20:13 [PATCH-v2 0/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 1/3] target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 2/3] target: Add/check max_write_same_len device attribute + update block limits VPD Nicholas A. Bellinger
@ 2012-11-15 20:13 ` Nicholas A. Bellinger
2012-11-15 20:39 ` Nicholas A. Bellinger
2 siblings, 1 reply; 6+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 20:13 UTC (permalink / raw)
To: target-devel
Cc: linux-scsi, linux-kernel, Nicholas Bellinger, Christoph Hellwig,
Martin K. Petersen
From: Nicholas Bellinger <nab@linux-iscsi.org>
This patch adds support for emulation of WRITE_SAME w/ UNMAP=0 within
iblock_execute_write_same() backend code.
The emulation uses a bio_add_page() call for each sector, and by default
enforces a limit of max_write_same_len=0xFFFF (65536) sectors following
what scsi_debug reports per default for MAXIMUM WRITE SAME LENGTH.
It also sets max_write_same_len to the operational default at setup ->
iblock_configure_device() time.
(hch: Move unmap logic into iblock_execute_write_same_unmap + add
check for single sector SGLs in iblock_execute_write_same)
(mkp: Update comment for 0xFFFF magic constant)
Cc: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
drivers/target/target_core_iblock.c | 91 ++++++++++++++++++++++++++++++++---
1 files changed, 84 insertions(+), 7 deletions(-)
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 53f4501..5abbd55 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -151,6 +151,11 @@ static int iblock_configure_device(struct se_device *dev)
pr_debug("IBLOCK: BLOCK Discard support available,"
" disabled by default\n");
}
+ /*
+ * Enable write same emulation for IBLOCK and use 0xFFFF as
+ * the samller WRITE_SAME(10) only has a two-byte block count.
+ */
+ dev->dev_attrib.max_write_same_len = 0xFFFF;
if (blk_queue_nonrot(q))
dev->dev_attrib.is_nonrot = 1;
@@ -375,17 +380,20 @@ err:
return ret;
}
+static struct bio *iblock_get_bio(struct se_cmd *, sector_t, u32);
+static void iblock_submit_bios(struct bio_list *, int);
+static void iblock_complete_cmd(struct se_cmd *);
+
static sense_reason_t
-iblock_execute_write_same(struct se_cmd *cmd)
+iblock_execute_write_same_unmap(struct se_cmd *cmd)
{
struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev);
- int ret;
+ int rc;
- ret = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba,
- spc_get_write_same_sectors(cmd), GFP_KERNEL,
- 0);
- if (ret < 0) {
- pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
+ rc = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba,
+ spc_get_write_same_sectors(cmd), GFP_KERNEL, 0);
+ if (rc < 0) {
+ pr_warn("blkdev_issue_discard() failed: %d\n", rc);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
@@ -393,6 +401,74 @@ iblock_execute_write_same(struct se_cmd *cmd)
return 0;
}
+static sense_reason_t
+iblock_execute_write_same(struct se_cmd *cmd)
+{
+ struct iblock_req *ibr;
+ struct scatterlist *sg;
+ struct bio *bio;
+ struct bio_list list;
+ sector_t block_lba = cmd->t_task_lba;
+ unsigned int sectors = spc_get_write_same_sectors(cmd);
+
+ if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
+ pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",
+ sectors, cmd->se_dev->dev_attrib.max_write_same_len);
+ return TCM_INVALID_CDB_FIELD;
+ }
+ sg = &cmd->t_data_sg[0];
+
+ if (cmd->t_data_nents > 1 ||
+ sg->length != cmd->se_dev->dev_attrib.block_size) {
+ pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u"
+ " block_size: %u\n", cmd->t_data_nents, sg->length,
+ cmd->se_dev->dev_attrib.block_size);
+ return TCM_INVALID_CDB_FIELD;
+ }
+
+ ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
+ if (!ibr)
+ goto fail;
+ cmd->priv = ibr;
+
+ bio = iblock_get_bio(cmd, block_lba, 1);
+ if (!bio)
+ goto fail_free_ibr;
+
+ bio_list_init(&list);
+ bio_list_add(&list, bio);
+
+ atomic_set(&ibr->pending, 1);
+
+ while (sectors) {
+ while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
+ != sg->length) {
+
+ bio = iblock_get_bio(cmd, block_lba, 1);
+ if (!bio)
+ goto fail_put_bios;
+
+ atomic_inc(&ibr->pending);
+ bio_list_add(&list, bio);
+ }
+
+ /* Always in 512 byte units for Linux/Block */
+ block_lba += sg->length >> IBLOCK_LBA_SHIFT;
+ sectors -= 1;
+ }
+
+ iblock_submit_bios(&list, WRITE);
+ return 0;
+
+fail_put_bios:
+ while ((bio = bio_list_pop(&list)))
+ bio_put(bio);
+fail_free_ibr:
+ kfree(ibr);
+fail:
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+}
+
enum {
Opt_udev_path, Opt_readonly, Opt_force, Opt_err
};
@@ -701,6 +777,7 @@ static struct sbc_ops iblock_sbc_ops = {
.execute_rw = iblock_execute_rw,
.execute_sync_cache = iblock_execute_sync_cache,
.execute_write_same = iblock_execute_write_same,
+ .execute_write_same_unmap = iblock_execute_write_same_unmap,
.execute_unmap = iblock_execute_unmap,
};
--
1.7.2.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH-v2 2/3] target: Add/check max_write_same_len device attribute + update block limits VPD
2012-11-15 20:13 ` [PATCH-v2 2/3] target: Add/check max_write_same_len device attribute + update block limits VPD Nicholas A. Bellinger
@ 2012-11-15 20:38 ` Nicholas A. Bellinger
0 siblings, 0 replies; 6+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 20:38 UTC (permalink / raw)
To: target-devel
Cc: linux-scsi, linux-kernel, Christoph Hellwig, Martin K. Petersen,
Robert Elliot
On Thu, 2012-11-15 at 20:13 +0000, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
>
> This patch adds a new max_write_same_len device attribute for use with
> WRITE_SAME w/ UNMAP=0 backend emulation. This can be useful for
> lowering the default backend value (IBLOCK uses 0xFFFF).
>
> Also, update block limits VPD emulation code in spc_emulate_evpd_b0() to
> report MAXIMUM WRITE SAME LENGTH, and enforce max_write_same_len during
> sbc_parse() -> sbc_setup_write_same() CDB sanity checking for all emulated
> WRITE_SAME w/ UNMAP=0 cases.
>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Martin K. Petersen <martin.petersen@oracle.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
> drivers/target/target_core_configfs.c | 4 ++++
> drivers/target/target_core_device.c | 11 +++++++++++
> drivers/target/target_core_internal.h | 1 +
> drivers/target/target_core_sbc.c | 8 ++++++++
> drivers/target/target_core_spc.c | 8 +++++++-
> include/target/target_core_base.h | 3 +++
> 6 files changed, 34 insertions(+), 1 deletions(-)
>
<SNIP>
> diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
> index a5a8f46..8dd8a802 100644
> --- a/drivers/target/target_core_sbc.c
> +++ b/drivers/target/target_core_sbc.c
> @@ -238,6 +238,8 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
> static sense_reason_t
> sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
> {
> + unsigned int sectors = spc_get_write_same_sectors(cmd);
> +
> if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
> pr_err("WRITE_SAME PBDATA and LBDATA"
> " bits not supported for Block Discard"
> @@ -258,6 +260,12 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
> if (!ops->execute_write_same)
> return TCM_UNSUPPORTED_SCSI_OPCODE;
>
> + if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
> + pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",
> + sectors, cmd->se_dev->dev_attrib.max_write_same_len);
> + return TCM_INVALID_CDB_FIELD;
> + }
> +
> cmd->execute_cmd = ops->execute_write_same;
> return 0;
> }
Now moving the max_write_same_len check above directly ahead of the
UNMAP conditional branch, so that both WRITE_SAME w/ UNMAP=[1,0] are
properly checked against this value as per hch's + Robert's input.
Thanks!
--nab
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH-v2 3/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support
2012-11-15 20:13 ` [PATCH-v2 3/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support Nicholas A. Bellinger
@ 2012-11-15 20:39 ` Nicholas A. Bellinger
0 siblings, 0 replies; 6+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 20:39 UTC (permalink / raw)
To: target-devel
Cc: linux-scsi, linux-kernel, Christoph Hellwig, Martin K. Petersen
On Thu, 2012-11-15 at 20:13 +0000, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
>
> This patch adds support for emulation of WRITE_SAME w/ UNMAP=0 within
> iblock_execute_write_same() backend code.
>
> The emulation uses a bio_add_page() call for each sector, and by default
> enforces a limit of max_write_same_len=0xFFFF (65536) sectors following
> what scsi_debug reports per default for MAXIMUM WRITE SAME LENGTH.
>
> It also sets max_write_same_len to the operational default at setup ->
> iblock_configure_device() time.
>
> (hch: Move unmap logic into iblock_execute_write_same_unmap + add
> check for single sector SGLs in iblock_execute_write_same)
> (mkp: Update comment for 0xFFFF magic constant)
>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Martin K. Petersen <martin.petersen@oracle.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
> drivers/target/target_core_iblock.c | 91 ++++++++++++++++++++++++++++++++---
> 1 files changed, 84 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
> index 53f4501..5abbd55 100644
> --- a/drivers/target/target_core_iblock.c
> +++ b/drivers/target/target_core_iblock.c
> +static sense_reason_t
> +iblock_execute_write_same(struct se_cmd *cmd)
> +{
> + struct iblock_req *ibr;
> + struct scatterlist *sg;
> + struct bio *bio;
> + struct bio_list list;
> + sector_t block_lba = cmd->t_task_lba;
> + unsigned int sectors = spc_get_write_same_sectors(cmd);
> +
> + if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
> + pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n",
> + sectors, cmd->se_dev->dev_attrib.max_write_same_len);
> + return TCM_INVALID_CDB_FIELD;
> + }
<SNIP>
Forgot to remove this now redundant check for max_write_same_len.
Dropping now..
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-11-15 21:38 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-15 20:13 [PATCH-v2 0/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 1/3] target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 2/3] target: Add/check max_write_same_len device attribute + update block limits VPD Nicholas A. Bellinger
2012-11-15 20:38 ` Nicholas A. Bellinger
2012-11-15 20:13 ` [PATCH-v2 3/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support Nicholas A. Bellinger
2012-11-15 20:39 ` Nicholas A. Bellinger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.