From 5ef4414f4bc26a19cfd5cd11aee9697a863e4d51 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 19 Aug 2013 08:48:12 +0200 Subject: UBI: Fix PEB leak in wear_leveling_worker() get_peb_for_wl() removes the PEB from the free list. If the WL subsystem detects that no wear leveling is needed it cancels the operation and drops the gained PEB. In this case we have to put the PEB back into the free list. This issue was introduced with commit ed4b7021c (UBI: remove PEB from free tree in get_peb_for_wl()). Cc: # 3.7.x Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 5df49d3..c95bfb1 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1069,6 +1069,9 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD)) { dbg_wl("no WL needed: min used EC %d, max free EC %d", e1->ec, e2->ec); + + /* Give the unused PEB back */ + wl_tree_add(e2, &ubi->free); goto out_cancel; } self_check_in_wl_tree(ubi, e1, &ubi->used); -- cgit v0.10.2 From 8930fa500f55215f0211db9b78255e727ac3f282 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 19 Aug 2013 22:31:49 +0200 Subject: UBI: Fix invalidate_fastmap() Onging tests uncovered that invalidate_fastmap() is broken. It must not call ubi_wl_put_fm_peb() because all PEBs used by the old fastmap have already been put back. Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 1542751..f5aa4b0 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1343,7 +1343,7 @@ out: static int invalidate_fastmap(struct ubi_device *ubi, struct ubi_fastmap_layout *fm) { - int ret, i; + int ret; struct ubi_vid_hdr *vh; ret = erase_block(ubi, fm->e[0]->pnum); @@ -1360,9 +1360,6 @@ static int invalidate_fastmap(struct ubi_device *ubi, vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); ret = ubi_io_write_vid_hdr(ubi, fm->e[0]->pnum, vh); - for (i = 0; i < fm->used_blocks; i++) - ubi_wl_put_fm_peb(ubi, fm->e[i], i, fm->to_be_tortured[i]); - return ret; } -- cgit v0.10.2