aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2014-01-31 14:30:37 -0500
committerMike Snitzer <snitzer@redhat.com>2014-02-17 11:00:05 -0500
commit80ae49aaed32af72630251eb06161b15cde15ac8 (patch)
tree02d587182910cb2b259803535ff772a7545f519a
parentc6eda5e81c4fcc77185117255c7419eda771f67f (diff)
dm cache: do not add migration to completed list before unhooking bio
When completing an overwrite bio, in overwrite_endio(), the associated migration should not be added to the 'completed_migrations' until the bio's fields are restored with dm_unhook_bio(). Otherwise, do_worker() can race to process 'completed_migrations' before dm_unhook_bio() -- so the bio's bi_end_io is incorrect. This is unlikely to cause any problems given the current code but should be fixed on the basis of correctness. Also, the cache's spinlock only needs to be held when manipulating the 'completed_migrations' list -- other changes don't need protection. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Acked-by: Joe Thornber <ejt@redhat.com>
-rw-r--r--drivers/md/dm-cache-target.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 14256b7fce79..db0944465127 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -1010,13 +1010,15 @@ static void overwrite_endio(struct bio *bio, int err)
1010 struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size); 1010 struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
1011 unsigned long flags; 1011 unsigned long flags;
1012 1012
1013 dm_unhook_bio(&pb->hook_info, bio);
1014
1013 if (err) 1015 if (err)
1014 mg->err = true; 1016 mg->err = true;
1015 1017
1018 mg->requeue_holder = false;
1019
1016 spin_lock_irqsave(&cache->lock, flags); 1020 spin_lock_irqsave(&cache->lock, flags);
1017 list_add_tail(&mg->list, &cache->completed_migrations); 1021 list_add_tail(&mg->list, &cache->completed_migrations);
1018 dm_unhook_bio(&pb->hook_info, bio);
1019 mg->requeue_holder = false;
1020 spin_unlock_irqrestore(&cache->lock, flags); 1022 spin_unlock_irqrestore(&cache->lock, flags);
1021 1023
1022 wake_worker(cache); 1024 wake_worker(cache);