]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
lightnvm: pblk: handle bad sectors in the emeta area correctly
authorHans Holmberg <hans.holmberg@cnexlabs.com>
Thu, 29 Mar 2018 22:04:50 +0000 (00:04 +0200)
committerJens Axboe <axboe@kernel.dk>
Thu, 29 Mar 2018 23:29:09 +0000 (17:29 -0600)
Unless we check if there are bad sectors in the entire emeta-area
we risk ending up with valid bitmap / available sector count inconsistency.
This results in lines with a bad chunk at the last LUN marked as bad,
so go through the whole emeta area and mark up the invalid sectors.

Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/lightnvm/pblk-core.c

index 0487b9340c1dca59a77acb9e7e3e6be9ad665d65..9027cf2ed1d87aa8c6f19e015319892b38ff0f17 100644 (file)
@@ -1021,6 +1021,7 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
        int nr_bb = 0;
        u64 off;
        int bit = -1;
+       int emeta_secs;
 
        line->sec_in_line = lm->sec_per_line;
 
@@ -1055,18 +1056,18 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
        /* Mark emeta metadata sectors as bad sectors. We need to consider bad
         * blocks to make sure that there are enough sectors to store emeta
         */
-       off = lm->sec_per_line - lm->emeta_sec[0];
-       bitmap_set(line->invalid_bitmap, off, lm->emeta_sec[0]);
-       while (nr_bb) {
+       emeta_secs = lm->emeta_sec[0];
+       off = lm->sec_per_line;
+       while (emeta_secs) {
                off -= geo->sec_per_pl;
                if (!test_bit(off, line->invalid_bitmap)) {
                        bitmap_set(line->invalid_bitmap, off, geo->sec_per_pl);
-                       nr_bb--;
+                       emeta_secs -= geo->sec_per_pl;
                }
        }
 
-       line->sec_in_line -= lm->emeta_sec[0];
        line->emeta_ssec = off;
+       line->sec_in_line -= lm->emeta_sec[0];
        line->nr_valid_lbas = 0;
        line->left_msecs = line->sec_in_line;
        *line->vsc = cpu_to_le32(line->sec_in_line);