From: Mike Snitzer <snitzer@xxxxxxxxxx> 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@xxxxxxxxxx> Signed-off-by: Susan LeGendre-McGhee <slegendr@xxxxxxxxxx> Signed-off-by: Matthew Sakai <msakai@xxxxxxxxxx> --- drivers/md/dm-vdo/data-vio.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/md/dm-vdo/data-vio.c b/drivers/md/dm-vdo/data-vio.c index e0f1574ae112..d77adeb5006e 100644 --- a/drivers/md/dm-vdo/data-vio.c +++ b/drivers/md/dm-vdo/data-vio.c @@ -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); -- 2.42.0