diff options
-rw-r--r-- | drivers/mtd/ubi/eba.c | 90 |
1 files changed, 89 insertions, 1 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 250e30fac61b..593a4f9d97e3 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -490,6 +490,82 @@ out_unlock: | |||
490 | return err; | 490 | return err; |
491 | } | 491 | } |
492 | 492 | ||
493 | #ifdef CONFIG_MTD_UBI_FASTMAP | ||
494 | /** | ||
495 | * check_mapping - check and fixup a mapping | ||
496 | * @ubi: UBI device description object | ||
497 | * @vol: volume description object | ||
498 | * @lnum: logical eraseblock number | ||
499 | * @pnum: physical eraseblock number | ||
500 | * | ||
501 | * Checks whether a given mapping is valid. Fastmap cannot track LEB unmap | ||
502 | * operations, if such an operation is interrupted the mapping still looks | ||
503 | * good, but upon first read an ECC is reported to the upper layer. | ||
504 | * Normaly during the full-scan at attach time this is fixed, for Fastmap | ||
505 | * we have to deal with it while reading. | ||
506 | * If the PEB behind a LEB shows this symthom we change the mapping to | ||
507 | * %UBI_LEB_UNMAPPED and schedule the PEB for erasure. | ||
508 | * | ||
509 | * Returns 0 on success, negative error code in case of failure. | ||
510 | */ | ||
511 | static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | ||
512 | int *pnum) | ||
513 | { | ||
514 | int err; | ||
515 | struct ubi_vid_io_buf *vidb; | ||
516 | |||
517 | if (!ubi->fast_attach) | ||
518 | return 0; | ||
519 | |||
520 | vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS); | ||
521 | if (!vidb) | ||
522 | return -ENOMEM; | ||
523 | |||
524 | err = ubi_io_read_vid_hdr(ubi, *pnum, vidb, 0); | ||
525 | if (err > 0 && err != UBI_IO_BITFLIPS) { | ||
526 | int torture = 0; | ||
527 | |||
528 | switch (err) { | ||
529 | case UBI_IO_FF: | ||
530 | case UBI_IO_FF_BITFLIPS: | ||
531 | case UBI_IO_BAD_HDR: | ||
532 | case UBI_IO_BAD_HDR_EBADMSG: | ||
533 | break; | ||
534 | default: | ||
535 | ubi_assert(0); | ||
536 | } | ||
537 | |||
538 | if (err == UBI_IO_BAD_HDR_EBADMSG || err == UBI_IO_FF_BITFLIPS) | ||
539 | torture = 1; | ||
540 | |||
541 | down_read(&ubi->fm_eba_sem); | ||
542 | vol->eba_tbl->entries[lnum].pnum = UBI_LEB_UNMAPPED; | ||
543 | up_read(&ubi->fm_eba_sem); | ||
544 | ubi_wl_put_peb(ubi, vol->vol_id, lnum, *pnum, torture); | ||
545 | |||
546 | *pnum = UBI_LEB_UNMAPPED; | ||
547 | } else if (err < 0) { | ||
548 | ubi_err(ubi, "unable to read VID header back from PEB %i: %i", | ||
549 | *pnum, err); | ||
550 | |||
551 | goto out_free; | ||
552 | } | ||
553 | |||
554 | err = 0; | ||
555 | |||
556 | out_free: | ||
557 | ubi_free_vid_buf(vidb); | ||
558 | |||
559 | return err; | ||
560 | } | ||
561 | #else | ||
562 | static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | ||
563 | int *pnum) | ||
564 | { | ||
565 | return 0; | ||
566 | } | ||
567 | #endif | ||
568 | |||
493 | /** | 569 | /** |
494 | * ubi_eba_read_leb - read data. | 570 | * ubi_eba_read_leb - read data. |
495 | * @ubi: UBI device description object | 571 | * @ubi: UBI device description object |
@@ -522,7 +598,13 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
522 | return err; | 598 | return err; |
523 | 599 | ||
524 | pnum = vol->eba_tbl->entries[lnum].pnum; | 600 | pnum = vol->eba_tbl->entries[lnum].pnum; |
525 | if (pnum < 0) { | 601 | if (pnum >= 0) { |
602 | err = check_mapping(ubi, vol, lnum, &pnum); | ||
603 | if (err < 0) | ||
604 | goto out_unlock; | ||
605 | } | ||
606 | |||
607 | if (pnum == UBI_LEB_UNMAPPED) { | ||
526 | /* | 608 | /* |
527 | * The logical eraseblock is not mapped, fill the whole buffer | 609 | * The logical eraseblock is not mapped, fill the whole buffer |
528 | * with 0xFF bytes. The exception is static volumes for which | 610 | * with 0xFF bytes. The exception is static volumes for which |
@@ -931,6 +1013,12 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
931 | 1013 | ||
932 | pnum = vol->eba_tbl->entries[lnum].pnum; | 1014 | pnum = vol->eba_tbl->entries[lnum].pnum; |
933 | if (pnum >= 0) { | 1015 | if (pnum >= 0) { |
1016 | err = check_mapping(ubi, vol, lnum, &pnum); | ||
1017 | if (err < 0) | ||
1018 | goto out; | ||
1019 | } | ||
1020 | |||
1021 | if (pnum >= 0) { | ||
934 | dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", | 1022 | dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", |
935 | len, offset, vol_id, lnum, pnum); | 1023 | len, offset, vol_id, lnum, pnum); |
936 | 1024 | ||