Commit 18adc57779866ba451237dccca2ebf019be2fa20

Authored by Joe Thornber
Committed by Mike Snitzer
1 parent 3e1a069909

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)