Skip to content

Commit 174364f

Browse files
damien-lemoalsnitm
authored andcommitted
dm zoned: Fix zone reclaim trigger
Only triggering reclaim based on the percentage of unmapped cache zones can fail to detect cases where reclaim is needed, e.g. if the target has only 2 or 3 cache zones and only one unmapped cache zone, the percentage of free cache zones is higher than DMZ_RECLAIM_LOW_UNMAP_ZONES (30%) and reclaim does not trigger. This problem, combined with the fact that dmz_schedule_reclaim() is called from dmz_handle_bio() without the map lock held, leads to a race between zone allocation and dmz_should_reclaim() result. Depending on the workload applied, this race can lead to the write path waiting forever for a free zone without reclaim being triggered. Fix this by moving dmz_schedule_reclaim() inside dmz_alloc_zone() under the map lock. This results in checking the need for zone reclaim whenever a new data or buffer zone needs to be allocated. Also fix dmz_reclaim_percentage() to always return 0 if the number of unmapped cache (or random) zones is less than or equal to 1. Suggested-by: Shin'ichiro Kawasaki <[email protected]> Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent ce34c9b commit 174364f

File tree

3 files changed

+11
-10
lines changed

3 files changed

+11
-10
lines changed

drivers/md/dm-zoned-metadata.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2217,8 +2217,15 @@ struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd, unsigned int dev_idx,
22172217
{
22182218
struct list_head *list;
22192219
struct dm_zone *zone;
2220-
int i = 0;
2220+
int i;
2221+
2222+
/* Schedule reclaim to ensure free zones are available */
2223+
if (!(flags & DMZ_ALLOC_RECLAIM)) {
2224+
for (i = 0; i < zmd->nr_devs; i++)
2225+
dmz_schedule_reclaim(zmd->dev[i].reclaim);
2226+
}
22212227

2228+
i = 0;
22222229
again:
22232230
if (flags & DMZ_ALLOC_CACHE)
22242231
list = &zmd->unmap_cache_list;

drivers/md/dm-zoned-reclaim.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,8 @@ static unsigned int dmz_reclaim_percentage(struct dmz_reclaim *zrc)
456456
nr_zones = dmz_nr_rnd_zones(zmd, zrc->dev_idx);
457457
nr_unmap = dmz_nr_unmap_rnd_zones(zmd, zrc->dev_idx);
458458
}
459+
if (nr_unmap <= 1)
460+
return 0;
459461
return nr_unmap * 100 / nr_zones;
460462
}
461463

drivers/md/dm-zoned-target.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -400,15 +400,7 @@ static void dmz_handle_bio(struct dmz_target *dmz, struct dm_chunk_work *cw,
400400
dm_per_bio_data(bio, sizeof(struct dmz_bioctx));
401401
struct dmz_metadata *zmd = dmz->metadata;
402402
struct dm_zone *zone;
403-
int i, ret;
404-
405-
/*
406-
* Write may trigger a zone allocation. So make sure the
407-
* allocation can succeed.
408-
*/
409-
if (bio_op(bio) == REQ_OP_WRITE)
410-
for (i = 0; i < dmz->nr_ddevs; i++)
411-
dmz_schedule_reclaim(dmz->dev[i].reclaim);
403+
int ret;
412404

413405
dmz_lock_metadata(zmd);
414406

0 commit comments

Comments
 (0)