- A bunch of minor, mostly stability related, fixes.

- Docs update


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@248 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2008-01-24 10:56:35 +00:00
parent 87013ddcde
commit 9847aa17ba
18 changed files with 198 additions and 119 deletions
+10 -1
View File
@@ -102,7 +102,7 @@ should be: the target driver is responsible for handling targets and
their parameters, SCST core is responsible for handling backstorage.
If you need to configure different LUs for different targets you should
create for each target group "Default_target_name", where target name
create for each target group "Default_target_name", where "target_name"
means name of the target, for example:
"Default_iqn.2007-05.com.example:storage.disk1.sys1.xyz", and add there
all necessary LUNs. Check SCST README file for details.
@@ -114,6 +114,15 @@ abort or reset messages, then try to reduce QueuedCommands parameter in
iscsi-scstd.conf file for the corresponding target. 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.
-17
View File
@@ -109,23 +109,6 @@ case "$1" in
exit 1
fi
;;
dump)
DUMP=`tempfile -p iscsi-scstd`
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
echo "Failed to create dump file $DUMP"
exit 1
fi
iscsi-scst-adm --mode dump --all >$DUMP
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
echo "Error dumping config from daemon"
rm $DUMP
exit 1
fi
mv -u $DUMP $CONFIG_FILE
echo "Config dumped to $CONFIG_FILE"
;;
*)
echo $"Usage: $0 {start|stop|restart|status|dump}"
exit 1
+16 -3
View File
@@ -92,6 +92,8 @@ static inline u32 cmnd_read_size(struct iscsi_cmnd *cmnd)
static inline void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd)
{
EXTRACHECKS_BUG_ON(cmnd->data_waiting);
cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
scst_restart_cmd(cmnd->scst_cmd, SCST_PREPROCESS_STATUS_SUCCESS,
SCST_CONTEXT_THREAD);
@@ -166,6 +168,12 @@ void cmnd_free(struct iscsi_cmnd *cmnd)
{
TRACE_DBG("%p", cmnd);
if (unlikely(cmnd->tmfabort)) {
TRACE_MGMT_DBG("Free aborted cmd %p (scst cmd %p, state %d, "
"parent_req %p)", cmnd, cmnd->scst_cmd, cmnd->scst_state,
cmnd->parent_req);
}
/* Catch users from cmd_list or rsp_cmd_list */
EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) != 0);
@@ -221,12 +229,16 @@ void cmnd_done(struct iscsi_cmnd *cmnd)
if (cmnd->scst_cmd) {
switch(cmnd->scst_state) {
case ISCSI_CMD_STATE_AFTER_PREPROC:
{
struct scst_cmd *scst_cmd = cmnd->scst_cmd;
TRACE_DBG("cmd %p AFTER_PREPROC", cmnd);
cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED;
scst_restart_cmd(cmnd->scst_cmd,
cmnd->scst_cmd = NULL;
scst_restart_cmd(scst_cmd,
SCST_PREPROCESS_STATUS_ERROR_FATAL,
SCST_CONTEXT_DIRECT);
SCST_CONTEXT_THREAD);
break;
}
case ISCSI_CMD_STATE_PROCESSED:
TRACE_DBG("cmd %p PROCESSED", cmnd);
scst_tgt_cmd_done(cmnd->scst_cmd);
@@ -1300,7 +1312,8 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req)
if (dir == SCST_DATA_WRITE) {
req->is_unsolicited_data = !(req_hdr->flags & ISCSI_CMD_FINAL);
req->r2t_length = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize;
req->data_waiting = 1;
if (req->r2t_length > 0)
req->data_waiting = 1;
}
req->target_task_tag = get_next_ttt(conn);
req->sg = scst_cmd_get_sg(scst_cmd);
+2 -2
View File
@@ -103,7 +103,7 @@ struct iscsi_session {
u32 tm_sn;
struct iscsi_cmnd *tm_rsp;
/* read only, if there are connection(s) */
/* Read only, if there are connection(s) */
struct iscsi_sess_param sess_param;
spinlock_t cmnd_hash_lock;
@@ -113,7 +113,7 @@ struct iscsi_session {
struct list_head session_list_entry;
/* Bot don't need any protection */
/* Both don't need any protection */
char *initiator_name;
u64 sid;
};
+12 -3
View File
@@ -183,6 +183,15 @@ static void close_conn(struct iscsi_conn *conn)
/* We want all our already send operations to complete */
conn->sock->ops->shutdown(conn->sock, RCV_SHUTDOWN);
/*
* We need to call scst_unregister_session() ASAP to make SCST start
* stuck commands recovery.
*
* ToDo: this is incompatible with MC/S
*/
scst_unregister_session(session->scst_sess, 0, NULL);
session->scst_sess = NULL;
if (conn->read_state != RX_INIT_BHS) {
struct iscsi_cmnd *cmnd = conn->read_cmnd;
conn->read_cmnd = NULL;
@@ -295,7 +304,7 @@ static void close_conn(struct iscsi_conn *conn)
}
iscsi_make_conn_wr_active(conn);
msleep(50);
msleep(200);
TRACE_CONN_CLOSE("conn %p, conn_ref_cnt %d left, wr_state %d, "
"exp_cmd_sn %u", conn, atomic_read(&conn->conn_ref_cnt),
@@ -379,8 +388,8 @@ static void close_conn(struct iscsi_conn *conn)
mutex_lock(&target->target_mutex);
conn_free(conn);
if (list_empty(&session->conn_list))
session_del(target, session->sid);
/* ToDo: this is incompatible with MC/S */
session_free(session);
mutex_unlock(&target->target_mutex);
TRACE_EXIT();
+2 -1
View File
@@ -136,7 +136,8 @@ int session_free(struct iscsi_session *session)
for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++)
sBUG_ON(!list_empty(&session->cmnd_hash[i]));
scst_unregister_session(session->scst_sess, 1, NULL);
if (session->scst_sess != NULL)
scst_unregister_session(session->scst_sess, 1, NULL);
list_del(&session->session_list_entry);
+23 -16
View File
@@ -426,7 +426,11 @@ subdirectories "vdisk" and "vcdrom". They have similar layout:
and "FLAGS" are valid only for disk VDISK. The block size must be
power of 2 and >= 512 bytes. Default is 512. Possible flags:
- WRITE_THROUGH - write back caching disabled
- WRITE_THROUGH - write back caching disabled. Note, this option
has sense only if you also *manually* disable write-back cache
in *all* your backstorage devices and make sure it's actually
disabled, since many devices are known to lie about this mode to
get better benchmark results.
- READ_ONLY - read only
@@ -439,20 +443,23 @@ subdirectories "vdisk" and "vcdrom". They have similar layout:
way as "*_perf" handlers.
- NV_CACHE - enables "non-volatile cache" mode. In this mode it is
assumed that the target has GOOD UPS and software/hardware bug
free, i.e. all data from the target's cache are guaranteed
sooner or later to go to the media, hence all data
synchronization with media operations, like SYNCHRONIZE_CACHE,
are ignored (BTW, so violating SCSI standard) in order to bring
a bit more performance. Use with extreme caution, since in this
mode after a crash of the target journaled file systems don't
guarantee the consistency after journal recovery, therefore
manual fsck MUST be ran. The main intent for it is to determine
the performance impact caused by the cache synchronization.
Note, that since usually the journal barrier protection (see
"IMPORTANT" below) turned off, enabling NV_CACHE could change
nothing, since no data synchronization with media operations
will go from the initiator.
assumed that the target has a GOOD UPS with ability to cleanly
shutdown target in case of power failure and it is
software/hardware bugs free, i.e. all data from the target's
cache are guaranteed sooner or later to go to the media. Hence
all data synchronization with media operations, like
SYNCHRONIZE_CACHE, are ignored in order to bring more
performance. Also in this mode target reports to initiators that
the corresponding device has write-through cache to disable all
write-back cache workarounds used by initiators. Use with
extreme caution, since in this mode after a crash of the target
journaled file systems don't guarantee the consistency after
journal recovery, therefore manual fsck MUST be ran. Note, that
since usually the journal barrier protection (see "IMPORTANT"
note below) turned off, enabling NV_CACHE could change nothing
from data protection point of view, since no data
synchronization with media operations will go from the
initiator. This option overrides WRITE_THROUGH.
- BLOCKIO - enables block mode, which will perform direct block
IO with a block device, bypassing page-cache for all operations.
@@ -503,7 +510,7 @@ IMPORTANT: By default for performance reasons VDISK FILEIO devices use write
backstorage device and lost on power failure event. Thus,
ever with write-through cache mode, you still need a good UPS
to protect yourself from your data loss (note, data loss, not
the file system integrity).
the file system integrity corruption).
IMPORTANT: Some disk and partition table management utilities don't support
========= block sizes >512 bytes, therefore make sure that your favorite one
+17 -7
View File
@@ -1621,13 +1621,23 @@ struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
* Parameter:
* - sess - session
*
* Note: All outstanding commands will be finished regularly. After
* scst_unregister_session() returned no new commands must be sent to
* SCST via scst_rx_cmd(). Also, the caller must ensure that no
* scst_rx_cmd() or scst_rx_mgmt_fn_*() is called in paralell with
* scst_unregister_session().
* Can be called before result_fn() of scst_register_session() called,
* i.e. during the session registration/initialization.
* Notes:
*
* - All outstanding commands will be finished regularly. After
* scst_unregister_session() returned no new commands must be sent to
* SCST via scst_rx_cmd().
*
* - The caller must ensure that no scst_rx_cmd() or scst_rx_mgmt_fn_*() is
* called in paralell with scst_unregister_session().
*
* - Can be called before result_fn() of scst_register_session() called,
* i.e. during the session registration/initialization.
*
* - It is highly recommended to call scst_unregister_session() as soon as it
* gets clear that session will be unregistered and not to wait until all
* related commands finished. This function provides the wait functionality,
* 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(struct scst_session *sess, int wait,
void (*unreg_done_fn) (struct scst_session *sess));
+6 -1
View File
@@ -148,8 +148,13 @@ int cdrom_attach(struct scst_device *dev)
}
res = scst_obtain_device_parameters(dev);
if (res != 0)
if (res != 0) {
PRINT_ERROR("Failed to obtain control parameters for device "
"%d:%d:%d:%d", dev->scsi_dev->host->host_no,
dev->scsi_dev->channel, dev->scsi_dev->id,
dev->scsi_dev->lun);
goto out_free_buf;
}
out_free_buf:
kfree(buffer);
+6 -1
View File
@@ -96,8 +96,13 @@ int changer_attach(struct scst_device *dev)
}
res = scst_obtain_device_parameters(dev);
if (res != 0)
if (res != 0) {
PRINT_ERROR("Failed to obtain control parameters for device "
"%d:%d:%d:%d", dev->scsi_dev->host->host_no,
dev->scsi_dev->channel, dev->scsi_dev->id,
dev->scsi_dev->lun);
goto out;
}
out:
TRACE_EXIT_HRES(res);
+6 -1
View File
@@ -220,8 +220,13 @@ int disk_attach(struct scst_device *dev)
}
res = scst_obtain_device_parameters(dev);
if (res != 0)
if (res != 0) {
PRINT_ERROR("Failed to obtain control parameters for device "
"%d:%d:%d:%d", dev->scsi_dev->host->host_no,
dev->scsi_dev->channel, dev->scsi_dev->id,
dev->scsi_dev->lun);
goto out_free_buf;
}
out_free_buf:
kfree(buffer);
+6 -1
View File
@@ -235,8 +235,13 @@ int modisk_attach(struct scst_device *dev)
}
res = scst_obtain_device_parameters(dev);
if (res != 0)
if (res != 0) {
PRINT_ERROR("Failed to obtain control parameters for device "
"%d:%d:%d:%d: %x", dev->scsi_dev->host->host_no,
dev->scsi_dev->channel, dev->scsi_dev->id,
dev->scsi_dev->lun, res);
goto out_free_buf;
}
out_free_buf:
kfree(buffer);
+6 -1
View File
@@ -96,8 +96,13 @@ int processor_attach(struct scst_device *dev)
}
res = scst_obtain_device_parameters(dev);
if (res != 0)
if (res != 0) {
PRINT_ERROR("Failed to obtain control parameters for device "
"%d:%d:%d:%d", dev->scsi_dev->host->host_no,
dev->scsi_dev->channel, dev->scsi_dev->id,
dev->scsi_dev->lun);
goto out;
}
out:
TRACE_EXIT();
+6 -1
View File
@@ -96,8 +96,13 @@ int raid_attach(struct scst_device *dev)
}
res = scst_obtain_device_parameters(dev);
if (res != 0)
if (res != 0) {
PRINT_ERROR("Failed to obtain control parameters for device "
"%d:%d:%d:%d", dev->scsi_dev->host->host_no,
dev->scsi_dev->channel, dev->scsi_dev->id,
dev->scsi_dev->lun);
goto out;
}
out:
TRACE_EXIT();
+6 -1
View File
@@ -223,8 +223,13 @@ int tape_attach(struct scst_device *dev)
}
res = scst_obtain_device_parameters(dev);
if (res != 0)
if (res != 0) {
PRINT_ERROR("Failed to obtain control parameters for device "
"%d:%d:%d:%d", dev->scsi_dev->host->host_no,
dev->scsi_dev->channel, dev->scsi_dev->id,
dev->scsi_dev->lun);
goto out_free_buf;
}
out_free_buf:
kfree(buffer);
+6 -6
View File
@@ -351,7 +351,7 @@ static struct file *vdisk_open(const struct scst_vdisk_dev *virt_dev)
open_flags |= O_RDWR;
if (virt_dev->o_direct_flag)
open_flags |= O_DIRECT;
if (virt_dev->wt_flag)
if (virt_dev->wt_flag && !virt_dev->nv_cache)
open_flags |= O_SYNC;
TRACE_DBG("Opening file %s, flags 0x%x", virt_dev->file_name, open_flags);
fd = filp_open(virt_dev->file_name, O_LARGEFILE | open_flags, 0600);
@@ -494,7 +494,7 @@ static int vdisk_attach(struct scst_device *dev)
dev->dh_priv = virt_dev;
dev->tst = DEF_TST;
if (virt_dev->wt_flag)
if (virt_dev->wt_flag && !virt_dev->nv_cache)
dev->queue_alg = DEF_QUEUE_ALG_WT;
else
dev->queue_alg = DEF_QUEUE_ALG;
@@ -1313,7 +1313,7 @@ static int vdisk_caching_pg(unsigned char *p, int pcontrol,
0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0};
memcpy(p, caching_pg, sizeof(caching_pg));
p[2] |= !(virt_dev->wt_flag) ? WCE : 0;
p[2] |= !(virt_dev->wt_flag || virt_dev->nv_cache) ? WCE : 0;
if (1 == pcontrol)
memset(p + 2, 0, sizeof(caching_pg) - 2);
return sizeof(caching_pg);
@@ -1344,7 +1344,7 @@ static int vdisk_ctrl_m_pg(unsigned char *p, int pcontrol,
break;
case 2:
p[2] |= DEF_TST << 5;
if (virt_dev->wt_flag)
if (virt_dev->wt_flag || virt_dev->nv_cache)
p[3] |= DEF_QUEUE_ALG_WT << 4;
else
p[3] |= DEF_QUEUE_ALG << 4;
@@ -1529,7 +1529,7 @@ static int vdisk_set_wt(struct scst_vdisk_dev *virt_dev, int wt)
TRACE_ENTRY();
if ((virt_dev->wt_flag == wt) || virt_dev->nullio)
if ((virt_dev->wt_flag == wt) || virt_dev->nullio || virt_dev->nv_cache)
goto out;
spin_lock(&virt_dev->flags_lock);
@@ -2486,7 +2486,7 @@ static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
struct scst_vdisk_dev *virt_dev =
(struct scst_vdisk_dev *)dev->dh_priv;
dev->tst = DEF_TST;
if (virt_dev->wt_flag)
if (virt_dev->wt_flag && !virt_dev->nv_cache)
dev->queue_alg = DEF_QUEUE_ALG_WT;
else
dev->queue_alg = DEF_QUEUE_ALG;
+15 -18
View File
@@ -2296,7 +2296,11 @@ int scst_obtain_device_parameters(struct scst_device *dev)
goto out;
} else {
#if 0 /* 3ware controller is buggy and returns CONDITION_GOOD instead of CHECK_CONDITION */
if ((status_byte(res) == CHECK_CONDITION) &&
#else
if (
#endif
SCST_SENSE_VALID(sense_buffer) &&
(sense_buffer[2] == ILLEGAL_REQUEST)) {
TRACE(TRACE_SCSI|TRACE_MGMT_MINOR, "Device %d:%d:%d:%d "
@@ -3103,7 +3107,6 @@ static spinlock_t scst_tm_dbg_lock = SPIN_LOCK_UNLOCKED;
/* All serialized by scst_tm_dbg_lock */
struct
{
unsigned int tm_dbg_active:1;
unsigned int tm_dbg_release:1;
unsigned int tm_dbg_blocked:1;
} tm_dbg_flags;
@@ -3122,19 +3125,16 @@ void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev,
{
if ((acg_dev->acg == scst_default_acg) && (acg_dev->lun == 0)) {
unsigned long flags;
/* Do TM debugging only for LUN 0 */
spin_lock_irqsave(&scst_tm_dbg_lock, flags);
if (!tm_dbg_flags.tm_dbg_active) {
/* Do TM debugging only for LUN 0 */
tm_dbg_p_cmd_list_waitQ =
&tgt_dev->dev->p_cmd_lists->cmd_list_waitQ;
tm_dbg_state = INIT_TM_DBG_STATE;
tm_dbg_on_state_passes =
tm_dbg_on_state_num_passes[tm_dbg_state];
__set_bit(SCST_TGT_DEV_UNDER_TM_DBG, &tgt_dev->tgt_dev_flags);
PRINT_INFO("LUN 0 connected from initiator %s is under "
"TM debugging", tgt_dev->sess->tgt->tgtt->name);
tm_dbg_flags.tm_dbg_active = 1;
}
tm_dbg_p_cmd_list_waitQ =
&tgt_dev->dev->p_cmd_lists->cmd_list_waitQ;
tm_dbg_state = INIT_TM_DBG_STATE;
tm_dbg_on_state_passes =
tm_dbg_on_state_num_passes[tm_dbg_state];
__set_bit(SCST_TGT_DEV_UNDER_TM_DBG, &tgt_dev->tgt_dev_flags);
PRINT_INFO("LUN 0 connected from initiator %s is under "
"TM debugging", tgt_dev->sess->tgt->tgtt->name);
spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
}
}
@@ -3146,7 +3146,6 @@ void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev)
del_timer_sync(&tm_dbg_timer);
spin_lock_irqsave(&scst_tm_dbg_lock, flags);
tm_dbg_p_cmd_list_waitQ = NULL;
tm_dbg_flags.tm_dbg_active = 0;
spin_unlock_irqrestore(&scst_tm_dbg_lock, flags);
}
}
@@ -3342,9 +3341,6 @@ void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, int force)
{
unsigned long flags;
if (!tm_dbg_flags.tm_dbg_active)
goto out;
if (dev != NULL) {
struct scst_tgt_dev *tgt_dev;
bool found = 0;
@@ -3371,7 +3367,8 @@ void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, int force)
tm_dbg_change_state();
tm_dbg_flags.tm_dbg_release = 1;
smp_mb();
wake_up_all(tm_dbg_p_cmd_list_waitQ);
if (tm_dbg_p_cmd_list_waitQ != NULL)
wake_up_all(tm_dbg_p_cmd_list_waitQ);
} else {
TRACE_MGMT_DBG("%s: while OFFLINE state, doing nothing", fn);
}
+53 -38
View File
@@ -208,9 +208,16 @@ void scst_cmd_init_done(struct scst_cmd *cmd, int pref_context)
spin_lock_irqsave(&sess->sess_list_lock, flags);
list_add_tail(&cmd->search_cmd_list_entry, &sess->search_cmd_list);
if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) {
/*
* We have to always keep command in the search list from the
* very beginning, because otherwise it can be missed during
* TM processing. This check is needed because there might be
* old, i.e. deferred, commands and new, i.e. just coming, ones.
*/
if (cmd->search_cmd_list_entry.next == NULL)
list_add_tail(&cmd->search_cmd_list_entry,
&sess->search_cmd_list);
switch(sess->init_phase) {
case SCST_SESS_IPH_SUCCESS:
break;
@@ -228,7 +235,8 @@ void scst_cmd_init_done(struct scst_cmd *cmd, int pref_context)
default:
sBUG();
}
}
} else
list_add_tail(&cmd->search_cmd_list_entry, &sess->search_cmd_list);
spin_unlock_irqrestore(&sess->sess_list_lock, flags);
@@ -1845,6 +1853,7 @@ static int scst_send_to_midlev(struct scst_cmd **active_cmd)
struct scst_cmd *cmd = *active_cmd;
struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
struct scst_device *dev = cmd->dev;
struct scst_session *sess = cmd->sess;
typeof(tgt_dev->expected_sn) expected_sn;
int count;
@@ -1852,11 +1861,12 @@ static int scst_send_to_midlev(struct scst_cmd **active_cmd)
res = SCST_CMD_STATE_RES_CONT_NEXT;
__scst_get(0); /* protect dev & tgt_dev */
__scst_get(0); /* protect dev */
scst_sess_get(sess); /* protect tgt_dev */
if (unlikely(cmd->internal || cmd->retry)) {
rc = scst_do_send_to_midlev(cmd);
/* !! At this point cmd, sess & tgt_dev can be already freed !! */
/* !! At this point cmd can be already freed !! */
if (rc == SCST_EXEC_NEED_THREAD) {
TRACE_DBG("%s", "scst_do_send_to_midlev() requested "
"thread context, rescheduling");
@@ -1875,7 +1885,7 @@ static int scst_send_to_midlev(struct scst_cmd **active_cmd)
getnstimeofday(&ts);
cmd->pre_exec_finish = scst_sec_to_nsec(ts.tv_sec) + ts.tv_nsec;
TRACE_DBG("cmd %p (sess %p): pre_exec_finish %Ld (tv_sec %ld, "
"tv_nsec %ld)", cmd, cmd->sess, cmd->pre_exec_finish, ts.tv_sec,
"tv_nsec %ld)", cmd, sess, cmd->pre_exec_finish, ts.tv_sec,
ts.tv_nsec);
}
#endif
@@ -1960,6 +1970,7 @@ out_unplug:
generic_unplug_device(dev->scsi_dev->request_queue);
out_put:
scst_sess_put(sess);
__scst_put();
/* !! At this point sess, dev and tgt_dev can be already freed !! */
@@ -2434,6 +2445,19 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd)
TRACE_ENTRY();
#ifdef DEBUG_TM
if (cmd->tm_dbg_delayed && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
if (scst_cmd_atomic(cmd)) {
TRACE_MGMT_DBG("%s", "DEBUG_TM delayed cmd needs a thread");
res = SCST_CMD_STATE_RES_NEED_THREAD;
return res;
}
TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second",
cmd, cmd->tag);
schedule_timeout_uninterruptible(HZ);
}
#endif
if (cmd->tgt_dev != NULL) {
if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
scst_on_hq_cmd_response(cmd);
@@ -2516,19 +2540,6 @@ static int scst_xmit_response(struct scst_cmd *cmd)
goto out;
}
#ifdef DEBUG_TM
if (cmd->tm_dbg_delayed && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
if (atomic && !cmd->tgtt->xmit_response_atomic) {
TRACE_MGMT_DBG("%s", "DEBUG_TM delayed cmd needs a thread");
res = SCST_CMD_STATE_RES_NEED_THREAD;
goto out;
}
TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second",
cmd, cmd->tag);
schedule_timeout_uninterruptible(HZ);
}
#endif
while (1) {
int finished_cmds = atomic_read(&cmd->sess->tgt->finished_cmds);
@@ -3439,12 +3450,12 @@ static int scst_set_mcmd_next_state(struct scst_mgmt_cmd *mcmd)
return res;
}
static int __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd)
static bool __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd,
struct list_head *list_entry)
{
int res;
bool res;
if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
TRACE_MGMT_DBG("Adding aborted blocked cmd %p to active cmd "
"list", cmd);
list_del(list_entry);
spin_lock(&cmd->cmd_lists->cmd_list_lock);
list_add_tail(&cmd->cmd_list_entry,
&cmd->cmd_lists->active_cmd_list);
@@ -3472,8 +3483,11 @@ static void scst_unblock_aborted_cmds(int scst_mutex_held)
local_irq_disable();
list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list,
blocked_cmd_list_entry) {
if (__scst_check_unblock_aborted_cmd(cmd))
list_del(&cmd->blocked_cmd_list_entry);
if (__scst_check_unblock_aborted_cmd(cmd,
&cmd->blocked_cmd_list_entry)) {
TRACE_MGMT_DBG("Unblock aborted blocked cmd %p",
cmd);
}
}
local_irq_enable();
spin_unlock_bh(&dev->dev_lock);
@@ -3485,11 +3499,11 @@ static void scst_unblock_aborted_cmds(int scst_mutex_held)
list_for_each_entry_safe(cmd, tcmd,
&tgt_dev->deferred_cmd_list,
sn_cmd_list_entry) {
if (__scst_check_unblock_aborted_cmd(cmd)) {
TRACE_MGMT_DBG("Deleting aborted SN "
"cmd %p from SN list", cmd);
if (__scst_check_unblock_aborted_cmd(cmd,
&cmd->sn_cmd_list_entry)) {
TRACE_MGMT_DBG("Unblockd aborted SN "
"cmd %p", cmd);
tgt_dev->def_cmd_count--;
list_del(&cmd->sn_cmd_list_entry);
}
}
spin_unlock(&tgt_dev->sn_lock);
@@ -4105,6 +4119,9 @@ static void scst_mgmt_cmd_send_done(struct scst_mgmt_cmd *mcmd)
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->sess->tgt->tgtt->task_mgmt_fn_done) {
TRACE_DBG("Calling target %s task_mgmt_fn_done()",
mcmd->sess->tgt->tgtt->name);
@@ -4557,7 +4574,6 @@ restart:
TRACE_DBG("Deleting cmd %p from init deferred cmd list", cmd);
list_del(&cmd->cmd_list_entry);
atomic_dec(&sess->sess_cmd_count);
list_del(&cmd->search_cmd_list_entry);
spin_unlock_irq(&sess->sess_list_lock);
scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD);
spin_lock_irq(&sess->sess_list_lock);
@@ -4666,11 +4682,12 @@ void scst_unregister_session(struct scst_session *sess, int wait,
sess->shutdown_compl = NULL;
#endif
TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess);
list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list);
spin_unlock_irqrestore(&scst_mgmt_lock, flags);
tm_dbg_task_mgmt(NULL, "UNREGISTER SESSION", 1);
scst_sess_put(sess);
wake_up(&scst_mgmt_waitQ);
if (wait) {
TRACE_DBG("Waiting for session %p to complete", sess);
@@ -4689,10 +4706,11 @@ static void scst_pre_unreg_sess(struct scst_session *sess)
{
int i;
struct scst_tgt_dev *tgt_dev;
unsigned long flags;
TRACE_ENTRY();
tm_dbg_task_mgmt(NULL, "UNREGISTER SESSION", 1);
mutex_lock(&scst_mutex);
for(i = 0; i < TGT_DEV_HASH_SIZE; i++) {
struct list_head *sess_tgt_dev_list_head =
@@ -4713,10 +4731,7 @@ static void scst_pre_unreg_sess(struct scst_session *sess)
sess->shut_phase = SCST_SESS_SPH_SHUTDOWN;
spin_lock_irqsave(&scst_mgmt_lock, flags);
TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess);
list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list);
spin_unlock_irqrestore(&scst_mgmt_lock, flags);
scst_sess_put(sess);
TRACE_EXIT();
return;