Skip to content

Commit e35fddb

Browse files
committed
scst_cmd_set_sn: remove lockless fast path
The lockless fast path for scst_cmd_set_sn() can cause commands to lockup in state EXEC_CHECK_SN when there are multiple scst_tgts accessing the same scst_device, for example two initiators connected to the two ports of a dual-port QLogic FC HBA in target mode both reading from the same shared disk. The multithreaded_init_done value is too low-level for this; it does not take the higher-level configuration into account. - Remove the lockless fast path. - Remove multithreaded_init_done, which enabled/disabled the lockless fast path. - Push the locking down into scst_cmd_set_sn(), which will now apply regardless of set_sn_on_restart_cmd, which matters for mixed-driver (e.g. iSCSI+qla2xxx) target-mode setups. - Remove a bunch of comments explaining the rules for the lockless fast path. Fixes: #333 Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
1 parent cb6cdf3 commit e35fddb

3 files changed

Lines changed: 12 additions & 50 deletions

File tree

scst/include/scst.h

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -755,12 +755,6 @@ struct scst_tgt_template {
755755
/* True, if this target doesn't need "enabled" attribute */
756756
unsigned enabled_attr_not_needed:1;
757757

758-
/*
759-
* True, if this target adapter can call scst_cmd_init_done() from
760-
* several threads at the same time.
761-
*/
762-
unsigned multithreaded_init_done:1;
763-
764758
/*
765759
* True, if this target driver supports T10-PI (DIF), i.e. sending and
766760
* receiving DIF PI tags. If false, SCST will not allow to add
@@ -2033,10 +2027,7 @@ struct scst_order_data {
20332027
atomic_t *cur_sn_slot;
20342028
atomic_t sn_slots[15];
20352029

2036-
/*
2037-
* Used to serialized scst_cmd_init_done() if the corresponding
2038-
* session's target template has multithreaded_init_done set
2039-
*/
2030+
/* Used to serialize scst_cmd_init_done(). */
20402031
spinlock_t init_done_lock;
20412032
};
20422033

@@ -3590,8 +3581,6 @@ void scst_cmd_init_done(struct scst_cmd *cmd, enum scst_exec_context pref_contex
35903581
* SCST done the command's preprocessing preprocessing_done() function
35913582
* should be called. The second argument sets preferred command execution
35923583
* context. See SCST_CONTEXT_* constants for details.
3593-
*
3594-
* See comment for scst_cmd_init_done() for the serialization requirements.
35953584
*/
35963585
static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd,
35973586
enum scst_exec_context pref_context, int set_sn)

scst/src/scst_targ.c

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -783,20 +783,6 @@ static int scst_init_cmd(struct scst_cmd *cmd, enum scst_exec_context *context)
783783
* initialization and also that the command is ready for execution. The
784784
* second argument sets the preferred command execution context. See also
785785
* SCST_CONTEXT_* constants for more information.
786-
*
787-
* !!IMPORTANT!!
788-
*
789-
* If cmd->set_sn_on_restart_cmd has not been set, this function, as well
790-
* as scst_cmd_init_stage1_done() and scst_restart_cmd(), must not be
791-
* called simultaneously for the same session (more precisely, for the same
792-
* session/LUN, i.e. tgt_dev), i.e. they must be somehow externally
793-
* serialized. This is needed to have lock free fast path in
794-
* scst_cmd_set_sn(). For majority of targets those functions are naturally
795-
* serialized by the single source of commands. Only some, like iSCSI
796-
* immediate commands with multiple connections per session or scst_local,
797-
* are exceptions. For it, some mutex/lock must be used for the
798-
* serialization. Or, alternatively, multithreaded_init_done can be set in
799-
* the target's template.
800786
*/
801787
void scst_cmd_init_done(struct scst_cmd *cmd, enum scst_exec_context pref_context)
802788
{
@@ -1618,9 +1604,6 @@ static int scst_preprocessing_done(struct scst_cmd *cmd)
16181604
*
16191605
* The second argument sets completion status
16201606
* (see SCST_PREPROCESS_STATUS_* constants for details)
1621-
*
1622-
* See also comment for scst_cmd_init_done() for the serialization
1623-
* requirements.
16241607
*/
16251608
void scst_restart_cmd(struct scst_cmd *cmd, int status, enum scst_exec_context pref_context)
16261609
{
@@ -1652,10 +1635,8 @@ void scst_restart_cmd(struct scst_cmd *cmd, int status, enum scst_exec_context p
16521635
} else {
16531636
scst_set_cmd_state(cmd, SCST_CMD_STATE_TGT_PRE_EXEC);
16541637
}
1655-
if (cmd->set_sn_on_restart_cmd) {
1656-
EXTRACHECKS_BUG_ON(cmd->tgtt->multithreaded_init_done);
1638+
if (cmd->set_sn_on_restart_cmd)
16571639
scst_cmd_set_sn(cmd);
1658-
}
16591640
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
16601641
if (cmd->op_flags & SCST_TEST_IO_IN_SIRQ_ALLOWED)
16611642
break;
@@ -3848,7 +3829,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
38483829

38493830
EXTRACHECKS_BUG_ON(cmd->sn_set || cmd->hq_cmd_inced);
38503831

3851-
/* Optimized for lockless fast path of sequence of SIMPLE commands */
3832+
/* Optimized for fast path of sequence of SIMPLE commands */
38523833

38533834
scst_check_debug_sn(cmd);
38543835

@@ -3870,6 +3851,8 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
38703851
}
38713852
}
38723853

3854+
spin_lock_irqsave(&order_data->init_done_lock, flags);
3855+
38733856
again:
38743857
switch (cmd->queue_type) {
38753858
case SCST_CMD_QUEUE_SIMPLE:
@@ -3927,7 +3910,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
39273910
} else {
39283911
order_data->prev_cmd_ordered = 1;
39293912

3930-
spin_lock_irqsave(&order_data->sn_lock, flags);
3913+
spin_lock(&order_data->sn_lock); /* irqs already off */
39313914

39323915
/*
39333916
* If no commands are going to reach
@@ -3948,7 +3931,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
39483931
scst_inc_expected_sn_idle(order_data);
39493932
}
39503933
}
3951-
spin_unlock_irqrestore(&order_data->sn_lock, flags);
3934+
spin_unlock(&order_data->sn_lock);
39523935
}
39533936

39543937
cmd->sn = order_data->curr_sn;
@@ -3957,9 +3940,9 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
39573940

39583941
case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
39593942
TRACE_SN("HQ cmd %p (op %s)", cmd, scst_get_opcode_name(cmd));
3960-
spin_lock_irqsave(&order_data->sn_lock, flags);
3943+
spin_lock(&order_data->sn_lock); /* irqs already off */
39613944
order_data->hq_cmd_count++;
3962-
spin_unlock_irqrestore(&order_data->sn_lock, flags);
3945+
spin_unlock(&order_data->sn_lock);
39633946
cmd->hq_cmd_inced = 1;
39643947
goto out;
39653948

@@ -3977,6 +3960,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
39773960
order_data->cur_sn_slot - order_data->sn_slots);
39783961

39793962
out:
3963+
spin_unlock_irqrestore(&order_data->init_done_lock, flags);
39803964
TRACE_EXIT();
39813965
}
39823966

@@ -4226,18 +4210,8 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
42264210
if (cmd->completed)
42274211
goto out;
42284212

4229-
if (!cmd->set_sn_on_restart_cmd) {
4230-
if (!cmd->tgtt->multithreaded_init_done) {
4231-
scst_cmd_set_sn(cmd);
4232-
} else {
4233-
struct scst_order_data *order_data = cmd->cur_order_data;
4234-
unsigned long flags;
4235-
4236-
spin_lock_irqsave(&order_data->init_done_lock, flags);
4237-
scst_cmd_set_sn(cmd);
4238-
spin_unlock_irqrestore(&order_data->init_done_lock, flags);
4239-
}
4240-
}
4213+
if (!cmd->set_sn_on_restart_cmd)
4214+
scst_cmd_set_sn(cmd);
42414215
} else if (res < 0) {
42424216
TRACE_DBG("Finishing cmd %p", cmd);
42434217
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_lun_not_supported));

scst_local/scst_local.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,6 @@ static struct scst_tgt_template scst_local_targ_tmpl = {
13521352
.name = "scst_local",
13531353
.sg_tablesize = 0xffff,
13541354
.xmit_response_atomic = 1,
1355-
.multithreaded_init_done = 1,
13561355
.enabled_attr_not_needed = 1,
13571356
.tgtt_attrs = scst_local_tgtt_attrs,
13581357
.tgt_attrs = scst_local_tgt_attrs,

0 commit comments

Comments
 (0)