Commit f2e02457 authored by Igor Konopko's avatar Igor Konopko Committed by Jens Axboe

lightnvm: pblk: GC error handling

Currently when there is an IO error (or similar) on GC read path, pblk
still move the line, which was currently under GC process to free state.
Such a behaviour can lead to silent data mismatch issue.

With this patch, the line which was under GC process on which some IO
errors occurred, will be putted back to closed state (instead of free
state as it was without this patch) and the L2P mapping for such a
failed sectors will not be updated.

Then in case of any user IOs to such a failed sectors, pblk would be
able to return at least real IO error instead of stale data as it is
right now.
Signed-off-by: default avatarIgor Konopko <igor.j.konopko@intel.com>
Reviewed-by: default avatarJavier González <javier@javigon.com>
Reviewed-by: default avatarHans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: default avatarMatias Bjørling <mb@lightnvm.io>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 32ac0fa3
......@@ -1703,6 +1703,14 @@ static void __pblk_line_put(struct pblk *pblk, struct pblk_line *line)
spin_lock(&line->lock);
WARN_ON(line->state != PBLK_LINESTATE_GC);
if (line->w_err_gc->has_gc_err) {
spin_unlock(&line->lock);
pblk_err(pblk, "line %d had errors during GC\n", line->id);
pblk_put_line_back(pblk, line);
line->w_err_gc->has_gc_err = 0;
return;
}
line->state = PBLK_LINESTATE_FREE;
trace_pblk_line_state(pblk_disk_name(pblk), line->id,
line->state);
......
......@@ -59,7 +59,7 @@ static void pblk_gc_writer_kick(struct pblk_gc *gc)
wake_up_process(gc->gc_writer_ts);
}
static void pblk_put_line_back(struct pblk *pblk, struct pblk_line *line)
void pblk_put_line_back(struct pblk *pblk, struct pblk_line *line)
{
struct pblk_line_mgmt *l_mg = &pblk->l_mg;
struct list_head *move_list;
......@@ -98,8 +98,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
/* Read from GC victim block */
ret = pblk_submit_read_gc(pblk, gc_rq);
if (ret) {
pblk_err(pblk, "failed GC read in line:%d (err:%d)\n",
line->id, ret);
line->w_err_gc->has_gc_err = 1;
goto out;
}
......
......@@ -641,7 +641,6 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq)
if (pblk_submit_io_sync(pblk, &rqd)) {
ret = -EIO;
pblk_err(pblk, "GC read request failed\n");
goto err_free_bio;
}
......
......@@ -437,6 +437,7 @@ struct pblk_smeta {
struct pblk_w_err_gc {
int has_write_err;
int has_gc_err;
__le64 *lba_list;
};
......@@ -917,6 +918,7 @@ void pblk_gc_free_full_lines(struct pblk *pblk);
void pblk_gc_sysfs_state_show(struct pblk *pblk, int *gc_enabled,
int *gc_active);
int pblk_gc_sysfs_force(struct pblk *pblk, int force);
void pblk_put_line_back(struct pblk *pblk, struct pblk_line *line);
/*
* pblk rate limiter
......
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