diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-07-28 03:07:03 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-08-22 15:26:21 -0400 |
commit | 706d5860969b3b24d65d9a57bd3bb5e4a1419c08 (patch) | |
tree | a6293f322a5327d3c317c09197b33d66e22d010e /drivers/target/target_core_cdb.c | |
parent | 16ab8e60a0ebc22cfbe61d84e620457a15f3a0bc (diff) |
target: Add WRITE_SAME (10) parsing and refactor passthrough checks
This patch adds initial WRITE_SAME (10) w/ UNMAP=1 support following updates in
sbcr26 to allow UNMAP=1 for the non 16 + 32 byte CDB case. It also refactors
current pSCSI passthrough passthrough checks into target_check_write_same_discard()
ahead of UNMAP=0 w/ write payload support into target_core_iblock.c.
This includes the support for handling WRITE_SAME in transport_emulate_control_cdb(),
and converts target_emulate_write_same to accept num_blocks directly for
WRITE_SAME, WRITE_SAME_16 and WRITE_SAME_32.
Reported-by: Eric Seppanen <eric@purestorage.com>
Cc: Roland Dreier <roland@purestorage.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
Diffstat (limited to 'drivers/target/target_core_cdb.c')
-rw-r--r-- | drivers/target/target_core_cdb.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index d095408dbd5f..4c1d3a98e894 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c | |||
@@ -1090,24 +1090,17 @@ err: | |||
1090 | * Note this is not used for TCM/pSCSI passthrough | 1090 | * Note this is not used for TCM/pSCSI passthrough |
1091 | */ | 1091 | */ |
1092 | static int | 1092 | static int |
1093 | target_emulate_write_same(struct se_task *task, int write_same32) | 1093 | target_emulate_write_same(struct se_task *task, u32 num_blocks) |
1094 | { | 1094 | { |
1095 | struct se_cmd *cmd = task->task_se_cmd; | 1095 | struct se_cmd *cmd = task->task_se_cmd; |
1096 | struct se_device *dev = cmd->se_dev; | 1096 | struct se_device *dev = cmd->se_dev; |
1097 | sector_t range; | 1097 | sector_t range; |
1098 | sector_t lba = cmd->t_task_lba; | 1098 | sector_t lba = cmd->t_task_lba; |
1099 | unsigned int num_blocks; | ||
1100 | int ret; | 1099 | int ret; |
1101 | /* | 1100 | /* |
1102 | * Extract num_blocks from the WRITE_SAME_* CDB. Then use the explict | 1101 | * Use the explicit range when non zero is supplied, otherwise calculate |
1103 | * range when non zero is supplied, otherwise calculate the remaining | 1102 | * the remaining range based on ->get_blocks() - starting LBA. |
1104 | * range based on ->get_blocks() - starting LBA. | ||
1105 | */ | 1103 | */ |
1106 | if (write_same32) | ||
1107 | num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]); | ||
1108 | else | ||
1109 | num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]); | ||
1110 | |||
1111 | if (num_blocks != 0) | 1104 | if (num_blocks != 0) |
1112 | range = num_blocks; | 1105 | range = num_blocks; |
1113 | else | 1106 | else |
@@ -1170,13 +1163,23 @@ transport_emulate_control_cdb(struct se_task *task) | |||
1170 | } | 1163 | } |
1171 | ret = target_emulate_unmap(task); | 1164 | ret = target_emulate_unmap(task); |
1172 | break; | 1165 | break; |
1166 | case WRITE_SAME: | ||
1167 | if (!dev->transport->do_discard) { | ||
1168 | pr_err("WRITE_SAME emulation not supported" | ||
1169 | " for: %s\n", dev->transport->name); | ||
1170 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
1171 | } | ||
1172 | ret = target_emulate_write_same(task, | ||
1173 | get_unaligned_be16(&cmd->t_task_cdb[7])); | ||
1174 | break; | ||
1173 | case WRITE_SAME_16: | 1175 | case WRITE_SAME_16: |
1174 | if (!dev->transport->do_discard) { | 1176 | if (!dev->transport->do_discard) { |
1175 | pr_err("WRITE_SAME_16 emulation not supported" | 1177 | pr_err("WRITE_SAME_16 emulation not supported" |
1176 | " for: %s\n", dev->transport->name); | 1178 | " for: %s\n", dev->transport->name); |
1177 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | 1179 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; |
1178 | } | 1180 | } |
1179 | ret = target_emulate_write_same(task, 0); | 1181 | ret = target_emulate_write_same(task, |
1182 | get_unaligned_be32(&cmd->t_task_cdb[10])); | ||
1180 | break; | 1183 | break; |
1181 | case VARIABLE_LENGTH_CMD: | 1184 | case VARIABLE_LENGTH_CMD: |
1182 | service_action = | 1185 | service_action = |
@@ -1189,7 +1192,8 @@ transport_emulate_control_cdb(struct se_task *task) | |||
1189 | dev->transport->name); | 1192 | dev->transport->name); |
1190 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | 1193 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; |
1191 | } | 1194 | } |
1192 | ret = target_emulate_write_same(task, 1); | 1195 | ret = target_emulate_write_same(task, |
1196 | get_unaligned_be32(&cmd->t_task_cdb[28])); | ||
1193 | break; | 1197 | break; |
1194 | default: | 1198 | default: |
1195 | pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" | 1199 | pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" |