mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
15
scst/README
15
scst/README
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user