aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/mtd/ubi/build.c2
-rw-r--r--drivers/mtd/ubi/eba.c6
-rw-r--r--drivers/mtd/ubi/scan.c48
-rw-r--r--drivers/mtd/ubi/ubi.h3
-rw-r--r--drivers/mtd/ubi/vmt.c6
-rw-r--r--drivers/mtd/ubi/vtbl.c8
-rw-r--r--drivers/mtd/ubi/wl.c19
7 files changed, 45 insertions, 47 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index f247c4e7b40d..5ebe280225d6 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -591,6 +591,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
591 591
592 ubi->bad_peb_count = si->bad_peb_count; 592 ubi->bad_peb_count = si->bad_peb_count;
593 ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; 593 ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
594 ubi->corr_peb_count = si->corr_peb_count;
594 ubi->max_ec = si->max_ec; 595 ubi->max_ec = si->max_ec;
595 ubi->mean_ec = si->mean_ec; 596 ubi->mean_ec = si->mean_ec;
596 ubi_msg("max. sequence number: %llu", si->max_sqnum); 597 ubi_msg("max. sequence number: %llu", si->max_sqnum);
@@ -972,6 +973,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
972 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); 973 ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
973 ubi_msg("number of good PEBs: %d", ubi->good_peb_count); 974 ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
974 ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); 975 ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
976 ubi_msg("number of corrupted PEBs: %d", ubi->corr_peb_count);
975 ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); 977 ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
976 ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); 978 ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
977 ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); 979 ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 334865ef5220..4be671815014 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1201,6 +1201,9 @@ static void print_rsvd_warning(struct ubi_device *ubi,
1201 1201
1202 ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d," 1202 ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
1203 " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level); 1203 " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
1204 if (ubi->corr_peb_count)
1205 ubi_warn("%d PEBs are corrupted and not used",
1206 ubi->corr_peb_count);
1204} 1207}
1205 1208
1206/** 1209/**
@@ -1263,6 +1266,9 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
1263 if (ubi->avail_pebs < EBA_RESERVED_PEBS) { 1266 if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
1264 ubi_err("no enough physical eraseblocks (%d, need %d)", 1267 ubi_err("no enough physical eraseblocks (%d, need %d)",
1265 ubi->avail_pebs, EBA_RESERVED_PEBS); 1268 ubi->avail_pebs, EBA_RESERVED_PEBS);
1269 if (ubi->corr_peb_count)
1270 ubi_err("%d PEBs are corrupted and not used",
1271 ubi->corr_peb_count);
1266 err = -ENOSPC; 1272 err = -ENOSPC;
1267 goto out_free; 1273 goto out_free;
1268 } 1274 }
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
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 8831d7ba9f21..0b0149c41fe3 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -361,6 +361,8 @@ struct ubi_wl_entry;
361 * @peb_size: physical eraseblock size 361 * @peb_size: physical eraseblock size
362 * @bad_peb_count: count of bad physical eraseblocks 362 * @bad_peb_count: count of bad physical eraseblocks
363 * @good_peb_count: count of good physical eraseblocks 363 * @good_peb_count: count of good physical eraseblocks
364 * @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
365 * used by UBI)
364 * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous 366 * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous
365 * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks 367 * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks
366 * @min_io_size: minimal input/output unit size of the underlying MTD device 368 * @min_io_size: minimal input/output unit size of the underlying MTD device
@@ -447,6 +449,7 @@ struct ubi_device {
447 int peb_size; 449 int peb_size;
448 int bad_peb_count; 450 int bad_peb_count;
449 int good_peb_count; 451 int good_peb_count;
452 int corr_peb_count;
450 int erroneous_peb_count; 453 int erroneous_peb_count;
451 int max_erroneous; 454 int max_erroneous;
452 int min_io_size; 455 int min_io_size;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index e42afab9a9fe..c47620dfc722 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -261,6 +261,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
261 /* Reserve physical eraseblocks */ 261 /* Reserve physical eraseblocks */
262 if (vol->reserved_pebs > ubi->avail_pebs) { 262 if (vol->reserved_pebs > ubi->avail_pebs) {
263 dbg_err("not enough PEBs, only %d available", ubi->avail_pebs); 263 dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
264 if (ubi->corr_peb_count)
265 dbg_err("%d PEBs are corrupted and not used",
266 ubi->corr_peb_count);
264 err = -ENOSPC; 267 err = -ENOSPC;
265 goto out_unlock; 268 goto out_unlock;
266 } 269 }
@@ -527,6 +530,9 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
527 if (pebs > ubi->avail_pebs) { 530 if (pebs > ubi->avail_pebs) {
528 dbg_err("not enough PEBs: requested %d, available %d", 531 dbg_err("not enough PEBs: requested %d, available %d",
529 pebs, ubi->avail_pebs); 532 pebs, ubi->avail_pebs);
533 if (ubi->corr_peb_count)
534 dbg_err("%d PEBs are corrupted and not used",
535 ubi->corr_peb_count);
530 spin_unlock(&ubi->volumes_lock); 536 spin_unlock(&ubi->volumes_lock);
531 err = -ENOSPC; 537 err = -ENOSPC;
532 goto out_free; 538 goto out_free;
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 3bfe00a94667..fcdb7f65fe0b 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -662,9 +662,13 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
662 ubi->vol_count += 1; 662 ubi->vol_count += 1;
663 vol->ubi = ubi; 663 vol->ubi = ubi;
664 664
665 if (reserved_pebs > ubi->avail_pebs) 665 if (reserved_pebs > ubi->avail_pebs) {
666 ubi_err("not enough PEBs, required %d, available %d", 666 ubi_err("not enough PEBs, required %d, available %d",
667 reserved_pebs, ubi->avail_pebs); 667 reserved_pebs, ubi->avail_pebs);
668 if (ubi->corr_peb_count)
669 ubi_err("%d PEBs are corrupted and not used",
670 ubi->corr_peb_count);
671 }
668 ubi->rsvd_pebs += reserved_pebs; 672 ubi->rsvd_pebs += reserved_pebs;
669 ubi->avail_pebs -= reserved_pebs; 673 ubi->avail_pebs -= reserved_pebs;
670 674
@@ -837,7 +841,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
837 return PTR_ERR(ubi->vtbl); 841 return PTR_ERR(ubi->vtbl);
838 } 842 }
839 843
840 ubi->avail_pebs = ubi->good_peb_count; 844 ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count;
841 845
842 /* 846 /*
843 * The layout volume is OK, initialize the corresponding in-RAM data 847 * The layout volume is OK, initialize the corresponding in-RAM data
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 605ecb1e22bb..655bbbe415d9 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1478,22 +1478,6 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
1478 ubi->lookuptbl[e->pnum] = e; 1478 ubi->lookuptbl[e->pnum] = e;
1479 } 1479 }
1480 1480
1481 list_for_each_entry(seb, &si->corr, u.list) {
1482 cond_resched();
1483
1484 e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
1485 if (!e)
1486 goto out_free;
1487
1488 e->pnum = seb->pnum;
1489 e->ec = seb->ec;
1490 ubi->lookuptbl[e->pnum] = e;
1491 if (schedule_erase(ubi, e, 0)) {
1492 kmem_cache_free(ubi_wl_entry_slab, e);
1493 goto out_free;
1494 }
1495 }
1496
1497 ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { 1481 ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
1498 ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { 1482 ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
1499 cond_resched(); 1483 cond_resched();
@@ -1520,6 +1504,9 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
1520 if (ubi->avail_pebs < WL_RESERVED_PEBS) { 1504 if (ubi->avail_pebs < WL_RESERVED_PEBS) {
1521 ubi_err("no enough physical eraseblocks (%d, need %d)", 1505 ubi_err("no enough physical eraseblocks (%d, need %d)",
1522 ubi->avail_pebs, WL_RESERVED_PEBS); 1506 ubi->avail_pebs, WL_RESERVED_PEBS);
1507 if (ubi->corr_peb_count)
1508 ubi_err("%d PEBs are corrupted and not used",
1509 ubi->corr_peb_count);
1523 goto out_free; 1510 goto out_free;
1524 } 1511 }
1525 ubi->avail_pebs -= WL_RESERVED_PEBS; 1512 ubi->avail_pebs -= WL_RESERVED_PEBS;