Reimplement dropping of TM requests in a more reliable manner

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5395 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2014-03-26 23:51:36 +00:00
parent 87ce86ee2d
commit 8599ec4452
5 changed files with 59 additions and 28 deletions

View File

@@ -61,7 +61,8 @@ static struct page *dummy_page;
static struct scatterlist dummy_sg;
static void cmnd_remove_data_wait_hash(struct iscsi_cmnd *cmnd);
static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status);
static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status,
bool dropped);
static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess);
static void req_cmnd_release(struct iscsi_cmnd *req);
static int cmnd_insert_data_wait_hash(struct iscsi_cmnd *cmnd);
@@ -2660,7 +2661,7 @@ static void execute_task_management(struct iscsi_cmnd *req)
reject:
if (rc != 0)
iscsi_send_task_mgmt_resp(req, status);
iscsi_send_task_mgmt_resp(req, status, false);
return;
}
@@ -3488,7 +3489,8 @@ out:
return;
}
static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status,
bool drop)
{
struct iscsi_cmnd *rsp;
struct iscsi_task_mgt_hdr *req_hdr =
@@ -3500,7 +3502,26 @@ static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
TRACE_ENTRY();
TRACE_MGMT_DBG("TM req %p finished", req);
TRACE(TRACE_MGMT, "iSCSI TM fn %d finished, status %d", fn, status);
TRACE(TRACE_MGMT, "iSCSI TM fn %d finished, status %d, dropped %d",
fn, status, drop);
if (drop) {
spin_lock(&sess->sn_lock);
sess->tm_active--;
spin_unlock(&sess->sn_lock);
if (fn == ISCSI_FUNCTION_TARGET_COLD_RESET) {
struct iscsi_target *target = req->conn->session->target;
PRINT_INFO("Closing all connections for target %x at "
"COLD RESET from initiator %s", target->tid,
req->conn->session->initiator_name);
mutex_lock(&target->target_mutex);
target_del_all_sess(target, 0);
mutex_unlock(&target->target_mutex);
}
goto out_release;
}
rsp = iscsi_alloc_rsp(req);
rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs;
@@ -3569,8 +3590,7 @@ static void iscsi_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
int fn = scst_mgmt_cmd_get_fn(scst_mcmd);
struct iscsi_cmnd *req = (struct iscsi_cmnd *)
scst_mgmt_cmd_get_tgt_priv(scst_mcmd);
int status =
iscsi_get_mgmt_response(scst_mgmt_cmd_get_status(scst_mcmd));
int status = iscsi_get_mgmt_response(scst_mgmt_cmd_get_status(scst_mcmd));
if ((status == ISCSI_RESPONSE_UNKNOWN_TASK) &&
(fn == SCST_ABORT_TASK)) {
@@ -3592,7 +3612,7 @@ static void iscsi_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
sBUG_ON(1);
break;
default:
iscsi_send_task_mgmt_resp(req, status);
iscsi_send_task_mgmt_resp(req, status, scst_mgmt_cmd_dropped(scst_mcmd));
scst_mgmt_cmd_set_tgt_priv(scst_mcmd, NULL);
break;
}

View File

@@ -603,16 +603,19 @@ Every target should have at least the following entries:
* 2 - immediately abort all coming commands and drop all coming TM
commands
* 3 - immediately abort all coming data transfer commands. This is
the most evil mode, because it is not too well handled by many
initiator OS'es, including Linux, so they may never recover from
it.
* 3 - immediately abort all coming data transfer commands.
* 4 - immediately abort all coming data transfer commands and drop all
coming TM commands
CAUTION! With some target drivers modes 2 and 4 can cause internal
resources leaks, so don't abuse those options!
Modes 3 and 4 are the most evil ones, because they are not too well
handled by many initiator OS'es, including Linux, so they may never
recover from it.
Note, dropping TM commands, i.e. not sending response on them,
implemented not for all target drivers. If it's implemented for your
particular target driver or not, you can find out by checking traces
or the target driver's source code.
- cpu_mask - defines CPU affinity mask for threads serving this target.
For threads serving LUNs it is used only for devices with

View File

@@ -465,16 +465,19 @@ Every target should have at least the following entries:
* 2 - immediately abort all coming commands and drop all coming TM
commands
* 3 - immediately abort all coming data transfer commands. This is
the most evil mode, because it is not too well handled by many
initiator OS'es, including Linux, so they may never recover from
it.
* 3 - immediately abort all coming data transfer commands.
* 4 - immediately abort all coming data transfer commands and drop all
coming TM commands
CAUTION! With some target drivers modes 2 and 4 can cause internal
resources leaks, so don't abuse those options!
Modes 3 and 4 are the most evil ones, because they are not too well
handled by many initiator OS'es, including Linux, so they may never
recover from it.
Note, dropping TM commands, i.e. not sending response on them,
implemented not for all target drivers. If it's implemented for your
particular target driver or not, you can find out by checking traces
or the target driver's source code.
- cpu_mask - defines CPU affinity mask for threads serving this target.
For threads serving LUNs it is used only for devices with

View File

@@ -2289,6 +2289,7 @@ struct scst_mgmt_cmd {
unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */
/* Set if dev handler's task_mgmt_fn_received was called */
unsigned int task_mgmt_fn_received_called:1;
unsigned int mcmd_dropped:1; /* set if mcmd was dropped */
/*
* Number of commands to finish before sending response,
@@ -3717,12 +3718,6 @@ static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd)
return mcmd->status;
}
/* Returns mgmt cmd's TM fn */
static inline int scst_mgmt_cmd_get_fn(struct scst_mgmt_cmd *mcmd)
{
return mcmd->fn;
}
static inline void scst_mgmt_cmd_set_status(struct scst_mgmt_cmd *mcmd,
int status)
{
@@ -3732,6 +3727,18 @@ static inline void scst_mgmt_cmd_set_status(struct scst_mgmt_cmd *mcmd,
mcmd->status = status;
}
/* Returns mgmt cmd's TM fn */
static inline int scst_mgmt_cmd_get_fn(struct scst_mgmt_cmd *mcmd)
{
return mcmd->fn;
}
/* Returns true if mgmt cmd should be dropped, i.e. response not sent */
static inline bool scst_mgmt_cmd_dropped(struct scst_mgmt_cmd *mcmd)
{
return mcmd->mcmd_dropped;
}
/*
* Called by dev handler's task_mgmt_fn_*() to notify SCST core that mcmd
* is going to complete asynchronously.

View File

@@ -5497,13 +5497,11 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
TRACE_ENTRY();
t = mcmd->sess->acg->acg_black_hole_type;
if (unlikely((t == SCST_ACG_BLACK_HOLE_ALL) ||
(t == SCST_ACG_BLACK_HOLE_DATA_MCMD))) {
TRACE_MGMT_DBG("Dropping mcmd %p (fn %d, initiator %s)", mcmd,
mcmd->fn, mcmd->sess->initiator_name);
mcmd->state = SCST_MCMD_STATE_FINISHED;
goto out;
mcmd->mcmd_dropped = 1;
}
switch (mcmd->fn) {