diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-20 14:39:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-20 14:39:11 -0400 |
commit | 3243f50b0c564a1b492defebe7218d26a2b811c9 (patch) | |
tree | 888d2d9115fd975a602de407952ddf6203f301d1 | |
parent | 3bd8f7d87dd12a97f0215f0d1a4afdd20ba49854 (diff) | |
parent | 0f69a38737538c8a265f75d26996818f98c899e4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target fixes from Nicholas Bellinger:
"This contains a v4.2-rc specific RCU module unload regression bug-fix,
a long-standing iscsi-target bug-fix for duplicate target_xfer_tags
during NOP processing from Alexei, and two more small REPORT_LUNs
emulation related patches to make Solaris FC host LUN scanning happy
from Roland.
There is also one patch not included that allows target-core to limit
the number of fabric driver SGLs per I/O request using residuals, that
is currently required as a work-around for FC hosts which don't honor
EVPD block-limits settings. At this point, it will most likely become
for-next material"
* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
target: Fix handling of small allocation lengths in REPORT LUNS
target: REPORT LUNS should return LUN 0 even for dynamic ACLs
target/iscsi: Fix double free of a TUR followed by a solicited NOPOUT
target: Perform RCU callback barrier before backend/fabric unload
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 4 | ||||
-rw-r--r-- | drivers/target/target_core_configfs.c | 9 | ||||
-rw-r--r-- | drivers/target/target_core_hba.c | 10 | ||||
-rw-r--r-- | drivers/target/target_core_spc.c | 44 |
4 files changed, 44 insertions, 23 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index cd77a064c772..fd092909a457 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -968,9 +968,9 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
968 | cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA; | 968 | cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA; |
969 | 969 | ||
970 | conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt; | 970 | conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt; |
971 | if (hdr->flags & ISCSI_FLAG_CMD_READ) { | 971 | if (hdr->flags & ISCSI_FLAG_CMD_READ) |
972 | cmd->targ_xfer_tag = session_get_next_ttt(conn->sess); | 972 | cmd->targ_xfer_tag = session_get_next_ttt(conn->sess); |
973 | } else if (hdr->flags & ISCSI_FLAG_CMD_WRITE) | 973 | else |
974 | cmd->targ_xfer_tag = 0xFFFFFFFF; | 974 | cmd->targ_xfer_tag = 0xFFFFFFFF; |
975 | cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); | 975 | cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); |
976 | cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); | 976 | cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); |
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index c2e9fea90b4a..860e84046177 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -457,8 +457,15 @@ void target_unregister_template(const struct target_core_fabric_ops *fo) | |||
457 | if (!strcmp(t->tf_ops->name, fo->name)) { | 457 | if (!strcmp(t->tf_ops->name, fo->name)) { |
458 | BUG_ON(atomic_read(&t->tf_access_cnt)); | 458 | BUG_ON(atomic_read(&t->tf_access_cnt)); |
459 | list_del(&t->tf_list); | 459 | list_del(&t->tf_list); |
460 | mutex_unlock(&g_tf_lock); | ||
461 | /* | ||
462 | * Wait for any outstanding fabric se_deve_entry->rcu_head | ||
463 | * callbacks to complete post kfree_rcu(), before allowing | ||
464 | * fabric driver unload of TFO->module to proceed. | ||
465 | */ | ||
466 | rcu_barrier(); | ||
460 | kfree(t); | 467 | kfree(t); |
461 | break; | 468 | return; |
462 | } | 469 | } |
463 | } | 470 | } |
464 | mutex_unlock(&g_tf_lock); | 471 | mutex_unlock(&g_tf_lock); |
diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c index 62ea4e8e70a8..be9cefc07407 100644 --- a/drivers/target/target_core_hba.c +++ b/drivers/target/target_core_hba.c | |||
@@ -84,8 +84,16 @@ void target_backend_unregister(const struct target_backend_ops *ops) | |||
84 | list_for_each_entry(tb, &backend_list, list) { | 84 | list_for_each_entry(tb, &backend_list, list) { |
85 | if (tb->ops == ops) { | 85 | if (tb->ops == ops) { |
86 | list_del(&tb->list); | 86 | list_del(&tb->list); |
87 | mutex_unlock(&backend_mutex); | ||
88 | /* | ||
89 | * Wait for any outstanding backend driver ->rcu_head | ||
90 | * callbacks to complete post TBO->free_device() -> | ||
91 | * call_rcu(), before allowing backend driver module | ||
92 | * unload of target_backend_ops->owner to proceed. | ||
93 | */ | ||
94 | rcu_barrier(); | ||
87 | kfree(tb); | 95 | kfree(tb); |
88 | break; | 96 | return; |
89 | } | 97 | } |
90 | } | 98 | } |
91 | mutex_unlock(&backend_mutex); | 99 | mutex_unlock(&backend_mutex); |
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index b5ba1ec3c354..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 | /* |
@@ -1221,11 +1217,9 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) | |||
1221 | * coming via a target_core_mod PASSTHROUGH op, and not through | 1217 | * coming via a target_core_mod PASSTHROUGH op, and not through |
1222 | * a $FABRIC_MOD. In that case, report LUN=0 only. | 1218 | * a $FABRIC_MOD. In that case, report LUN=0 only. |
1223 | */ | 1219 | */ |
1224 | if (!sess) { | 1220 | if (!sess) |
1225 | int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); | ||
1226 | lun_count = 1; | ||
1227 | goto done; | 1221 | goto done; |
1228 | } | 1222 | |
1229 | nacl = sess->se_node_acl; | 1223 | nacl = sess->se_node_acl; |
1230 | 1224 | ||
1231 | rcu_read_lock(); | 1225 | rcu_read_lock(); |
@@ -1236,10 +1230,12 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) | |||
1236 | * See SPC2-R20 7.19. | 1230 | * See SPC2-R20 7.19. |
1237 | */ | 1231 | */ |
1238 | lun_count++; | 1232 | lun_count++; |
1239 | if ((offset + 8) > cmd->data_length) | 1233 | if (offset >= cmd->data_length) |
1240 | continue; | 1234 | continue; |
1241 | 1235 | ||
1242 | 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)); | ||
1243 | offset += 8; | 1239 | offset += 8; |
1244 | } | 1240 | } |
1245 | rcu_read_unlock(); | 1241 | rcu_read_unlock(); |
@@ -1248,12 +1244,22 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) | |||
1248 | * See SPC3 r07, page 159. | 1244 | * See SPC3 r07, page 159. |
1249 | */ | 1245 | */ |
1250 | done: | 1246 | done: |
1251 | lun_count *= 8; | 1247 | /* |
1252 | buf[0] = ((lun_count >> 24) & 0xff); | 1248 | * If no LUNs are accessible, report virtual LUN 0. |
1253 | buf[1] = ((lun_count >> 16) & 0xff); | 1249 | */ |
1254 | buf[2] = ((lun_count >> 8) & 0xff); | 1250 | if (lun_count == 0) { |
1255 | buf[3] = (lun_count & 0xff); | 1251 | int_to_scsilun(0, &slun); |
1256 | transport_kunmap_data_sg(cmd); | 1252 | if (cmd->data_length > 8) |
1253 | memcpy(buf + offset, &slun, | ||
1254 | min(8u, cmd->data_length - offset)); | ||
1255 | lun_count = 1; | ||
1256 | } | ||
1257 | |||
1258 | if (buf) { | ||
1259 | len = cpu_to_be32(lun_count * 8); | ||
1260 | memcpy(buf, &len, min_t(int, sizeof len, cmd->data_length)); | ||
1261 | transport_kunmap_data_sg(cmd); | ||
1262 | } | ||
1257 | 1263 | ||
1258 | target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); | 1264 | target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); |
1259 | return 0; | 1265 | return 0; |