Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm thin: fix deadlock in __requeue_bio_list

The spin lock in requeue_io() was held for too long, allowing deadlock.
Don't worry, due to other issues addressed in the following "dm thin:
fix noflush suspend IO queueing" commit, this code was never called.

Fix this by taking the spin lock for a much shorter period of time.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

authored by

Joe Thornber and committed by
Mike Snitzer
18adc577 3e1a0699

+7 -6
+7 -6
drivers/md/dm-thin.c
··· 369 struct dm_thin_new_mapping *overwrite_mapping; 370 }; 371 372 - static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) 373 { 374 struct bio *bio; 375 struct bio_list bios; 376 377 bio_list_init(&bios); 378 bio_list_merge(&bios, master); 379 bio_list_init(master); 380 381 while ((bio = bio_list_pop(&bios))) { 382 struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); ··· 395 static void requeue_io(struct thin_c *tc) 396 { 397 struct pool *pool = tc->pool; 398 - unsigned long flags; 399 400 - spin_lock_irqsave(&pool->lock, flags); 401 - __requeue_bio_list(tc, &pool->deferred_bios); 402 - __requeue_bio_list(tc, &pool->retry_on_resume_list); 403 - spin_unlock_irqrestore(&pool->lock, flags); 404 } 405 406 static void error_retry_list(struct pool *pool)
··· 369 struct dm_thin_new_mapping *overwrite_mapping; 370 }; 371 372 + static void requeue_bio_list(struct thin_c *tc, struct bio_list *master) 373 { 374 struct bio *bio; 375 struct bio_list bios; 376 + unsigned long flags; 377 378 bio_list_init(&bios); 379 + 380 + spin_lock_irqsave(&tc->pool->lock, flags); 381 bio_list_merge(&bios, master); 382 bio_list_init(master); 383 + spin_unlock_irqrestore(&tc->pool->lock, flags); 384 385 while ((bio = bio_list_pop(&bios))) { 386 struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); ··· 391 static void requeue_io(struct thin_c *tc) 392 { 393 struct pool *pool = tc->pool; 394 395 + requeue_bio_list(tc, &pool->deferred_bios); 396 + requeue_bio_list(tc, &pool->retry_on_resume_list); 397 } 398 399 static void error_retry_list(struct pool *pool)