mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-17 20:56:24 +00:00
Fix possible deadlock on waiting on blocking. As a side effect it leaded to a nice cleanup.
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2272 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+2
-6
@@ -82,12 +82,8 @@ void ft_cmd_dump(struct scst_cmd *cmd, const char *caller)
|
||||
ft_cmd_flag(buf, sizeof(buf), "retry");
|
||||
if (cmd->internal)
|
||||
ft_cmd_flag(buf, sizeof(buf), "internal");
|
||||
if (cmd->inc_blocking)
|
||||
ft_cmd_flag(buf, sizeof(buf), "inc_blk");
|
||||
if (cmd->needs_unblocking)
|
||||
ft_cmd_flag(buf, sizeof(buf), "needs_unblk");
|
||||
if (cmd->dec_on_dev_needed)
|
||||
ft_cmd_flag(buf, sizeof(buf), "dec_on_dev");
|
||||
if (cmd->unblock_dev)
|
||||
ft_cmd_flag(buf, sizeof(buf), "unblock_dev");
|
||||
if (cmd->cmd_hw_pending)
|
||||
ft_cmd_flag(buf, sizeof(buf), "hw_pend");
|
||||
if (cmd->tgt_need_alloc_data_buf)
|
||||
|
||||
+11
-26
@@ -1636,14 +1636,8 @@ struct scst_cmd {
|
||||
/* 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;
|
||||
|
||||
/* Set if the device should be unblocked after cmd's finish */
|
||||
unsigned int needs_unblocking:1;
|
||||
|
||||
/* Set if scst_dec_on_dev_cmd() call is needed on the cmd's finish */
|
||||
unsigned int dec_on_dev_needed:1;
|
||||
/* Set if the device was blocked by scst_check_blocked_dev() */
|
||||
unsigned int unblock_dev:1;
|
||||
|
||||
/* Set if cmd is queued as hw pending */
|
||||
unsigned int cmd_hw_pending:1;
|
||||
@@ -2068,6 +2062,15 @@ struct scst_device {
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/*
|
||||
* How many times device was blocked for new cmds execution.
|
||||
* Protected by dev_lock
|
||||
*/
|
||||
int block_count;
|
||||
|
||||
/* How many cmds alive on this dev */
|
||||
atomic_t dev_cmd_count;
|
||||
|
||||
/*
|
||||
* Set if dev is persistently reserved. Protected by dev_pr_mutex.
|
||||
* Modified independently to the above field, hence the alignment.
|
||||
@@ -2105,21 +2108,6 @@ struct scst_device {
|
||||
/* Memory limits for this device */
|
||||
struct scst_mem_lim dev_mem_lim;
|
||||
|
||||
/* How many cmds alive on this dev */
|
||||
atomic_t dev_cmd_count;
|
||||
|
||||
/*
|
||||
* How many there are "on_dev" commands, i.e. ones those are being
|
||||
* executed by the underlying SCSI/virtual device.
|
||||
*/
|
||||
atomic_t on_dev_count;
|
||||
|
||||
/*
|
||||
* How many times device was blocked for new cmds execution.
|
||||
* Protected by dev_lock
|
||||
*/
|
||||
int block_count;
|
||||
|
||||
/* How many write cmds alive on this dev. Temporary, ToDo */
|
||||
atomic_t write_cmd_count;
|
||||
|
||||
@@ -2168,9 +2156,6 @@ struct scst_device {
|
||||
|
||||
struct list_head blocked_cmd_list; /* protected by dev_lock */
|
||||
|
||||
/* Used to wait for requested amount of "on_dev" commands */
|
||||
wait_queue_head_t on_dev_waitQ;
|
||||
|
||||
/* A list entry used during TM, protected by scst_mutex */
|
||||
struct list_head tm_dev_list_entry;
|
||||
|
||||
|
||||
@@ -141,6 +141,10 @@ enum scst_cmd_queue_type {
|
||||
|
||||
/*************************************************************
|
||||
** CDB flags
|
||||
**
|
||||
** Implicit ordered used for commands which need calm environment
|
||||
** without any simultaneous activities. For instance, for MODE
|
||||
** SELECT it is needed to correctly generate its UA.
|
||||
*************************************************************/
|
||||
enum scst_cdb_flags {
|
||||
SCST_TRANSFER_LEN_TYPE_FIXED = 0x0001,
|
||||
@@ -150,13 +154,14 @@ enum scst_cdb_flags {
|
||||
SCST_INFO_VALID = 0x0010, /* must be single bit */
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x0020,
|
||||
SCST_IMPLICIT_HQ = 0x0040,
|
||||
SCST_SKIP_UA = 0x0080,
|
||||
SCST_WRITE_MEDIUM = 0x0100,
|
||||
SCST_LOCAL_CMD = 0x0200,
|
||||
SCST_FULLY_LOCAL_CMD = 0x0400,
|
||||
SCST_REG_RESERVE_ALLOWED = 0x0800,
|
||||
SCST_WRITE_EXCL_ALLOWED = 0x1000,
|
||||
SCST_EXCL_ACCESS_ALLOWED = 0x2000,
|
||||
SCST_IMPLICIT_ORDERED = 0x0080,
|
||||
SCST_SKIP_UA = 0x0100,
|
||||
SCST_WRITE_MEDIUM = 0x0200,
|
||||
SCST_LOCAL_CMD = 0x0400,
|
||||
SCST_FULLY_LOCAL_CMD = 0x0800,
|
||||
SCST_REG_RESERVE_ALLOWED = 0x1000,
|
||||
SCST_WRITE_EXCL_ALLOWED = 0x2000,
|
||||
SCST_EXCL_ACCESS_ALLOWED = 0x4000,
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED = 0x8000,
|
||||
#endif
|
||||
|
||||
+14
-63
@@ -271,7 +271,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
2, get_trans_len_3},
|
||||
{0x15, "OMOOOOOOOOOOOOOO", "MODE SELECT(6)",
|
||||
SCST_DATA_WRITE, SCST_LOCAL_CMD, 4, get_trans_len_1},
|
||||
SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 4, get_trans_len_1},
|
||||
{0x16, "MMMMMMMMMMMMMMMM", "RESERVE",
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
|
||||
SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
|
||||
@@ -432,7 +432,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x4B, " O ", "PAUSE/RESUME",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0x4C, "OOOOOOOOOOOOOOOO", "LOG SELECT",
|
||||
SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 7, get_trans_len_2},
|
||||
SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 7, get_trans_len_2},
|
||||
{0x4D, "OOOOOOOOOOOOOOOO", "LOG SENSE",
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
@@ -458,7 +458,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x54, " O ", "SEND OPC INFORMATION",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
|
||||
{0x55, "OOOOOOOOOOOOOOOO", "MODE SELECT(10)",
|
||||
SCST_DATA_WRITE, SCST_LOCAL_CMD, 7, get_trans_len_2},
|
||||
SCST_DATA_WRITE, SCST_IMPLICIT_ORDERED, 7, get_trans_len_2},
|
||||
{0x56, "OOOOOOOOOOOOOOOO", "RESERVE(10)",
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD,
|
||||
0, get_trans_len_none},
|
||||
@@ -2579,11 +2579,9 @@ int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev)
|
||||
atomic_set(&dev->write_cmd_count, 0);
|
||||
scst_init_mem_lim(&dev->dev_mem_lim);
|
||||
spin_lock_init(&dev->dev_lock);
|
||||
atomic_set(&dev->on_dev_count, 0);
|
||||
INIT_LIST_HEAD(&dev->blocked_cmd_list);
|
||||
INIT_LIST_HEAD(&dev->dev_tgt_dev_list);
|
||||
INIT_LIST_HEAD(&dev->dev_acg_dev_list);
|
||||
init_waitqueue_head(&dev->on_dev_waitQ);
|
||||
dev->dev_double_ua_possible = 1;
|
||||
dev->queue_alg = SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER;
|
||||
|
||||
@@ -4231,8 +4229,7 @@ void scst_free_cmd(struct scst_cmd *cmd)
|
||||
cmd, atomic_read(&scst_cmd_count));
|
||||
}
|
||||
|
||||
sBUG_ON(cmd->inc_blocking || cmd->needs_unblocking ||
|
||||
cmd->dec_on_dev_needed);
|
||||
sBUG_ON(cmd->unblock_dev);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
#if defined(CONFIG_SCST_EXTRACHECKS)
|
||||
@@ -6685,47 +6682,12 @@ bool scst_del_thr_data(struct scst_tgt_dev *tgt_dev, struct task_struct *tsk)
|
||||
}
|
||||
|
||||
/* dev_lock supposed to be held and BH disabled */
|
||||
void __scst_block_dev(struct scst_device *dev)
|
||||
void scst_block_dev(struct scst_device *dev)
|
||||
{
|
||||
dev->block_count++;
|
||||
TRACE_MGMT_DBG("Device BLOCK(new %d), dev %p", dev->block_count, dev);
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
static void scst_block_dev(struct scst_device *dev, int outstanding)
|
||||
{
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
|
||||
/*
|
||||
* Memory barrier is necessary here, because we need to read
|
||||
* on_dev_count in wait_event() below after we increased block_count.
|
||||
* Otherwise, we can miss wake up in scst_dec_on_dev_cmd().
|
||||
* We use the explicit barrier, because spin_unlock_bh() doesn't
|
||||
* provide the necessary memory barrier functionality.
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
TRACE_MGMT_DBG("Waiting during blocking outstanding %d (on_dev_count "
|
||||
"%d)", outstanding, atomic_read(&dev->on_dev_count));
|
||||
wait_event(dev->on_dev_waitQ,
|
||||
atomic_read(&dev->on_dev_count) <= outstanding);
|
||||
TRACE_MGMT_DBG("%s", "wait_event() returned");
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
void scst_block_dev_cmd(struct scst_cmd *cmd, int outstanding)
|
||||
{
|
||||
sBUG_ON(cmd->needs_unblocking);
|
||||
|
||||
cmd->needs_unblocking = 1;
|
||||
TRACE_MGMT_DBG("Needs unblocking cmd %p (tag %llu)",
|
||||
cmd, (long long unsigned int)cmd->tag);
|
||||
|
||||
scst_block_dev(cmd->dev, outstanding);
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
void scst_unblock_dev(struct scst_device *dev)
|
||||
{
|
||||
@@ -6739,25 +6701,14 @@ void scst_unblock_dev(struct scst_device *dev)
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
void scst_unblock_dev_cmd(struct scst_cmd *cmd)
|
||||
bool __scst_check_blocked_dev(struct scst_cmd *cmd)
|
||||
{
|
||||
scst_unblock_dev(cmd->dev);
|
||||
cmd->needs_unblocking = 0;
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
int scst_inc_on_dev_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = 0;
|
||||
int res = false;
|
||||
struct scst_device *dev = cmd->dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
sBUG_ON(cmd->inc_blocking || cmd->dec_on_dev_needed);
|
||||
|
||||
atomic_inc(&dev->on_dev_count);
|
||||
cmd->dec_on_dev_needed = 1;
|
||||
TRACE_DBG("New on_dev_count %d", atomic_read(&dev->on_dev_count));
|
||||
EXTRACHECKS_BUG_ON(cmd->unblock_dev);
|
||||
|
||||
if (unlikely(cmd->internal) && (cmd->cdb[0] == REQUEST_SENSE)) {
|
||||
/*
|
||||
@@ -6768,18 +6719,17 @@ int scst_inc_on_dev_cmd(struct scst_cmd *cmd)
|
||||
}
|
||||
|
||||
repeat:
|
||||
if (unlikely(dev->block_count > 0)) {
|
||||
if (dev->block_count > 0) {
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
|
||||
goto out_unlock;
|
||||
if (dev->block_count > 0) {
|
||||
scst_dec_on_dev_cmd(cmd);
|
||||
TRACE_MGMT_DBG("Delaying cmd %p due to blocking "
|
||||
"(tag %llu, dev %p)", cmd,
|
||||
(long long unsigned int)cmd->tag, dev);
|
||||
list_add_tail(&cmd->blocked_cmd_list_entry,
|
||||
&dev->blocked_cmd_list);
|
||||
res = 1;
|
||||
res = true;
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
goto out;
|
||||
} else {
|
||||
@@ -6788,14 +6738,15 @@ repeat:
|
||||
}
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
}
|
||||
if (unlikely(dev->dev_double_ua_possible)) {
|
||||
|
||||
if (dev->dev_double_ua_possible) {
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
if (dev->block_count == 0) {
|
||||
TRACE_MGMT_DBG("cmd %p (tag %llu), blocking further "
|
||||
"cmds due to possible double reset UA (dev %p)",
|
||||
cmd, (long long unsigned int)cmd->tag, dev);
|
||||
__scst_block_dev(dev);
|
||||
cmd->inc_blocking = 1;
|
||||
scst_block_dev(dev);
|
||||
cmd->unblock_dev = 1;
|
||||
} else {
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
TRACE_MGMT_DBG("Somebody blocked the device, "
|
||||
|
||||
+21
-27
@@ -558,6 +558,11 @@ static inline bool scst_is_implicit_hq(struct scst_cmd *cmd)
|
||||
return (cmd->op_flags & SCST_IMPLICIT_HQ) != 0;
|
||||
}
|
||||
|
||||
static inline bool scst_is_implicit_ordered(struct scst_cmd *cmd)
|
||||
{
|
||||
return (cmd->op_flags & SCST_IMPLICIT_ORDERED) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some notes on devices "blocking". Blocking means that no
|
||||
* commands will go from SCST to underlying SCSI device until it
|
||||
@@ -565,40 +570,29 @@ static inline bool scst_is_implicit_hq(struct scst_cmd *cmd)
|
||||
* already on the device.
|
||||
*/
|
||||
|
||||
extern int scst_inc_on_dev_cmd(struct scst_cmd *cmd);
|
||||
|
||||
extern void __scst_block_dev(struct scst_device *dev);
|
||||
extern void scst_block_dev_cmd(struct scst_cmd *cmd, int outstanding);
|
||||
extern void scst_block_dev(struct scst_device *dev);
|
||||
extern void scst_unblock_dev(struct scst_device *dev);
|
||||
extern void scst_unblock_dev_cmd(struct scst_cmd *cmd);
|
||||
|
||||
extern bool __scst_check_blocked_dev(struct scst_cmd *cmd);
|
||||
|
||||
static inline bool scst_check_blocked_dev(struct scst_cmd *cmd)
|
||||
{
|
||||
if (unlikely(cmd->dev->block_count > 0) ||
|
||||
unlikely(cmd->dev->dev_double_ua_possible))
|
||||
return __scst_check_blocked_dev(cmd);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No locks */
|
||||
static inline void scst_dec_on_dev_cmd(struct scst_cmd *cmd)
|
||||
static inline void scst_check_unblock_dev(struct scst_cmd *cmd)
|
||||
{
|
||||
struct scst_device *dev = cmd->dev;
|
||||
bool unblock_dev = cmd->inc_blocking;
|
||||
|
||||
if (cmd->inc_blocking) {
|
||||
if (unlikely(cmd->unblock_dev)) {
|
||||
TRACE_MGMT_DBG("cmd %p (tag %llu): unblocking dev %p", cmd,
|
||||
(long long unsigned int)cmd->tag, cmd->dev);
|
||||
cmd->inc_blocking = 0;
|
||||
cmd->unblock_dev = 0;
|
||||
scst_unblock_dev(cmd->dev);
|
||||
}
|
||||
cmd->dec_on_dev_needed = 0;
|
||||
|
||||
if (unblock_dev)
|
||||
scst_unblock_dev(dev);
|
||||
|
||||
atomic_dec(&dev->on_dev_count);
|
||||
/* See comment in scst_block_dev() */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+13
-32
@@ -414,9 +414,10 @@ static int scst_pre_parse(struct scst_cmd *cmd)
|
||||
cmd->inc_expected_sn_on_done = 1;
|
||||
#else
|
||||
cmd->inc_expected_sn_on_done = dev->handler->exec_sync ||
|
||||
(!dev->has_own_order_mgmt &&
|
||||
(dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER ||
|
||||
cmd->queue_type == SCST_CMD_QUEUE_ORDERED));
|
||||
scst_is_implicit_ordered(cmd) ||
|
||||
(!dev->has_own_order_mgmt &&
|
||||
(dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER ||
|
||||
cmd->queue_type == SCST_CMD_QUEUE_ORDERED));
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1927,20 +1928,6 @@ out_unlock_compl:
|
||||
goto out_compl;
|
||||
}
|
||||
|
||||
static int scst_pre_select(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = SCST_EXEC_NOT_COMPLETED;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
scst_block_dev_cmd(cmd, 1);
|
||||
|
||||
/* Check for local events will be done when cmd will be executed */
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int scst_reserve_local(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = SCST_EXEC_NOT_COMPLETED, rc;
|
||||
@@ -2704,11 +2691,6 @@ static int scst_do_local_exec(struct scst_cmd *cmd)
|
||||
}
|
||||
|
||||
switch (cmd->cdb[0]) {
|
||||
case MODE_SELECT:
|
||||
case MODE_SELECT_10:
|
||||
case LOG_SELECT:
|
||||
res = scst_pre_select(cmd);
|
||||
break;
|
||||
case RESERVE:
|
||||
case RESERVE_10:
|
||||
res = scst_reserve_local(cmd);
|
||||
@@ -2780,7 +2762,7 @@ static int scst_exec(struct scst_cmd **active_cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (unlikely(scst_inc_on_dev_cmd(cmd) != 0))
|
||||
if (unlikely(scst_check_blocked_dev(cmd)))
|
||||
goto out;
|
||||
|
||||
/* To protect tgt_dev */
|
||||
@@ -2823,7 +2805,7 @@ done:
|
||||
if (cmd == NULL)
|
||||
break;
|
||||
|
||||
if (unlikely(scst_inc_on_dev_cmd(cmd) != 0))
|
||||
if (unlikely(scst_check_blocked_dev(cmd)))
|
||||
break;
|
||||
|
||||
__scst_cmd_put(ref_cmd);
|
||||
@@ -3372,11 +3354,7 @@ static int scst_dev_done(struct scst_cmd *cmd)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cmd->needs_unblocking)
|
||||
scst_unblock_dev_cmd(cmd);
|
||||
|
||||
if (likely(cmd->dec_on_dev_needed))
|
||||
scst_dec_on_dev_cmd(cmd);
|
||||
scst_check_unblock_dev(cmd);
|
||||
|
||||
if (cmd->inc_expected_sn_on_done && cmd->sent_for_exec)
|
||||
scst_inc_check_expected_sn(cmd);
|
||||
@@ -3694,6 +3672,9 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
|
||||
cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
|
||||
}
|
||||
|
||||
if (unlikely(scst_is_implicit_ordered(cmd)))
|
||||
cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
|
||||
|
||||
EXTRACHECKS_BUG_ON(cmd->sn_set || cmd->hq_cmd_inced);
|
||||
|
||||
/* Optimized for lockless fast path */
|
||||
@@ -5047,7 +5028,7 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
|
||||
*/
|
||||
mcmd->needs_unblocking = 1;
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
scst_block_dev(dev);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
#endif
|
||||
|
||||
@@ -5207,7 +5188,7 @@ static int scst_target_reset(struct scst_mgmt_cmd *mcmd)
|
||||
dev = acg_dev->dev;
|
||||
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
scst_block_dev(dev);
|
||||
scst_process_reset(dev, mcmd->sess, NULL, mcmd, true);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
|
||||
@@ -5311,7 +5292,7 @@ static int scst_lun_reset(struct scst_mgmt_cmd *mcmd)
|
||||
mcmd->needs_unblocking = 1;
|
||||
|
||||
spin_lock_bh(&dev->dev_lock);
|
||||
__scst_block_dev(dev);
|
||||
scst_block_dev(dev);
|
||||
scst_process_reset(dev, mcmd->sess, NULL, mcmd, true);
|
||||
spin_unlock_bh(&dev->dev_lock);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user