Skip to content

Commit c4595fe

Browse files
Zhihao Chengrichardweinberger
authored andcommitted
ubi: fastmap: wl: Schedule fm_work if wear-leveling pool is empty
Since commit 14072ee ("ubi: fastmap: Check wl_pool for free peb before wear leveling"), wear_leveling_worker() won't schedule fm_work if wear-leveling pool is empty, which could temporarily disable the wear-leveling until the fastmap is updated(eg. pool becomes empty). Fix it by scheduling fm_work if wl_pool is empty during wear-leveing. Fixes: 14072ee ("ubi: fastmap: Check wl_pool for free peb before wear leveling") Signed-off-by: Zhihao Cheng <[email protected]> Signed-off-by: Richard Weinberger <[email protected]>
1 parent d610020 commit c4595fe

File tree

3 files changed

+19
-5
lines changed

3 files changed

+19
-5
lines changed

drivers/mtd/ubi/fastmap-wl.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,27 @@ int ubi_wl_get_peb(struct ubi_device *ubi)
346346
* WL sub-system.
347347
*
348348
* @ubi: UBI device description object
349+
* @need_fill: whether to fill wear-leveling pool when no PEBs are found
349350
*/
350-
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
351+
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
352+
bool need_fill)
351353
{
352354
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
353355
int pnum;
354356

355-
if (pool->used == pool->size)
357+
if (pool->used == pool->size) {
358+
if (need_fill && !ubi->fm_work_scheduled) {
359+
/*
360+
* We cannot update the fastmap here because this
361+
* function is called in atomic context.
362+
* Let's fail here and refill/update it as soon as
363+
* possible.
364+
*/
365+
ubi->fm_work_scheduled = 1;
366+
schedule_work(&ubi->fm_work);
367+
}
356368
return NULL;
369+
}
357370

358371
pnum = pool->pebs[pool->used];
359372
return ubi->lookuptbl[pnum];
@@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
375388
if (!ubi->used.rb_node)
376389
return false;
377390

378-
e = next_peb_for_wl(ubi);
391+
e = next_peb_for_wl(ubi, false);
379392
if (!e) {
380393
if (!ubi->free.rb_node)
381394
return false;

drivers/mtd/ubi/wl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
683683
ubi_assert(!ubi->move_to_put);
684684

685685
#ifdef CONFIG_MTD_UBI_FASTMAP
686-
if (!next_peb_for_wl(ubi) ||
686+
if (!next_peb_for_wl(ubi, true) ||
687687
#else
688688
if (!ubi->free.rb_node ||
689689
#endif

drivers/mtd/ubi/wl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
static void update_fastmap_work_fn(struct work_struct *wrk);
66
static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
77
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
8-
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi);
8+
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
9+
bool need_fill);
910
static bool need_wear_leveling(struct ubi_device *ubi);
1011
static void ubi_fastmap_close(struct ubi_device *ubi);
1112
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)

0 commit comments

Comments
 (0)