diff options
author | Joe Thornber <ejt@redhat.com> | 2015-09-01 06:38:19 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2015-09-01 08:56:14 -0400 |
commit | cc7da0ba9c96699592d0a69d7d146ac6adcc18e7 (patch) | |
tree | 84a021e91e6bb4a9e395315fcf4a80bfc3f3fd51 /drivers/md/dm-cache-target.c | |
parent | dc9cee5db50afaf38506bc12eb479fb8ea536dba (diff) |
dm cache: fix use after freeing migrations
Both free_io_migration() and issue_discard() dereference a migration
that was just freed. Fix those by saving off the migrations's cache
object before freeing the migration. Also cleanup needless mg->cache
dereferences now that the cache object is available directly.
Fixes: e44b6a5a3c ("dm cache: move wake_waker() from free_migrations() to where it is needed")
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-cache-target.c')
-rw-r--r-- | drivers/md/dm-cache-target.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index e13e5edf2298..f9d9cc6a094b 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c | |||
@@ -1113,9 +1113,11 @@ static void cell_requeue(struct cache *cache, struct dm_bio_prison_cell *cell) | |||
1113 | 1113 | ||
1114 | static void free_io_migration(struct dm_cache_migration *mg) | 1114 | static void free_io_migration(struct dm_cache_migration *mg) |
1115 | { | 1115 | { |
1116 | dec_io_migrations(mg->cache); | 1116 | struct cache *cache = mg->cache; |
1117 | |||
1118 | dec_io_migrations(cache); | ||
1117 | free_migration(mg); | 1119 | free_migration(mg); |
1118 | wake_worker(mg->cache); | 1120 | wake_worker(cache); |
1119 | } | 1121 | } |
1120 | 1122 | ||
1121 | static void migration_failure(struct dm_cache_migration *mg) | 1123 | static void migration_failure(struct dm_cache_migration *mg) |
@@ -1342,17 +1344,18 @@ static void issue_discard(struct dm_cache_migration *mg) | |||
1342 | { | 1344 | { |
1343 | dm_dblock_t b, e; | 1345 | dm_dblock_t b, e; |
1344 | struct bio *bio = mg->new_ocell->holder; | 1346 | struct bio *bio = mg->new_ocell->holder; |
1347 | struct cache *cache = mg->cache; | ||
1345 | 1348 | ||
1346 | calc_discard_block_range(mg->cache, bio, &b, &e); | 1349 | calc_discard_block_range(cache, bio, &b, &e); |
1347 | while (b != e) { | 1350 | while (b != e) { |
1348 | set_discard(mg->cache, b); | 1351 | set_discard(cache, b); |
1349 | b = to_dblock(from_dblock(b) + 1); | 1352 | b = to_dblock(from_dblock(b) + 1); |
1350 | } | 1353 | } |
1351 | 1354 | ||
1352 | bio_endio(bio, 0); | 1355 | bio_endio(bio, 0); |
1353 | cell_defer(mg->cache, mg->new_ocell, false); | 1356 | cell_defer(cache, mg->new_ocell, false); |
1354 | free_migration(mg); | 1357 | free_migration(mg); |
1355 | wake_worker(mg->cache); | 1358 | wake_worker(cache); |
1356 | } | 1359 | } |
1357 | 1360 | ||
1358 | static void issue_copy_or_discard(struct dm_cache_migration *mg) | 1361 | static void issue_copy_or_discard(struct dm_cache_migration *mg) |