diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2022-01-09 02:28:48 +0100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2022-01-25 06:25:05 +0100 |
commit | b05d4e481eff1b4cdd38d9bb7914d3273b11885b (patch) | |
tree | 407deced6a29b3df99edfda0f4a744b7f147aa22 /drivers/scsi/scsi_debug.c | |
parent | scsi: scsi_debug: Use TASK SET FULL more (diff) | |
download | linux-b05d4e481eff1b4cdd38d9bb7914d3273b11885b.tar.xz linux-b05d4e481eff1b4cdd38d9bb7914d3273b11885b.zip |
scsi: scsi_debug: Refine sdebug_blk_mq_poll()
Refine the sdebug_blk_mq_poll() function so it only takes the spinlock on
the queue when it can see one or more requests with the in_use bitmap flag
set.
Link: https://lore.kernel.org/r/20220109012853.301953-5-dgilbert@interlog.com
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to '')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 8abe95a0d869..c6798d991fbe 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -7396,6 +7396,7 @@ static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num) { bool first; bool retiring = false; + bool locked = false; int num_entries = 0; unsigned int qc_idx = 0; unsigned long iflags; @@ -7407,16 +7408,23 @@ static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num) struct sdebug_defer *sd_dp; sqp = sdebug_q_arr + queue_num; - spin_lock_irqsave(&sqp->qc_lock, iflags); + qc_idx = find_first_bit(sqp->in_use_bm, sdebug_max_queue); + if (qc_idx >= sdebug_max_queue) + return 0; for (first = true; first || qc_idx + 1 < sdebug_max_queue; ) { + if (!locked) { + spin_lock_irqsave(&sqp->qc_lock, iflags); + locked = true; + } if (first) { - qc_idx = find_first_bit(sqp->in_use_bm, sdebug_max_queue); first = false; + if (!test_bit(qc_idx, sqp->in_use_bm)) + continue; } else { qc_idx = find_next_bit(sqp->in_use_bm, sdebug_max_queue, qc_idx + 1); } - if (unlikely(qc_idx >= sdebug_max_queue)) + if (qc_idx >= sdebug_max_queue) break; sqcp = &sqp->qc_arr[qc_idx]; @@ -7465,11 +7473,14 @@ static int sdebug_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num) } WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_NONE); spin_unlock_irqrestore(&sqp->qc_lock, iflags); + locked = false; scsi_done(scp); /* callback to mid level */ - spin_lock_irqsave(&sqp->qc_lock, iflags); num_entries++; + if (find_first_bit(sqp->in_use_bm, sdebug_max_queue) >= sdebug_max_queue) + break; /* if no more then exit without retaking spinlock */ } - spin_unlock_irqrestore(&sqp->qc_lock, iflags); + if (locked) + spin_unlock_irqrestore(&sqp->qc_lock, iflags); if (num_entries > 0) atomic_add(num_entries, &sdeb_mq_poll_count); return num_entries; |