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 | |
| 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>
| -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 | ||||
| -rw-r--r-- | include/target/target_core_base.h | 3 |
6 files changed, 33 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 | ||
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5350f6e580f0..645d90ac6097 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
| @@ -71,6 +71,8 @@ | |||
| 71 | #define DA_UNMAP_GRANULARITY_DEFAULT 0 | 71 | #define DA_UNMAP_GRANULARITY_DEFAULT 0 |
| 72 | /* Default unmap_granularity_alignment */ | 72 | /* Default unmap_granularity_alignment */ |
| 73 | #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0 | 73 | #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0 |
| 74 | /* Default max_write_same_len, disabled by default */ | ||
| 75 | #define DA_MAX_WRITE_SAME_LEN 0 | ||
| 74 | /* Default max transfer length */ | 76 | /* Default max transfer length */ |
| 75 | #define DA_FABRIC_MAX_SECTORS 8192 | 77 | #define DA_FABRIC_MAX_SECTORS 8192 |
| 76 | /* Emulation for Direct Page Out */ | 78 | /* Emulation for Direct Page Out */ |
| @@ -609,6 +611,7 @@ struct se_dev_attrib { | |||
| 609 | u32 max_unmap_block_desc_count; | 611 | u32 max_unmap_block_desc_count; |
| 610 | u32 unmap_granularity; | 612 | u32 unmap_granularity; |
| 611 | u32 unmap_granularity_alignment; | 613 | u32 unmap_granularity_alignment; |
| 614 | u32 max_write_same_len; | ||
| 612 | struct se_device *da_dev; | 615 | struct se_device *da_dev; |
| 613 | struct config_group da_group; | 616 | struct config_group da_group; |
| 614 | }; | 617 | }; |
