dm vdo data-vio: silence sparse warnings about locking context imbalances
authorMike Snitzer <snitzer@kernel.org>
Tue, 6 Feb 2024 02:04:19 +0000 (21:04 -0500)
committerMike Snitzer <snitzer@kernel.org>
Tue, 20 Feb 2024 18:43:18 +0000 (13:43 -0500)
Factor wait_permit() out from acquire_permit() so that the latter
always holds the spinlock and the former always releases it.

Otherwise sparse complains about locking context imbalances due to
conditional spin_unlock in acquire_permit:
 warning: context imbalance in 'acquire_permit' - different lock contexts for basic block
 warning: context imbalance in 'vdo_launch_bio' - unexpected unlock

Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Susan LeGendre-McGhee <slegendr@redhat.com>
Signed-off-by: Matthew Sakai <msakai@redhat.com>
drivers/md/dm-vdo/data-vio.c

index e0f1574ae1129e398addcc9f7abfc98238bc04ca..d77adeb5006efe9fa4d954db004dc9357eab0a40 100644 (file)
@@ -929,27 +929,30 @@ void free_data_vio_pool(struct data_vio_pool *pool)
        uds_free(pool);
 }
 
-static bool acquire_permit(struct limiter *limiter, struct bio *bio)
+static bool acquire_permit(struct limiter *limiter)
 {
-       if (limiter->busy >= limiter->limit) {
-               DEFINE_WAIT(wait);
-
-               bio_list_add(&limiter->new_waiters, bio);
-               prepare_to_wait_exclusive(&limiter->blocked_threads, &wait,
-                                         TASK_UNINTERRUPTIBLE);
-               spin_unlock(&limiter->pool->lock);
-               io_schedule();
-               finish_wait(&limiter->blocked_threads, &wait);
+       if (limiter->busy >= limiter->limit)
                return false;
-       }
 
        WRITE_ONCE(limiter->busy, limiter->busy + 1);
        if (limiter->max_busy < limiter->busy)
                WRITE_ONCE(limiter->max_busy, limiter->busy);
-
        return true;
 }
 
+static void wait_permit(struct limiter *limiter, struct bio *bio)
+       __releases(&limiter->pool->lock)
+{
+       DEFINE_WAIT(wait);
+
+       bio_list_add(&limiter->new_waiters, bio);
+       prepare_to_wait_exclusive(&limiter->blocked_threads, &wait,
+                                 TASK_UNINTERRUPTIBLE);
+       spin_unlock(&limiter->pool->lock);
+       io_schedule();
+       finish_wait(&limiter->blocked_threads, &wait);
+}
+
 /**
  * vdo_launch_bio() - Acquire a data_vio from the pool, assign the bio to it, and launch it.
  *
@@ -965,11 +968,15 @@ void vdo_launch_bio(struct data_vio_pool *pool, struct bio *bio)
        bio->bi_private = (void *) jiffies;
        spin_lock(&pool->lock);
        if ((bio_op(bio) == REQ_OP_DISCARD) &&
-           !acquire_permit(&pool->discard_limiter, bio))
+           !acquire_permit(&pool->discard_limiter)) {
+               wait_permit(&pool->discard_limiter, bio);
                return;
+       }
 
-       if (!acquire_permit(&pool->limiter, bio))
+       if (!acquire_permit(&pool->limiter)) {
+               wait_permit(&pool->limiter, bio);
                return;
+       }
 
        data_vio = get_available_data_vio(pool);
        spin_unlock(&pool->lock);