diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-11-15 14:02:49 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-11-15 15:27:21 -0500 |
commit | 773cbaf7460aa58c67d4dca83c3f8bca10323bbe (patch) | |
tree | 91e6015ade8d62c34c64861f1f3810b3c15a6a25 /drivers/target | |
parent | cd063bef414c51d79b9c6ea7a8ef8f9d319529bc (diff) |
target: Add/check max_write_same_len device attribute + update block limits VPD
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.
(Robert: Move max_write_same_len check in sbc_setup_write_same() to
check both WRITE_SAME w/ UNMAP=1 and w/ UNMAP=0 cases)
Cc: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Robert Elliott <Elliott@hp.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_configfs.c | 4 | ||||
-rw-r--r-- | drivers/target/target_core_device.c | 11 | ||||
-rw-r--r-- | drivers/target/target_core_internal.h | 1 | ||||
-rw-r--r-- | drivers/target/target_core_sbc.c | 7 | ||||
-rw-r--r-- | drivers/target/target_core_spc.c | 8 |
5 files changed, 30 insertions, 1 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 7b473b66da7b..2b141643f06e 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); | |||
676 | DEF_DEV_ATTRIB(unmap_granularity_alignment); | 676 | DEF_DEV_ATTRIB(unmap_granularity_alignment); |
677 | SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); | 677 | SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); |
678 | 678 | ||
679 | DEF_DEV_ATTRIB(max_write_same_len); | ||
680 | SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR); | ||
681 | |||
679 | CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); | 682 | CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); |
680 | 683 | ||
681 | static struct configfs_attribute *target_core_dev_attrib_attrs[] = { | 684 | static struct configfs_attribute *target_core_dev_attrib_attrs[] = { |
@@ -701,6 +704,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { | |||
701 | &target_core_dev_attrib_max_unmap_block_desc_count.attr, | 704 | &target_core_dev_attrib_max_unmap_block_desc_count.attr, |
702 | &target_core_dev_attrib_unmap_granularity.attr, | 705 | &target_core_dev_attrib_unmap_granularity.attr, |
703 | &target_core_dev_attrib_unmap_granularity_alignment.attr, | 706 | &target_core_dev_attrib_unmap_granularity_alignment.attr, |
707 | &target_core_dev_attrib_max_write_same_len.attr, | ||
704 | NULL, | 708 | NULL, |
705 | }; | 709 | }; |
706 | 710 | ||
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 599374e6d245..54439bc42dab 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( | |||
706 | return 0; | 706 | return 0; |
707 | } | 707 | } |
708 | 708 | ||
709 | int se_dev_set_max_write_same_len( | ||
710 | struct se_device *dev, | ||
711 | u32 max_write_same_len) | ||
712 | { | ||
713 | dev->dev_attrib.max_write_same_len = max_write_same_len; | ||
714 | pr_debug("dev[%p]: Set max_write_same_len: %u\n", | ||
715 | dev, dev->dev_attrib.max_write_same_len); | ||
716 | return 0; | ||
717 | } | ||
718 | |||
709 | int se_dev_set_emulate_dpo(struct se_device *dev, int flag) | 719 | int se_dev_set_emulate_dpo(struct se_device *dev, int flag) |
710 | { | 720 | { |
711 | if (flag != 0 && flag != 1) { | 721 | if (flag != 0 && flag != 1) { |
@@ -1393,6 +1403,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
1393 | dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; | 1403 | dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; |
1394 | dev->dev_attrib.unmap_granularity_alignment = | 1404 | dev->dev_attrib.unmap_granularity_alignment = |
1395 | DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; | 1405 | DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; |
1406 | dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; | ||
1396 | dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; | 1407 | dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; |
1397 | dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; | 1408 | dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; |
1398 | 1409 | ||
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index bc9c52284845..93e9c1f580b0 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); | |||
24 | int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); | 24 | int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); |
25 | int se_dev_set_unmap_granularity(struct se_device *, u32); | 25 | int se_dev_set_unmap_granularity(struct se_device *, u32); |
26 | int se_dev_set_unmap_granularity_alignment(struct se_device *, u32); | 26 | int se_dev_set_unmap_granularity_alignment(struct se_device *, u32); |
27 | int se_dev_set_max_write_same_len(struct se_device *, u32); | ||
27 | int se_dev_set_emulate_dpo(struct se_device *, int); | 28 | int se_dev_set_emulate_dpo(struct se_device *, int); |
28 | int se_dev_set_emulate_fua_write(struct se_device *, int); | 29 | int se_dev_set_emulate_fua_write(struct se_device *, int); |
29 | int se_dev_set_emulate_fua_read(struct se_device *, int); | 30 | 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 a5a8f463004b..45e11d0e38c4 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -238,12 +238,19 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) | |||
238 | static sense_reason_t | 238 | static sense_reason_t |
239 | sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) | 239 | sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) |
240 | { | 240 | { |
241 | unsigned int sectors = spc_get_write_same_sectors(cmd); | ||
242 | |||
241 | if ((flags[0] & 0x04) || (flags[0] & 0x02)) { | 243 | if ((flags[0] & 0x04) || (flags[0] & 0x02)) { |
242 | pr_err("WRITE_SAME PBDATA and LBDATA" | 244 | pr_err("WRITE_SAME PBDATA and LBDATA" |
243 | " bits not supported for Block Discard" | 245 | " bits not supported for Block Discard" |
244 | " Emulation\n"); | 246 | " Emulation\n"); |
245 | return TCM_UNSUPPORTED_SCSI_OPCODE; | 247 | return TCM_UNSUPPORTED_SCSI_OPCODE; |
246 | } | 248 | } |
249 | if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) { | ||
250 | pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n", | ||
251 | sectors, cmd->se_dev->dev_attrib.max_write_same_len); | ||
252 | return TCM_INVALID_CDB_FIELD; | ||
253 | } | ||
247 | /* | 254 | /* |
248 | * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting | 255 | * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting |
249 | * translated into block discard requests within backend code. | 256 | * translated into block discard requests within backend code. |
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4b3c18305ec8..cf1b8bb310c4 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) | |||
465 | * Exit now if we don't support TP. | 465 | * Exit now if we don't support TP. |
466 | */ | 466 | */ |
467 | if (!have_tp) | 467 | if (!have_tp) |
468 | return 0; | 468 | goto max_write_same; |
469 | 469 | ||
470 | /* | 470 | /* |
471 | * Set MAXIMUM UNMAP LBA COUNT | 471 | * Set MAXIMUM UNMAP LBA COUNT |
@@ -491,6 +491,12 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | |||
491 | if (dev->dev_attrib.unmap_granularity_alignment != 0) | 491 | if (dev->dev_attrib.unmap_granularity_alignment != 0) |
492 | buf[32] |= 0x80; /* Set the UGAVALID bit */ | 492 | buf[32] |= 0x80; /* Set the UGAVALID bit */ |
493 | 493 | ||
494 | /* | ||
495 | * MAXIMUM WRITE SAME LENGTH | ||
496 | */ | ||
497 | max_write_same: | ||
498 | put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]); | ||
499 | |||
494 | return 0; | 500 | return 0; |
495 | } | 501 | } |
496 | 502 | ||