diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 5054eb98c..c518b9daf 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -3573,8 +3573,12 @@ static void iscsi_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd) switch (fn) { case SCST_NEXUS_LOSS_SESS: + /* Internal */ + break; case SCST_ABORT_ALL_TASKS_SESS: - /* They are internal */ + case SCST_ABORT_ALL_TASKS: + case SCST_NEXUS_LOSS: + sBUG_ON(1); break; default: iscsi_send_task_mgmt_resp(req, status); diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index bc55776c8..b7d93d256 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -325,14 +325,13 @@ void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd) switch (fn) { case SCST_NEXUS_LOSS_SESS: - case SCST_ABORT_ALL_TASKS_SESS: { struct iscsi_conn *conn = (struct iscsi_conn *)priv; struct iscsi_session *sess = conn->session; struct iscsi_conn *c; if (sess->sess_reinst_successor != NULL) - scst_reassign_persistent_sess_states( + scst_reassign_retained_sess_states( sess->sess_reinst_successor->scst_sess, sess->scst_sess); @@ -367,6 +366,11 @@ void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd) complete_all(&conn->ready_to_free); break; } + case SCST_ABORT_ALL_TASKS_SESS: + case SCST_ABORT_ALL_TASKS: + case SCST_NEXUS_LOSS: + sBUG_ON(1); + break; default: /* Nothing to do */ break; @@ -383,9 +387,10 @@ static void close_conn(struct iscsi_conn *conn) typeof(jiffies) start_waiting = jiffies; typeof(jiffies) shut_start_waiting = start_waiting; bool pending_reported = 0, wait_expired = 0, shut_expired = 0; - bool reinst; uint32_t tid, cid; uint64_t sid; + int rc; + int lun = 0; #define CONN_PENDING_TIMEOUT ((typeof(jiffies))10*HZ) #define CONN_WAIT_TIMEOUT ((typeof(jiffies))10*HZ) @@ -412,30 +417,14 @@ static void close_conn(struct iscsi_conn *conn) mutex_lock(&session->target->target_mutex); set_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags); - reinst = (conn->conn_reinst_successor != NULL); mutex_unlock(&session->target->target_mutex); - if (reinst) { - int rc; - int lun = 0; - - /* Abort all outstanding commands */ - rc = scst_rx_mgmt_fn_lun(session->scst_sess, - SCST_ABORT_ALL_TASKS_SESS, (uint8_t *)&lun, sizeof(lun), - SCST_NON_ATOMIC, conn); - if (rc != 0) - PRINT_ERROR("SCST_ABORT_ALL_TASKS_SESS failed %d", rc); - } else { - int rc; - int lun = 0; - - rc = scst_rx_mgmt_fn_lun(session->scst_sess, - SCST_NEXUS_LOSS_SESS, (uint8_t *)&lun, sizeof(lun), - SCST_NON_ATOMIC, conn); - if (rc != 0) - PRINT_ERROR("SCST_NEXUS_LOSS_SESS failed %d", rc); - } + rc = scst_rx_mgmt_fn_lun(session->scst_sess, + SCST_NEXUS_LOSS_SESS, (uint8_t *)&lun, sizeof(lun), + SCST_NON_ATOMIC, conn); + if (rc != 0) + PRINT_ERROR("SCST_NEXUS_LOSS_SESS failed %d", rc); if (conn->read_state != RX_INIT_BHS) { struct iscsi_cmnd *cmnd = conn->read_cmnd; diff --git a/scst/include/scst.h b/scst/include/scst.h index d31220dc0..48e1053b5 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -1262,6 +1262,18 @@ struct scst_dev_type { int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd, struct scst_tgt_dev *tgt_dev); + /* + * Called to reassign retained states (mode pages, etc.) from + * old_tgt_dev to new_tgt_dev during nexus loss (iSCSI sessions + * reinstatement, etc.) processing. + * + * Can be called under scst_mutex. + * + * OPTIONAL + */ + void (*reassign_retained_states) (struct scst_tgt_dev *new_tgt_dev, + struct scst_tgt_dev *old_tgt_dev); + /* * Called to notify dev handler that its sg_tablesize is too low to * satisfy this command's data transfer requirements. Should return @@ -4109,7 +4121,7 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd, int scst_obtain_device_parameters(struct scst_device *dev); -void scst_reassign_persistent_sess_states(struct scst_session *new_sess, +void scst_reassign_retained_sess_states(struct scst_session *new_sess, struct scst_session *old_sess); int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun); diff --git a/scst/include/scst_const.h b/scst/include/scst_const.h index 7dad646d3..3d197d1a5 100644 --- a/scst/include/scst_const.h +++ b/scst/include/scst_const.h @@ -97,8 +97,7 @@ /* * Notifies about I_T nexus loss event in the corresponding session. - * Aborts all tasks there, resets the reservation, if any, and sets - * up the I_T Nexus loss UA. + * Aborts all tasks there and sets up the I_T Nexus loss UA. */ #define SCST_NEXUS_LOSS_SESS 6 @@ -107,8 +106,7 @@ /* * Notifies about I_T nexus loss event. Aborts all tasks in all sessions - * of the tgt, resets the reservations, if any, and sets up the I_T Nexus - * loss UA. + * of the tgt, and sets up in them the I_T Nexus loss UA. */ #define SCST_NEXUS_LOSS 8 diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index a7a0cee93..ed9455de8 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -3482,25 +3482,13 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA) { TRACE_ENTRY(); - scst_clear_reservation(tgt_dev); - -#if 0 /* Clearing UAs and last sense isn't required by SAM and it looks to be - * better to not clear them to not loose important events, so let's - * disable it. - */ - /* With activity suspended the lock isn't needed, but let's be safe */ - spin_lock_bh(&tgt_dev->tgt_dev_lock); - scst_free_all_UA(tgt_dev); - memset(tgt_dev->tgt_dev_sense, 0, sizeof(tgt_dev->tgt_dev_sense)); - spin_unlock_bh(&tgt_dev->tgt_dev_lock); -#endif - if (queue_UA) { uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN]; int sl = scst_set_sense(sense_buffer, sizeof(sense_buffer), tgt_dev->dev->d_sense, SCST_LOAD_SENSE(scst_sense_nexus_loss_UA)); - scst_check_set_UA(tgt_dev, sense_buffer, sl, 0); + scst_check_set_UA(tgt_dev, sense_buffer, sl, + SCST_SET_UA_FLAG_AT_HEAD); } TRACE_EXIT(); @@ -6930,18 +6918,18 @@ int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun) EXPORT_SYMBOL(scst_get_max_lun_commands); /** - * scst_reassign_persistent_sess_states() - reassigns persistent states + * scst_reassign_retained_sess_states() - reassigns retained states * - * Reassigns persistent states from old_sess to new_sess. + * Reassigns retained during nexus loss states from old_sess to new_sess. */ -void scst_reassign_persistent_sess_states(struct scst_session *new_sess, +void scst_reassign_retained_sess_states(struct scst_session *new_sess, struct scst_session *old_sess) { struct scst_device *dev; TRACE_ENTRY(); - TRACE_PR("Reassigning persistent states from old_sess %p to " + TRACE_MGMT_DBG("Reassigning retained states from old_sess %p to " "new_sess %p", old_sess, new_sess); if ((new_sess == NULL) || (old_sess == NULL)) { @@ -6989,6 +6977,24 @@ void scst_reassign_persistent_sess_states(struct scst_session *new_sess, continue; } + /** Reassign regualar reservations **/ + + if (dev->dev_reserved && + !test_bit(SCST_TGT_DEV_RESERVED, &old_tgt_dev->tgt_dev_flags)) { + clear_bit(SCST_TGT_DEV_RESERVED, &new_tgt_dev->tgt_dev_flags); + set_bit(SCST_TGT_DEV_RESERVED, &old_tgt_dev->tgt_dev_flags); + TRACE_DBG("Reservation reassigned from old_tgt_dev %p " + "to new_tgt_dev %p", old_tgt_dev, new_tgt_dev); + } + + /** Reassign PRs **/ + + if ((new_sess->transport_id == NULL) || + (old_sess->transport_id == NULL)) { + TRACE_DBG("%s", "new_sess or old_sess doesn't support PRs"); + goto next; + } + scst_pr_write_lock(dev); if (old_tgt_dev->registrant != NULL) { @@ -7006,6 +7012,16 @@ void scst_reassign_persistent_sess_states(struct scst_session *new_sess, } scst_pr_write_unlock(dev); +next: + /** Reassign other DH specific states **/ + + if (dev->handler->reassign_retained_states != NULL) { + TRACE_DBG("Calling dev's %s reassign_retained_states(%p, %p)", + dev->virt_name, new_tgt_dev, old_tgt_dev); + dev->handler->reassign_retained_states(new_tgt_dev, old_tgt_dev); + TRACE_DBG("Dev's %s reassign_retained_states() returned", + dev->virt_name); + } } mutex_unlock(&scst_mutex); @@ -7014,7 +7030,7 @@ out: TRACE_EXIT(); return; } -EXPORT_SYMBOL(scst_reassign_persistent_sess_states); +EXPORT_SYMBOL(scst_reassign_retained_sess_states); /** * scst_get_next_lexem() - parse and return next lexem in the string