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:
Vladislav Bolkhovitin
2008-10-16 17:34:33 +00:00
parent d747aa2fa4
commit ad6366bbf9
7 changed files with 651 additions and 529 deletions

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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)

View File

@@ -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