From: Mike Christie michael.christie@oracle.com
stable inclusion from linux-4.19.198 commit bf20d85a88384574fabb3d53ad62a8af57e7ab11
--------------------------------
If we haven't done a unbind target call we can race where iscsi_conn_teardown wakes up the EH thread and then frees the conn while those threads are still accessing the conn ehwait.
We can only do one TMF per session so this just moves the TMF fields from the conn to the session. We can then rely on the iscsi_session_teardown->iscsi_remove_session->__iscsi_unbind_session call to remove the target and it's devices, and know after that point there is no device or scsi-ml callout trying to access the session.
Link: https://lore.kernel.org/r/20210525181821.7617-14-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com
conflcits: drivers/scsi/libiscsi.c
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/libiscsi.c | 116 +++++++++++++++++++--------------------- include/scsi/libiscsi.h | 11 ++-- 2 files changed, 61 insertions(+), 66 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 8ea441fe8aba3..75096f1565425 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -265,11 +265,11 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task) */ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) { - struct iscsi_conn *conn = task->conn; - struct iscsi_tm *tmf = &conn->tmhdr; + struct iscsi_session *session = task->conn->session; + struct iscsi_tm *tmf = &session->tmhdr; u64 hdr_lun;
- if (conn->tmf_state == TMF_INITIAL) + if (session->tmf_state == TMF_INITIAL) return 0;
if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC) @@ -289,24 +289,19 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) * Fail all SCSI cmd PDUs */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) { - iscsi_conn_printk(KERN_INFO, conn, - "task [op %x itt " - "0x%x/0x%x] " - "rejected.\n", - opcode, task->itt, - task->hdr_itt); + iscsi_session_printk(KERN_INFO, session, + "task [op %x itt 0x%x/0x%x] rejected.\n", + opcode, task->itt, task->hdr_itt); return -EACCES; } /* * And also all data-out PDUs in response to R2T * if fast_abort is set. */ - if (conn->session->fast_abort) { - iscsi_conn_printk(KERN_INFO, conn, - "task [op %x itt " - "0x%x/0x%x] fast abort.\n", - opcode, task->itt, - task->hdr_itt); + if (session->fast_abort) { + iscsi_session_printk(KERN_INFO, session, + "task [op %x itt 0x%x/0x%x] fast abort.\n", + opcode, task->itt, task->hdr_itt); return -EACCES; } break; @@ -319,7 +314,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) */ if (opcode == ISCSI_OP_SCSI_DATA_OUT && task->hdr_itt == tmf->rtt) { - ISCSI_DBG_SESSION(conn->session, + ISCSI_DBG_SESSION(session, "Preventing task %x/%x from sending " "data-out due to abort task in " "progress\n", task->itt, @@ -993,20 +988,21 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) { struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr; + struct iscsi_session *session = conn->session;
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++;
- if (conn->tmf_state != TMF_QUEUED) + if (session->tmf_state != TMF_QUEUED) return;
if (tmf->response == ISCSI_TMF_RSP_COMPLETE) - conn->tmf_state = TMF_SUCCESS; + session->tmf_state = TMF_SUCCESS; else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) - conn->tmf_state = TMF_NOT_FOUND; + session->tmf_state = TMF_NOT_FOUND; else - conn->tmf_state = TMF_FAILED; - wake_up(&conn->ehwait); + session->tmf_state = TMF_FAILED; + wake_up(&session->ehwait); }
static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) @@ -1879,15 +1875,14 @@ EXPORT_SYMBOL_GPL(iscsi_target_alloc);
static void iscsi_tmf_timedout(struct timer_list *t) { - struct iscsi_conn *conn = from_timer(conn, t, tmf_timer); - struct iscsi_session *session = conn->session; + struct iscsi_session *session = from_timer(session, t, tmf_timer);
spin_lock(&session->frwd_lock); - if (conn->tmf_state == TMF_QUEUED) { - conn->tmf_state = TMF_TIMEDOUT; + if (session->tmf_state == TMF_QUEUED) { + session->tmf_state = TMF_TIMEDOUT; ISCSI_DBG_EH(session, "tmf timedout\n"); /* unblock eh_abort() */ - wake_up(&conn->ehwait); + wake_up(&session->ehwait); } spin_unlock(&session->frwd_lock); } @@ -1910,8 +1905,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, return -EPERM; } conn->tmfcmd_pdus_cnt++; - conn->tmf_timer.expires = timeout * HZ + jiffies; - add_timer(&conn->tmf_timer); + session->tmf_timer.expires = timeout * HZ + jiffies; + add_timer(&session->tmf_timer); ISCSI_DBG_EH(session, "tmf set timeout\n");
spin_unlock_bh(&session->frwd_lock); @@ -1925,12 +1920,12 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, * 3) session is terminated or restarted or userspace has * given up on recovery */ - wait_event_interruptible(conn->ehwait, age != session->age || + wait_event_interruptible(session->ehwait, age != session->age || session->state != ISCSI_STATE_LOGGED_IN || - conn->tmf_state != TMF_QUEUED); + session->tmf_state != TMF_QUEUED); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&conn->tmf_timer); + del_timer_sync(&session->tmf_timer);
mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -2320,17 +2315,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) }
/* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto failed; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED;
- hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_abort_task_pdu(task, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) goto failed;
- switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: spin_unlock_bh(&session->frwd_lock); /* @@ -2345,7 +2340,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) */ spin_lock_bh(&session->frwd_lock); fail_scsi_task(task, DID_ABORT); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); spin_unlock_bh(&session->frwd_lock); iscsi_start_tx(conn); @@ -2356,7 +2351,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto failed_unlocked; case TMF_NOT_FOUND: if (!sc->SCp.ptr) { - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); /* task completed before tmf abort response */ ISCSI_DBG_EH(session, "sc completed while abort in " @@ -2365,7 +2360,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) } /* fall through */ default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto failed; }
@@ -2424,11 +2419,11 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) conn = session->leadconn;
/* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto unlock; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED;
- hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_lun_reset_pdu(sc, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2437,7 +2432,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) goto unlock; }
- switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2445,7 +2440,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto unlock; }
@@ -2457,7 +2452,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock);
iscsi_start_tx(conn); @@ -2480,8 +2475,7 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) spin_lock_bh(&session->frwd_lock); if (session->state != ISCSI_STATE_LOGGED_IN) { session->state = ISCSI_STATE_RECOVERY_FAILED; - if (session->leadconn) - wake_up(&session->leadconn->ehwait); + wake_up(&session->ehwait); } spin_unlock_bh(&session->frwd_lock); } @@ -2536,7 +2530,7 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
ISCSI_DBG_EH(session, "wait for relogin\n"); - wait_event_interruptible_timeout(conn->ehwait, + wait_event_interruptible_timeout(session->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || session->state == ISCSI_STATE_RECOVERY_FAILED, @@ -2598,11 +2592,11 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) conn = session->leadconn;
/* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto unlock; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED;
- hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_tgt_reset_pdu(sc, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2611,7 +2605,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) goto unlock; }
- switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2619,7 +2613,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto unlock; }
@@ -2631,7 +2625,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, -1, DID_ERROR); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock);
iscsi_start_tx(conn); @@ -2961,7 +2955,10 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, session->tt = iscsit; session->dd_data = cls_session->dd_data + sizeof(*session);
+ session->tmf_state = TMF_INITIAL; + timer_setup(&session->tmf_timer, iscsi_tmf_timedout, 0); mutex_init(&session->eh_mutex); + spin_lock_init(&session->frwd_lock); spin_lock_init(&session->back_lock);
@@ -3065,7 +3062,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->id = conn_idx; conn->exp_statsn = 0; - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; conn->intimate_cpu = -1;
timer_setup(&conn->transport_timer, iscsi_check_transport_timeouts, 0); @@ -3091,8 +3088,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, goto login_task_data_alloc_fail; conn->login_task->data = conn->data = data;
- timer_setup(&conn->tmf_timer, iscsi_tmf_timedout, 0); - init_waitqueue_head(&conn->ehwait); + init_waitqueue_head(&session->ehwait);
return cls_conn;
@@ -3127,7 +3123,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) * leading connection? then give up on recovery. */ session->state = ISCSI_STATE_TERMINATE; - wake_up(&conn->ehwait); + wake_up(&session->ehwait); } spin_unlock_bh(&session->frwd_lock);
@@ -3202,7 +3198,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) * commands after successful recovery */ conn->stop_stage = 0; - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; session->age++; if (session->age == 16) session->age = 0; @@ -3216,7 +3212,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) spin_unlock_bh(&session->frwd_lock);
iscsi_unblock_session(session->cls_session); - wake_up(&conn->ehwait); + wake_up(&session->ehwait); return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_start); @@ -3309,7 +3305,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, spin_lock_bh(&session->frwd_lock); fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); fail_mgmt_tasks(session, conn); - memset(&conn->tmhdr, 0, sizeof(conn->tmhdr)); + memset(&session->tmhdr, 0, sizeof(session->tmhdr)); spin_unlock_bh(&session->frwd_lock); mutex_unlock(&session->eh_mutex); } diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index c14d739c88873..156232a9e48b2 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -208,12 +208,6 @@ struct iscsi_conn { unsigned long suspend_tx; /* suspend Tx */ unsigned long suspend_rx; /* suspend Rx */
- /* abort */ - wait_queue_head_t ehwait; /* used in eh_abort() */ - struct iscsi_tm tmhdr; - struct timer_list tmf_timer; - int tmf_state; /* see TMF_INITIAL, etc.*/ - /* negotiated params */ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ unsigned max_xmit_dlength; /* target_max_recv_dsl */ @@ -284,6 +278,11 @@ struct iscsi_session { * and recv lock. */ struct mutex eh_mutex; + /* abort */ + wait_queue_head_t ehwait; /* used in eh_abort() */ + struct iscsi_tm tmhdr; + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/
/* iSCSI session-wide sequencing */ uint32_t cmdsn;
From: Ye Bin yebin10@huawei.com
hulk inclusion category: bugfix bugzilla: NA CVE: NA
-----------------------------------------------
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/scsi/scsi_transport_iscsi.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 484e9787d817b..848ba2822a21d 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -258,6 +258,18 @@ struct iscsi_cls_session { struct device dev; /* sysfs transport/container device */ };
+struct iscsi_cls_session_wrapper { + /* abort */ + wait_queue_head_t ehwait; /* used in eh_abort() */ + struct iscsi_tm tmhdr; + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/ + struct iscsi_cls_session cls_sess; +}; + +#define iscsi_cls_session_to_wrapper(session) \ + container_of(session, struct iscsi_cls_session_wrapper, cls_sess) + #define iscsi_dev_to_session(_dev) \ container_of(_dev, struct iscsi_cls_session, dev)
From: Ye Bin yebin10@huawei.com
hulk inclusion category: bugfix bugzilla: NA CVE: NA
-----------------------------------------------
Now we wrapper iscsi_cls_session wtih iscsi_cls_session_warpper, so we alloc iscsi_cls_session_wrapper instead of iscsi_cls_session.
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/scsi_transport_iscsi.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 20e69052161e6..d3632547799c9 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1705,12 +1705,14 @@ EXPORT_SYMBOL_GPL(iscsi_is_session_online); static void iscsi_session_release(struct device *dev) { struct iscsi_cls_session *session = iscsi_dev_to_session(dev); + struct iscsi_cls_session_wrapper *session_wrapper = + iscsi_cls_session_to_wrapper(session); struct Scsi_Host *shost;
shost = iscsi_session_to_shost(session); scsi_host_put(shost); ISCSI_DBG_TRANS_SESSION(session, "Completing session release\n"); - kfree(session); + kfree(session_wrapper); }
int iscsi_is_session_dev(const struct device *dev) @@ -2014,13 +2016,14 @@ struct iscsi_cls_session * iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, int dd_size) { + struct iscsi_cls_session_wrapper *session_wrapper; struct iscsi_cls_session *session;
- session = kzalloc(sizeof(*session) + dd_size, - GFP_KERNEL); - if (!session) + session_wrapper = kzalloc(sizeof(*session_wrapper) + dd_size, + GFP_KERNEL); + if (!session_wrapper) return NULL; - + session = &session_wrapper->cls_sess; session->transport = transport; session->creator = -1; session->recovery_tmo = 120;
From: Ye Bin yebin10@huawei.com
hulk inclusion category: bugfix bugzilla: NA CVE: NA
-----------------------------------------------
Use struct iscsi_cls_session_wrapper to avoid kabi broken.
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/libiscsi.c | 109 +++++++++++++++++++++++++--------------- include/scsi/libiscsi.h | 20 +++++--- 2 files changed, 82 insertions(+), 47 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 75096f1565425..02060aec08bf9 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -266,10 +266,12 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task) static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) { struct iscsi_session *session = task->conn->session; - struct iscsi_tm *tmf = &session->tmhdr; + struct iscsi_cls_session_wrapper *cls_session = + iscsi_cls_session_to_wrapper(session->cls_session); + struct iscsi_tm *tmf = &cls_session->tmhdr; u64 hdr_lun;
- if (session->tmf_state == TMF_INITIAL) + if (cls_session->tmf_state == TMF_INITIAL) return 0;
if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC) @@ -988,7 +990,8 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) { struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr; - struct iscsi_session *session = conn->session; + struct iscsi_cls_session_wrapper *session = + iscsi_cls_session_to_wrapper(conn->session->cls_session);
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++; @@ -1875,14 +1878,16 @@ EXPORT_SYMBOL_GPL(iscsi_target_alloc);
static void iscsi_tmf_timedout(struct timer_list *t) { - struct iscsi_session *session = from_timer(session, t, tmf_timer); + struct iscsi_cls_session_wrapper *cls_session = + from_timer(cls_session, t, tmf_timer); + struct iscsi_session *session = cls_session->cls_sess.dd_data;
spin_lock(&session->frwd_lock); - if (session->tmf_state == TMF_QUEUED) { - session->tmf_state = TMF_TIMEDOUT; + if (cls_session->tmf_state == TMF_QUEUED) { + cls_session->tmf_state = TMF_TIMEDOUT; ISCSI_DBG_EH(session, "tmf timedout\n"); /* unblock eh_abort() */ - wake_up(&session->ehwait); + wake_up(&cls_session->ehwait); } spin_unlock(&session->frwd_lock); } @@ -1893,6 +1898,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, __must_hold(&session->frwd_lock) { struct iscsi_session *session = conn->session; + struct iscsi_cls_session_wrapper *cls_session = + iscsi_cls_session_to_wrapper(session->cls_session); struct iscsi_task *task;
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, @@ -1905,8 +1912,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, return -EPERM; } conn->tmfcmd_pdus_cnt++; - session->tmf_timer.expires = timeout * HZ + jiffies; - add_timer(&session->tmf_timer); + cls_session->tmf_timer.expires = timeout * HZ + jiffies; + add_timer(&cls_session->tmf_timer); ISCSI_DBG_EH(session, "tmf set timeout\n");
spin_unlock_bh(&session->frwd_lock); @@ -1920,12 +1927,12 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, * 3) session is terminated or restarted or userspace has * given up on recovery */ - wait_event_interruptible(session->ehwait, age != session->age || + wait_event_interruptible(cls_session->ehwait, age != session->age || session->state != ISCSI_STATE_LOGGED_IN || - session->tmf_state != TMF_QUEUED); + cls_session->tmf_state != TMF_QUEUED); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&session->tmf_timer); + del_timer_sync(&cls_session->tmf_timer);
mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -2252,6 +2259,7 @@ static void iscsi_prep_abort_task_pdu(struct iscsi_task *task, int iscsi_eh_abort(struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; + struct iscsi_cls_session_wrapper *session_wrapper; struct iscsi_session *session; struct iscsi_conn *conn; struct iscsi_task *task; @@ -2259,6 +2267,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) int age;
cls_session = starget_to_session(scsi_target(sc->device)); + session_wrapper = iscsi_cls_session_to_wrapper(cls_session); session = cls_session->dd_data;
ISCSI_DBG_EH(session, "aborting sc %p\n", sc); @@ -2315,17 +2324,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) }
/* only have one tmf outstanding at a time */ - if (session->tmf_state != TMF_INITIAL) + if (session_wrapper->tmf_state != TMF_INITIAL) goto failed; - session->tmf_state = TMF_QUEUED; + session_wrapper->tmf_state = TMF_QUEUED;
- hdr = &session->tmhdr; + hdr = &session_wrapper->tmhdr; iscsi_prep_abort_task_pdu(task, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) goto failed;
- switch (session->tmf_state) { + switch (session_wrapper->tmf_state) { case TMF_SUCCESS: spin_unlock_bh(&session->frwd_lock); /* @@ -2340,7 +2349,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) */ spin_lock_bh(&session->frwd_lock); fail_scsi_task(task, DID_ABORT); - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); spin_unlock_bh(&session->frwd_lock); iscsi_start_tx(conn); @@ -2351,7 +2360,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto failed_unlocked; case TMF_NOT_FOUND: if (!sc->SCp.ptr) { - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); /* task completed before tmf abort response */ ISCSI_DBG_EH(session, "sc completed while abort in " @@ -2360,7 +2369,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) } /* fall through */ default: - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; goto failed; }
@@ -2397,12 +2406,14 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) int iscsi_eh_device_reset(struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; + struct iscsi_cls_session_wrapper *session_wrapper; struct iscsi_session *session; struct iscsi_conn *conn; struct iscsi_tm *hdr; int rc = FAILED;
cls_session = starget_to_session(scsi_target(sc->device)); + session_wrapper = iscsi_cls_session_to_wrapper(cls_session); session = cls_session->dd_data;
ISCSI_DBG_EH(session, "LU Reset [sc %p lun %llu]\n", sc, @@ -2419,11 +2430,11 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) conn = session->leadconn;
/* only have one tmf outstanding at a time */ - if (session->tmf_state != TMF_INITIAL) + if (session_wrapper->tmf_state != TMF_INITIAL) goto unlock; - session->tmf_state = TMF_QUEUED; + session_wrapper->tmf_state = TMF_QUEUED;
- hdr = &session->tmhdr; + hdr = &session_wrapper->tmhdr; iscsi_prep_lun_reset_pdu(sc, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2432,7 +2443,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) goto unlock; }
- switch (session->tmf_state) { + switch (session_wrapper->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2440,7 +2451,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; goto unlock; }
@@ -2452,7 +2463,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock);
iscsi_start_tx(conn); @@ -2471,11 +2482,13 @@ EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) { struct iscsi_session *session = cls_session->dd_data; + struct iscsi_cls_session_wrapper *session_wrapper = + iscsi_cls_session_to_wrapper(cls_session);
spin_lock_bh(&session->frwd_lock); if (session->state != ISCSI_STATE_LOGGED_IN) { session->state = ISCSI_STATE_RECOVERY_FAILED; - wake_up(&session->ehwait); + wake_up(&session_wrapper->ehwait); } spin_unlock_bh(&session->frwd_lock); } @@ -2491,10 +2504,12 @@ EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); int iscsi_eh_session_reset(struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; + struct iscsi_cls_session_wrapper *session_wrapper; struct iscsi_session *session; struct iscsi_conn *conn;
cls_session = starget_to_session(scsi_target(sc->device)); + session_wrapper = iscsi_cls_session_to_wrapper(cls_session); session = cls_session->dd_data; conn = session->leadconn;
@@ -2530,7 +2545,7 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
ISCSI_DBG_EH(session, "wait for relogin\n"); - wait_event_interruptible_timeout(session->ehwait, + wait_event_interruptible_timeout(session_wrapper->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || session->state == ISCSI_STATE_RECOVERY_FAILED, @@ -2570,12 +2585,14 @@ static void iscsi_prep_tgt_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) static int iscsi_eh_target_reset(struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; + struct iscsi_cls_session_wrapper *session_wrapper; struct iscsi_session *session; struct iscsi_conn *conn; struct iscsi_tm *hdr; int rc = FAILED;
cls_session = starget_to_session(scsi_target(sc->device)); + session_wrapper = iscsi_cls_session_to_wrapper(cls_session); session = cls_session->dd_data;
ISCSI_DBG_EH(session, "tgt Reset [sc %p tgt %s]\n", sc, @@ -2592,11 +2609,11 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) conn = session->leadconn;
/* only have one tmf outstanding at a time */ - if (session->tmf_state != TMF_INITIAL) + if (session_wrapper->tmf_state != TMF_INITIAL) goto unlock; - session->tmf_state = TMF_QUEUED; + session_wrapper->tmf_state = TMF_QUEUED;
- hdr = &session->tmhdr; + hdr = &session_wrapper->tmhdr; iscsi_prep_tgt_reset_pdu(sc, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2605,7 +2622,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) goto unlock; }
- switch (session->tmf_state) { + switch (session_wrapper->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2613,7 +2630,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; goto unlock; }
@@ -2625,7 +2642,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, -1, DID_ERROR); - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock);
iscsi_start_tx(conn); @@ -2918,6 +2935,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, struct iscsi_host *ihost = shost_priv(shost); struct iscsi_session *session; struct iscsi_cls_session *cls_session; + struct iscsi_cls_session_wrapper *cls_sess_wrapper; int cmd_i, scsi_cmds; unsigned long flags;
@@ -2955,8 +2973,9 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, session->tt = iscsit; session->dd_data = cls_session->dd_data + sizeof(*session);
- session->tmf_state = TMF_INITIAL; - timer_setup(&session->tmf_timer, iscsi_tmf_timedout, 0); + cls_sess_wrapper = iscsi_cls_session_to_wrapper(cls_session); + cls_sess_wrapper->tmf_state = TMF_INITIAL; + timer_setup(&cls_sess_wrapper->tmf_timer, iscsi_tmf_timedout, 0); mutex_init(&session->eh_mutex);
spin_lock_init(&session->frwd_lock); @@ -3045,6 +3064,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, uint32_t conn_idx) { struct iscsi_session *session = cls_session->dd_data; + struct iscsi_cls_session_wrapper *session_wrapper = + iscsi_cls_session_to_wrapper(cls_session); struct iscsi_conn *conn; struct iscsi_cls_conn *cls_conn; char *data; @@ -3062,7 +3083,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->id = conn_idx; conn->exp_statsn = 0; - session->tmf_state = TMF_INITIAL; + session_wrapper->tmf_state = TMF_INITIAL; conn->intimate_cpu = -1;
timer_setup(&conn->transport_timer, iscsi_check_transport_timeouts, 0); @@ -3088,7 +3109,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, goto login_task_data_alloc_fail; conn->login_task->data = conn->data = data;
- init_waitqueue_head(&session->ehwait); + init_waitqueue_head(&session_wrapper->ehwait);
return cls_conn;
@@ -3119,11 +3140,13 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) spin_lock_bh(&session->frwd_lock); conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; if (session->leadconn == conn) { + struct iscsi_cls_session_wrapper *cls_session = + iscsi_cls_session_to_wrapper(session->cls_session); /* * leading connection? then give up on recovery. */ session->state = ISCSI_STATE_TERMINATE; - wake_up(&session->ehwait); + wake_up(&cls_session->ehwait); } spin_unlock_bh(&session->frwd_lock);
@@ -3153,6 +3176,8 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; + struct iscsi_cls_session_wrapper *cls_session = + iscsi_cls_session_to_wrapper(session->cls_session);
if (!session) { iscsi_conn_printk(KERN_ERR, conn, @@ -3198,7 +3223,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) * commands after successful recovery */ conn->stop_stage = 0; - session->tmf_state = TMF_INITIAL; + cls_session->tmf_state = TMF_INITIAL; session->age++; if (session->age == 16) session->age = 0; @@ -3212,7 +3237,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) spin_unlock_bh(&session->frwd_lock);
iscsi_unblock_session(session->cls_session); - wake_up(&session->ehwait); + wake_up(&cls_session->ehwait); return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_start); @@ -3253,6 +3278,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, struct iscsi_conn *conn, int flag) { int old_stop_stage; + struct iscsi_cls_session_wrapper *cls_session = + iscsi_cls_session_to_wrapper(session->cls_session);
mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -3305,7 +3332,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, spin_lock_bh(&session->frwd_lock); fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); fail_mgmt_tasks(session, conn); - memset(&session->tmhdr, 0, sizeof(session->tmhdr)); + memset(&cls_session->tmhdr, 0, sizeof(cls_session->tmhdr)); spin_unlock_bh(&session->frwd_lock); mutex_unlock(&session->eh_mutex); } diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 156232a9e48b2..254e72b46d10f 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -208,6 +208,20 @@ struct iscsi_conn { unsigned long suspend_tx; /* suspend Tx */ unsigned long suspend_rx; /* suspend Rx */
+ /* follow four member move to iscsi_cls_session_wrapper, discard it */ +#ifndef __GENKSYMS__ + /* abort */ + wait_queue_head_t ehwait_discard; /* used in eh_abort() */ + struct iscsi_tm tmhdr_discard; + struct timer_list tmf_timer_discard; + int tmf_state_discard; /* see TMF_INITIAL, etc.*/ +#else + /* abort */ + wait_queue_head_t ehwait; /* used in eh_abort() */ + struct iscsi_tm tmhdr; + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/ +#endif /* negotiated params */ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ unsigned max_xmit_dlength; /* target_max_recv_dsl */ @@ -278,12 +292,6 @@ struct iscsi_session { * and recv lock. */ struct mutex eh_mutex; - /* abort */ - wait_queue_head_t ehwait; /* used in eh_abort() */ - struct iscsi_tm tmhdr; - struct timer_list tmf_timer; - int tmf_state; /* see TMF_INITIAL, etc.*/ - /* iSCSI session-wide sequencing */ uint32_t cmdsn; uint32_t exp_cmdsn;