mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
- TM fixes
- Optimizations and send timeout introduced in r295 temporary disabled - Big connection shutdown times improvements. Great thanks to Alexey Kuznetsov for suggestions! - RESERVE/RELEASE serialization now made with TST field 0 (i.e. single task set) - Other minor fixes and improvements git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@297 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -115,15 +115,6 @@ iscsi-scstd.conf file for the corresponding target to some lower value,
|
||||
like 8 (default is 32). See also SCST README file for more details about
|
||||
that issue.
|
||||
|
||||
Sometimes, when there are communication problems with initiator(s),
|
||||
shutting down iSCSI-SCST can take very long time, up to about 10
|
||||
minutes. This can happen, because iSCSI-SCST can't be shutdown before
|
||||
all already sent to TCP for initiator(s) data will be actually sent
|
||||
and/or released by TCP. In case of communication failures this can take
|
||||
up to TCP transmit timeout, which is about 10 minutes. In such cases
|
||||
using netstat utility you can see that there is/are connection(s) to
|
||||
initiator(s) with non-0 "Send-Q".
|
||||
|
||||
CAUTION: Working of target and initiator on the same host isn't
|
||||
======== supported. See SCST README file for details.
|
||||
|
||||
|
||||
@@ -1742,7 +1742,7 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
struct iscsi_session *sess = conn->session;
|
||||
struct iscsi_task_mgt_hdr *req_hdr =
|
||||
(struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
|
||||
int err = 0, function = req_hdr->function & ISCSI_FUNCTION_MASK;
|
||||
int rc, status, function = req_hdr->function & ISCSI_FUNCTION_MASK;
|
||||
struct scst_rx_mgmt_params params;
|
||||
|
||||
TRACE((function == ISCSI_FUNCTION_ABORT_TASK) ? TRACE_MGMT_MINOR : TRACE_MGMT,
|
||||
@@ -1754,13 +1754,20 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
iscsi_extracheck_is_rd_thread(conn);
|
||||
|
||||
spin_lock(&sess->sn_lock);
|
||||
sess->tm_active = 1;
|
||||
sess->tm_active++;
|
||||
sess->tm_sn = req_hdr->cmd_sn;
|
||||
if (sess->tm_rsp != NULL) {
|
||||
struct iscsi_cmnd *tm_rsp = sess->tm_rsp;
|
||||
|
||||
TRACE(TRACE_MGMT_MINOR, "Dropping delayed TM rsp %p", tm_rsp);
|
||||
|
||||
sess->tm_rsp = NULL;
|
||||
sess->tm_active--;
|
||||
|
||||
spin_unlock(&sess->sn_lock);
|
||||
|
||||
sBUG_ON(sess->tm_active < 0);
|
||||
|
||||
rsp_cmnd_release(tm_rsp);
|
||||
} else
|
||||
spin_unlock(&sess->sn_lock);
|
||||
@@ -1773,7 +1780,8 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
(req_hdr->rtt != ISCSI_RESERVED_TAG)) {
|
||||
PRINT_ERROR("Invalid RTT %x (TM fn %x)", req_hdr->rtt,
|
||||
function);
|
||||
err = -1;
|
||||
rc = -1;
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
goto reject;
|
||||
}
|
||||
|
||||
@@ -1781,8 +1789,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
|
||||
switch (function) {
|
||||
case ISCSI_FUNCTION_ABORT_TASK:
|
||||
err = cmnd_abort(req);
|
||||
if (err == 0) {
|
||||
rc = -1;
|
||||
status = cmnd_abort(req);
|
||||
if (status == 0) {
|
||||
params.fn = SCST_ABORT_TASK;
|
||||
params.tag = req_hdr->rtt;
|
||||
params.tag_set = 1;
|
||||
@@ -1791,8 +1800,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
params.lun_set = 1;
|
||||
params.cmd_sn = req_hdr->cmd_sn;
|
||||
params.cmd_sn_set = 1;
|
||||
err = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
rc = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
¶ms);
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
}
|
||||
break;
|
||||
case ISCSI_FUNCTION_ABORT_TASK_SET:
|
||||
@@ -1803,8 +1813,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
params.lun_set = 1;
|
||||
params.cmd_sn = req_hdr->cmd_sn;
|
||||
params.cmd_sn_set = 1;
|
||||
err = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
rc = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
¶ms);
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
break;
|
||||
case ISCSI_FUNCTION_CLEAR_TASK_SET:
|
||||
task_set_abort(req);
|
||||
@@ -1814,8 +1825,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
params.lun_set = 1;
|
||||
params.cmd_sn = req_hdr->cmd_sn;
|
||||
params.cmd_sn_set = 1;
|
||||
err = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
rc = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
¶ms);
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
break;
|
||||
case ISCSI_FUNCTION_CLEAR_ACA:
|
||||
params.fn = SCST_CLEAR_ACA;
|
||||
@@ -1824,8 +1836,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
params.lun_set = 1;
|
||||
params.cmd_sn = req_hdr->cmd_sn;
|
||||
params.cmd_sn_set = 1;
|
||||
err = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
rc = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
¶ms);
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
break;
|
||||
case ISCSI_FUNCTION_TARGET_COLD_RESET:
|
||||
case ISCSI_FUNCTION_TARGET_WARM_RESET:
|
||||
@@ -1833,8 +1846,9 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
params.fn = SCST_TARGET_RESET;
|
||||
params.cmd_sn = req_hdr->cmd_sn;
|
||||
params.cmd_sn_set = 1;
|
||||
err = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
rc = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
¶ms);
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
break;
|
||||
case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:
|
||||
target_abort(req, 0);
|
||||
@@ -1844,25 +1858,26 @@ static void execute_task_management(struct iscsi_cmnd *req)
|
||||
params.lun_set = 1;
|
||||
params.cmd_sn = req_hdr->cmd_sn;
|
||||
params.cmd_sn_set = 1;
|
||||
err = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
rc = scst_rx_mgmt_fn(conn->session->scst_sess,
|
||||
¶ms);
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
break;
|
||||
case ISCSI_FUNCTION_TASK_REASSIGN:
|
||||
iscsi_send_task_mgmt_resp(req,
|
||||
ISCSI_RESPONSE_FUNCTION_UNSUPPORTED);
|
||||
rc = -1;
|
||||
status = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("Unknown TM function %d", function);
|
||||
iscsi_send_task_mgmt_resp(req,
|
||||
ISCSI_RESPONSE_FUNCTION_REJECTED);
|
||||
rc = -1;
|
||||
status = ISCSI_RESPONSE_FUNCTION_REJECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
reject:
|
||||
if (err != 0) {
|
||||
iscsi_send_task_mgmt_resp(req,
|
||||
ISCSI_RESPONSE_FUNCTION_REJECTED);
|
||||
}
|
||||
if (rc != 0)
|
||||
iscsi_send_task_mgmt_resp(req, status);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void noop_out_exec(struct iscsi_cmnd *req)
|
||||
@@ -2140,7 +2155,7 @@ static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd)
|
||||
while (1) {
|
||||
session->exp_cmd_sn = ++cmd_sn;
|
||||
|
||||
if (unlikely(session->tm_active)) {
|
||||
if (unlikely(session->tm_active > 0)) {
|
||||
if (before(cmd_sn, session->tm_sn)) {
|
||||
struct iscsi_conn *conn = cmnd->conn;
|
||||
|
||||
@@ -2476,7 +2491,11 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
|
||||
u8 *sense = scst_cmd_get_sense_buffer(scst_cmd);
|
||||
int sense_len = scst_cmd_get_sense_buffer_len(scst_cmd);
|
||||
int old_state = req->scst_state;
|
||||
#if 0 /* temp. ToDo */
|
||||
bool single_only = !scst_get_long_xmit(scst_cmd);
|
||||
#else
|
||||
bool single_only = 0;
|
||||
#endif
|
||||
|
||||
scst_cmd_set_tgt_priv(scst_cmd, NULL);
|
||||
|
||||
@@ -2622,10 +2641,12 @@ static void iscsi_check_send_delayed_tm_resp(struct iscsi_session *sess)
|
||||
TRACE(TRACE_MGMT_MINOR, "Sending delayed rsp %p", tm_rsp);
|
||||
|
||||
sess->tm_rsp = NULL;
|
||||
sess->tm_active = 0;
|
||||
sess->tm_active--;
|
||||
|
||||
spin_unlock(&sess->sn_lock);
|
||||
|
||||
sBUG_ON(sess->tm_active < 0);
|
||||
|
||||
iscsi_cmnd_init_write(tm_rsp,
|
||||
ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
|
||||
|
||||
@@ -2676,9 +2697,11 @@ static void iscsi_send_task_mgmt_resp(struct iscsi_cmnd *req, int status)
|
||||
spin_unlock(&sess->sn_lock);
|
||||
goto out_release;
|
||||
}
|
||||
sess->tm_active = 0;
|
||||
sess->tm_active--;
|
||||
spin_unlock(&sess->sn_lock);
|
||||
|
||||
sBUG_ON(sess->tm_active < 0);
|
||||
|
||||
iscsi_cmnd_init_write(rsp,
|
||||
ISCSI_INIT_WRITE_REMOVE_HASH | ISCSI_INIT_WRITE_WAKE);
|
||||
|
||||
|
||||
@@ -99,8 +99,7 @@ struct iscsi_session {
|
||||
u32 exp_cmd_sn; /* protected by sn_lock */
|
||||
|
||||
/* All 3 protected by sn_lock */
|
||||
unsigned int tm_active:1;
|
||||
unsigned int shutting_down:1; /* Let's save some cache footprint by putting it here */
|
||||
int tm_active;
|
||||
u32 tm_sn;
|
||||
struct iscsi_cmnd *tm_rsp;
|
||||
|
||||
@@ -118,6 +117,7 @@ struct iscsi_session {
|
||||
|
||||
/* Both don't need any protection */
|
||||
char *initiator_name;
|
||||
unsigned int shutting_down:1;
|
||||
u64 sid;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#ifdef DEBUG
|
||||
#define ISCSI_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_LINE | TRACE_PID | \
|
||||
TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_MINOR | TRACE_MGMT_DEBUG | \
|
||||
TRACE_MINOR | TRACE_SPECIAL | TRACE_CONN_OC | TRACE_CONN_OC_DBG)
|
||||
TRACE_MINOR | TRACE_SPECIAL | TRACE_CONN_OC)
|
||||
#else
|
||||
#define ISCSI_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
|
||||
TRACE_MINOR | TRACE_SPECIAL)
|
||||
|
||||
@@ -61,16 +61,17 @@ static void iscsi_check_closewait(struct iscsi_conn *conn)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if ((conn->sock->sk->sk_state != TCP_CLOSE_WAIT) &&
|
||||
(conn->sock->sk->sk_state != TCP_CLOSE)) {
|
||||
TRACE_CONN_CLOSE("sk_state %d, skipping",
|
||||
conn->sock->sk->sk_state);
|
||||
TRACE_CONN_CLOSE("conn %p, sk_state %d", conn, conn->sock->sk->sk_state);
|
||||
|
||||
if (conn->sock->sk->sk_state != TCP_CLOSE) {
|
||||
TRACE_CONN_CLOSE_DBG("conn %p, skipping", conn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* No data are going to be sent, so all being sent buffers can be freed
|
||||
* now. Strange that TCP doesn't do that itself.
|
||||
* No data are going to be sent, so all queued buffers can be freed
|
||||
* now. In many cases TCP does that only in close(), but we can't rely
|
||||
* on user space on calling it.
|
||||
*/
|
||||
|
||||
again:
|
||||
@@ -235,7 +236,8 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
TRACE(TRACE_MGMT_MINOR, "Dropping delayed TM rsp %p",
|
||||
tm_rsp);
|
||||
session->tm_rsp = NULL;
|
||||
session->tm_active = 0;
|
||||
session->tm_active--;
|
||||
WARN_ON(session->tm_active < 0);
|
||||
spin_unlock(&session->sn_lock);
|
||||
mutex_unlock(&target->target_mutex);
|
||||
|
||||
@@ -329,10 +331,18 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
iscsi_make_conn_wr_active(conn);
|
||||
|
||||
if (time_after(jiffies, start_waiting + 7*HZ)) {
|
||||
TRACE_CONN_CLOSE("%s", "Wait time expired");
|
||||
TRACE_CONN_CLOSE("Wait time expired (conn %p, "
|
||||
"sk_state %d)", conn, conn->sock->sk->sk_state);
|
||||
conn->sock->ops->shutdown(conn->sock, SEND_SHUTDOWN);
|
||||
}
|
||||
|
||||
if (time_after(jiffies, start_waiting + 15*HZ)) {
|
||||
TRACE_CONN_CLOSE("Wait time after shutdown expired "
|
||||
"(conn %p, sk_state %d)", conn,
|
||||
conn->sock->sk->sk_state);
|
||||
conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0);
|
||||
}
|
||||
|
||||
msleep(200);
|
||||
|
||||
TRACE_CONN_CLOSE("conn %p, conn_ref_cnt %d left, wr_state %d, "
|
||||
@@ -914,6 +924,7 @@ static int write_data(struct iscsi_conn *conn)
|
||||
spin_unlock_bh(&conn->write_list_lock);
|
||||
}
|
||||
|
||||
#if 0 /* temp. ToDo */
|
||||
if (!timer_pending(&conn->rsp_timer)) {
|
||||
sBUG_ON(!ref_cmd->on_written_list);
|
||||
spin_lock_bh(&conn->write_list_lock);
|
||||
@@ -925,6 +936,7 @@ static int write_data(struct iscsi_conn *conn)
|
||||
}
|
||||
spin_unlock_bh(&conn->write_list_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = conn->file;
|
||||
saved_size = size = conn->write_size;
|
||||
|
||||
@@ -2571,6 +2571,43 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void vdisk_report_registering(const char *type,
|
||||
const struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
char buf[128];
|
||||
int i, j;
|
||||
|
||||
i = snprintf(buf, sizeof(buf), "Registering virtual %s device %s",
|
||||
type, virt_dev->name);
|
||||
j = i;
|
||||
|
||||
if (virt_dev->wt_flag)
|
||||
i += snprintf(&buf[i], sizeof(buf) - i, " (WRITE_THROUGH");
|
||||
|
||||
if (virt_dev->nv_cache)
|
||||
i += snprintf(&buf[i], sizeof(buf) - i, "%sNV_CACHE",
|
||||
(j == i) ? "(" : ", ");
|
||||
|
||||
if (virt_dev->rd_only_flag)
|
||||
i += snprintf(&buf[i], sizeof(buf) - i, "%sREAD_ONLY",
|
||||
(j == i) ? "(" : ", ");
|
||||
|
||||
if (virt_dev->o_direct_flag)
|
||||
i += snprintf(&buf[i], sizeof(buf) - i, "%sO_DIRECT",
|
||||
(j == i) ? "(" : ", ");
|
||||
|
||||
if (virt_dev->nullio)
|
||||
i += snprintf(&buf[i], sizeof(buf) - i, "%sNULLIO",
|
||||
(j == i) ? "(" : ", ");
|
||||
|
||||
if (j == i)
|
||||
PRINT_INFO("%s", buf);
|
||||
else
|
||||
PRINT_INFO("%s)", buf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a file in the /proc/VDISK_NAME/VDISK_NAME is written
|
||||
*/
|
||||
@@ -2753,14 +2790,17 @@ static int vdisk_write_proc(char *buffer, char **start, off_t offset,
|
||||
list_add_tail(&virt_dev->vdisk_dev_list_entry,
|
||||
&vdisk_dev_list);
|
||||
|
||||
if (virt_dev->blockio)
|
||||
if (virt_dev->blockio) {
|
||||
vdisk_report_registering("BLOCKIO", virt_dev);
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&vdisk_blk_devtype,
|
||||
virt_dev->name);
|
||||
else
|
||||
} else {
|
||||
vdisk_report_registering("FILEIO", virt_dev);
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&vdisk_devtype,
|
||||
virt_dev->name);
|
||||
}
|
||||
if (virt_dev->virt_id < 0) {
|
||||
res = virt_dev->virt_id;
|
||||
goto out_free_vpath;
|
||||
@@ -2880,6 +2920,8 @@ static int vcdrom_open(char *p, char *name)
|
||||
list_add_tail(&virt_dev->vdisk_dev_list_entry,
|
||||
&vcdrom_dev_list);
|
||||
|
||||
PRINT_INFO("Registering virtual CDROM %s", name);
|
||||
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&vcdrom_devtype,
|
||||
virt_dev->name);
|
||||
|
||||
@@ -719,13 +719,15 @@ int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev, lun_t lun,
|
||||
out:
|
||||
if (res == 0) {
|
||||
if (dev->virt_name != NULL) {
|
||||
PRINT_INFO("Added device %s to group %s",
|
||||
dev->virt_name, acg->acg_name);
|
||||
PRINT_INFO("Added device %s to group %s (LUN %Ld, "
|
||||
"rd_only %d)", dev->virt_name, acg->acg_name,
|
||||
lun, read_only);
|
||||
} else {
|
||||
PRINT_INFO("Added device %d:%d:%d:%d to group %s",
|
||||
dev->scsi_dev->host->host_no,
|
||||
PRINT_INFO("Added device %d:%d:%d:%d to group %s (LUN "
|
||||
"%Ld, rd_only %d)", dev->scsi_dev->host->host_no,
|
||||
dev->scsi_dev->channel, dev->scsi_dev->id,
|
||||
dev->scsi_dev->lun, acg->acg_name);
|
||||
dev->scsi_dev->lun, acg->acg_name, lun,
|
||||
read_only);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,9 +1570,9 @@ int scst_alloc_space(struct scst_cmd *cmd)
|
||||
flags |= SCST_POOL_ALLOC_NO_CACHED;
|
||||
|
||||
if (unlikely(cmd->bufflen == 0)) {
|
||||
TRACE(TRACE_MGMT_MINOR, "Data direction %d or/and zero buffer "
|
||||
"length. Opcode 0x%x, handler %s, target %s",
|
||||
cmd->data_direction, cmd->cdb[0],
|
||||
TRACE(TRACE_MGMT_MINOR, "Warning: data direction %d or/and "
|
||||
"zero buffer length. Opcode 0x%x, handler %s, target "
|
||||
"%s", cmd->data_direction, cmd->cdb[0],
|
||||
cmd->dev->handler->name, cmd->tgtt->name);
|
||||
/*
|
||||
* Be on the safe side and alloc stub buffer. Neither target
|
||||
|
||||
@@ -240,7 +240,9 @@ static inline void scst_make_deferred_commands_active(
|
||||
spin_lock_irq(&c->cmd_lists->cmd_list_lock);
|
||||
list_add_tail(&c->cmd_list_entry,
|
||||
&c->cmd_lists->active_cmd_list);
|
||||
#if 0 /* temp. ToDo */
|
||||
if (!curr_cmd->context_processable || curr_cmd->long_xmit)
|
||||
#endif
|
||||
wake_up(&c->cmd_lists->cmd_list_waitQ);
|
||||
spin_unlock_irq(&c->cmd_lists->cmd_list_lock);
|
||||
}
|
||||
|
||||
@@ -476,6 +476,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
PRINT_ERROR("Dev handler supplied data buffer (size %d), "
|
||||
"is less, than required (size %d)", cmd->bufflen,
|
||||
orig_bufflen);
|
||||
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
@@ -487,6 +488,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
PRINT_ERROR("Unknown data transfer length for opcode 0x%x "
|
||||
"(handler %s, target %s)", cmd->cdb[0],
|
||||
dev->handler->name, cmd->tgtt->name);
|
||||
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
@@ -499,6 +501,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
"or sg %p (opcode 0x%x)", dev->handler->name,
|
||||
cmd->data_direction, cmd->bufflen, state, cmd->sg,
|
||||
cmd->cdb[0]);
|
||||
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
|
||||
goto out_error;
|
||||
}
|
||||
#endif
|
||||
@@ -513,20 +516,27 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
"bufflen %d, expected_transfer_len %d",
|
||||
cmd->data_direction, cmd->expected_data_direction,
|
||||
cmd->bufflen, cmd->expected_transfer_len);
|
||||
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
|
||||
}
|
||||
# endif
|
||||
cmd->data_direction = cmd->expected_data_direction;
|
||||
cmd->bufflen = cmd->expected_transfer_len;
|
||||
#else
|
||||
if (unlikely(cmd->data_direction != cmd->expected_data_direction)) {
|
||||
PRINT_ERROR("Expected data direction %d for opcode "
|
||||
"0x%02x (handler %s, target %s) doesn't match "
|
||||
"decoded value %d", cmd->data_direction,
|
||||
cmd->cdb[0], dev->handler->name,
|
||||
cmd->tgtt->name, cmd->expected_data_direction);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_message));
|
||||
goto out_dev_done;
|
||||
if (((cmd->expected_data_direction != SCST_DATA_NONE) ||
|
||||
(cmd->bufflen != 0)) &&
|
||||
/* Crazy VMware people sometimes do TUR with READ direction */
|
||||
!(cmd->cdb[0] == TEST_UNIT_READY)) {
|
||||
PRINT_ERROR("Expected data direction %d for opcode "
|
||||
"0x%02x (handler %s, target %s) doesn't match "
|
||||
"decoded value %d", cmd->expected_data_direction,
|
||||
cmd->cdb[0], dev->handler->name,
|
||||
cmd->tgtt->name, cmd->data_direction);
|
||||
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_message));
|
||||
goto out_dev_done;
|
||||
}
|
||||
}
|
||||
if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
|
||||
TRACE(TRACE_MINOR, "Warning: expected transfer length "
|
||||
@@ -547,6 +557,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
PRINT_ERROR("Unknown data direction. Opcode 0x%x, handler %s, "
|
||||
"target %s", cmd->cdb[0], dev->handler->name,
|
||||
cmd->tgtt->name);
|
||||
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
@@ -1418,7 +1429,8 @@ static int scst_reserve_local(struct scst_cmd *cmd)
|
||||
|
||||
dev = cmd->dev;
|
||||
|
||||
scst_block_dev_cmd(cmd, 1);
|
||||
if (dev->tst == SCST_CONTR_MODE_ONE_TASK_SET)
|
||||
scst_block_dev_cmd(cmd, 1);
|
||||
|
||||
rc = scst_check_local_events(cmd);
|
||||
if (unlikely(rc != 0))
|
||||
@@ -1473,7 +1485,8 @@ static int scst_release_local(struct scst_cmd *cmd)
|
||||
|
||||
dev = cmd->dev;
|
||||
|
||||
scst_block_dev_cmd(cmd, 1);
|
||||
if (dev->tst == SCST_CONTR_MODE_ONE_TASK_SET)
|
||||
scst_block_dev_cmd(cmd, 1);
|
||||
|
||||
rc = scst_check_local_events(cmd);
|
||||
if (unlikely(rc != 0))
|
||||
@@ -3497,7 +3510,7 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE(((mcmd != NULL) && (mcmd->fn == SCST_ABORT_TASK)) ? TRACE_MGMT_MINOR : TRACE_MGMT,
|
||||
"Aborting cmd %p (tag %llu)", cmd, cmd->tag);
|
||||
"Aborting cmd %p (tag %llu, op %x)", cmd, cmd->tag, cmd->cdb[0]);
|
||||
|
||||
if (other_ini) {
|
||||
set_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags);
|
||||
@@ -3890,11 +3903,17 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
}
|
||||
|
||||
case SCST_TARGET_RESET:
|
||||
case SCST_ABORT_ALL_TASKS:
|
||||
case SCST_NEXUS_LOSS_SESS:
|
||||
case SCST_ABORT_ALL_TASKS_SESS:
|
||||
case SCST_NEXUS_LOSS:
|
||||
case SCST_ABORT_ALL_TASKS:
|
||||
case SCST_UNREG_SESS_TM:
|
||||
break;
|
||||
|
||||
default:
|
||||
case SCST_ABORT_TASK_SET:
|
||||
case SCST_CLEAR_ACA:
|
||||
case SCST_CLEAR_TASK_SET:
|
||||
case SCST_LUN_RESET:
|
||||
rc = scst_mgmt_translate_lun(mcmd);
|
||||
if (rc < 0) {
|
||||
PRINT_ERROR("Corresponding device for lun %Ld not "
|
||||
@@ -3904,6 +3923,9 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
} else if (rc != 0)
|
||||
res = rc;
|
||||
break;
|
||||
|
||||
default:
|
||||
sBUG();
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -4315,9 +4337,13 @@ static int scst_mgmt_cmd_check_nexus_loss(struct scst_mgmt_cmd *mcmd)
|
||||
if ((mcmd->fn == SCST_UNREG_SESS_TM) &&
|
||||
(mcmd->sess->unreg_cmds_done_fn != NULL)) {
|
||||
struct scst_session *sess = mcmd->sess;
|
||||
|
||||
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;
|
||||
@@ -4332,6 +4358,7 @@ 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();
|
||||
|
||||
@@ -4342,13 +4369,20 @@ static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
|
||||
TRACE(TRACE_MGMT_MINOR, "TM command fn %d finished, status %x",
|
||||
mcmd->fn, mcmd->status);
|
||||
|
||||
if (mcmd->sess->tgt->tgtt->task_mgmt_fn_done &&
|
||||
(mcmd->fn != SCST_UNREG_SESS_TM)) {
|
||||
TRACE_DBG("Calling target %s task_mgmt_fn_done()",
|
||||
mcmd->sess->tgt->tgtt->name);
|
||||
mcmd->sess->tgt->tgtt->task_mgmt_fn_done(mcmd);
|
||||
TRACE_MGMT_DBG("Target's %s task_mgmt_fn_done() returned",
|
||||
mcmd->sess->tgt->tgtt->name);
|
||||
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->needs_unblocking) {
|
||||
|
||||
Reference in New Issue
Block a user