Skip to content

Commit

Permalink
ubi: wl: Put source PEB into correct list if trying locking LEB failed
Browse files Browse the repository at this point in the history
commit d610020 upstream.

During wear-leveing work, the source PEB will be moved into scrub list
when source LEB cannot be locked in ubi_eba_copy_leb(), which is wrong
for non-scrub type source PEB. The problem could bring extra and
ineffective wear-leveing jobs, which makes more or less negative effects
for the life time of flash. Specifically, the process is divided 2 steps:
1. wear_leveling_worker // generate false scrub type PEB
     ubi_eba_copy_leb // MOVE_RETRY is returned
       leb_write_trylock // trylock failed
     scrubbing = 1;
     e1 is put into ubi->scrub
2. wear_leveling_worker // schedule false scrub type PEB for wl
     scrubbing = 1
     e1 = rb_entry(rb_first(&ubi->scrub))

The problem can be reproduced easily by running fsstress on a small
UBIFS partition(<64M, simulated by nandsim) for 5~10mins
(CONFIG_MTD_UBI_FASTMAP=y,CONFIG_MTD_UBI_WL_THRESHOLD=50). Following
message is shown:
 ubi0: scrubbed PEB 66 (LEB 0:10), data moved to PEB 165

Since scrub type source PEB has set variable scrubbing as '1', and
variable scrubbing is checked before variable keep, so the problem can
be fixed by setting keep variable as 1 directly if the source LEB cannot
be locked.

Fixes: e801e12 ("UBI: fix missing scrub when there is a bit-flip")
CC: [email protected]
Signed-off-by: Zhihao Cheng <[email protected]>
Signed-off-by: Richard Weinberger <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Zhihao Cheng authored and gregkh committed Dec 9, 2024
1 parent de70a7e commit 5e1feaf
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion drivers/mtd/ubi/wl.c
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
goto out_not_moved;
}
if (err == MOVE_RETRY) {
scrubbing = 1;
/*
* For source PEB:
* 1. The scrubbing is set for scrub type PEB, it will
* be put back into ubi->scrub list.
* 2. Non-scrub type PEB will be put back into ubi->used
* list.
*/
keep = 1;
dst_leb_clean = 1;
goto out_not_moved;
}
Expand Down

0 comments on commit 5e1feaf

Please sign in to comment.