mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 13:16:34 +00:00
- Cleanups
- scst_set_initial_UA() added. It sets initial Unit Attention for session, replacing default scst_sense_reset_UA - task_mgmt_affected_cmds_done() callback added in struct scst_tgt_template. It's informs target driver that a received task management fun ction has been completed. - Now devices blocked only in reset TM commands. ABORTs, etc. now done without devices blocking - scst_unregister_session_ex() removed, since there are no users of it git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@684 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+35
-36
@@ -153,22 +153,22 @@ typedef _Bool bool;
|
||||
*************************************************************/
|
||||
|
||||
/* LUN translation (mcmd->tgt_dev assignment) */
|
||||
#define SCST_MGMT_CMD_STATE_INIT 0
|
||||
#define SCST_MCMD_STATE_INIT 0
|
||||
|
||||
/* Mgmt cmd is ready for processing */
|
||||
#define SCST_MGMT_CMD_STATE_READY 1
|
||||
#define SCST_MCMD_STATE_READY 1
|
||||
|
||||
/* Mgmt cmd is being executing */
|
||||
#define SCST_MGMT_CMD_STATE_EXECUTING 2
|
||||
#define SCST_MCMD_STATE_EXECUTING 2
|
||||
|
||||
/* Reservations are going to be cleared, if necessary */
|
||||
#define SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS 3
|
||||
/* Post check when affected commands done */
|
||||
#define SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE 3
|
||||
|
||||
/* Target driver's task_mgmt_fn_done() is going to be called */
|
||||
#define SCST_MGMT_CMD_STATE_DONE 4
|
||||
#define SCST_MCMD_STATE_DONE 4
|
||||
|
||||
/* The mcmd finished */
|
||||
#define SCST_MGMT_CMD_STATE_FINISHED 5
|
||||
#define SCST_MCMD_STATE_FINISHED 5
|
||||
|
||||
/*************************************************************
|
||||
** Constants for "atomic" parameter of SCST's functions
|
||||
@@ -616,21 +616,28 @@ struct scst_tgt_template {
|
||||
int (*pre_exec) (struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* This function informs the driver that a
|
||||
* received task management function has been completed. This
|
||||
* function is necessary because low-level protocols have some
|
||||
* means of informing the initiator about the completion of a
|
||||
* Task Management function. This function being called will
|
||||
* signify that a Task Management function is completed as far
|
||||
* as the mid-level is concerned. Any information that must be
|
||||
* stored about the command is the responsibility of the low-
|
||||
* level driver. No return value expected.
|
||||
* This function informs the driver that all affected by the
|
||||
* corresponding task management function commands have beed completed.
|
||||
* No return value expected.
|
||||
*
|
||||
* This function is expected to be NON-BLOCKING
|
||||
* This function is expected to be NON-BLOCKING.
|
||||
*
|
||||
* Called without any locks held from a thread context.
|
||||
*
|
||||
* MUST HAVE if the target supports ABORTs
|
||||
* OPTIONAL
|
||||
*/
|
||||
void (*task_mgmt_affected_cmds_done) (struct scst_mgmt_cmd *mgmt_cmd);
|
||||
|
||||
/*
|
||||
* This function informs the driver that the corresponding task
|
||||
* management function has been completed, i.e. all the corresponding
|
||||
* commands completed and freed. No return value expected.
|
||||
*
|
||||
* This function is expected to be NON-BLOCKING.
|
||||
*
|
||||
* Called without any locks held from a thread context.
|
||||
*
|
||||
* MUST HAVE if the target supports task management.
|
||||
*/
|
||||
void (*task_mgmt_fn_done) (struct scst_mgmt_cmd *mgmt_cmd);
|
||||
|
||||
@@ -987,7 +994,6 @@ struct scst_session {
|
||||
void (*init_result_fn) (struct scst_session *sess, void *data,
|
||||
int result);
|
||||
void (*unreg_done_fn) (struct scst_session *sess);
|
||||
void (*unreg_cmds_done_fn) (struct scst_session *sess);
|
||||
|
||||
#ifdef CONFIG_SCST_MEASURE_LATENCY /* must be last */
|
||||
spinlock_t meas_lock;
|
||||
@@ -1299,7 +1305,7 @@ struct scst_mgmt_cmd {
|
||||
|
||||
struct scst_session *sess;
|
||||
|
||||
/* Mgmt cmd state, one of SCST_MGMT_CMD_STATE_* constants */
|
||||
/* Mgmt cmd state, one of SCST_MCMD_STATE_* constants */
|
||||
int state;
|
||||
|
||||
int fn;
|
||||
@@ -1309,8 +1315,8 @@ struct scst_mgmt_cmd {
|
||||
unsigned int needs_unblocking:1;
|
||||
unsigned int lun_set:1; /* set, if lun field is valid */
|
||||
unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */
|
||||
/* set, if nexus loss check is done */
|
||||
unsigned int nexus_loss_check_done:1;
|
||||
/* set, if scst_mgmt_affected_cmds_done was called */
|
||||
unsigned int affected_cmds_done_called:1;
|
||||
|
||||
/*
|
||||
* Number of commands to finish before sending response,
|
||||
@@ -1690,11 +1696,6 @@ struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
|
||||
* the session is about to be completely freed. Can be NULL.
|
||||
* Parameter:
|
||||
* - sess - session
|
||||
* unreg_cmds_done_fn - pointer to the function that will be
|
||||
* asynchronously called when the last session's command completes, i.e.
|
||||
* goes to XMIT stage. Can be NULL.
|
||||
* Parameter:
|
||||
* - sess - session
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
@@ -1714,15 +1715,8 @@ struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
|
||||
* but it also starts recovering stuck commands, if there are any.
|
||||
* Otherwise, your target driver could wait for those commands forever.
|
||||
*/
|
||||
void scst_unregister_session_ex(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess),
|
||||
void (*unreg_cmds_done_fn) (struct scst_session *sess));
|
||||
|
||||
static inline void scst_unregister_session(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess))
|
||||
{
|
||||
scst_unregister_session_ex(sess, wait, unreg_done_fn, NULL);
|
||||
}
|
||||
void scst_unregister_session(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess));
|
||||
|
||||
/*
|
||||
* Registers dev handler driver
|
||||
@@ -1921,6 +1915,11 @@ void scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq);
|
||||
*/
|
||||
void scst_set_busy(struct scst_cmd *cmd);
|
||||
|
||||
/*
|
||||
* Sets initial Unit Attention for sess, replacing default scst_sense_reset_UA
|
||||
*/
|
||||
void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq);
|
||||
|
||||
/*
|
||||
* Finds a command based on the supplied tag comparing it with one
|
||||
* that previously set by scst_cmd_set_tag().
|
||||
|
||||
@@ -74,7 +74,10 @@
|
||||
|
||||
/*
|
||||
* Internal TM command issued by SCST in scst_unregister_session(). It is the
|
||||
* same as SCST_NEXUS_LOSS_SESS, except it calls unreg_cmds_done_fn().
|
||||
* same as SCST_NEXUS_LOSS_SESS, except:
|
||||
* - it doesn't call task_mgmt_affected_cmds_done()
|
||||
* - it doesn't call task_mgmt_fn_done()
|
||||
* - it doesn't queue NEXUS LOSS UA.
|
||||
*
|
||||
* Target driver shall NEVER use it!!
|
||||
*/
|
||||
|
||||
+58
-6
@@ -197,6 +197,56 @@ void scst_set_busy(struct scst_cmd *cmd)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_set_busy);
|
||||
|
||||
void scst_set_initial_UA(struct scst_session *sess, int key, int asc, int ascq)
|
||||
{
|
||||
int i;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_MGMT_DBG("Setting for sess %p initial UA %x/%x/%x", sess, key,
|
||||
asc, ascq);
|
||||
|
||||
/* Protect sess_tgt_dev_list_hash */
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
|
||||
struct list_head *sess_tgt_dev_list_head =
|
||||
&sess->sess_tgt_dev_list_hash[i];
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
|
||||
list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
|
||||
sess_tgt_dev_list_entry) {
|
||||
spin_lock_bh(&tgt_dev->tgt_dev_lock);
|
||||
if (!list_empty(&tgt_dev->UA_list)) {
|
||||
struct scst_tgt_dev_UA *ua;
|
||||
uint8_t *sense;
|
||||
|
||||
ua = list_entry(tgt_dev->UA_list.next,
|
||||
typeof(*ua), UA_list_entry);
|
||||
sense = ua->UA_sense_buffer;
|
||||
if ((sense[2] == UNIT_ATTENTION) &&
|
||||
(sense[12] == 0x29) &&
|
||||
(sense[13] == 0)) {
|
||||
scst_set_sense(sense,
|
||||
sizeof(ua->UA_sense_buffer),
|
||||
key, asc, ascq);
|
||||
} else
|
||||
PRINT_ERROR("%s",
|
||||
"The first UA isn't RESET UA");
|
||||
} else
|
||||
PRINT_ERROR("%s", "There's no RESET UA to "
|
||||
"replace");
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_set_initial_UA);
|
||||
|
||||
int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
|
||||
{
|
||||
int res;
|
||||
@@ -642,7 +692,7 @@ out_free:
|
||||
static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev);
|
||||
|
||||
/* No locks supposed to be held, scst_mutex - held */
|
||||
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev)
|
||||
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -653,11 +703,13 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev)
|
||||
scst_free_all_UA(tgt_dev);
|
||||
spin_unlock_bh(&tgt_dev->tgt_dev_lock);
|
||||
|
||||
spin_lock_bh(&scst_temp_UA_lock);
|
||||
scst_set_sense(scst_temp_UA, sizeof(scst_temp_UA),
|
||||
SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
|
||||
scst_check_set_UA(tgt_dev, scst_temp_UA, sizeof(scst_temp_UA), 0);
|
||||
spin_unlock_bh(&scst_temp_UA_lock);
|
||||
if (queue_UA) {
|
||||
spin_lock_bh(&scst_temp_UA_lock);
|
||||
scst_set_sense(scst_temp_UA, sizeof(scst_temp_UA),
|
||||
SCST_LOAD_SENSE(scst_sense_nexus_loss_UA));
|
||||
scst_check_set_UA(tgt_dev, scst_temp_UA, sizeof(scst_temp_UA), 0);
|
||||
spin_unlock_bh(&scst_temp_UA_lock);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
|
||||
@@ -251,7 +251,7 @@ struct scst_acg *scst_alloc_add_acg(const char *acg_name);
|
||||
int scst_destroy_acg(struct scst_acg *acg);
|
||||
|
||||
int scst_sess_alloc_tgt_devs(struct scst_session *sess);
|
||||
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev);
|
||||
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA);
|
||||
|
||||
int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev,
|
||||
uint64_t lun, int read_only);
|
||||
|
||||
+63
-121
@@ -3659,9 +3659,9 @@ void scst_done_cmd_mgmt(struct scst_cmd *cmd)
|
||||
}
|
||||
|
||||
if (mcmd->completed) {
|
||||
sBUG_ON(mcmd->nexus_loss_check_done);
|
||||
sBUG_ON(mcmd->affected_cmds_done_called);
|
||||
mcmd->completed = 0;
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS;
|
||||
mcmd->state = SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE;
|
||||
TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
|
||||
"list", mcmd);
|
||||
list_add_tail(&mcmd->mgmt_cmd_list_entry,
|
||||
@@ -3692,7 +3692,7 @@ static int __scst_dec_finish_wait_count(struct scst_mgmt_cmd *mcmd, bool *wake)
|
||||
}
|
||||
|
||||
if (mcmd->completed) {
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_DONE;
|
||||
mcmd->state = SCST_MCMD_STATE_DONE;
|
||||
TRACE_MGMT_DBG("Adding mgmt cmd %p to active mgmt cmd "
|
||||
"list", mcmd);
|
||||
list_add_tail(&mcmd->mgmt_cmd_list_entry,
|
||||
@@ -3938,20 +3938,20 @@ static int scst_set_mcmd_next_state(struct scst_mgmt_cmd *mcmd)
|
||||
spin_lock_irq(&scst_mcmd_lock);
|
||||
|
||||
if (mcmd->cmd_finish_wait_count == 0) {
|
||||
if (!mcmd->nexus_loss_check_done)
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS;
|
||||
if (!mcmd->affected_cmds_done_called)
|
||||
mcmd->state = SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE;
|
||||
else
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_DONE;
|
||||
mcmd->state = SCST_MCMD_STATE_DONE;
|
||||
res = 0;
|
||||
} else if ((mcmd->cmd_done_wait_count == 0) &&
|
||||
(!mcmd->nexus_loss_check_done)) {
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS;
|
||||
(!mcmd->affected_cmds_done_called)) {
|
||||
mcmd->state = SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE;
|
||||
res = 0;
|
||||
goto out_unlock;
|
||||
} else {
|
||||
TRACE_MGMT_DBG("cmd_finish_wait_count(%d) not 0, preparing to "
|
||||
"wait", mcmd->cmd_finish_wait_count);
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_EXECUTING;
|
||||
mcmd->state = SCST_MCMD_STATE_EXECUTING;
|
||||
res = -1;
|
||||
}
|
||||
|
||||
@@ -4067,17 +4067,10 @@ static int scst_abort_task_set(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
int res;
|
||||
struct scst_tgt_dev *tgt_dev = mcmd->mcmd_tgt_dev;
|
||||
struct scst_device *dev = tgt_dev->dev;
|
||||
|
||||
TRACE(TRACE_MGMT, "Aborting task set (lun=%lld, mcmd=%p)",
|
||||
(long long unsigned int)tgt_dev->lun, mcmd);
|
||||
|
||||
mcmd->needs_unblocking = 1;
|
||||
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
|
||||
__scst_abort_task_set(mcmd, tgt_dev);
|
||||
|
||||
scst_unblock_aborted_cmds(0);
|
||||
@@ -4131,12 +4124,6 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
|
||||
TRACE(TRACE_MGMT, "Clearing task set (lun=%lld, mcmd=%p)",
|
||||
(long long unsigned int)mcmd->lun, mcmd);
|
||||
|
||||
mcmd->needs_unblocking = 1;
|
||||
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
|
||||
__scst_abort_task_set(mcmd, mcmd->mcmd_tgt_dev);
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
@@ -4201,7 +4188,7 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_READY;
|
||||
mcmd->state = SCST_MCMD_STATE_READY;
|
||||
|
||||
switch (mcmd->fn) {
|
||||
case SCST_ABORT_TASK:
|
||||
@@ -4216,7 +4203,7 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
"for tag %llu not found",
|
||||
(long long unsigned int)mcmd->tag);
|
||||
mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_DONE;
|
||||
mcmd->state = SCST_MCMD_STATE_DONE;
|
||||
spin_unlock_irq(&sess->sess_list_lock);
|
||||
goto out;
|
||||
}
|
||||
@@ -4269,7 +4256,7 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
"found",
|
||||
(long long unsigned int)mcmd->lun);
|
||||
mcmd->status = SCST_MGMT_STATUS_LUN_NOT_EXIST;
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_DONE;
|
||||
mcmd->state = SCST_MCMD_STATE_DONE;
|
||||
} else if (rc != 0)
|
||||
res = rc;
|
||||
break;
|
||||
@@ -4430,10 +4417,10 @@ static int scst_lun_reset(struct scst_mgmt_cmd *mcmd)
|
||||
if (rc != SUCCESS && mcmd->status == SCST_MGMT_STATUS_SUCCESS)
|
||||
mcmd->status = SCST_MGMT_STATUS_FAILED;
|
||||
#else
|
||||
/*
|
||||
* scsi_reset_provider() returns very weird status, so let's
|
||||
* always succeed
|
||||
*/
|
||||
/*
|
||||
* scsi_reset_provider() returns very weird status, so let's
|
||||
* always succeed
|
||||
*/
|
||||
#endif
|
||||
dev->scsi_dev->was_reset = 0;
|
||||
}
|
||||
@@ -4463,7 +4450,8 @@ static void scst_do_nexus_loss_sess(struct scst_mgmt_cmd *mcmd)
|
||||
&sess->sess_tgt_dev_list_hash[i];
|
||||
list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
|
||||
sess_tgt_dev_list_entry) {
|
||||
scst_nexus_loss(tgt_dev);
|
||||
scst_nexus_loss(tgt_dev,
|
||||
(mcmd->fn != SCST_UNREG_SESS_TM));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4490,9 +4478,6 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
|
||||
sess, mcmd);
|
||||
}
|
||||
|
||||
if (mcmd->fn != SCST_UNREG_SESS_TM)
|
||||
mcmd->needs_unblocking = 1;
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
|
||||
@@ -4500,15 +4485,8 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
|
||||
&sess->sess_tgt_dev_list_hash[i];
|
||||
list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
|
||||
sess_tgt_dev_list_entry) {
|
||||
struct scst_device *dev = tgt_dev->dev;
|
||||
int rc;
|
||||
|
||||
if (mcmd->fn != SCST_UNREG_SESS_TM) {
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
}
|
||||
|
||||
__scst_abort_task_set(mcmd, tgt_dev);
|
||||
|
||||
rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0);
|
||||
@@ -4543,7 +4521,7 @@ static void scst_do_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd)
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
list_for_each_entry(tgt_dev, sess_tgt_dev_list_head,
|
||||
sess_tgt_dev_list_entry) {
|
||||
scst_nexus_loss(tgt_dev);
|
||||
scst_nexus_loss(tgt_dev, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4558,9 +4536,7 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
|
||||
int res;
|
||||
int i;
|
||||
struct scst_tgt *tgt = mcmd->sess->tgt;
|
||||
struct scst_acg *acg = mcmd->sess->acg;
|
||||
struct scst_session *sess;
|
||||
struct scst_acg_dev *acg_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -4572,18 +4548,8 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
|
||||
tgt, mcmd);
|
||||
}
|
||||
|
||||
mcmd->needs_unblocking = 1;
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
|
||||
struct scst_device *dev = acg_dev->dev;
|
||||
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
}
|
||||
|
||||
list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
|
||||
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
|
||||
struct list_head *sess_tgt_dev_list_head =
|
||||
@@ -4596,7 +4562,7 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd,
|
||||
__scst_abort_task_set(mcmd, tgt_dev);
|
||||
|
||||
if (nexus_loss)
|
||||
scst_nexus_loss(tgt_dev);
|
||||
scst_nexus_loss(tgt_dev, true);
|
||||
|
||||
if (mcmd->sess == tgt_dev->sess) {
|
||||
rc = scst_call_dev_task_mgmt_fn(
|
||||
@@ -4685,11 +4651,26 @@ out:
|
||||
return res;
|
||||
|
||||
out_done:
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_DONE;
|
||||
mcmd->state = SCST_MCMD_STATE_DONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
|
||||
static void scst_call_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
struct scst_session *sess = mcmd->sess;
|
||||
|
||||
if ((sess->tgt->tgtt->task_mgmt_affected_cmds_done != NULL) &&
|
||||
(mcmd->fn != SCST_UNREG_SESS_TM)) {
|
||||
TRACE_DBG("Calling target %s task_mgmt_affected_cmds_done(%p)",
|
||||
sess->tgt->tgtt->name, sess);
|
||||
sess->tgt->tgtt->task_mgmt_affected_cmds_done(mcmd);
|
||||
TRACE_MGMT_DBG("Target's %s task_mgmt_affected_cmds_done() "
|
||||
"returned", sess->tgt->tgtt->name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int scst_mgmt_affected_cmds_done(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -4710,19 +4691,9 @@ static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
if ((mcmd->fn == SCST_UNREG_SESS_TM) &&
|
||||
(mcmd->sess->unreg_cmds_done_fn != NULL)) {
|
||||
struct scst_session *sess = mcmd->sess;
|
||||
scst_call_task_mgmt_affected_cmds_done(mcmd);
|
||||
|
||||
TRACE_MGMT_DBG("Calling unreg_cmds_done_fn(%p)", sess);
|
||||
sess->unreg_cmds_done_fn(sess);
|
||||
TRACE_MGMT_DBG("task_mgmt_all_cmds_done(%p) returned", sess);
|
||||
|
||||
/* To prevent scst_mgmt_cmd_send_done() to call it again */
|
||||
sess->unreg_cmds_done_fn = NULL;
|
||||
}
|
||||
|
||||
mcmd->nexus_loss_check_done = 1;
|
||||
mcmd->affected_cmds_done_called = 1;
|
||||
|
||||
res = scst_set_mcmd_next_state(mcmd);
|
||||
|
||||
@@ -4733,46 +4704,38 @@ static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
|
||||
static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
struct scst_session *sess = mcmd->sess;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_FINISHED;
|
||||
mcmd->state = SCST_MCMD_STATE_FINISHED;
|
||||
if (scst_is_strict_mgmt_fn(mcmd->fn) && (mcmd->completed_cmd_count > 0))
|
||||
mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST;
|
||||
|
||||
TRACE(TRACE_MGMT_MINOR, "TM command fn %d finished, status %x",
|
||||
mcmd->fn, mcmd->status);
|
||||
|
||||
if (mcmd->fn == SCST_UNREG_SESS_TM) {
|
||||
if (sess->unreg_cmds_done_fn != NULL) {
|
||||
TRACE_MGMT_DBG("Calling unreg_cmds_done_fn(%p)", sess);
|
||||
sess->unreg_cmds_done_fn(sess);
|
||||
TRACE_MGMT_DBG("task_mgmt_all_cmds_done(%p) returned",
|
||||
sess);
|
||||
}
|
||||
} else {
|
||||
if (sess->tgt->tgtt->task_mgmt_fn_done) {
|
||||
TRACE_DBG("Calling target %s task_mgmt_fn_done(%p)",
|
||||
sess->tgt->tgtt->name, sess);
|
||||
sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
|
||||
TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() "
|
||||
"returned", sess->tgt->tgtt->name);
|
||||
}
|
||||
if (!mcmd->affected_cmds_done_called) {
|
||||
/* It might happen in case of errors */
|
||||
scst_call_task_mgmt_affected_cmds_done(mcmd);
|
||||
}
|
||||
|
||||
if ((sess->tgt->tgtt->task_mgmt_fn_done != NULL) &&
|
||||
(mcmd->fn != SCST_UNREG_SESS_TM)) {
|
||||
TRACE_DBG("Calling target %s task_mgmt_fn_done(%p)",
|
||||
sess->tgt->tgtt->name, sess);
|
||||
sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
|
||||
TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() "
|
||||
"returned", sess->tgt->tgtt->name);
|
||||
}
|
||||
|
||||
if (mcmd->needs_unblocking) {
|
||||
switch (mcmd->fn) {
|
||||
case SCST_ABORT_TASK_SET:
|
||||
case SCST_CLEAR_TASK_SET:
|
||||
case SCST_LUN_RESET:
|
||||
scst_unblock_dev(mcmd->mcmd_tgt_dev->dev);
|
||||
break;
|
||||
|
||||
case SCST_TARGET_RESET:
|
||||
case SCST_ABORT_ALL_TASKS:
|
||||
case SCST_NEXUS_LOSS:
|
||||
{
|
||||
struct scst_acg *acg = mcmd->sess->acg;
|
||||
struct scst_acg_dev *acg_dev;
|
||||
@@ -4787,25 +4750,6 @@ static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
|
||||
break;
|
||||
}
|
||||
|
||||
case SCST_NEXUS_LOSS_SESS:
|
||||
case SCST_ABORT_ALL_TASKS_SESS:
|
||||
{
|
||||
int i;
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
|
||||
struct list_head *sess_tgt_dev_list_head =
|
||||
&mcmd->sess->sess_tgt_dev_list_hash[i];
|
||||
list_for_each_entry(tgt_dev,
|
||||
sess_tgt_dev_list_head,
|
||||
sess_tgt_dev_list_entry) {
|
||||
scst_unblock_dev(tgt_dev->dev);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sBUG();
|
||||
break;
|
||||
@@ -4829,23 +4773,23 @@ static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
|
||||
|
||||
while (1) {
|
||||
switch (mcmd->state) {
|
||||
case SCST_MGMT_CMD_STATE_INIT:
|
||||
case SCST_MCMD_STATE_INIT:
|
||||
res = scst_mgmt_cmd_init(mcmd);
|
||||
if (res)
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case SCST_MGMT_CMD_STATE_READY:
|
||||
case SCST_MCMD_STATE_READY:
|
||||
if (scst_mgmt_cmd_exec(mcmd))
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case SCST_MGMT_CMD_STATE_CHECK_NEXUS_LOSS:
|
||||
if (scst_mgmt_cmd_check_nexus_loss(mcmd))
|
||||
case SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE:
|
||||
if (scst_mgmt_affected_cmds_done(mcmd))
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case SCST_MGMT_CMD_STATE_DONE:
|
||||
case SCST_MCMD_STATE_DONE:
|
||||
scst_mgmt_cmd_send_done(mcmd);
|
||||
break;
|
||||
|
||||
@@ -4854,12 +4798,12 @@ static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
|
||||
mcmd->state);
|
||||
res = -1;
|
||||
/* go through */
|
||||
case SCST_MGMT_CMD_STATE_FINISHED:
|
||||
case SCST_MCMD_STATE_FINISHED:
|
||||
scst_free_mgmt_cmd(mcmd);
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
case SCST_MGMT_CMD_STATE_EXECUTING:
|
||||
case SCST_MCMD_STATE_EXECUTING:
|
||||
sBUG();
|
||||
#endif
|
||||
}
|
||||
@@ -4973,7 +4917,7 @@ static struct scst_mgmt_cmd *scst_pre_rx_mgmt_cmd(struct scst_session
|
||||
|
||||
mcmd->sess = sess;
|
||||
mcmd->fn = fn;
|
||||
mcmd->state = SCST_MGMT_CMD_STATE_INIT;
|
||||
mcmd->state = SCST_MCMD_STATE_INIT;
|
||||
mcmd->tgt_priv = tgt_priv;
|
||||
|
||||
out:
|
||||
@@ -5299,9 +5243,8 @@ EXPORT_SYMBOL(scst_register_session);
|
||||
* Must not be called in parallel with scst_rx_cmd() or
|
||||
* scst_rx_mgmt_fn_*() for the same sess
|
||||
*/
|
||||
void scst_unregister_session_ex(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess),
|
||||
void (*unreg_cmds_done_fn) (struct scst_session *sess))
|
||||
void scst_unregister_session(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess))
|
||||
{
|
||||
unsigned long flags;
|
||||
struct completion *pc;
|
||||
@@ -5321,7 +5264,6 @@ void scst_unregister_session_ex(struct scst_session *sess, int wait,
|
||||
#endif
|
||||
|
||||
sess->unreg_done_fn = unreg_done_fn;
|
||||
sess->unreg_cmds_done_fn = unreg_cmds_done_fn;
|
||||
|
||||
/* Abort all outstanding commands and clear reservation, if necessary */
|
||||
lun = 0;
|
||||
@@ -5359,7 +5301,7 @@ void scst_unregister_session_ex(struct scst_session *sess, int wait,
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_unregister_session_ex);
|
||||
EXPORT_SYMBOL(scst_unregister_session);
|
||||
|
||||
static inline int test_mgmt_list(void)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user