Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
"Fixes for two fairly obscure but annoying when triggered races in
iSCSI"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
scsi: target: iscsi: Fix cmd abort fabric stop race
scsi: libiscsi: Fix NOP race condition

+31 -12
+15 -8
drivers/scsi/libiscsi.c
··· 533 533 if (conn->task == task) 534 534 conn->task = NULL; 535 535 536 - if (conn->ping_task == task) 537 - conn->ping_task = NULL; 536 + if (READ_ONCE(conn->ping_task) == task) 537 + WRITE_ONCE(conn->ping_task, NULL); 538 538 539 539 /* release get from queueing */ 540 540 __iscsi_put_task(task); ··· 737 737 task->hdr->itt = build_itt(task->itt, 738 738 task->conn->session->age); 739 739 } 740 + 741 + if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK)) 742 + WRITE_ONCE(conn->ping_task, task); 740 743 741 744 if (!ihost->workq) { 742 745 if (iscsi_prep_mgmt_task(conn, task)) ··· 944 941 struct iscsi_nopout hdr; 945 942 struct iscsi_task *task; 946 943 947 - if (!rhdr && conn->ping_task) 948 - return -EINVAL; 944 + if (!rhdr) { 945 + if (READ_ONCE(conn->ping_task)) 946 + return -EINVAL; 947 + WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK); 948 + } 949 949 950 950 memset(&hdr, 0, sizeof(struct iscsi_nopout)); 951 951 hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; ··· 963 957 964 958 task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); 965 959 if (!task) { 960 + if (!rhdr) 961 + WRITE_ONCE(conn->ping_task, NULL); 966 962 iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); 967 963 return -EIO; 968 964 } else if (!rhdr) { 969 965 /* only track our nops */ 970 - conn->ping_task = task; 971 966 conn->last_ping = jiffies; 972 967 } 973 968 ··· 991 984 struct iscsi_conn *conn = task->conn; 992 985 int rc = 0; 993 986 994 - if (conn->ping_task != task) { 987 + if (READ_ONCE(conn->ping_task) != task) { 995 988 /* 996 989 * If this is not in response to one of our 997 990 * nops then it must be from userspace. ··· 1930 1923 */ 1931 1924 static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) 1932 1925 { 1933 - if (conn->ping_task && 1926 + if (READ_ONCE(conn->ping_task) && 1934 1927 time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + 1935 1928 (conn->ping_timeout * HZ), jiffies)) 1936 1929 return 1; ··· 2065 2058 * Checking the transport already or nop from a cmd timeout still 2066 2059 * running 2067 2060 */ 2068 - if (conn->ping_task) { 2061 + if (READ_ONCE(conn->ping_task)) { 2069 2062 task->have_checked_conn = true; 2070 2063 rc = BLK_EH_RESET_TIMER; 2071 2064 goto done;
+13 -4
drivers/target/iscsi/iscsi_target.c
··· 483 483 void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) 484 484 { 485 485 spin_lock_bh(&conn->cmd_lock); 486 - if (!list_empty(&cmd->i_conn_node) && 487 - !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP)) 486 + if (!list_empty(&cmd->i_conn_node)) 488 487 list_del_init(&cmd->i_conn_node); 489 488 spin_unlock_bh(&conn->cmd_lock); 490 489 ··· 4082 4083 spin_lock_bh(&conn->cmd_lock); 4083 4084 list_splice_init(&conn->conn_cmd_list, &tmp_list); 4084 4085 4085 - list_for_each_entry(cmd, &tmp_list, i_conn_node) { 4086 + list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) { 4086 4087 struct se_cmd *se_cmd = &cmd->se_cmd; 4087 4088 4088 4089 if (se_cmd->se_tfo != NULL) { 4089 4090 spin_lock_irq(&se_cmd->t_state_lock); 4090 - se_cmd->transport_state |= CMD_T_FABRIC_STOP; 4091 + if (se_cmd->transport_state & CMD_T_ABORTED) { 4092 + /* 4093 + * LIO's abort path owns the cleanup for this, 4094 + * so put it back on the list and let 4095 + * aborted_task handle it. 4096 + */ 4097 + list_move_tail(&cmd->i_conn_node, 4098 + &conn->conn_cmd_list); 4099 + } else { 4100 + se_cmd->transport_state |= CMD_T_FABRIC_STOP; 4101 + } 4091 4102 spin_unlock_irq(&se_cmd->t_state_lock); 4092 4103 } 4093 4104 }
+3
include/scsi/libiscsi.h
··· 132 132 void *dd_data; /* driver/transport data */ 133 133 }; 134 134 135 + /* invalid scsi_task pointer */ 136 + #define INVALID_SCSI_TASK (struct iscsi_task *)-1l 137 + 135 138 static inline int iscsi_task_has_unsol_data(struct iscsi_task *task) 136 139 { 137 140 return task->unsol_r2t.data_length > task->unsol_r2t.sent;