Skip to content

Commit

Permalink
dm thin: fix deadlock in __requeue_bio_list
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Joe Thornber authored and Mike Snitzer committed Mar 5, 2014
1 parent 3e1a069 commit 18adc57
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions drivers/md/dm-thin.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,18 @@ struct dm_thin_endio_hook {
struct dm_thin_new_mapping *overwrite_mapping;
};

static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
static void requeue_bio_list(struct thin_c *tc, struct bio_list *master)
{
struct bio *bio;
struct bio_list bios;
unsigned long flags;

bio_list_init(&bios);

spin_lock_irqsave(&tc->pool->lock, flags);
bio_list_merge(&bios, master);
bio_list_init(master);
spin_unlock_irqrestore(&tc->pool->lock, flags);

while ((bio = bio_list_pop(&bios))) {
struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
Expand All @@ -391,12 +395,9 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
static void requeue_io(struct thin_c *tc)
{
struct pool *pool = tc->pool;
unsigned long flags;

spin_lock_irqsave(&pool->lock, flags);
__requeue_bio_list(tc, &pool->deferred_bios);
__requeue_bio_list(tc, &pool->retry_on_resume_list);
spin_unlock_irqrestore(&pool->lock, flags);
requeue_bio_list(tc, &pool->deferred_bios);
requeue_bio_list(tc, &pool->retry_on_resume_list);
}

static void error_retry_list(struct pool *pool)
Expand Down

0 comments on commit 18adc57

Please sign in to comment.