diff --git a/nightly/conf/nightly.conf b/nightly/conf/nightly.conf index eac93b0c7..d0bdffa5b 100644 --- a/nightly/conf/nightly.conf +++ b/nightly/conf/nightly.conf @@ -3,26 +3,26 @@ ABT_DETAILS="x86_64" ABT_JOBS=5 ABT_KERNELS=" \ -5.2.5 \ +5.2.6 \ 5.1.21-nc \ 5.0.21-nc \ 4.20.17-nc \ -4.19.63-nc \ +4.19.64-nc \ 4.18.20-nc \ 4.17.19-nc \ 4.16.18-nc \ 4.15.18-nc \ -4.14.135-nc \ +4.14.136-nc \ 4.13.16-nc \ 4.12.14-nc \ 4.11.12-nc \ 4.10.17-nc \ -4.9.186-nc \ +4.9.187-nc \ 4.8.17-nc \ 4.7.10-nc \ 4.6.7-nc \ 4.5.7-nc \ -4.4.186-nc \ +4.4.187-nc \ 4.3.6-nc \ 4.2.8-nc \ 4.1.52-nc \ diff --git a/scst/include/scst.h b/scst/include/scst.h index 24a40fcaa..35af18bd8 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2317,6 +2317,9 @@ struct scst_cmd { /* Set by WRITE VERIFY commands to trigger a verify after write */ unsigned int do_verify:1; + /* For debugging purposes. */ + unsigned int owns_refcnt:1; + /**************************************************************/ /* cmd's async flags */ diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 32179653e..b5b7289ef 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4578,7 +4578,7 @@ static void scst_tgt_dev_free_workfn(struct work_struct *work) scst_put(a); } -void scst_free_tgt_dev_rcu(struct rcu_head *rcu) +static void scst_free_tgt_dev_rcu(struct rcu_head *rcu) { struct scst_tgt_dev *tgt_dev = container_of(rcu, typeof(*tgt_dev), rcu); @@ -5541,6 +5541,12 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA) return; } +void scst_tgt_dev_dec_cmd_count(struct scst_tgt_dev *tgt_dev) +{ + if (atomic_dec_return(&tgt_dev->tgt_dev_cmd_count) == 0) + call_rcu(&tgt_dev->rcu, scst_free_tgt_dev_rcu); +} + static void scst_del_tgt_dev(struct scst_tgt_dev *tgt_dev) { struct scst_tgt_template *tgtt = tgt_dev->tgtt; @@ -5563,8 +5569,7 @@ static void scst_del_tgt_dev(struct scst_tgt_dev *tgt_dev) if (tgtt->get_initiator_port_transport_id == NULL) dev->not_pr_supporting_tgt_devs_num--; - if (atomic_dec_return(&tgt_dev->tgt_dev_cmd_count) == 0) - call_rcu(&tgt_dev->rcu, scst_free_tgt_dev_rcu); + scst_tgt_dev_dec_cmd_count(tgt_dev); } /* diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index 84788dd89..9864e6971 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -382,7 +382,7 @@ void scst_check_reassign_sessions(void); int scst_sess_alloc_tgt_devs(struct scst_session *sess); void scst_sess_free_tgt_devs(struct scst_session *sess); struct scst_tgt_dev *scst_lookup_tgt_dev(struct scst_session *sess, u64 lun); -void scst_free_tgt_dev_rcu(struct rcu_head *rcu); +void scst_tgt_dev_dec_cmd_count(struct scst_tgt_dev *tgt_dev); void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA); #define SCST_ADD_LUN_READ_ONLY 1 diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index a0918ae71..bee0ae2de 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -4504,8 +4504,8 @@ static int scst_pre_xmit_response1(struct scst_cmd *cmd) * latency, so we should decrement them after cmd completed. */ smp_mb__before_atomic_dec(); - if (atomic_dec_return(&cmd->tgt_dev->tgt_dev_cmd_count) == 0) - call_rcu(&cmd->tgt_dev->rcu, scst_free_tgt_dev_rcu); + cmd->owns_refcnt = false; + scst_tgt_dev_dec_cmd_count(cmd->tgt_dev); percpu_ref_put(&cmd->dev->refcnt); #ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT atomic_dec(&cmd->dev->dev_cmd_count); @@ -4694,6 +4694,8 @@ static int scst_finish_cmd(struct scst_cmd *cmd) TRACE_ENTRY(); + WARN_ON_ONCE(cmd->owns_refcnt); + if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) { if ((cmd->tgt_dev != NULL) && (cmd->status == SAM_STAT_CHECK_CONDITION) && @@ -4997,6 +4999,9 @@ static int scst_translate_lun(struct scst_cmd *cmd) rcu_read_lock(); tgt_dev = scst_lookup_tgt_dev(cmd->sess, cmd->lun); + if (tgt_dev && + !atomic_inc_not_zero(&tgt_dev->tgt_dev_cmd_count)) + tgt_dev = NULL; rcu_read_unlock(); if (tgt_dev) { @@ -5015,6 +5020,7 @@ static int scst_translate_lun(struct scst_cmd *cmd) "the device will not be visible remotely", (unsigned long long)cmd->lun); nul_dev = true; + scst_tgt_dev_dec_cmd_count(tgt_dev); } } if (unlikely(res != 0)) { @@ -5143,7 +5149,7 @@ static int __scst_init_cmd(struct scst_cmd *cmd) scst_set_cmd_state(cmd, SCST_CMD_STATE_PARSE); - cnt = atomic_inc_return(&tgt_dev->tgt_dev_cmd_count) - 1; + cnt = atomic_read(&tgt_dev->tgt_dev_cmd_count) - 1; if (unlikely(cnt > dev->max_tgt_dev_commands)) { TRACE(TRACE_FLOW_CONTROL, "Too many pending commands (%d) in " @@ -5153,6 +5159,7 @@ static int __scst_init_cmd(struct scst_cmd *cmd) failure = true; } + cmd->owns_refcnt = true; percpu_ref_get(&dev->refcnt); #ifdef CONFIG_SCST_PER_DEVICE_CMD_COUNT_LIMIT atomic_inc(&dev->dev_cmd_count);