diff options
| author | peter dunlap <Peter.Dunlap@Sun.COM> | 2009-05-08 16:46:37 -0600 |
|---|---|---|
| committer | peter dunlap <Peter.Dunlap@Sun.COM> | 2009-05-08 16:46:37 -0600 |
| commit | 72cf314316bed51cd2e5fd0cb021a9725316a6b0 (patch) | |
| tree | af9287fcfa264668b275e1aea7211c5071ac21a0 /usr/src/uts/common/io/idm | |
| parent | 8fe960854f0d52e2e8a80ba68e8621a5ac6a866d (diff) | |
| download | illumos-gate-72cf314316bed51cd2e5fd0cb021a9725316a6b0.tar.gz | |
6832684 Panic in idm while running iser tests on snv_113 BAD TRAP: type=e (#pf Page fault)
6835844 iSCSI target server panic with RHEL 4.5.2 client, mutex_destroy
6755803 win2003 initiator numerous iscsi connection lost and connection retries mesgs to iscsi target
6823971 iscsit returns an overly pessimistic login error when the target is offline
Diffstat (limited to 'usr/src/uts/common/io/idm')
| -rw-r--r-- | usr/src/uts/common/io/idm/idm.c | 8 | ||||
| -rw-r--r-- | usr/src/uts/common/io/idm/idm_impl.c | 71 |
2 files changed, 62 insertions, 17 deletions
diff --git a/usr/src/uts/common/io/idm/idm.c b/usr/src/uts/common/io/idm/idm.c index 4dd1700975..6ab5811a8a 100644 --- a/usr/src/uts/common/io/idm/idm.c +++ b/usr/src/uts/common/io/idm/idm.c @@ -833,6 +833,7 @@ idm_buf_tx_to_ini_done(idm_task_t *idt, idm_buf_t *idb, idm_status_t status) switch (idt->idt_state) { case TASK_ACTIVE: + idt->idt_ic->ic_timestamp = ddi_get_lbolt(); idm_buf_unbind_in_locked(idt, idb); mutex_exit(&idt->idt_mutex); (*idb->idb_buf_cb)(idb, status); @@ -903,6 +904,7 @@ idm_buf_rx_from_ini_done(idm_task_t *idt, idm_buf_t *idb, idm_status_t status) switch (idt->idt_state) { case TASK_ACTIVE: + idt->idt_ic->ic_timestamp = ddi_get_lbolt(); idm_buf_unbind_out_locked(idt, idb); mutex_exit(&idt->idt_mutex); (*idb->idb_buf_cb)(idb, status); @@ -2100,6 +2102,12 @@ idm_refcnt_init(idm_refcnt_t *refcnt, void *referenced_obj) void idm_refcnt_destroy(idm_refcnt_t *refcnt) { + /* + * Grab the mutex to there are no other lingering threads holding + * the mutex before we destroy it (e.g. idm_refcnt_rele just after + * the refcnt goes to zero if ir_waiting == REF_WAIT_ASYNC) + */ + mutex_enter(&refcnt->ir_mutex); ASSERT(refcnt->ir_refcnt == 0); cv_destroy(&refcnt->ir_cv); mutex_destroy(&refcnt->ir_mutex); diff --git a/usr/src/uts/common/io/idm/idm_impl.c b/usr/src/uts/common/io/idm/idm_impl.c index bf64226f8f..2e39caea15 100644 --- a/usr/src/uts/common/io/idm/idm_impl.c +++ b/usr/src/uts/common/io/idm/idm_impl.c @@ -1012,8 +1012,47 @@ idm_wd_thread(void *arg) idle_time = ddi_get_lbolt() - ic->ic_timestamp; /* + * If this connection is in FFP then grab a hold + * and check the various timeout thresholds. Otherwise + * the connection is closing and we should just + * move on to the next one. + */ + mutex_enter(&ic->ic_state_mutex); + if (ic->ic_ffp) { + idm_conn_hold(ic); + } else { + mutex_exit(&ic->ic_state_mutex); + continue; + } + + /* * If there hasn't been any activity on this - * connection for the specified period then + * connection for the keepalive timeout period + * and if the client has provided a keepalive + * callback then call the keepalive callback. + * This allows the client to take action to keep + * the link alive (like send a nop PDU). + */ + if ((TICK_TO_SEC(idle_time) >= + IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT) && + !ic->ic_keepalive) { + ic->ic_keepalive = B_TRUE; + if (ic->ic_conn_ops.icb_keepalive) { + mutex_exit(&ic->ic_state_mutex); + mutex_exit(&idm.idm_global_mutex); + (*ic->ic_conn_ops.icb_keepalive)(ic); + mutex_enter(&idm.idm_global_mutex); + mutex_enter(&ic->ic_state_mutex); + } + } else if ((TICK_TO_SEC(idle_time) < + IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT)) { + /* Reset keepalive */ + ic->ic_keepalive = B_FALSE; + } + + /* + * If there hasn't been any activity on this + * connection for the failure timeout period then * drop the connection. We expect the initiator * to keep the connection alive if it wants the * connection to stay open. @@ -1026,25 +1065,23 @@ idm_wd_thread(void *arg) */ if (TICK_TO_SEC(idle_time) > IDM_TRANSPORT_FAIL_IDLE_TIMEOUT) { - /* - * Only send the transport fail if we're in - * FFP. State machine timers should handle - * problems in non-ffp states. - */ - if (ic->ic_ffp) { - mutex_exit(&idm.idm_global_mutex); - IDM_SM_LOG(CE_WARN, "idm_wd_thread: " - "conn %p idle for %d seconds, " - "sending CE_TRANSPORT_FAIL", - (void *)ic, (int)idle_time); - idm_conn_event(ic, CE_TRANSPORT_FAIL, - NULL); - mutex_enter(&idm.idm_global_mutex); - } + mutex_exit(&ic->ic_state_mutex); + mutex_exit(&idm.idm_global_mutex); + IDM_SM_LOG(CE_WARN, "idm_wd_thread: " + "conn %p idle for %d seconds, " + "sending CE_TRANSPORT_FAIL", + (void *)ic, (int)idle_time); + idm_conn_event(ic, CE_TRANSPORT_FAIL, NULL); + mutex_enter(&idm.idm_global_mutex); + mutex_enter(&ic->ic_state_mutex); } + + idm_conn_rele(ic); + + mutex_exit(&ic->ic_state_mutex); } - wake_time = lbolt + SEC_TO_TICK(IDM_WD_INTERVAL); + wake_time = ddi_get_lbolt() + SEC_TO_TICK(IDM_WD_INTERVAL); (void) cv_timedwait(&idm.idm_wd_cv, &idm.idm_global_mutex, wake_time); } |
