iscsi-scst: Do not clear reservations during nexus loss (merge r4546 from trunk)

git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.2.x@4701 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2013-01-06 13:41:22 +00:00
parent 87fdc2901b
commit fa8479a821
5 changed files with 68 additions and 49 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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