> On 3 Oct 2017, at 12.05, Hans Holmberg <[email protected]> wrote:
> 
> From: Hans Holmberg <[email protected]>
> 
> Finish garbage collect of the lines that are in the gc pipeline
> before exiting. Ensure that all lines already in in the pipeline
> goes through, from read to write.
> 
> Do this by keeping track of how many lines are in the pipeline
> and waiting for that number to reach zero before exiting the gc
> reader task.
> 
> Since we're adding a new gc line counter, change the name of
> inflight_gc to read_inflight_gc to make the distinction clear.
> 
> Signed-off-by: Hans Holmberg <[email protected]>
> ---
> drivers/lightnvm/pblk-core.c  |  3 +++
> drivers/lightnvm/pblk-gc.c    | 31 ++++++++++++++++++++++++-------
> drivers/lightnvm/pblk-sysfs.c |  2 +-
> drivers/lightnvm/pblk.h       |  5 ++++-
> 4 files changed, 32 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
> index 15e1e28..e62e6eb 100644
> --- a/drivers/lightnvm/pblk-core.c
> +++ b/drivers/lightnvm/pblk-core.c
> @@ -1463,6 +1463,7 @@ void pblk_line_free(struct pblk *pblk, struct pblk_line 
> *line)
> static void __pblk_line_put(struct pblk *pblk, struct pblk_line *line)
> {
>       struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> +     struct pblk_gc *gc = &pblk->gc;
> 
>       spin_lock(&line->lock);
>       WARN_ON(line->state != PBLK_LINESTATE_GC);
> @@ -1471,6 +1472,8 @@ static void __pblk_line_put(struct pblk *pblk, struct 
> pblk_line *line)
>       pblk_line_free(pblk, line);
>       spin_unlock(&line->lock);
> 
> +     atomic_dec(&gc->pipeline_gc);
> +
>       spin_lock(&l_mg->free_lock);
>       list_add_tail(&line->list, &l_mg->free_list);
>       l_mg->nr_free_lines++;
> diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
> index f343f90..475a13e 100644
> --- a/drivers/lightnvm/pblk-gc.c
> +++ b/drivers/lightnvm/pblk-gc.c
> @@ -234,7 +234,7 @@ static void pblk_gc_line_prepare_ws(struct work_struct 
> *work)
>       kfree(invalid_bitmap);
> 
>       kref_put(&line->ref, pblk_line_put);
> -     atomic_dec(&gc->inflight_gc);
> +     atomic_dec(&gc->read_inflight_gc);
> 
>       return;
> 
> @@ -249,7 +249,7 @@ static void pblk_gc_line_prepare_ws(struct work_struct 
> *work)
> 
>       pblk_put_line_back(pblk, line);
>       kref_put(&line->ref, pblk_line_put);
> -     atomic_dec(&gc->inflight_gc);
> +     atomic_dec(&gc->read_inflight_gc);
> 
>       pr_err("pblk: Failed to GC line %d\n", line->id);
> }
> @@ -268,6 +268,7 @@ static int pblk_gc_line(struct pblk *pblk, struct 
> pblk_line *line)
>       line_ws->pblk = pblk;
>       line_ws->line = line;
> 
> +     atomic_inc(&gc->pipeline_gc);
>       INIT_WORK(&line_ws->ws, pblk_gc_line_prepare_ws);
>       queue_work(gc->gc_reader_wq, &line_ws->ws);
> 
> @@ -333,6 +334,7 @@ static bool pblk_gc_should_run(struct pblk_gc *gc, struct 
> pblk_rl *rl)
> void pblk_gc_free_full_lines(struct pblk *pblk)
> {
>       struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> +     struct pblk_gc *gc = &pblk->gc;
>       struct pblk_line *line;
> 
>       do {
> @@ -353,6 +355,7 @@ void pblk_gc_free_full_lines(struct pblk *pblk)
>               list_del(&line->list);
>               spin_unlock(&l_mg->gc_lock);
> 
> +             atomic_inc(&gc->pipeline_gc);
>               kref_put(&line->ref, pblk_line_put);
>       } while (1);
> }
> @@ -370,12 +373,12 @@ static void pblk_gc_run(struct pblk *pblk)
>       struct pblk_line *line;
>       struct list_head *group_list;
>       bool run_gc;
> -     int inflight_gc, gc_group = 0, prev_group = 0;
> +     int read_inflight_gc, gc_group = 0, prev_group = 0;
> 
>       pblk_gc_free_full_lines(pblk);
> 
>       run_gc = pblk_gc_should_run(&pblk->gc, &pblk->rl);
> -     if (!run_gc || (atomic_read(&gc->inflight_gc) >= PBLK_GC_L_QD))
> +     if (!run_gc || (atomic_read(&gc->read_inflight_gc) >= PBLK_GC_L_QD))
>               return;
> 
> next_gc_group:
> @@ -402,14 +405,14 @@ static void pblk_gc_run(struct pblk *pblk)
>               list_add_tail(&line->list, &gc->r_list);
>               spin_unlock(&gc->r_lock);
> 
> -             inflight_gc = atomic_inc_return(&gc->inflight_gc);
> +             read_inflight_gc = atomic_inc_return(&gc->read_inflight_gc);
>               pblk_gc_reader_kick(gc);
> 
>               prev_group = 1;
> 
>               /* No need to queue up more GC lines than we can handle */
>               run_gc = pblk_gc_should_run(&pblk->gc, &pblk->rl);
> -             if (!run_gc || inflight_gc >= PBLK_GC_L_QD)
> +             if (!run_gc || read_inflight_gc >= PBLK_GC_L_QD)
>                       break;
>       } while (1);
> 
> @@ -470,6 +473,7 @@ static int pblk_gc_writer_ts(void *data)
> static int pblk_gc_reader_ts(void *data)
> {
>       struct pblk *pblk = data;
> +     struct pblk_gc *gc = &pblk->gc;
> 
>       while (!kthread_should_stop()) {
>               if (!pblk_gc_read(pblk))
> @@ -478,6 +482,18 @@ static int pblk_gc_reader_ts(void *data)
>               io_schedule();
>       }
> 
> +#ifdef CONFIG_NVM_DEBUG
> +     pr_info("pblk: flushing gc pipeline, %d lines left\n",
> +             atomic_read(&gc->pipeline_gc));
> +#endif
> +
> +     do {
> +             if (!atomic_read(&gc->pipeline_gc))
> +                     break;
> +
> +             schedule();
> +     } while (1);
> +
>       return 0;
> }
> 
> @@ -581,7 +597,8 @@ int pblk_gc_init(struct pblk *pblk)
>       gc->gc_forced = 0;
>       gc->gc_enabled = 1;
>       gc->w_entries = 0;
> -     atomic_set(&gc->inflight_gc, 0);
> +     atomic_set(&gc->read_inflight_gc, 0);
> +     atomic_set(&gc->pipeline_gc, 0);
> 
>       /* Workqueue that reads valid sectors from a line and submit them to the
>        * GC writer to be recycled.
> diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c
> index 95fb434..cd49e88 100644
> --- a/drivers/lightnvm/pblk-sysfs.c
> +++ b/drivers/lightnvm/pblk-sysfs.c
> @@ -253,7 +253,7 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char 
> *page)
>       sz += snprintf(page + sz, PAGE_SIZE - sz,
>               "GC: full:%d, high:%d, mid:%d, low:%d, empty:%d, queue:%d\n",
>                       gc_full, gc_high, gc_mid, gc_low, gc_empty,
> -                     atomic_read(&pblk->gc.inflight_gc));
> +                     atomic_read(&pblk->gc.read_inflight_gc));
> 
>       sz += snprintf(page + sz, PAGE_SIZE - sz,
>               "data (%d) cur:%d, left:%d, vsc:%d, s:%d, map:%d/%d (%d)\n",
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index f76583b..03965da 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -238,7 +238,10 @@ struct pblk_gc {
>       struct timer_list gc_timer;
> 
>       struct semaphore gc_sem;
> -     atomic_t inflight_gc;
> +     atomic_t read_inflight_gc; /* Number of lines with inflight GC reads */
> +     atomic_t pipeline_gc;      /* Number of lines in the GC pipeline -
> +                                 * started reads to finished writes
> +                                 */
>       int w_entries;
> 
>       struct list_head w_list;
> --
> 2.7.4

LGTM.

Reviewed-by: Javier González <[email protected]>

Attachment: signature.asc
Description: Message signed with OpenPGP

Reply via email to