aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/fastmap.c
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2016-08-24 14:36:14 +0200
committerRichard Weinberger <richard@nod.at>2016-10-02 22:54:01 +0200
commit2e8f08deabbc7eefe4c5838aaa6aa9a23a8acf2e (patch)
tree978c8095e114898a898df44014996611a39ddfef /drivers/mtd/ubi/fastmap.c
parentubi: Deal with interrupted erasures in WL (diff)
downloadlinux-dev-2e8f08deabbc7eefe4c5838aaa6aa9a23a8acf2e.tar.xz
linux-dev-2e8f08deabbc7eefe4c5838aaa6aa9a23a8acf2e.zip
ubi: Fix races around ubi_refill_pools()
When writing a new Fastmap the first thing that happens is refilling the pools in memory. At this stage it is possible that new PEBs from the new pools get already claimed and written with data. If this happens before the new Fastmap data structure hits the flash and we face power cut the freshly written PEB will not scanned and unnoticed. Solve the issue by locking the pools until Fastmap is written. Cc: <stable@vger.kernel.org> Fixes: dbb7d2a88d ("UBI: Add fastmap core") Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'drivers/mtd/ubi/fastmap.c')
-rw-r--r--drivers/mtd/ubi/fastmap.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 4adffb893376..8bd468332ec0 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1492,22 +1492,30 @@ int ubi_update_fastmap(struct ubi_device *ubi)
struct ubi_wl_entry *tmp_e;
down_write(&ubi->fm_protect);
+ down_write(&ubi->work_sem);
+ down_write(&ubi->fm_eba_sem);
ubi_refill_pools(ubi);
if (ubi->ro_mode || ubi->fm_disabled) {
+ up_write(&ubi->fm_eba_sem);
+ up_write(&ubi->work_sem);
up_write(&ubi->fm_protect);
return 0;
}
ret = ubi_ensure_anchor_pebs(ubi);
if (ret) {
+ up_write(&ubi->fm_eba_sem);
+ up_write(&ubi->work_sem);
up_write(&ubi->fm_protect);
return ret;
}
new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
if (!new_fm) {
+ up_write(&ubi->fm_eba_sem);
+ up_write(&ubi->work_sem);
up_write(&ubi->fm_protect);
return -ENOMEM;
}
@@ -1616,16 +1624,14 @@ int ubi_update_fastmap(struct ubi_device *ubi)
new_fm->e[0] = tmp_e;
}
- down_write(&ubi->work_sem);
- down_write(&ubi->fm_eba_sem);
ret = ubi_write_fastmap(ubi, new_fm);
- up_write(&ubi->fm_eba_sem);
- up_write(&ubi->work_sem);
if (ret)
goto err;
out_unlock:
+ up_write(&ubi->fm_eba_sem);
+ up_write(&ubi->work_sem);
up_write(&ubi->fm_protect);
kfree(old_fm);
return ret;