Commit 18adc57779866ba451237dccca2ebf019be2fa20
Committed by
Mike Snitzer
1 parent
3e1a069909
Exists in
master
and in
16 other branches
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>
Showing 1 changed file with 7 additions and 6 deletions Side-by-side Diff
drivers/md/dm-thin.c
... | ... | @@ -369,14 +369,18 @@ |
369 | 369 | struct dm_thin_new_mapping *overwrite_mapping; |
370 | 370 | }; |
371 | 371 | |
372 | -static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) | |
372 | +static void requeue_bio_list(struct thin_c *tc, struct bio_list *master) | |
373 | 373 | { |
374 | 374 | struct bio *bio; |
375 | 375 | struct bio_list bios; |
376 | + unsigned long flags; | |
376 | 377 | |
377 | 378 | bio_list_init(&bios); |
379 | + | |
380 | + spin_lock_irqsave(&tc->pool->lock, flags); | |
378 | 381 | bio_list_merge(&bios, master); |
379 | 382 | bio_list_init(master); |
383 | + spin_unlock_irqrestore(&tc->pool->lock, flags); | |
380 | 384 | |
381 | 385 | while ((bio = bio_list_pop(&bios))) { |
382 | 386 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
383 | 387 | |
... | ... | @@ -391,12 +395,9 @@ |
391 | 395 | static void requeue_io(struct thin_c *tc) |
392 | 396 | { |
393 | 397 | struct pool *pool = tc->pool; |
394 | - unsigned long flags; | |
395 | 398 | |
396 | - spin_lock_irqsave(&pool->lock, flags); | |
397 | - __requeue_bio_list(tc, &pool->deferred_bios); | |
398 | - __requeue_bio_list(tc, &pool->retry_on_resume_list); | |
399 | - spin_unlock_irqrestore(&pool->lock, flags); | |
399 | + requeue_bio_list(tc, &pool->deferred_bios); | |
400 | + requeue_bio_list(tc, &pool->retry_on_resume_list); | |
400 | 401 | } |
401 | 402 | |
402 | 403 | static void error_retry_list(struct pool *pool) |