mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
ubi: fastmap: wl: Schedule fm_work if wear-leveling pool is empty
Since commit14072ee33d("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:14072ee33d("ubi: fastmap: Check wl_pool for free peb before wear leveling") Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
committed by
Richard Weinberger
parent
d610020f03
commit
c4595fe394
@@ -346,14 +346,27 @@ out:
|
||||
* WL sub-system.
|
||||
*
|
||||
* @ubi: UBI device description object
|
||||
* @need_fill: whether to fill wear-leveling pool when no PEBs are found
|
||||
*/
|
||||
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
|
||||
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
|
||||
bool need_fill)
|
||||
{
|
||||
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
|
||||
int pnum;
|
||||
|
||||
if (pool->used == pool->size)
|
||||
if (pool->used == pool->size) {
|
||||
if (need_fill && !ubi->fm_work_scheduled) {
|
||||
/*
|
||||
* We cannot update the fastmap here because this
|
||||
* function is called in atomic context.
|
||||
* Let's fail here and refill/update it as soon as
|
||||
* possible.
|
||||
*/
|
||||
ubi->fm_work_scheduled = 1;
|
||||
schedule_work(&ubi->fm_work);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pnum = pool->pebs[pool->used];
|
||||
return ubi->lookuptbl[pnum];
|
||||
@@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
|
||||
if (!ubi->used.rb_node)
|
||||
return false;
|
||||
|
||||
e = next_peb_for_wl(ubi);
|
||||
e = next_peb_for_wl(ubi, false);
|
||||
if (!e) {
|
||||
if (!ubi->free.rb_node)
|
||||
return false;
|
||||
|
||||
@@ -683,7 +683,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
||||
ubi_assert(!ubi->move_to_put);
|
||||
|
||||
#ifdef CONFIG_MTD_UBI_FASTMAP
|
||||
if (!next_peb_for_wl(ubi) ||
|
||||
if (!next_peb_for_wl(ubi, true) ||
|
||||
#else
|
||||
if (!ubi->free.rb_node ||
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
static void update_fastmap_work_fn(struct work_struct *wrk);
|
||||
static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
|
||||
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
|
||||
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi);
|
||||
static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
|
||||
bool need_fill);
|
||||
static bool need_wear_leveling(struct ubi_device *ubi);
|
||||
static void ubi_fastmap_close(struct ubi_device *ubi);
|
||||
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
|
||||
|
||||
Reference in New Issue
Block a user