lightnvm: pblk: free full lines during recovery
authorHans Holmberg <hans.holmberg@cnexlabs.com>
Fri, 13 Oct 2017 12:46:36 +0000 (14:46 +0200)
committerJens Axboe <axboe@kernel.dk>
Fri, 13 Oct 2017 14:34:57 +0000 (08:34 -0600)
When rebuilding the L2P table, any full lines (lines without any
valid sectors) will be identified. If these lines are not freed,
we risk not being able to allocate the first data line.

This patch refactors the part of GC that frees empty lines
into a separate function and adds a call to this after the
L2P table has been rebuilt.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/lightnvm/pblk-gc.c
drivers/lightnvm/pblk-init.c
drivers/lightnvm/pblk.h

index 81efac18ff571fb33c373112e35e42d621eeac3b..374089fe4326bc7436d6a1b98dec9e4d7a66db70 100644 (file)
@@ -330,26 +330,16 @@ static bool pblk_gc_should_run(struct pblk_gc *gc, struct pblk_rl *rl)
        return ((gc->gc_active) && (nr_blocks_need > nr_blocks_free));
 }
 
-/*
- * Lines with no valid sectors will be returned to the free list immediately. If
- * GC is activated - either because the free block count is under the determined
- * threshold, or because it is being forced from user space - only lines with a
- * high count of invalid sectors will be recycled.
- */
-static void pblk_gc_run(struct pblk *pblk)
+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;
-       struct list_head *group_list;
-       bool run_gc;
-       int inflight_gc, gc_group = 0, prev_group = 0;
 
        do {
                spin_lock(&l_mg->gc_lock);
                if (list_empty(&l_mg->gc_full_list)) {
                        spin_unlock(&l_mg->gc_lock);
-                       break;
+                       return;
                }
 
                line = list_first_entry(&l_mg->gc_full_list,
@@ -365,6 +355,24 @@ static void pblk_gc_run(struct pblk *pblk)
 
                kref_put(&line->ref, pblk_line_put);
        } while (1);
+}
+
+/*
+ * Lines with no valid sectors will be returned to the free list immediately. If
+ * GC is activated - either because the free block count is under the determined
+ * threshold, or because it is being forced from user space - only lines with a
+ * high count of invalid sectors will be recycled.
+ */
+static void pblk_gc_run(struct pblk *pblk)
+{
+       struct pblk_line_mgmt *l_mg = &pblk->l_mg;
+       struct pblk_gc *gc = &pblk->gc;
+       struct pblk_line *line;
+       struct list_head *group_list;
+       bool run_gc;
+       int 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))
index 27eb430958ff67b616447e68246172844ca2047e..f08fa2083fbcc5a6e5d8ea3d5e91d2901d8023da 100644 (file)
@@ -508,6 +508,9 @@ static int pblk_lines_configure(struct pblk *pblk, int flags)
                }
        }
 
+       /* Free full lines directly as GC has not been started yet */
+       pblk_gc_free_full_lines(pblk);
+
        if (!line) {
                /* Configure next line for user data */
                line = pblk_line_get_first_data(pblk);
index 191b1ec0627b027f533cf4b6aef68de67a8035c8..21438d1550a2435aa7a1b56f83e3304c71a474de 100644 (file)
@@ -831,6 +831,7 @@ void pblk_gc_exit(struct pblk *pblk);
 void pblk_gc_should_start(struct pblk *pblk);
 void pblk_gc_should_stop(struct pblk *pblk);
 void pblk_gc_kick(struct pblk *pblk);
+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);