Skip to content

Commit 13bd677

Browse files
Mikulas Patockasnitm
authored andcommitted
dm cache: fix bugs when a GFP_NOWAIT allocation fails
GFP_NOWAIT allocation can fail anytime - it doesn't wait for memory being available and it fails if the mempool is exhausted and there is not enough memory. If we go down this path: map_bio -> mg_start -> alloc_migration -> mempool_alloc(GFP_NOWAIT) we can see that map_bio() doesn't check the return value of mg_start(), and the bio is leaked. If we go down this path: map_bio -> mg_start -> mg_lock_writes -> alloc_prison_cell -> dm_bio_prison_alloc_cell_v2 -> mempool_alloc(GFP_NOWAIT) -> mg_lock_writes -> mg_complete the bio is ended with an error - it is unacceptable because it could cause filesystem corruption if the machine ran out of memory temporarily. Change GFP_NOWAIT to GFP_NOIO, so that the mempool code will properly wait until memory becomes available. mempool_alloc with GFP_NOIO can't fail, so remove the code paths that deal with allocation failure. Cc: [email protected] Signed-off-by: Mikulas Patocka <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent b215557 commit 13bd677

File tree

1 file changed

+2
-26
lines changed

1 file changed

+2
-26
lines changed

drivers/md/dm-cache-target.c

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ static void wake_migration_worker(struct cache *cache)
542542

543543
static struct dm_bio_prison_cell_v2 *alloc_prison_cell(struct cache *cache)
544544
{
545-
return dm_bio_prison_alloc_cell_v2(cache->prison, GFP_NOWAIT);
545+
return dm_bio_prison_alloc_cell_v2(cache->prison, GFP_NOIO);
546546
}
547547

548548
static void free_prison_cell(struct cache *cache, struct dm_bio_prison_cell_v2 *cell)
@@ -554,9 +554,7 @@ static struct dm_cache_migration *alloc_migration(struct cache *cache)
554554
{
555555
struct dm_cache_migration *mg;
556556

557-
mg = mempool_alloc(&cache->migration_pool, GFP_NOWAIT);
558-
if (!mg)
559-
return NULL;
557+
mg = mempool_alloc(&cache->migration_pool, GFP_NOIO);
560558

561559
memset(mg, 0, sizeof(*mg));
562560

@@ -664,10 +662,6 @@ static bool bio_detain_shared(struct cache *cache, dm_oblock_t oblock, struct bi
664662
struct dm_bio_prison_cell_v2 *cell_prealloc, *cell;
665663

666664
cell_prealloc = alloc_prison_cell(cache); /* FIXME: allow wait if calling from worker */
667-
if (!cell_prealloc) {
668-
defer_bio(cache, bio);
669-
return false;
670-
}
671665

672666
build_key(oblock, end, &key);
673667
r = dm_cell_get_v2(cache->prison, &key, lock_level(bio), bio, cell_prealloc, &cell);
@@ -1493,11 +1487,6 @@ static int mg_lock_writes(struct dm_cache_migration *mg)
14931487
struct dm_bio_prison_cell_v2 *prealloc;
14941488

14951489
prealloc = alloc_prison_cell(cache);
1496-
if (!prealloc) {
1497-
DMERR_LIMIT("%s: alloc_prison_cell failed", cache_device_name(cache));
1498-
mg_complete(mg, false);
1499-
return -ENOMEM;
1500-
}
15011490

15021491
/*
15031492
* Prevent writes to the block, but allow reads to continue.
@@ -1535,11 +1524,6 @@ static int mg_start(struct cache *cache, struct policy_work *op, struct bio *bio
15351524
}
15361525

15371526
mg = alloc_migration(cache);
1538-
if (!mg) {
1539-
policy_complete_background_work(cache->policy, op, false);
1540-
background_work_end(cache);
1541-
return -ENOMEM;
1542-
}
15431527

15441528
mg->op = op;
15451529
mg->overwrite_bio = bio;
@@ -1628,10 +1612,6 @@ static int invalidate_lock(struct dm_cache_migration *mg)
16281612
struct dm_bio_prison_cell_v2 *prealloc;
16291613

16301614
prealloc = alloc_prison_cell(cache);
1631-
if (!prealloc) {
1632-
invalidate_complete(mg, false);
1633-
return -ENOMEM;
1634-
}
16351615

16361616
build_key(mg->invalidate_oblock, oblock_succ(mg->invalidate_oblock), &key);
16371617
r = dm_cell_lock_v2(cache->prison, &key,
@@ -1669,10 +1649,6 @@ static int invalidate_start(struct cache *cache, dm_cblock_t cblock,
16691649
return -EPERM;
16701650

16711651
mg = alloc_migration(cache);
1672-
if (!mg) {
1673-
background_work_end(cache);
1674-
return -ENOMEM;
1675-
}
16761652

16771653
mg->overwrite_bio = bio;
16781654
mg->invalidate_cblock = cblock;

0 commit comments

Comments
 (0)