|
@@ -490,6 +490,82 @@ out_unlock:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_MTD_UBI_FASTMAP
|
|
|
+/**
|
|
|
+ * check_mapping - check and fixup a mapping
|
|
|
+ * @ubi: UBI device description object
|
|
|
+ * @vol: volume description object
|
|
|
+ * @lnum: logical eraseblock number
|
|
|
+ * @pnum: physical eraseblock number
|
|
|
+ *
|
|
|
+ * Checks whether a given mapping is valid. Fastmap cannot track LEB unmap
|
|
|
+ * operations, if such an operation is interrupted the mapping still looks
|
|
|
+ * good, but upon first read an ECC is reported to the upper layer.
|
|
|
+ * Normaly during the full-scan at attach time this is fixed, for Fastmap
|
|
|
+ * we have to deal with it while reading.
|
|
|
+ * If the PEB behind a LEB shows this symthom we change the mapping to
|
|
|
+ * %UBI_LEB_UNMAPPED and schedule the PEB for erasure.
|
|
|
+ *
|
|
|
+ * Returns 0 on success, negative error code in case of failure.
|
|
|
+ */
|
|
|
+static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
|
|
+ int *pnum)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+ struct ubi_vid_io_buf *vidb;
|
|
|
+
|
|
|
+ if (!ubi->fast_attach)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
|
|
|
+ if (!vidb)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ err = ubi_io_read_vid_hdr(ubi, *pnum, vidb, 0);
|
|
|
+ if (err > 0 && err != UBI_IO_BITFLIPS) {
|
|
|
+ int torture = 0;
|
|
|
+
|
|
|
+ switch (err) {
|
|
|
+ case UBI_IO_FF:
|
|
|
+ case UBI_IO_FF_BITFLIPS:
|
|
|
+ case UBI_IO_BAD_HDR:
|
|
|
+ case UBI_IO_BAD_HDR_EBADMSG:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ubi_assert(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (err == UBI_IO_BAD_HDR_EBADMSG || err == UBI_IO_FF_BITFLIPS)
|
|
|
+ torture = 1;
|
|
|
+
|
|
|
+ down_read(&ubi->fm_eba_sem);
|
|
|
+ vol->eba_tbl->entries[lnum].pnum = UBI_LEB_UNMAPPED;
|
|
|
+ up_read(&ubi->fm_eba_sem);
|
|
|
+ ubi_wl_put_peb(ubi, vol->vol_id, lnum, *pnum, torture);
|
|
|
+
|
|
|
+ *pnum = UBI_LEB_UNMAPPED;
|
|
|
+ } else if (err < 0) {
|
|
|
+ ubi_err(ubi, "unable to read VID header back from PEB %i: %i",
|
|
|
+ *pnum, err);
|
|
|
+
|
|
|
+ goto out_free;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = 0;
|
|
|
+
|
|
|
+out_free:
|
|
|
+ ubi_free_vid_buf(vidb);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+#else
|
|
|
+static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
|
|
+ int *pnum)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/**
|
|
|
* ubi_eba_read_leb - read data.
|
|
|
* @ubi: UBI device description object
|
|
@@ -522,7 +598,13 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
|
|
|
return err;
|
|
|
|
|
|
pnum = vol->eba_tbl->entries[lnum].pnum;
|
|
|
- if (pnum < 0) {
|
|
|
+ if (pnum >= 0) {
|
|
|
+ err = check_mapping(ubi, vol, lnum, &pnum);
|
|
|
+ if (err < 0)
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pnum == UBI_LEB_UNMAPPED) {
|
|
|
/*
|
|
|
* The logical eraseblock is not mapped, fill the whole buffer
|
|
|
* 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,
|
|
|
return err;
|
|
|
|
|
|
pnum = vol->eba_tbl->entries[lnum].pnum;
|
|
|
+ if (pnum >= 0) {
|
|
|
+ err = check_mapping(ubi, vol, lnum, &pnum);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
if (pnum >= 0) {
|
|
|
dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d",
|
|
|
len, offset, vol_id, lnum, pnum);
|