Skip to content

Commit

Permalink
dm zoned: improve error handling in reclaim
Browse files Browse the repository at this point in the history
There are several places in reclaim code where errors are not
propagated to the main function, dmz_reclaim(). This function
is responsible for unlocking zones that might be still locked
at the end of any failed reclaim iterations. As the result,
some device zones may be left permanently locked for reclaim,
degrading target's capability to reclaim zones.

This patch fixes these issues as follows -

Make sure that dmz_reclaim_buf(), dmz_reclaim_seq_data() and
dmz_reclaim_rnd_data() return error codes to the caller.

dmz_reclaim() function is renamed to dmz_do_reclaim() to avoid
clashing with "struct dmz_reclaim" and is modified to return the
error to the caller.

dmz_get_zone_for_reclaim() now returns an error instead of NULL
pointer and reclaim code checks for that error.

Error logging/debug messages are added where necessary.

Fixes: 3b1a94c ("dm zoned: drive-managed zoned block device target")
Cc: [email protected]
Signed-off-by: Dmitry Fomichev <[email protected]>
Reviewed-by: Damien Le Moal <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
  • Loading branch information
dmitry-fomichev authored and snitm committed Aug 15, 2019
1 parent d1fef41 commit b234c6d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 11 deletions.
4 changes: 2 additions & 2 deletions drivers/md/dm-zoned-metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
struct dm_zone *zone;

if (list_empty(&zmd->map_rnd_list))
return NULL;
return ERR_PTR(-EBUSY);

list_for_each_entry(zone, &zmd->map_rnd_list, link) {
if (dmz_is_buf(zone))
Expand All @@ -1553,7 +1553,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
return dzone;
}

return NULL;
return ERR_PTR(-EBUSY);
}

/*
Expand Down
28 changes: 19 additions & 9 deletions drivers/md/dm-zoned-reclaim.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ static int dmz_reclaim_buf(struct dmz_reclaim *zrc, struct dm_zone *dzone)

dmz_unlock_flush(zmd);

return 0;
return ret;
}

/*
Expand Down Expand Up @@ -259,7 +259,7 @@ static int dmz_reclaim_seq_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)

dmz_unlock_flush(zmd);

return 0;
return ret;
}

/*
Expand Down Expand Up @@ -312,7 +312,7 @@ static int dmz_reclaim_rnd_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)

dmz_unlock_flush(zmd);

return 0;
return ret;
}

/*
Expand All @@ -334,7 +334,7 @@ static void dmz_reclaim_empty(struct dmz_reclaim *zrc, struct dm_zone *dzone)
/*
* Find a candidate zone for reclaim and process it.
*/
static void dmz_reclaim(struct dmz_reclaim *zrc)
static int dmz_do_reclaim(struct dmz_reclaim *zrc)
{
struct dmz_metadata *zmd = zrc->metadata;
struct dm_zone *dzone;
Expand All @@ -344,8 +344,8 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)

/* Get a data zone */
dzone = dmz_get_zone_for_reclaim(zmd);
if (!dzone)
return;
if (IS_ERR(dzone))
return PTR_ERR(dzone);

start = jiffies;

Expand Down Expand Up @@ -391,13 +391,20 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)
out:
if (ret) {
dmz_unlock_zone_reclaim(dzone);
return;
return ret;
}

(void) dmz_flush_metadata(zrc->metadata);
ret = dmz_flush_metadata(zrc->metadata);
if (ret) {
dmz_dev_debug(zrc->dev,
"Metadata flush for zone %u failed, err %d\n",
dmz_id(zmd, rzone), ret);
return ret;
}

dmz_dev_debug(zrc->dev, "Reclaimed zone %u in %u ms",
dmz_id(zmd, rzone), jiffies_to_msecs(jiffies - start));
return 0;
}

/*
Expand Down Expand Up @@ -442,6 +449,7 @@ static void dmz_reclaim_work(struct work_struct *work)
struct dmz_metadata *zmd = zrc->metadata;
unsigned int nr_rnd, nr_unmap_rnd;
unsigned int p_unmap_rnd;
int ret;

if (!dmz_should_reclaim(zrc)) {
mod_delayed_work(zrc->wq, &zrc->work, DMZ_IDLE_PERIOD);
Expand Down Expand Up @@ -471,7 +479,9 @@ static void dmz_reclaim_work(struct work_struct *work)
(dmz_target_idle(zrc) ? "Idle" : "Busy"),
p_unmap_rnd, nr_unmap_rnd, nr_rnd);

dmz_reclaim(zrc);
ret = dmz_do_reclaim(zrc);
if (ret)
dmz_dev_debug(zrc->dev, "Reclaim error %d\n", ret);

dmz_schedule_reclaim(zrc);
}
Expand Down

0 comments on commit b234c6d

Please sign in to comment.