mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 03:31:26 +00:00
A major cleanup of sending commands for execution code path fixing found problems in it: handling double UA and internal REQUEST SENSE + possible wrong context assignment. Plus several other minor cleanups and fixes.
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@523 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -34,16 +34,6 @@
|
||||
|
||||
#include <scst_const.h>
|
||||
|
||||
#ifndef DECLARE_MUTEX_LOCKED
|
||||
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
typedef _Bool bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Version numbers, the same as for the kernel.
|
||||
*
|
||||
@@ -55,6 +45,18 @@ typedef _Bool bool;
|
||||
#define SCST_VERSION_STRING "1.0.1"
|
||||
#define SCST_INTERFACE_VERSION SCST_VERSION_STRING "$Revision$" SCST_CONST_VERSION
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
typedef _Bool bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#ifndef DECLARE_MUTEX_LOCKED
|
||||
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
|
||||
#endif
|
||||
|
||||
#define SCST_LOCAL_NAME "scst_lcl_drvr"
|
||||
|
||||
/*************************************************************
|
||||
** States of command processing state machine. At first,
|
||||
** "active" states, then - "passive" ones. This is to have
|
||||
@@ -77,26 +79,32 @@ typedef _Bool bool;
|
||||
/* Target driver's pre_exec() is going to be called */
|
||||
#define SCST_CMD_STATE_TGT_PRE_EXEC 4
|
||||
|
||||
/* CDB is going to be sent to SCSI mid-level for execution */
|
||||
#define SCST_CMD_STATE_SEND_TO_MIDLEV 5
|
||||
/* Cmd is going to be sent for execution */
|
||||
#define SCST_CMD_STATE_SEND_FOR_EXEC 5
|
||||
|
||||
/* Internal pos-exec checks */
|
||||
#define SCST_CMD_STATE_PRE_DEV_DONE 6
|
||||
/* Cmd is being checked if it should be executed locally */
|
||||
#define SCST_CMD_STATE_LOCAL_EXEC 6
|
||||
|
||||
/* Cmd is ready for execution */
|
||||
#define SCST_CMD_STATE_REAL_EXEC 7
|
||||
|
||||
/* Internal post-exec checks */
|
||||
#define SCST_CMD_STATE_PRE_DEV_DONE 8
|
||||
|
||||
/* Internal MODE SELECT pages related checks */
|
||||
#define SCST_CMD_STATE_MODE_SELECT_CHECKS 7
|
||||
#define SCST_CMD_STATE_MODE_SELECT_CHECKS 9
|
||||
|
||||
/* Dev handler's dev_done() is going to be called */
|
||||
#define SCST_CMD_STATE_DEV_DONE 8
|
||||
#define SCST_CMD_STATE_DEV_DONE 10
|
||||
|
||||
/* Target driver's xmit_response() is going to be called */
|
||||
#define SCST_CMD_STATE_PRE_XMIT_RESP 9
|
||||
#define SCST_CMD_STATE_PRE_XMIT_RESP 11
|
||||
|
||||
/* Target driver's xmit_response() is going to be called */
|
||||
#define SCST_CMD_STATE_XMIT_RESP 10
|
||||
#define SCST_CMD_STATE_XMIT_RESP 12
|
||||
|
||||
/* The cmd finished */
|
||||
#define SCST_CMD_STATE_FINISHED 11
|
||||
#define SCST_CMD_STATE_FINISHED 13
|
||||
|
||||
#define SCST_CMD_STATE_LAST_ACTIVE (SCST_CMD_STATE_FINISHED+100)
|
||||
|
||||
@@ -113,7 +121,7 @@ typedef _Bool bool;
|
||||
#define SCST_CMD_STATE_DATA_WAIT (SCST_CMD_STATE_LAST_ACTIVE+4)
|
||||
|
||||
/* Waiting for CDB's execution finish */
|
||||
#define SCST_CMD_STATE_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+5)
|
||||
#define SCST_CMD_STATE_REAL_EXECUTING (SCST_CMD_STATE_LAST_ACTIVE+5)
|
||||
|
||||
/* Waiting for response's transmission finish */
|
||||
#define SCST_CMD_STATE_XMIT_WAIT (SCST_CMD_STATE_LAST_ACTIVE+6)
|
||||
@@ -989,13 +997,10 @@ struct scst_cmd {
|
||||
** Cmd's flags
|
||||
*************************************************************/
|
||||
/*
|
||||
* Set if expected_sn was incremented, i.e. cmd was sent to
|
||||
* SCSI mid-level for execution
|
||||
* Set if expected_sn should be incremented, i.e. cmd was sent
|
||||
* for execution
|
||||
*/
|
||||
unsigned int sent_to_midlev:1;
|
||||
|
||||
/* Set if scst_local_exec() was already called for this cmd */
|
||||
unsigned int local_exec_done:1;
|
||||
unsigned int sent_for_exec:1;
|
||||
|
||||
/* Set if the cmd's action is completed */
|
||||
unsigned int completed:1;
|
||||
@@ -1018,12 +1023,12 @@ struct scst_cmd {
|
||||
*/
|
||||
unsigned int context_processable:1;
|
||||
|
||||
/* Set if cmd is internally generated */
|
||||
unsigned int internal:1;
|
||||
|
||||
/* Set if cmd is being retried */
|
||||
unsigned int retry:1;
|
||||
|
||||
/* Set if cmd is internally generated */
|
||||
unsigned int internal:1;
|
||||
|
||||
/* Set if the device was blocked by scst_inc_on_dev_cmd() (for debug) */
|
||||
unsigned int inc_blocking:1;
|
||||
|
||||
|
||||
@@ -254,6 +254,11 @@ static int vcdrom_write_proc(char *buffer, char **start, off_t offset,
|
||||
static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
|
||||
struct scst_tgt_dev *tgt_dev);
|
||||
|
||||
/*
|
||||
* Name of FILEIO vdisk can't be changed from "vdisk", since it is the name
|
||||
* of the corresponding /proc/scsi_tgt entry, hence a part of user space ABI.
|
||||
*/
|
||||
|
||||
#define VDISK_TYPE { \
|
||||
.name = VDISK_NAME, \
|
||||
.type = TYPE_DISK, \
|
||||
@@ -290,6 +295,23 @@ static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
|
||||
.task_mgmt_fn = vdisk_task_mgmt_fn, \
|
||||
}
|
||||
|
||||
#define VDISK_NULL_TYPE { \
|
||||
.name = VDISK_NAME "_null", \
|
||||
.type = TYPE_DISK, \
|
||||
.threads_num = 0, \
|
||||
.parse_atomic = 1, \
|
||||
.exec_atomic = 1, \
|
||||
.dev_done_atomic = 1, \
|
||||
.no_proc = 1, \
|
||||
.attach = vdisk_attach, \
|
||||
.detach = vdisk_detach, \
|
||||
.attach_tgt = vdisk_attach_tgt, \
|
||||
.detach_tgt = vdisk_detach_tgt, \
|
||||
.parse = vdisk_parse, \
|
||||
.exec = vdisk_do_job, \
|
||||
.task_mgmt_fn = vdisk_task_mgmt_fn, \
|
||||
}
|
||||
|
||||
#define VCDROM_TYPE { \
|
||||
.name = VCDROM_NAME, \
|
||||
.type = TYPE_ROM, \
|
||||
@@ -313,8 +335,9 @@ static DEFINE_MUTEX(scst_vdisk_mutex);
|
||||
static LIST_HEAD(vdisk_dev_list);
|
||||
static LIST_HEAD(vcdrom_dev_list);
|
||||
|
||||
static struct scst_dev_type vdisk_devtype = VDISK_TYPE;
|
||||
static struct scst_dev_type vdisk_file_devtype = VDISK_TYPE;
|
||||
static struct scst_dev_type vdisk_blk_devtype = VDISK_BLK_TYPE;
|
||||
static struct scst_dev_type vdisk_null_devtype = VDISK_NULL_TYPE;
|
||||
static struct scst_dev_type vcdrom_devtype = VCDROM_TYPE;
|
||||
|
||||
static char *vdisk_proc_help_string =
|
||||
@@ -539,8 +562,7 @@ static void vdisk_detach(struct scst_device *dev)
|
||||
|
||||
static void vdisk_free_thr_data(struct scst_thr_data_hdr *d)
|
||||
{
|
||||
struct scst_vdisk_thr *thr = container_of(d, struct scst_vdisk_thr,
|
||||
hdr);
|
||||
struct scst_vdisk_thr *thr = container_of(d, struct scst_vdisk_thr, hdr);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -556,7 +578,7 @@ static void vdisk_free_thr_data(struct scst_thr_data_hdr *d)
|
||||
}
|
||||
|
||||
static struct scst_vdisk_thr *vdisk_init_thr_data(
|
||||
struct scst_tgt_dev *tgt_dev)
|
||||
struct scst_tgt_dev *tgt_dev, bool atomic)
|
||||
{
|
||||
struct scst_vdisk_thr *res;
|
||||
struct scst_vdisk_dev *virt_dev =
|
||||
@@ -565,11 +587,13 @@ static struct scst_vdisk_thr *vdisk_init_thr_data(
|
||||
TRACE_ENTRY();
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
|
||||
res = kmem_cache_alloc(vdisk_thr_cachep, GFP_KERNEL);
|
||||
res = kmem_cache_alloc(vdisk_thr_cachep,
|
||||
atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (res != NULL)
|
||||
memset(res, 0, sizeof(*res));
|
||||
#else
|
||||
res = kmem_cache_zalloc(vdisk_thr_cachep, GFP_KERNEL);
|
||||
res = kmem_cache_zalloc(vdisk_thr_cachep,
|
||||
atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
#endif
|
||||
if (res == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "Unable to allocate struct "
|
||||
@@ -680,13 +704,6 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
TRACE_DBG("%s", "vdisk exec() can not be done in atomic "
|
||||
"context, requesting thread context");
|
||||
res = SCST_EXEC_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (cmd->queue_type) {
|
||||
case SCST_CMD_QUEUE_ORDERED:
|
||||
TRACE(TRACE_ORDER, "ORDERED cmd %p", cmd);
|
||||
@@ -709,7 +726,7 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
|
||||
d = scst_find_thr_data(cmd->tgt_dev);
|
||||
if (unlikely(d == NULL)) {
|
||||
thr = vdisk_init_thr_data(cmd->tgt_dev);
|
||||
thr = vdisk_init_thr_data(cmd->tgt_dev, scst_cmd_atomic(cmd));
|
||||
if (thr == NULL) {
|
||||
scst_set_busy(cmd);
|
||||
goto out_compl;
|
||||
@@ -965,7 +982,6 @@ out_thr:
|
||||
|
||||
res = SCST_EXEC_COMPLETED;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -1940,7 +1956,8 @@ static struct iovec *vdisk_alloc_iv(struct scst_cmd *cmd,
|
||||
iv_count = scst_get_buf_count(cmd);
|
||||
if (iv_count > thr->iv_count) {
|
||||
kfree(thr->iv);
|
||||
thr->iv = kmalloc(sizeof(*thr->iv) * iv_count, GFP_KERNEL);
|
||||
thr->iv = kmalloc(sizeof(*thr->iv) * iv_count,
|
||||
scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (thr->iv == NULL) {
|
||||
PRINT_ERROR("Unable to allocate iv (%d)", iv_count);
|
||||
scst_set_busy(cmd);
|
||||
@@ -2846,10 +2863,15 @@ static int vdisk_write_proc(char *buffer, char **start, off_t offset,
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&vdisk_blk_devtype,
|
||||
virt_dev->name);
|
||||
} else if (virt_dev->nullio) {
|
||||
vdisk_report_registering("NULLIO", virt_dev);
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&vdisk_null_devtype,
|
||||
virt_dev->name);
|
||||
} else {
|
||||
vdisk_report_registering("FILEIO", virt_dev);
|
||||
virt_dev->virt_id =
|
||||
scst_register_virtual_device(&vdisk_devtype,
|
||||
scst_register_virtual_device(&vdisk_file_devtype,
|
||||
virt_dev->name);
|
||||
}
|
||||
if (virt_dev->virt_id < 0) {
|
||||
@@ -3426,10 +3448,10 @@ static int __init init_scst_vdisk_driver(void)
|
||||
}
|
||||
|
||||
num_threads = num_online_cpus() + 2;
|
||||
vdisk_devtype.threads_num = num_threads;
|
||||
vdisk_file_devtype.threads_num = num_threads;
|
||||
vcdrom_devtype.threads_num = num_threads;
|
||||
|
||||
res = init_scst_vdisk(&vdisk_devtype);
|
||||
res = init_scst_vdisk(&vdisk_file_devtype);
|
||||
if (res != 0)
|
||||
goto out_free_slab;
|
||||
|
||||
@@ -3437,18 +3459,25 @@ static int __init init_scst_vdisk_driver(void)
|
||||
if (res != 0)
|
||||
goto out_free_vdisk;
|
||||
|
||||
res = init_scst_vdisk(&vdisk_null_devtype);
|
||||
if (res != 0)
|
||||
goto out_free_blk;
|
||||
|
||||
res = init_scst_vdisk(&vcdrom_devtype);
|
||||
if (res != 0)
|
||||
goto out_err;
|
||||
goto out_free_null;
|
||||
|
||||
out:
|
||||
return res;
|
||||
|
||||
out_err:
|
||||
out_free_null:
|
||||
exit_scst_vdisk(&vdisk_null_devtype, &vdisk_dev_list);
|
||||
|
||||
out_free_blk:
|
||||
exit_scst_vdisk(&vdisk_blk_devtype, &vdisk_dev_list);
|
||||
|
||||
out_free_vdisk:
|
||||
exit_scst_vdisk(&vdisk_devtype, &vdisk_dev_list);
|
||||
exit_scst_vdisk(&vdisk_file_devtype, &vdisk_dev_list);
|
||||
|
||||
out_free_slab:
|
||||
kmem_cache_destroy(vdisk_thr_cachep);
|
||||
@@ -3457,8 +3486,9 @@ out_free_slab:
|
||||
|
||||
static void __exit exit_scst_vdisk_driver(void)
|
||||
{
|
||||
exit_scst_vdisk(&vdisk_null_devtype, &vdisk_dev_list);
|
||||
exit_scst_vdisk(&vdisk_blk_devtype, &vdisk_dev_list);
|
||||
exit_scst_vdisk(&vdisk_devtype, &vdisk_dev_list);
|
||||
exit_scst_vdisk(&vdisk_file_devtype, &vdisk_dev_list);
|
||||
exit_scst_vdisk(&vcdrom_devtype, &vcdrom_dev_list);
|
||||
kmem_cache_destroy(vdisk_thr_cachep);
|
||||
}
|
||||
|
||||
@@ -541,17 +541,15 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
|
||||
if (dev->handler->parse_atomic &&
|
||||
(sess->tgt->tgtt->preprocessing_done == NULL)) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic ||
|
||||
(sess->tgt->tgtt->rdy_to_xfer == NULL))
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic)
|
||||
__set_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
if (dev->handler->exec_atomic || (dev->handler->exec == NULL))
|
||||
if (dev->handler->exec_atomic)
|
||||
__set_bit(SCST_TGT_DEV_AFTER_INIT_OTH_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
}
|
||||
if (dev->handler->exec_atomic || (dev->handler->exec == NULL)) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic ||
|
||||
(sess->tgt->tgtt->rdy_to_xfer == NULL))
|
||||
if (dev->handler->exec_atomic) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic)
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RESTART_WR_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RESTART_OTH_ATOMIC,
|
||||
@@ -559,8 +557,7 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RX_DATA_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
}
|
||||
if ((dev->handler->dev_done_atomic ||
|
||||
(dev->handler->dev_done == NULL)) &&
|
||||
if (dev->handler->dev_done_atomic &&
|
||||
sess->tgt->tgtt->xmit_response_atomic) {
|
||||
__set_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
@@ -957,7 +954,6 @@ struct scst_cmd *scst_create_prepare_internal_cmd(
|
||||
|
||||
res->cmd_lists = orig_cmd->cmd_lists;
|
||||
res->sess = orig_cmd->sess;
|
||||
res->state = SCST_CMD_STATE_PRE_PARSE;
|
||||
res->atomic = scst_cmd_atomic(orig_cmd);
|
||||
res->internal = 1;
|
||||
res->tgtt = orig_cmd->tgtt;
|
||||
@@ -968,9 +964,10 @@ struct scst_cmd *scst_create_prepare_internal_cmd(
|
||||
res->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
|
||||
res->data_direction = SCST_DATA_UNKNOWN;
|
||||
res->orig_cmd = orig_cmd;
|
||||
|
||||
res->bufflen = bufsize;
|
||||
|
||||
res->state = SCST_CMD_STATE_PRE_PARSE;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_HRES((unsigned long)res);
|
||||
return res;
|
||||
@@ -988,7 +985,7 @@ void scst_free_internal_cmd(struct scst_cmd *cmd)
|
||||
|
||||
int scst_prepare_request_sense(struct scst_cmd *orig_cmd)
|
||||
{
|
||||
int res = SCST_CMD_STATE_RES_CONT_NEXT;
|
||||
int res = 0;
|
||||
#define sbuf_size 252
|
||||
static const uint8_t request_sense[6] =
|
||||
{ REQUEST_SENSE, 0, 0, 0, sbuf_size, 0 };
|
||||
@@ -1003,12 +1000,16 @@ int scst_prepare_request_sense(struct scst_cmd *orig_cmd)
|
||||
memcpy(rs_cmd->cdb, request_sense, sizeof(request_sense));
|
||||
rs_cmd->cdb_len = sizeof(request_sense);
|
||||
rs_cmd->data_direction = SCST_DATA_READ;
|
||||
rs_cmd->expected_data_direction = rs_cmd->data_direction;
|
||||
rs_cmd->expected_transfer_len = sbuf_size;
|
||||
rs_cmd->expected_values_set = 1;
|
||||
|
||||
TRACE(TRACE_MGMT_MINOR, "Adding REQUEST SENSE cmd %p to head of active "
|
||||
"cmd list ", rs_cmd);
|
||||
spin_lock_irq(&rs_cmd->cmd_lists->cmd_list_lock);
|
||||
list_add(&rs_cmd->cmd_list_entry, &rs_cmd->cmd_lists->active_cmd_list);
|
||||
spin_unlock_irq(&rs_cmd->cmd_lists->cmd_list_lock);
|
||||
wake_up(&rs_cmd->cmd_lists->cmd_list_waitQ);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -1028,16 +1029,7 @@ struct scst_cmd *scst_complete_request_sense(struct scst_cmd *req_cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (req_cmd->dev->handler->dev_done != NULL) {
|
||||
int rc;
|
||||
TRACE_DBG("Calling dev handler %s dev_done(%p)",
|
||||
req_cmd->dev->handler->name, req_cmd);
|
||||
rc = req_cmd->dev->handler->dev_done(req_cmd);
|
||||
TRACE_DBG("Dev handler %s dev_done() returned %d",
|
||||
req_cmd->dev->handler->name, rc);
|
||||
}
|
||||
|
||||
sBUG_ON(orig_cmd);
|
||||
sBUG_ON(orig_cmd == NULL);
|
||||
|
||||
len = scst_get_buf_first(req_cmd, &buf);
|
||||
|
||||
@@ -1372,6 +1364,7 @@ struct scst_cmd *scst_alloc_cmd(gfp_t gfp_mask)
|
||||
#endif
|
||||
|
||||
cmd->state = SCST_CMD_STATE_INIT_WAIT;
|
||||
cmd->start_time = jiffies;
|
||||
atomic_set(&cmd->cmd_ref, 1);
|
||||
cmd->cmd_lists = &scst_main_cmd_lists;
|
||||
INIT_LIST_HEAD(&cmd->mgmt_cmd_list);
|
||||
@@ -1466,7 +1459,7 @@ void scst_free_cmd(struct scst_cmd *cmd)
|
||||
|
||||
if (likely(cmd->tgt_dev != NULL)) {
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
if (unlikely(!cmd->sent_to_midlev)) {
|
||||
if (unlikely(!cmd->sent_for_exec)) {
|
||||
PRINT_ERROR("Finishing not executed cmd %p (opcode "
|
||||
"%d, target %s, lun %lld, sn %ld, expected_sn %ld)",
|
||||
cmd, cmd->cdb[0], cmd->tgtt->name,
|
||||
@@ -3033,6 +3026,14 @@ int scst_inc_on_dev_cmd(struct scst_cmd *cmd)
|
||||
cmd->dec_on_dev_needed = 1;
|
||||
TRACE_DBG("New on_dev_count %d", atomic_read(&dev->on_dev_count));
|
||||
|
||||
if (unlikely(cmd->internal) && (cmd->cdb[0] == REQUEST_SENSE)) {
|
||||
/*
|
||||
* The original command can already block the device, so
|
||||
* REQUEST SENSE command should always pass.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCST_STRICT_SERIALIZING
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
|
||||
@@ -3119,8 +3120,10 @@ void scst_unblock_cmds(struct scst_device *dev)
|
||||
* can't change behind us, if the corresponding cmd is in
|
||||
* blocked_cmd_list, but we could be called before
|
||||
* scst_inc_expected_sn().
|
||||
*
|
||||
* For HQ commands SN is not set.
|
||||
*/
|
||||
if (likely(!cmd->internal && !cmd->retry)) {
|
||||
if (likely(!cmd->internal && cmd->sn_set)) {
|
||||
typeof(cmd->tgt_dev->expected_sn) expected_sn;
|
||||
if (cmd->tgt_dev == NULL)
|
||||
sBUG();
|
||||
@@ -3176,7 +3179,7 @@ static void __scst_unblock_deferred(struct scst_tgt_dev *tgt_dev,
|
||||
|
||||
if (out_of_sn_cmd->sn == tgt_dev->expected_sn) {
|
||||
scst_inc_expected_sn(tgt_dev, out_of_sn_cmd->sn_slot);
|
||||
scst_make_deferred_commands_active(tgt_dev, out_of_sn_cmd);
|
||||
scst_make_deferred_commands_active(tgt_dev);
|
||||
} else {
|
||||
out_of_sn_cmd->out_of_sn = 1;
|
||||
spin_lock_irq(&tgt_dev->sn_lock);
|
||||
@@ -3230,7 +3233,7 @@ void scst_on_hq_cmd_response(struct scst_cmd *cmd)
|
||||
* unneeded run of the deferred commands.
|
||||
*/
|
||||
if (tgt_dev->hq_cmd_count == 0)
|
||||
scst_make_deferred_commands_active(tgt_dev, cmd);
|
||||
scst_make_deferred_commands_active(tgt_dev);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
|
||||
@@ -202,6 +202,9 @@ int __scst_register_target_template(struct scst_tgt_template *vtt,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (vtt->rdy_to_xfer == NULL)
|
||||
vtt->rdy_to_xfer_atomic = 1;
|
||||
|
||||
if (mutex_lock_interruptible(&m) != 0)
|
||||
goto out_err;
|
||||
|
||||
@@ -1484,7 +1487,9 @@ static int scst_add(struct device *cdev, struct class_interface *intf)
|
||||
#else
|
||||
scsidp = to_scsi_device(cdev->parent);
|
||||
#endif
|
||||
res = scst_register_device(scsidp);
|
||||
|
||||
if (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0)
|
||||
res = scst_register_device(scsidp);
|
||||
|
||||
TRACE_EXIT();
|
||||
return res;
|
||||
@@ -1505,7 +1510,9 @@ static void scst_remove(struct device *cdev, struct class_interface *intf)
|
||||
#else
|
||||
scsidp = to_scsi_device(cdev->parent);
|
||||
#endif
|
||||
scst_unregister_device(scsidp);
|
||||
|
||||
if (strcmp(scsidp->host->hostt->name, SCST_LOCAL_NAME) != 0)
|
||||
scst_unregister_device(scsidp);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
|
||||
@@ -98,11 +98,12 @@ extern unsigned long scst_trace_flag;
|
||||
#define SCST_FLAG_SUSPENDED 1
|
||||
|
||||
/**
|
||||
** Return codes for cmd state process functions
|
||||
** Return codes for cmd state process functions. Codes are the same as
|
||||
** for SCST_EXEC_* to avoid translation to them and, hence, have better code.
|
||||
**/
|
||||
#define SCST_CMD_STATE_RES_CONT_SAME 0
|
||||
#define SCST_CMD_STATE_RES_CONT_NEXT 1
|
||||
#define SCST_CMD_STATE_RES_NEED_THREAD 2
|
||||
#define SCST_CMD_STATE_RES_CONT_NEXT SCST_EXEC_COMPLETED
|
||||
#define SCST_CMD_STATE_RES_CONT_SAME SCST_EXEC_NOT_COMPLETED
|
||||
#define SCST_CMD_STATE_RES_NEED_THREAD SCST_EXEC_NEED_THREAD
|
||||
|
||||
/** Name of the "default" security group **/
|
||||
#define SCST_DEFAULT_ACG_NAME "Default"
|
||||
@@ -232,16 +233,13 @@ static inline struct scst_cmd *scst_check_deferred_commands(
|
||||
}
|
||||
|
||||
static inline void scst_make_deferred_commands_active(
|
||||
struct scst_tgt_dev *tgt_dev, struct scst_cmd *curr_cmd)
|
||||
struct scst_tgt_dev *tgt_dev)
|
||||
{
|
||||
struct scst_cmd *c;
|
||||
|
||||
c = __scst_check_deferred_commands(tgt_dev);
|
||||
if (c != NULL) {
|
||||
TRACE_SN("Adding cmd %p to active cmd list", c);
|
||||
|
||||
EXTRACHECKS_BUG_ON(c->cmd_lists != curr_cmd->cmd_lists);
|
||||
|
||||
spin_lock_irq(&c->cmd_lists->cmd_list_lock);
|
||||
list_add_tail(&c->cmd_list_entry,
|
||||
&c->cmd_lists->active_cmd_list);
|
||||
@@ -439,35 +437,33 @@ extern void scst_block_dev_cmd(struct scst_cmd *cmd, int outstanding);
|
||||
extern void scst_unblock_dev(struct scst_device *dev);
|
||||
extern void scst_unblock_dev_cmd(struct scst_cmd *cmd);
|
||||
|
||||
static inline void __scst_dec_on_dev_cmd(struct scst_device *dev,
|
||||
int unblock_dev)
|
||||
/* No locks */
|
||||
static inline void scst_dec_on_dev_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
if (unblock_dev)
|
||||
scst_unblock_dev(dev);
|
||||
atomic_dec(&dev->on_dev_count);
|
||||
smp_mb__after_atomic_dec();
|
||||
TRACE_DBG("New on_dev_count %d", atomic_read(&dev->on_dev_count));
|
||||
sBUG_ON(atomic_read(&dev->on_dev_count) < 0);
|
||||
if (unlikely(dev->block_count != 0))
|
||||
wake_up_all(&dev->on_dev_waitQ);
|
||||
}
|
||||
struct scst_device *dev = cmd->dev;
|
||||
bool unblock_dev = cmd->inc_blocking;
|
||||
|
||||
static inline int scst_pre_dec_on_dev_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
int cmd_blocking = cmd->inc_blocking;
|
||||
if (cmd_blocking) {
|
||||
if (cmd->inc_blocking) {
|
||||
TRACE_MGMT_DBG("cmd %p (tag %llu): unblocking dev %p", cmd,
|
||||
(long long unsigned int)cmd->tag, cmd->dev);
|
||||
cmd->inc_blocking = 0;
|
||||
}
|
||||
cmd->dec_on_dev_needed = 0;
|
||||
return cmd_blocking;
|
||||
}
|
||||
|
||||
static inline void scst_dec_on_dev_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
int cmd_blocking = scst_pre_dec_on_dev_cmd(cmd);
|
||||
__scst_dec_on_dev_cmd(cmd->dev, cmd_blocking);
|
||||
if (unblock_dev)
|
||||
scst_unblock_dev(dev);
|
||||
|
||||
atomic_dec(&dev->on_dev_count);
|
||||
smp_mb__after_atomic_dec();
|
||||
|
||||
TRACE_DBG("New on_dev_count %d", atomic_read(&dev->on_dev_count));
|
||||
|
||||
sBUG_ON(atomic_read(&dev->on_dev_count) < 0);
|
||||
|
||||
if (unlikely(dev->block_count != 0))
|
||||
wake_up_all(&dev->on_dev_waitQ);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void __scst_get(int barrier)
|
||||
|
||||
@@ -1566,8 +1566,16 @@ static ssize_t scst_proc_groups_devices_write(struct file *file, const char __us
|
||||
|
||||
while (isspace(*e) && *e != '\0')
|
||||
e++;
|
||||
if (!strncasecmp("READ_ONLY", e, 9))
|
||||
read_only = 1;
|
||||
|
||||
if (*e != '\0') {
|
||||
if (!strncasecmp("READ_ONLY", e, 9))
|
||||
read_only = 1;
|
||||
else {
|
||||
PRINT_ERROR("Unknown option \"%s\"", e);
|
||||
res = -EINVAL;
|
||||
goto out_free_up;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list,
|
||||
acg_dev_list_entry) {
|
||||
@@ -1901,8 +1909,8 @@ static int scst_groups_devices_show(struct seq_file *seq, void *v)
|
||||
goto out;
|
||||
}
|
||||
|
||||
seq_printf(seq, "%-60s%s %s\n", "Device (host:ch:id:lun or name)",
|
||||
"Virtual lun", "Options");
|
||||
seq_printf(seq, "%-60s%-13s%s\n", "Device (host:ch:id:lun or name)",
|
||||
"LUN", "Options");
|
||||
|
||||
list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
|
||||
if (acg_dev->dev->virt_id == 0) {
|
||||
@@ -1915,13 +1923,19 @@ static int scst_groups_devices_show(struct seq_file *seq, void *v)
|
||||
acg_dev->dev->scsi_dev->channel,
|
||||
acg_dev->dev->scsi_dev->id);
|
||||
seq_printf(seq, "%s", conv);
|
||||
sprintf(conv, "%%-%dd%%4d%%12s\n", 60 - size);
|
||||
seq_printf(seq, conv,
|
||||
|
||||
/*
|
||||
* For some reason the third string argument always
|
||||
* shown as NULL, so we have to split it on 2 calls.
|
||||
*/
|
||||
sprintf(conv, "%%-%dd%%-13d", 60 - size);
|
||||
size += seq_printf(seq, conv,
|
||||
acg_dev->dev->scsi_dev->lun,
|
||||
acg_dev->lun,
|
||||
acg_dev->rd_only_flag ? "RO" : "");
|
||||
acg_dev->lun);
|
||||
seq_printf(seq, "%s\n",
|
||||
acg_dev->rd_only_flag ? "RO" : "");
|
||||
} else {
|
||||
seq_printf(seq, "%-60s%4Ld%12s\n",
|
||||
seq_printf(seq, "%-60s%-13lld%s\n",
|
||||
acg_dev->dev->virt_name,
|
||||
(long long unsigned int)acg_dev->lun,
|
||||
acg_dev->rd_only_flag ? "RO" : "");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user