]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.8.5/ubi-deal-with-interrupted-erasures-in-wl.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.8.5 / ubi-deal-with-interrupted-erasures-in-wl.patch
CommitLineData
71fe0565
GKH
1From 2365418879e9abf12ea9def7f9f3caf0dfa7ffb0 Mon Sep 17 00:00:00 2001
2From: Richard Weinberger <richard@nod.at>
3Date: Wed, 24 Aug 2016 14:36:13 +0200
4Subject: ubi: Deal with interrupted erasures in WL
5
6From: Richard Weinberger <richard@nod.at>
7
8commit 2365418879e9abf12ea9def7f9f3caf0dfa7ffb0 upstream.
9
10When Fastmap is used we can face here an -EBADMSG
11since Fastmap cannot know about unmaps.
12If the erasure was interrupted the PEB may show ECC
13errors and UBI would go to ro-mode as it assumes
14that the PEB was check during attach time, which is
15not the case with Fastmap.
16
17Fixes: dbb7d2a88d ("UBI: Add fastmap core")
18Signed-off-by: Richard Weinberger <richard@nod.at>
19Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20
21---
22 drivers/mtd/ubi/wl.c | 21 +++++++++++++++++++--
23 1 file changed, 19 insertions(+), 2 deletions(-)
24
25--- a/drivers/mtd/ubi/wl.c
26+++ b/drivers/mtd/ubi/wl.c
27@@ -644,7 +644,7 @@ static int wear_leveling_worker(struct u
28 int shutdown)
29 {
30 int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
31- int vol_id = -1, lnum = -1;
32+ int erase = 0, keep = 0, vol_id = -1, lnum = -1;
33 #ifdef CONFIG_MTD_UBI_FASTMAP
34 int anchor = wrk->anchor;
35 #endif
36@@ -780,6 +780,16 @@ static int wear_leveling_worker(struct u
37 e1->pnum);
38 scrubbing = 1;
39 goto out_not_moved;
40+ } else if (ubi->fast_attach && err == UBI_IO_BAD_HDR_EBADMSG) {
41+ /*
42+ * While a full scan would detect interrupted erasures
43+ * at attach time we can face them here when attached from
44+ * Fastmap.
45+ */
46+ dbg_wl("PEB %d has ECC errors, maybe from an interrupted erasure",
47+ e1->pnum);
48+ erase = 1;
49+ goto out_not_moved;
50 }
51
52 ubi_err(ubi, "error %d while reading VID header from PEB %d",
53@@ -815,6 +825,7 @@ static int wear_leveling_worker(struct u
54 * Target PEB had bit-flips or write error - torture it.
55 */
56 torture = 1;
57+ keep = 1;
58 goto out_not_moved;
59 }
60
61@@ -901,7 +912,7 @@ out_not_moved:
62 ubi->erroneous_peb_count += 1;
63 } else if (scrubbing)
64 wl_tree_add(e1, &ubi->scrub);
65- else
66+ else if (keep)
67 wl_tree_add(e1, &ubi->used);
68 if (dst_leb_clean) {
69 wl_tree_add(e2, &ubi->free);
70@@ -921,6 +932,12 @@ out_not_moved:
71 if (err)
72 goto out_ro;
73 }
74+
75+ if (erase) {
76+ err = do_sync_erase(ubi, e1, vol_id, lnum, 1);
77+ if (err)
78+ goto out_ro;
79+ }
80
81 mutex_unlock(&ubi->move_mutex);
82 return 0;