aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-init.c
diff options
context:
space:
mode:
authorHans Holmberg <hans.holmberg@cnexlabs.com>2018-06-01 10:41:06 -0400
committerJens Axboe <axboe@kernel.dk>2018-06-01 11:02:53 -0400
commit48b8d20895f8a489e1527e9bdc5e372808542fa3 (patch)
tree754ad9c349589759af22adad8286e7fa2b7095bc /drivers/lightnvm/pblk-init.c
parent6a3abf5beef6ae46381c1fb6976e6f313c40f0c1 (diff)
lightnvm: pblk: garbage collect lines with failed writes
Write failures should not happen under normal circumstances, so in order to bring the chunk back into a known state as soon as possible, evacuate all the valid data out of the line and let the fw judge if the block can be written to in the next reset cycle. Do this by introducing a new gc list for lines with failed writes, and ensure that the rate limiter allocates a small portion of the write bandwidth to get the job done. The lba list is saved in memory for use during gc as we cannot gurantee that the emeta data is readable if a write error occurred. Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com> Reviewed-by: Javier González <javier@cnexlabs.com> Signed-off-by: Matias Bjørling <mb@lightnvm.io> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/lightnvm/pblk-init.c')
-rw-r--r--drivers/lightnvm/pblk-init.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 2a3302f7e853..783887b891b7 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -493,11 +493,17 @@ static void pblk_line_mg_free(struct pblk *pblk)
493 } 493 }
494} 494}
495 495
496static void pblk_line_meta_free(struct pblk_line *line) 496static void pblk_line_meta_free(struct pblk_line_mgmt *l_mg,
497 struct pblk_line *line)
497{ 498{
499 struct pblk_w_err_gc *w_err_gc = line->w_err_gc;
500
498 kfree(line->blk_bitmap); 501 kfree(line->blk_bitmap);
499 kfree(line->erase_bitmap); 502 kfree(line->erase_bitmap);
500 kfree(line->chks); 503 kfree(line->chks);
504
505 pblk_mfree(w_err_gc->lba_list, l_mg->emeta_alloc_type);
506 kfree(w_err_gc);
501} 507}
502 508
503static void pblk_lines_free(struct pblk *pblk) 509static void pblk_lines_free(struct pblk *pblk)
@@ -511,7 +517,7 @@ static void pblk_lines_free(struct pblk *pblk)
511 line = &pblk->lines[i]; 517 line = &pblk->lines[i];
512 518
513 pblk_line_free(line); 519 pblk_line_free(line);
514 pblk_line_meta_free(line); 520 pblk_line_meta_free(l_mg, line);
515 } 521 }
516 spin_unlock(&l_mg->free_lock); 522 spin_unlock(&l_mg->free_lock);
517 523
@@ -813,20 +819,28 @@ static int pblk_alloc_line_meta(struct pblk *pblk, struct pblk_line *line)
813 return -ENOMEM; 819 return -ENOMEM;
814 820
815 line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL); 821 line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
816 if (!line->erase_bitmap) { 822 if (!line->erase_bitmap)
817 kfree(line->blk_bitmap); 823 goto free_blk_bitmap;
818 return -ENOMEM; 824
819 }
820 825
821 line->chks = kmalloc(lm->blk_per_line * sizeof(struct nvm_chk_meta), 826 line->chks = kmalloc(lm->blk_per_line * sizeof(struct nvm_chk_meta),
822 GFP_KERNEL); 827 GFP_KERNEL);
823 if (!line->chks) { 828 if (!line->chks)
824 kfree(line->erase_bitmap); 829 goto free_erase_bitmap;
825 kfree(line->blk_bitmap); 830
826 return -ENOMEM; 831 line->w_err_gc = kzalloc(sizeof(struct pblk_w_err_gc), GFP_KERNEL);
827 } 832 if (!line->w_err_gc)
833 goto free_chks;
828 834
829 return 0; 835 return 0;
836
837free_chks:
838 kfree(line->chks);
839free_erase_bitmap:
840 kfree(line->erase_bitmap);
841free_blk_bitmap:
842 kfree(line->blk_bitmap);
843 return -ENOMEM;
830} 844}
831 845
832static int pblk_line_mg_init(struct pblk *pblk) 846static int pblk_line_mg_init(struct pblk *pblk)
@@ -851,12 +865,14 @@ static int pblk_line_mg_init(struct pblk *pblk)
851 INIT_LIST_HEAD(&l_mg->gc_mid_list); 865 INIT_LIST_HEAD(&l_mg->gc_mid_list);
852 INIT_LIST_HEAD(&l_mg->gc_low_list); 866 INIT_LIST_HEAD(&l_mg->gc_low_list);
853 INIT_LIST_HEAD(&l_mg->gc_empty_list); 867 INIT_LIST_HEAD(&l_mg->gc_empty_list);
868 INIT_LIST_HEAD(&l_mg->gc_werr_list);
854 869
855 INIT_LIST_HEAD(&l_mg->emeta_list); 870 INIT_LIST_HEAD(&l_mg->emeta_list);
856 871
857 l_mg->gc_lists[0] = &l_mg->gc_high_list; 872 l_mg->gc_lists[0] = &l_mg->gc_werr_list;
858 l_mg->gc_lists[1] = &l_mg->gc_mid_list; 873 l_mg->gc_lists[1] = &l_mg->gc_high_list;
859 l_mg->gc_lists[2] = &l_mg->gc_low_list; 874 l_mg->gc_lists[2] = &l_mg->gc_mid_list;
875 l_mg->gc_lists[3] = &l_mg->gc_low_list;
860 876
861 spin_lock_init(&l_mg->free_lock); 877 spin_lock_init(&l_mg->free_lock);
862 spin_lock_init(&l_mg->close_lock); 878 spin_lock_init(&l_mg->close_lock);
@@ -1063,7 +1079,7 @@ static int pblk_lines_init(struct pblk *pblk)
1063 1079
1064fail_free_lines: 1080fail_free_lines:
1065 while (--i >= 0) 1081 while (--i >= 0)
1066 pblk_line_meta_free(&pblk->lines[i]); 1082 pblk_line_meta_free(l_mg, &pblk->lines[i]);
1067 kfree(pblk->lines); 1083 kfree(pblk->lines);
1068fail_free_chunk_meta: 1084fail_free_chunk_meta:
1069 kfree(chunk_meta); 1085 kfree(chunk_meta);