aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/scan.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-09-03 16:08:15 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-10-19 10:19:57 -0400
commit5fc01ab6934c43b42c41bc753fe1123c16d7f38f (patch)
tree174a1e1a0d283ec8ca4c756d7f354a475ac46a36 /drivers/mtd/ubi/scan.c
parentfeeba4b872e5166ca64c44fbb5bbec234dfce199 (diff)
UBI: preserve corrupted PEBs
Currently UBI erases all corrupted eraseblocks, irrespectively of the nature of corruption: corruption due to power cuts and non-power cut corruption. The former case is OK, but the latter is not, because UBI may destroy potentially important data. With this patch, during scanning, when UBI hits a PEB with corrupted VID header, it checks whether this PEB contains only 0xFF data. If yes, it is safe to erase this PEB and it is put to the 'erase' list. If not, this may be important data and it is better to avoid erasing this PEB. Instead, UBI puts it to the corr list and moves out of the pool of available PEB. IOW, UBI preserves this PEB. Such corrupted PEB lessen the amount of available PEBs. So the more of them we accumulate, the less PEBs are available. The maximum amount of non-power cut corrupted PEBs is 8. This patch is a response to UBIFS problem where reporter (Matthew L. Creech <mlcreech@gmail.com>) observes that UBIFS index points to an unmapped LEB. The theory is that corresponding PEB somehow got corrupted and UBI wiped it. This patch (actually a series of patches) tries to make sure such PEBs are preserved - this would make it is easier to analyze the corruption. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/scan.c')
-rw-r--r--drivers/mtd/ubi/scan.c48
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index def0bf03d7fe..30b710216f26 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -706,8 +706,8 @@ out_free:
706struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, 706struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
707 struct ubi_scan_info *si) 707 struct ubi_scan_info *si)
708{ 708{
709 int err = 0, i; 709 int err = 0;
710 struct ubi_scan_leb *seb; 710 struct ubi_scan_leb *seb, *tmp_seb;
711 711
712 if (!list_empty(&si->free)) { 712 if (!list_empty(&si->free)) {
713 seb = list_entry(si->free.next, struct ubi_scan_leb, u.list); 713 seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
@@ -716,37 +716,27 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
716 return seb; 716 return seb;
717 } 717 }
718 718
719 for (i = 0; i < 2; i++) { 719 /*
720 struct list_head *head; 720 * We try to erase the first physical eraseblock from the erase list
721 struct ubi_scan_leb *tmp_seb; 721 * and pick it if we succeed, or try to erase the next one if not. And
722 722 * so forth. We don't want to take care about bad eraseblocks here -
723 if (i == 0) 723 * they'll be handled later.
724 head = &si->erase; 724 */
725 else 725 list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
726 head = &si->corr; 726 if (seb->ec == UBI_SCAN_UNKNOWN_EC)
727 727 seb->ec = si->mean_ec;
728 /*
729 * We try to erase the first physical eraseblock from the @head
730 * list and pick it if we succeed, or try to erase the
731 * next one if not. And so forth. We don't want to take care
732 * about bad eraseblocks here - they'll be handled later.
733 */
734 list_for_each_entry_safe(seb, tmp_seb, head, u.list) {
735 if (seb->ec == UBI_SCAN_UNKNOWN_EC)
736 seb->ec = si->mean_ec;
737 728
738 err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1); 729 err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
739 if (err) 730 if (err)
740 continue; 731 continue;
741 732
742 seb->ec += 1; 733 seb->ec += 1;
743 list_del(&seb->u.list); 734 list_del(&seb->u.list);
744 dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec); 735 dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
745 return seb; 736 return seb;
746 }
747 } 737 }
748 738
749 ubi_err("no eraseblocks found"); 739 ubi_err("no free eraseblocks");
750 return ERR_PTR(-ENOSPC); 740 return ERR_PTR(-ENOSPC);
751} 741}
752 742