[PATCH 20/21] UBI: Fastmap: Torture fastmap PEBs that showed bit flips

Richard Weinberger richard at nod.at
Wed Jun 13 06:42:17 EDT 2012


Signed-off-by: Richard Weinberger <richard at nod.at>
---
 drivers/mtd/ubi/attach.c  |    8 +++++-
 drivers/mtd/ubi/fastmap.c |   46 ++++++++++++++++++++++++++++----------------
 drivers/mtd/ubi/ubi.h     |    5 ++-
 3 files changed, 38 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 2a0c1ba..4c6b97b 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1371,8 +1371,12 @@ void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
 
 	/* Return all PEBs back to the WL sub-system */
 	if (ai->fm) {
-		while(ai->fm->used_blocks--)
-			ubi_wl_put_fm_peb(ubi, ai->fm->e[ai->fm->used_blocks], 0);
+		int i, torture;
+
+		for (i = 0; i < ai->fm->used_blocks; i++) {
+			torture = ai->fm->to_be_tortured[i];
+			ubi_wl_put_fm_peb(ubi, ai->fm->e[i], torture);
+		}
 
 		kfree(ai->fm);
 	}
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 8b09c29..ecc313d 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -713,7 +713,7 @@ fail:
  */
 static int ubi_find_fastmap(struct ubi_device *ubi, int *fm_start)
 {
-	int i, ret;
+	int i, ret = -ENOENT;
 	struct ubi_vid_hdr *vhdr;
 	unsigned long long max_sqnum = 0, sqnum;
 
@@ -772,8 +772,8 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	struct ubi_fm_sb *fmsb;
 	struct ubi_vid_hdr *vh;
 	struct ubi_ec_hdr *ech;
-	int ret, i, used_blocks, pnum, sb_pnum = 0;
-	void *fm_raw;
+	int i, used_blocks, pnum, sb_pnum = 0, ret = 0;
+	void *fm_raw = NULL;
 	size_t fm_size;
 	__be32 crc, tmp_crc;
 	unsigned long long sqnum = 0;
@@ -790,15 +790,20 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		goto out;
 	}
 
-	/* TODO: If 'ubi_io_read()' returns you UBI_IO_BITFLIP, this means that
-	 * the PEB has a bit-flip and has to be scrubbed. How will the
-	 * superblock be scrubbed or how is the bit-flip guaranteed to be taken
-	 * care of? */
+	ai->fm = kzalloc(sizeof(*ai->fm), GFP_KERNEL);
+	if (!ai->fm) {
+		ret = -ENOMEM;
+		kfree(fmsb);
+		goto free_raw;
+	}
+
 	ret = ubi_io_read(ubi, fmsb, sb_pnum, ubi->leb_start, sizeof(*fmsb));
 	if (ret && ret != UBI_IO_BITFLIPS) {
 		kfree(fmsb);
+		kfree(ai->fm);
 		goto out;
-	}
+	} else if (ret == UBI_IO_BITFLIPS)
+		ai->fm->to_be_tortured[0] = 1;
 
 	if (be32_to_cpu(fmsb->magic) != UBI_FM_SB_MAGIC) {
 		/* TODO: not urgent, but examine all the error messages and
@@ -811,6 +816,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		ubi_err("super block magic does not match");
 		ret = UBI_BAD_FASTMAP;
 		kfree(fmsb);
+		kfree(ai->fm);
 		goto out;
 	}
 
@@ -818,6 +824,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		ubi_err("unknown fastmap format version!");
 		ret = UBI_BAD_FASTMAP;
 		kfree(fmsb);
+		kfree(ai->fm);
 		goto out;
 	}
 
@@ -826,6 +833,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		ubi_err("number of fastmap blocks is invalid");
 		ret = UBI_BAD_FASTMAP;
 		kfree(fmsb);
+		kfree(ai->fm);
 		goto out;
 	}
 
@@ -835,6 +843,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	if (!fm_raw) {
 		ret = -ENOMEM;
 		kfree(fmsb);
+		kfree(ai->fm);
 		goto out;
 	}
 
@@ -842,6 +851,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	if (!ech) {
 		ret = -ENOMEM;
 		kfree(fmsb);
+		kfree(ai->fm);
 		goto free_raw;
 	}
 
@@ -849,6 +859,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	if (!vh) {
 		ret = -ENOMEM;
 		kfree(fmsb);
+		kfree(ai->fm);
 		kfree(ech);
 		goto free_raw;
 	}
@@ -858,6 +869,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 
 		if (ubi_io_is_bad(ubi, pnum)) {
 			ret = UBI_BAD_FASTMAP;
+			kfree(ai->fm);
 			kfree(fmsb);
 			goto free_hdr;
 		}
@@ -869,8 +881,10 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 			if (ret > 0)
 				ret = UBI_BAD_FASTMAP;
 			kfree(fmsb);
+			kfree(ai->fm);
 			goto free_hdr;
-		}
+		} else if (ret == UBI_IO_BITFLIPS)
+			ai->fm->to_be_tortured[i] = 1;
 
 		if (!ubi->image_seq)
 			ubi->image_seq = be32_to_cpu(ech->image_seq);
@@ -878,6 +892,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 		if (be32_to_cpu(ech->image_seq) != ubi->image_seq) {
 			ret = UBI_BAD_FASTMAP;
 			kfree(fmsb);
+			kfree(ai->fm);
 			goto free_hdr;
 		}
 
@@ -886,6 +901,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 			ubi_err("unable to read fastmap block# %i (PEB: %i)",
 				i, pnum);
 			kfree(fmsb);
+			kfree(ai->fm);
 			goto free_hdr;
 		}
 
@@ -893,7 +909,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 			if (be32_to_cpu(vh->vol_id) != UBI_FM_SB_VOLUME_ID) {
 				ret = UBI_BAD_FASTMAP;
 				kfree(fmsb);
-
+				kfree(ai->fm);
 				goto free_hdr;
 			}
 		} else {
@@ -913,6 +929,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 			ubi_err("unable to read fastmap block# %i (PEB: %i)",
 				i, pnum);
 			kfree(fmsb);
+			kfree(ai->fm);
 			goto free_hdr;
 		}
 	}
@@ -926,7 +943,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	if (crc != tmp_crc) {
 		ubi_err("fastmap data CRC is invalid");
 		ret = UBI_BAD_FASTMAP;
-
+		kfree(ai->fm);
 		goto free_hdr;
 	}
 
@@ -936,12 +953,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
 	if (ret) {
 		if (ret > 0)
 			ret = UBI_BAD_FASTMAP;
-		goto free_hdr;
-	}
-
-	ai->fm = kzalloc(sizeof(*ai->fm), GFP_KERNEL);
-	if (!ai->fm) {
-		ret = -ENOMEM;
+		kfree(ai->fm);
 		goto free_hdr;
 	}
 
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index ccd0da7..ba6bfd1 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -214,13 +214,14 @@ struct ubi_volume_desc;
 
 /**
  * struct ubi_fastmap_layout - in-memory fastmap data structure.
- * @peb: PEBs used by the current fastmap
- * @ec: the erase counter of each used PEB
+ * @e: PEBs used by the current fastmap
+ * @to_be_tortured: if non-zero tortured this PEB
  * @size: size of the fastmap in bytes
  * @used_blocks: number of used PEBs
  */
 struct ubi_fastmap_layout {
 	struct ubi_wl_entry *e[UBI_FM_MAX_BLOCKS];
+	int to_be_tortured[UBI_FM_MAX_BLOCKS];
 	size_t size;
 	int used_blocks;
 };
-- 
1.7.6.5




More information about the linux-mtd mailing list