aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <roland@purestorage.com>2015-08-14 00:59:19 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-08-19 00:51:54 -0400
commit0f69a38737538c8a265f75d26996818f98c899e4 (patch)
treedb21d5dc214d0dd9793dfee813e0e358d16013f5
parent9c395170a559d3b23dad100b01fc4a89d661c698 (diff)
target: Fix handling of small allocation lengths in REPORT LUNS
REPORT LUNS should not fail just because the allocation length is less than 16. The relevant section of SPC-4 is: 4.2.5.6 Allocation length The ALLOCATION LENGTH field specifies the maximum number of bytes or blocks that an application client has allocated in the Data-In Buffer. The ALLOCATION LENGTH field specifies bytes unless a different requirement is stated in the command definition. An allocation length of zero specifies that no data shall be transferred. This condition shall not be considered an error. So we should just truncate our response rather than return an error. Signed-off-by: Roland Dreier <roland@purestorage.com> Signed-off-by: Spencer Baugh <sbaugh@catern.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_spc.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 556ea1b2cdd8..f87d4cef6d39 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -1203,17 +1203,13 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
1203 struct se_dev_entry *deve; 1203 struct se_dev_entry *deve;
1204 struct se_session *sess = cmd->se_sess; 1204 struct se_session *sess = cmd->se_sess;
1205 struct se_node_acl *nacl; 1205 struct se_node_acl *nacl;
1206 struct scsi_lun slun;
1206 unsigned char *buf; 1207 unsigned char *buf;
1207 u32 lun_count = 0, offset = 8; 1208 u32 lun_count = 0, offset = 8;
1208 1209 __be32 len;
1209 if (cmd->data_length < 16) {
1210 pr_warn("REPORT LUNS allocation length %u too small\n",
1211 cmd->data_length);
1212 return TCM_INVALID_CDB_FIELD;
1213 }
1214 1210
1215 buf = transport_kmap_data_sg(cmd); 1211 buf = transport_kmap_data_sg(cmd);
1216 if (!buf) 1212 if (cmd->data_length && !buf)
1217 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1213 return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
1218 1214
1219 /* 1215 /*
@@ -1234,10 +1230,12 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
1234 * See SPC2-R20 7.19. 1230 * See SPC2-R20 7.19.
1235 */ 1231 */
1236 lun_count++; 1232 lun_count++;
1237 if ((offset + 8) > cmd->data_length) 1233 if (offset >= cmd->data_length)
1238 continue; 1234 continue;
1239 1235
1240 int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); 1236 int_to_scsilun(deve->mapped_lun, &slun);
1237 memcpy(buf + offset, &slun,
1238 min(8u, cmd->data_length - offset));
1241 offset += 8; 1239 offset += 8;
1242 } 1240 }
1243 rcu_read_unlock(); 1241 rcu_read_unlock();
@@ -1250,16 +1248,18 @@ done:
1250 * If no LUNs are accessible, report virtual LUN 0. 1248 * If no LUNs are accessible, report virtual LUN 0.
1251 */ 1249 */
1252 if (lun_count == 0) { 1250 if (lun_count == 0) {
1253 int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); 1251 int_to_scsilun(0, &slun);
1252 if (cmd->data_length > 8)
1253 memcpy(buf + offset, &slun,
1254 min(8u, cmd->data_length - offset));
1254 lun_count = 1; 1255 lun_count = 1;
1255 } 1256 }
1256 1257
1257 lun_count *= 8; 1258 if (buf) {
1258 buf[0] = ((lun_count >> 24) & 0xff); 1259 len = cpu_to_be32(lun_count * 8);
1259 buf[1] = ((lun_count >> 16) & 0xff); 1260 memcpy(buf, &len, min_t(int, sizeof len, cmd->data_length));
1260 buf[2] = ((lun_count >> 8) & 0xff); 1261 transport_kunmap_data_sg(cmd);
1261 buf[3] = (lun_count & 0xff); 1262 }
1262 transport_kunmap_data_sg(cmd);
1263 1263
1264 target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); 1264 target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
1265 return 0; 1265 return 0;