Skip to content

Commit 151f0ec

Browse files
johnpgarrymartinkpetersen
authored andcommitted
scsi: scsi_debug: Drop sdebug_dev_info.num_in_q
In schedule_resp(), under certain conditions we check whether the per-device queue is full (num_in_q == queue depth - 1) and we may inject a "task set full" (TSF) error if it is. However how we read num_in_q is racy - many threads may see the same "queue is full" value (and also issue a TSF). There is per-queue locking in reading per-device num_in_q, but that would not help. Replace how we read num_in_q at this location with a call to scsi_device_busy(). Calling scsi_device_busy() is likewise racy (as reading num_in_q), so nothing lost or gained. Calling scsi_device_busy() is also slow as it needs to read all bits in the per-device budget bitmap, but we can live with that since we're just a simulator and it's only under a certain configs which we would see this. Also move the "task set full" print earlier as it would only be called now under this condition. However, previously it may not have been called - like returning early - but keep it simple and always call it. At this point we can drop sdebug_dev_info.num_in_q - it is difficult to maintain properly and adds extra normal case command processing. Signed-off-by: John Garry <john.g.garry@oracle.com> Acked-by: Douglas Gilbert <dgilbert@interlog.com> Link: https://lore.kernel.org/r/20230313093114.1498305-10-john.g.garry@oracle.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 0befb87 commit 151f0ec

1 file changed

Lines changed: 16 additions & 47 deletions

File tree

drivers/scsi/scsi_debug.c

Lines changed: 16 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ struct sdebug_dev_info {
288288
uuid_t lu_name;
289289
struct sdebug_host_info *sdbg_host;
290290
unsigned long uas_bm[1];
291-
atomic_t num_in_q;
292291
atomic_t stopped; /* 1: by SSU, 2: device start */
293292
bool used;
294293

@@ -4931,7 +4930,6 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
49314930
struct sdebug_queue *sqp;
49324931
struct sdebug_queued_cmd *sqcp;
49334932
struct scsi_cmnd *scp;
4934-
struct sdebug_dev_info *devip;
49354933

49364934
if (unlikely(aborted))
49374935
sd_dp->aborted = false;
@@ -4956,11 +4954,7 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
49564954
sd_dp->sqa_idx, qc_idx, sd_dp->hc_idx);
49574955
return;
49584956
}
4959-
devip = (struct sdebug_dev_info *)scp->device->hostdata;
4960-
if (likely(devip))
4961-
atomic_dec(&devip->num_in_q);
4962-
else
4963-
pr_err("devip=NULL\n");
4957+
49644958
if (unlikely(atomic_read(&retired_max_queue) > 0))
49654959
retiring = 1;
49664960

@@ -5192,7 +5186,6 @@ static struct sdebug_dev_info *find_build_dev_info(struct scsi_device *sdev)
51925186
open_devip->target = sdev->id;
51935187
open_devip->lun = sdev->lun;
51945188
open_devip->sdbg_host = sdbg_host;
5195-
atomic_set(&open_devip->num_in_q, 0);
51965189
set_bit(SDEBUG_UA_POOCCUR, open_devip->uas_bm);
51975190
open_devip->used = true;
51985191
return open_devip;
@@ -5263,7 +5256,6 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
52635256
enum sdeb_defer_type l_defer_t;
52645257
struct sdebug_queue *sqp;
52655258
struct sdebug_queued_cmd *sqcp;
5266-
struct sdebug_dev_info *devip;
52675259
struct sdebug_defer *sd_dp;
52685260

52695261
for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
@@ -5278,10 +5270,6 @@ static bool stop_queued_cmnd(struct scsi_cmnd *cmnd)
52785270
if (cmnd != sqcp->a_cmnd)
52795271
continue;
52805272
/* found */
5281-
devip = (struct sdebug_dev_info *)
5282-
cmnd->device->hostdata;
5283-
if (devip)
5284-
atomic_dec(&devip->num_in_q);
52855273
sqcp->a_cmnd = NULL;
52865274
sd_dp = sqcp->sd_dp;
52875275
if (sd_dp) {
@@ -5308,7 +5296,6 @@ static void stop_all_queued(void)
53085296
enum sdeb_defer_type l_defer_t;
53095297
struct sdebug_queue *sqp;
53105298
struct sdebug_queued_cmd *sqcp;
5311-
struct sdebug_dev_info *devip;
53125299
struct sdebug_defer *sd_dp;
53135300

53145301
for (j = 0, sqp = sdebug_q_arr; j < submit_queues; ++j, ++sqp) {
@@ -5318,10 +5305,6 @@ static void stop_all_queued(void)
53185305
sqcp = &sqp->qc_arr[k];
53195306
if (sqcp->a_cmnd == NULL)
53205307
continue;
5321-
devip = (struct sdebug_dev_info *)
5322-
sqcp->a_cmnd->device->hostdata;
5323-
if (devip)
5324-
atomic_dec(&devip->num_in_q);
53255308
sqcp->a_cmnd = NULL;
53265309
sd_dp = sqcp->sd_dp;
53275310
if (sd_dp) {
@@ -5565,9 +5548,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
55655548
int delta_jiff, int ndelay)
55665549
{
55675550
bool new_sd_dp;
5568-
bool inject = false;
55695551
bool polled = scsi_cmd_to_rq(cmnd)->cmd_flags & REQ_POLLED;
5570-
int k, num_in_q, qdepth;
5552+
int k;
55715553
unsigned long iflags;
55725554
u64 ns_from_boot = 0;
55735555
struct sdebug_queue *sqp;
@@ -5591,16 +5573,21 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
55915573
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
55925574
return SCSI_MLQUEUE_HOST_BUSY;
55935575
}
5594-
num_in_q = atomic_read(&devip->num_in_q);
5595-
qdepth = cmnd->device->queue_depth;
5576+
55965577
if (unlikely(sdebug_every_nth && (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
55975578
(scsi_result == 0))) {
5579+
int num_in_q = scsi_device_busy(sdp);
5580+
int qdepth = cmnd->device->queue_depth;
5581+
55985582
if ((num_in_q == (qdepth - 1)) &&
55995583
(atomic_inc_return(&sdebug_a_tsf) >=
56005584
abs(sdebug_every_nth))) {
56015585
atomic_set(&sdebug_a_tsf, 0);
5602-
inject = true;
56035586
scsi_result = device_qfull_result;
5587+
5588+
if (unlikely(SDEBUG_OPT_Q_NOISE & sdebug_opts))
5589+
sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, <inject> status: TASK SET FULL\n",
5590+
__func__, num_in_q);
56045591
}
56055592
}
56065593

@@ -5616,7 +5603,6 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
56165603
goto respond_in_thread;
56175604
}
56185605
set_bit(k, sqp->in_use_bm);
5619-
atomic_inc(&devip->num_in_q);
56205606
sqcp = &sqp->qc_arr[k];
56215607
sqcp->a_cmnd = cmnd;
56225608
cmnd->host_scribble = (unsigned char *)sqcp;
@@ -5626,7 +5612,6 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
56265612
if (!sd_dp) {
56275613
sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC);
56285614
if (!sd_dp) {
5629-
atomic_dec(&devip->num_in_q);
56305615
clear_bit(k, sqp->in_use_bm);
56315616
return SCSI_MLQUEUE_HOST_BUSY;
56325617
}
@@ -5686,7 +5671,6 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
56865671
if (kt <= d) { /* elapsed duration >= kt */
56875672
spin_lock_irqsave(&sqp->qc_lock, iflags);
56885673
sqcp->a_cmnd = NULL;
5689-
atomic_dec(&devip->num_in_q);
56905674
clear_bit(k, sqp->in_use_bm);
56915675
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
56925676
if (new_sd_dp)
@@ -5762,9 +5746,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
57625746
sd_dp->aborted = false;
57635747
}
57645748
}
5765-
if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && scsi_result == device_qfull_result))
5766-
sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, %s%s\n", __func__,
5767-
num_in_q, (inject ? "<inject> " : ""), "status: TASK SET FULL");
5749+
57685750
return 0;
57695751

57705752
respond_in_thread: /* call back to mid-layer using invocation thread */
@@ -7369,17 +7351,12 @@ static void sdebug_do_remove_host(bool the_end)
73697351

73707352
static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
73717353
{
7372-
int num_in_q = 0;
7373-
struct sdebug_dev_info *devip;
7354+
struct sdebug_dev_info *devip = sdev->hostdata;
73747355

7375-
block_unblock_all_queues(true);
7376-
devip = (struct sdebug_dev_info *)sdev->hostdata;
7377-
if (NULL == devip) {
7378-
block_unblock_all_queues(false);
7356+
if (!devip)
73797357
return -ENODEV;
7380-
}
7381-
num_in_q = atomic_read(&devip->num_in_q);
73827358

7359+
block_unblock_all_queues(true);
73837360
if (qdepth > SDEBUG_CANQUEUE) {
73847361
qdepth = SDEBUG_CANQUEUE;
73857362
pr_warn("%s: requested qdepth [%d] exceeds canqueue [%d], trim\n", __func__,
@@ -7390,10 +7367,8 @@ static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
73907367
if (qdepth != sdev->queue_depth)
73917368
scsi_change_queue_depth(sdev, qdepth);
73927369

7393-
if (SDEBUG_OPT_Q_NOISE & sdebug_opts) {
7394-
sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d, num_in_q=%d\n",
7395-
__func__, qdepth, num_in_q);
7396-
}
7370+
if (SDEBUG_OPT_Q_NOISE & sdebug_opts)
7371+
sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d\n", __func__, qdepth);
73977372
block_unblock_all_queues(false);
73987373
return sdev->queue_depth;
73997374
}
@@ -7495,7 +7470,6 @@ static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
74957470
struct sdebug_queue *sqp;
74967471
struct sdebug_queued_cmd *sqcp;
74977472
struct scsi_cmnd *scp;
7498-
struct sdebug_dev_info *devip;
74997473
struct sdebug_defer *sd_dp;
75007474

75017475
sqp = sdebug_q_arr + queue_num;
@@ -7533,11 +7507,6 @@ static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
75337507

75347508
} else /* ignoring non REQ_POLLED requests */
75357509
continue;
7536-
devip = (struct sdebug_dev_info *)scp->device->hostdata;
7537-
if (likely(devip))
7538-
atomic_dec(&devip->num_in_q);
7539-
else
7540-
pr_err("devip=NULL from %s\n", __func__);
75417510
if (unlikely(atomic_read(&retired_max_queue) > 0))
75427511
retiring = true;
75437512

0 commit comments

Comments
 (0)