Commit 3ee39573 authored by Damien Le Moal's avatar Damien Le Moal Committed by Mike Snitzer

dm zoned: Fix random zone reclaim selection

Commit 2094045f ("dm zoned: prefer full zones for reclaim")
modified dmz_get_rnd_zone_for_reclaim() to add a search for the buffer
zone with the heaviest weight as an optimal candidate for reclaim. This
modification uses the zone pointer variabl "last" which is set only once
and never modified as zones are scanned, resulting in the search being
inefective. Furthermore, if the selected buffer zone at the end of the
search loop is active or already locked for reclaim,
dmz_get_rnd_zone_for_reclaim() returns NULL even if other random zones
with a lesser weight can be reclaimed.

To fix the search and to guarantee that reclaim can make forward
progress, fix dmz_get_rnd_zone_for_reclaim() loop to correctly find
the buffer zone with the heaviest weight using the variable maxw_z.
Also make sure to fallback to finding the first random zone that can
be reclaimed if this best candidate zone cannot be reclaimed.

While at it, also fix the device index check to consider only random
zones, ignoring cache zones belonging to the cache device if one is
used as that device does not have a reclaim process.

Fixes: 2094045f ("dm zoned: prefer full zones for reclaim")
Signed-off-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 415c79e1
......@@ -1950,7 +1950,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd,
unsigned int idx, bool idle)
{
struct dm_zone *dzone = NULL;
struct dm_zone *zone, *last = NULL;
struct dm_zone *zone, *maxw_z = NULL;
struct list_head *zone_list;
/* If we have cache zones select from the cache zone list */
......@@ -1962,18 +1962,37 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd,
} else
zone_list = &zmd->dev[idx].map_rnd_list;
/*
* Find the buffer zone with the heaviest weight or the first (oldest)
* data zone that can be reclaimed.
*/
list_for_each_entry(zone, zone_list, link) {
if (dmz_is_buf(zone)) {
dzone = zone->bzone;
if (dzone->dev->dev_idx != idx)
continue;
if (!last) {
last = dzone;
if (dmz_is_rnd(dzone) && dzone->dev->dev_idx != idx)
continue;
if (!maxw_z || maxw_z->weight < dzone->weight)
maxw_z = dzone;
} else {
dzone = zone;
if (dmz_lock_zone_reclaim(dzone))
return dzone;
}
}
if (last->weight < dzone->weight)
if (maxw_z && dmz_lock_zone_reclaim(maxw_z))
return maxw_z;
/*
* If we come here, none of the zones inspected could be locked for
* reclaim. Try again, being more aggressive, that is, find the
* first zone that can be reclaimed regardless of its weitght.
*/
list_for_each_entry(zone, zone_list, link) {
if (dmz_is_buf(zone)) {
dzone = zone->bzone;
if (dmz_is_rnd(dzone) && dzone->dev->dev_idx != idx)
continue;
dzone = last;
} else
dzone = zone;
if (dmz_lock_zone_reclaim(dzone))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment