Skip to content

Commit 7819323

Browse files
ubi: fastmap: Correctly handle interrupted erasures in EBA
Fastmap cannot track the LEB unmap operation, therefore it can happen that after an interrupted erasure the mapping still looks good from Fastmap's point of view, while reading from the PEB will cause an ECC error and confuses the upper layer. Instead of teaching users of UBI how to deal with that, we read back the VID header and check for errors. If the PEB is empty or shows ECC errors we fixup the mapping and schedule the PEB for erasure. Fixes: dbb7d2a ("UBI: Add fastmap core") Cc: <[email protected]> Reported-by: martin bayern <[email protected]> Signed-off-by: Richard Weinberger <[email protected]>
1 parent 6e7d801 commit 7819323

File tree

1 file changed

+89
-1
lines changed

1 file changed

+89
-1
lines changed

drivers/mtd/ubi/eba.c

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,82 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
490490
return err;
491491
}
492492

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+
493569
/**
494570
* ubi_eba_read_leb - read data.
495571
* @ubi: UBI device description object
@@ -522,7 +598,13 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
522598
return err;
523599

524600
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) {
526608
/*
527609
* The logical eraseblock is not mapped, fill the whole buffer
528610
* with 0xFF bytes. The exception is static volumes for which
@@ -930,6 +1012,12 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
9301012
return err;
9311013

9321014
pnum = vol->eba_tbl->entries[lnum].pnum;
1015+
if (pnum >= 0) {
1016+
err = check_mapping(ubi, vol, lnum, &pnum);
1017+
if (err < 0)
1018+
goto out;
1019+
}
1020+
9331021
if (pnum >= 0) {
9341022
dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d",
9351023
len, offset, vol_id, lnum, pnum);

0 commit comments

Comments
 (0)