]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: scsi_debug: Refine sdebug_blk_mq_poll()
authorDouglas Gilbert <dgilbert@interlog.com>
Sun, 9 Jan 2022 01:28:48 +0000 (20:28 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 25 Jan 2022 05:25:05 +0000 (00:25 -0500)
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>
drivers/scsi/scsi_debug.c

index 8abe95a0d869ac3fba67b55998f43c1e2ea5288a..c6798d991fbe8bc7351106110d22f57495dcdbdf 100644 (file)
@@ -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;