]>
Commit | Line | Data |
---|---|---|
71fe0565 GKH |
1 | From 2365418879e9abf12ea9def7f9f3caf0dfa7ffb0 Mon Sep 17 00:00:00 2001 |
2 | From: Richard Weinberger <richard@nod.at> | |
3 | Date: Wed, 24 Aug 2016 14:36:13 +0200 | |
4 | Subject: ubi: Deal with interrupted erasures in WL | |
5 | ||
6 | From: Richard Weinberger <richard@nod.at> | |
7 | ||
8 | commit 2365418879e9abf12ea9def7f9f3caf0dfa7ffb0 upstream. | |
9 | ||
10 | When Fastmap is used we can face here an -EBADMSG | |
11 | since Fastmap cannot know about unmaps. | |
12 | If the erasure was interrupted the PEB may show ECC | |
13 | errors and UBI would go to ro-mode as it assumes | |
14 | that the PEB was check during attach time, which is | |
15 | not the case with Fastmap. | |
16 | ||
17 | Fixes: dbb7d2a88d ("UBI: Add fastmap core") | |
18 | Signed-off-by: Richard Weinberger <richard@nod.at> | |
19 | Signed-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; |