mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Teresa Remmet <t.remmet@phytec.de>
To: barebox@lists.infradead.org
Subject: [PATCH v2 35/62] UBI: Fastmap: Rework fastmap error paths
Date: Fri, 27 May 2016 09:44:28 +0200	[thread overview]
Message-ID: <1464335095-35180-36-git-send-email-t.remmet@phytec.de> (raw)
In-Reply-To: <1464335095-35180-1-git-send-email-t.remmet@phytec.de>

From: Richard Weinberger <richard@nod.at>

If UBI is unable to write the fastmap to the device
we have make sure that upon next attach UBI will fall
back to scanning mode.
In case we cannot ensure that they only thing we can do
is falling back to read-only mode.

The current error handling code is not powercut proof.
It could happen that a powercut while invalidating would
lead to a state where an too old fastmap could be used upon
attach.
This patch addresses the issue by writing a fake fastmap
super block to a fresh PEB instead of reerasing the existing one.
The fake fastmap super block will UBI case to do a full scan.

Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
 drivers/mtd/ubi/fastmap.c | 162 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 114 insertions(+), 48 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index de395d5..7808744 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1309,31 +1309,87 @@ out:
 /**
  * invalidate_fastmap - destroys a fastmap.
  * @ubi: UBI device object
- * @fm: the fastmap to be destroyed
  *
+ * This function ensures that upon next UBI attach a full scan
+ * is issued. We need this if UBI is about to write a new fastmap
+ * but is unable to do so. In this case we have two options:
+ * a) Make sure that the current fastmap will not be usued upon
+ * attach time and contine or b) fall back to RO mode to have the
+ * current fastmap in a valid state.
  * Returns 0 on success, < 0 indicates an internal error.
  */
-static int invalidate_fastmap(struct ubi_device *ubi,
-			      struct ubi_fastmap_layout *fm)
+static int invalidate_fastmap(struct ubi_device *ubi)
 {
 	int ret;
-	struct ubi_vid_hdr *vh;
+	struct ubi_fastmap_layout *fm;
+	struct ubi_wl_entry *e;
+	struct ubi_vid_hdr *vh = NULL;
 
-	ret = erase_block(ubi, fm->e[0]->pnum);
-	if (ret < 0)
-		return ret;
+	if (!ubi->fm)
+		return 0;
+
+	ubi->fm = NULL;
+
+	ret = -ENOMEM;
+	fm = kzalloc(sizeof(*fm), GFP_KERNEL);
+	if (!fm)
+		goto out;
 
 	vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID);
 	if (!vh)
-		return -ENOMEM;
+		goto out_free_fm;
+
+	ret = -ENOSPC;
+	e = ubi_wl_get_fm_peb(ubi, 1);
+	if (!e)
+		goto out_free_fm;
 
-	/* deleting the current fastmap SB is not enough, an old SB may exist,
-	 * so create a (corrupted) SB such that fastmap will find it and fall
-	 * back to scanning mode in any case */
+	/*
+	 * Create fake fastmap such that UBI will fall back
+	 * to scanning mode.
+	 */
 	vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-	ret = ubi_io_write_vid_hdr(ubi, fm->e[0]->pnum, vh);
+	ret = ubi_io_write_vid_hdr(ubi, e->pnum, vh);
+	if (ret < 0) {
+		ubi_wl_put_fm_peb(ubi, e, 0, 0);
+		goto out_free_fm;
+	}
 
+	fm->used_blocks = 1;
+	fm->e[0] = e;
+
+	ubi->fm = fm;
+
+out:
+	ubi_free_vid_hdr(ubi, vh);
 	return ret;
+
+out_free_fm:
+	kfree(fm);
+	goto out;
+}
+
+/**
+ * return_fm_pebs - returns all PEBs used by a fastmap back to the
+ * WL sub-system.
+ * @ubi: UBI device object
+ * @fm: fastmap layout object
+ */
+static void return_fm_pebs(struct ubi_device *ubi,
+			   struct ubi_fastmap_layout *fm)
+{
+	int i;
+
+	if (!fm)
+		return;
+
+	for (i = 0; i < fm->used_blocks; i++) {
+		if (fm->e[i]) {
+			ubi_wl_put_fm_peb(ubi, fm->e[i], i,
+					  fm->to_be_tortured[i]);
+			fm->e[i] = NULL;
+		}
+	}
 }
 
 /**
@@ -1345,7 +1401,7 @@ static int invalidate_fastmap(struct ubi_device *ubi,
  */
 int ubi_update_fastmap(struct ubi_device *ubi)
 {
-	int ret, i;
+	int ret, i, j;
 	struct ubi_fastmap_layout *new_fm, *old_fm;
 	struct ubi_wl_entry *tmp_e;
 
@@ -1375,34 +1431,40 @@ int ubi_update_fastmap(struct ubi_device *ubi)
 	for (i = 1; i < new_fm->used_blocks; i++) {
 		tmp_e = ubi_wl_get_fm_peb(ubi, 0);
 
-		if (!tmp_e && !old_fm) {
-			int j;
-			ubi_err(ubi, "could not get any free erase block");
-
-			for (j = 1; j < i; j++)
-				ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0);
-
-			ret = -ENOSPC;
-			goto err;
-		} else if (!tmp_e && old_fm && old_fm->e[i]) {
-			ret = erase_block(ubi, old_fm->e[i]->pnum);
-			if (ret < 0) {
-				int j;
-
-				for (j = 1; j < i; j++)
-					ubi_wl_put_fm_peb(ubi, new_fm->e[j],
-							  j, 0);
+		if (!tmp_e) {
+			if (old_fm && old_fm->e[i]) {
+				ret = erase_block(ubi, old_fm->e[i]->pnum);
+				if (ret < 0) {
+					ubi_err(ubi, "could not erase old fastmap PEB");
+
+					for (j = 1; j < i; j++) {
+						ubi_wl_put_fm_peb(ubi, new_fm->e[j],
+								  j, 0);
+						new_fm->e[j] = NULL;
+					}
+					goto err;
+				}
+				new_fm->e[i] = old_fm->e[i];
+				old_fm->e[i] = NULL;
+			} else {
+				ubi_err(ubi, "could not get any free erase block");
+
+				for (j = 1; j < i; j++) {
+					ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0);
+					new_fm->e[j] = NULL;
+				}
 
-				ubi_err(ubi, "could not erase old fastmap PEB");
+				ret = -ENOSPC;
 				goto err;
 			}
-			new_fm->e[i] = old_fm->e[i];
 		} else {
 			new_fm->e[i] = tmp_e;
 
-			if (old_fm && old_fm->e[i])
+			if (old_fm && old_fm->e[i]) {
 				ubi_wl_put_fm_peb(ubi, old_fm->e[i], i,
 						  old_fm->to_be_tortured[i]);
+				old_fm->e[i] = NULL;
+			}
 		}
 	}
 
@@ -1410,6 +1472,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
 		for (i = new_fm->used_blocks; i < old_fm->used_blocks; i++) {
 			ubi_wl_put_fm_peb(ubi, old_fm->e[i], i,
 					  old_fm->to_be_tortured[i]);
+			old_fm->e[i] = NULL;
 		}
 	}
 
@@ -1420,29 +1483,33 @@ int ubi_update_fastmap(struct ubi_device *ubi)
 		if (!tmp_e) {
 			ret = erase_block(ubi, old_fm->e[0]->pnum);
 			if (ret < 0) {
-				int i;
 				ubi_err(ubi, "could not erase old anchor PEB");
 
-				for (i = 1; i < new_fm->used_blocks; i++)
+				for (i = 1; i < new_fm->used_blocks; i++) {
 					ubi_wl_put_fm_peb(ubi, new_fm->e[i],
 							  i, 0);
+					new_fm->e[i] = NULL;
+				}
 				goto err;
 			}
 			new_fm->e[0] = old_fm->e[0];
 			new_fm->e[0]->ec = ret;
+			old_fm->e[0] = NULL;
 		} else {
 			/* we've got a new anchor PEB, return the old one */
 			ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0,
 					  old_fm->to_be_tortured[0]);
 			new_fm->e[0] = tmp_e;
+			old_fm->e[0] = NULL;
 		}
 	} else {
 		if (!tmp_e) {
-			int i;
 			ubi_err(ubi, "could not find any anchor PEB");
 
-			for (i = 1; i < new_fm->used_blocks; i++)
+			for (i = 1; i < new_fm->used_blocks; i++) {
 				ubi_wl_put_fm_peb(ubi, new_fm->e[i], i, 0);
+				new_fm->e[i] = NULL;
+			}
 
 			ret = -ENOSPC;
 			goto err;
@@ -1460,19 +1527,18 @@ out_unlock:
 	return ret;
 
 err:
-	kfree(new_fm);
-
 	ubi_warn(ubi, "Unable to write new fastmap, err=%i", ret);
 
-	ret = 0;
-	if (old_fm) {
-		ret = invalidate_fastmap(ubi, old_fm);
-		if (ret < 0) {
-			ubi_err(ubi, "Unable to invalidiate current fastmap!");
-			ubi_ro_mode(ubi);
-		}
-		else if (ret)
-			ret = 0;
+	ret = invalidate_fastmap(ubi);
+	if (ret < 0) {
+		ubi_err(ubi, "Unable to invalidiate current fastmap!");
+		ubi_ro_mode(ubi);
+	} else {
+		return_fm_pebs(ubi, old_fm);
+		return_fm_pebs(ubi, new_fm);
+		ret = 0;
 	}
+
+	kfree(new_fm);
 	goto out_unlock;
 }
-- 
1.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2016-05-27  7:46 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-27  7:43 [PATCH v2 00/62] Update UBI Teresa Remmet
2016-05-27  7:43 ` [PATCH v2 01/62] UBI: add missing kmem_cache_free() in process_pool_aeb error path Teresa Remmet
2016-05-27  7:43 ` [PATCH v2 02/62] UBI: Improve comment on work_sem Teresa Remmet
2016-05-27  7:43 ` [PATCH v2 03/62] UBI: ubi_eba_read_leb: Remove in vain variable assignment Teresa Remmet
2016-05-27  7:43 ` [PATCH v2 04/62] UBI: wl: Rename cancel flag to shutdown Teresa Remmet
2016-05-27  7:43 ` [PATCH v2 05/62] UBI: Fix trivial typo in __schedule_ubi_work Teresa Remmet
2016-05-27  7:43 ` [PATCH v2 06/62] UBI: Fastmap: Calc fastmap size correctly Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 07/62] UBI: Extend UBI layer debug/messaging capabilities Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 08/62] UBI: vtbl: Use ubi_eba_atomic_leb_change() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 09/62] UBI: Fix double free after do_sync_erase() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 10/62] UBI: Fix invalid vfree() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 11/62] UBI: extend UBI layer debug/messaging capabilities - cosmetics Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 12/62] UBI: clean-up printing helpers Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 13/62] UBI: do propagate positive error codes up Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 14/62] UBI: Fastmap: Care about the protection queue Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 15/62] UBI: fix missing brace control flow Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 16/62] UBI: account for bitflips in both the VID header and data Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 17/62] UBI: fix out of bounds write Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 18/62] UBI: initialize LEB number variable Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 19/62] UBI: align comment for readability Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 20/62] UBI: Split __wl_get_peb() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 21/62] UBI: Fastmap: Make ubi_refill_pools() fair Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 22/62] UBI: Fastmap: Don't allocate new ubi_wl_entry objects Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 23/62] UBI: Fastmap: Fix memory leaks while closing the WL sub-system Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 24/62] UBI: Fastmap: Notify user in case of an ubi_update_fastmap() failure Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 25/62] UBI: Fastmap: Wrap fastmap specific function in a ifdef Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 26/62] UBI: Fastmap: Fix fastmap usage in ubi_volume_notify() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 27/62] UBI: Fastmap: Fix race in ubi_eba_atomic_leb_change() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 28/62] UBI: Fastmap: Remove bogus ubi_assert() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 29/62] UBI: Fastmap: Remove eba_orphans logic Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 30/62] UBI: Fastmap: Switch to ro mode if invalidate_fastmap() fails Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 31/62] UBI: Fastmap: Make WL pool size 50% of user pool size Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 32/62] UBI: Fastmap: Fix leb_count unbalance Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 33/62] UBI: Fastmap: Set used_ebs only for static volumes Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 34/62] UBI: Fastmap: Prepare for variable sized fastmaps Teresa Remmet
2016-05-27  7:44 ` Teresa Remmet [this message]
2016-05-27  7:44 ` [PATCH v2 36/62] UBI: Fix stale pointers in ubi->lookuptbl Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 37/62] UBI: Move fastmap specific functions out of wl.c Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 38/62] UBI: Add accessor functions for WL data structures Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 39/62] UBI: Fastmap: Wire up WL accessor functions Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 40/62] UBI: Fastmap: Introduce ubi_fastmap_init() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 41/62] UBI: Fastmap: Introduce may_reserve_for_fm() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 42/62] UBI: Fastmap: Remove is_fm_block() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 43/62] UBI: Fastmap: Fall back to scanning mode after ECC error Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 44/62] UBI: Fastmap: Use max() to get the larger value Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 45/62] UBI: Fastmap: Remove unnecessary `\' Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 46/62] UBI: Fastmap: Rename variables to make them meaningful Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 47/62] UBI: Init vol->reserved_pebs by assignment Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 48/62] UBI: Fastmap: Do not add vol if it already exists Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 49/62] UBI: add a helper function for updatting on-flash layout volumes Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 50/62] UBI: Remove unnecessary `\' Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 51/62] UBI: Validate data_size Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 52/62] UBI: return ENOSPC if no enough space available Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 53/62] UBI: Fastmap: Simplify expression Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 54/62] UBI: Fix typo in comment Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 55/62] UBI: Fix debug message Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 56/62] UBI: Fastmap: Fix PEB array type Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 57/62] UBI: fix use of "VID" vs. "EC" in header self-check Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 58/62] mtd: ubi: fixup error correction in do_sync_erase() Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 59/62] mtd: ubi: don't leak e if schedule_erase() fails Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 60/62] mtd: ubi: wl: avoid erasing a PEB which is empty Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 61/62] ubi: Fix out of bounds write in volume update code Teresa Remmet
2016-05-27  7:44 ` [PATCH v2 62/62] mtd: UBI: Remove ubi_free_fastmap Teresa Remmet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1464335095-35180-36-git-send-email-t.remmet@phytec.de \
    --to=t.remmet@phytec.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox