mirror of
https://github.com/torvalds/linux.git
synced 2026-01-12 00:42:35 +08:00
ubi: fastmap: fix ubi->fm memory leak
The problem is that scan_fast() allocate memory for ubi->fm and ubi->fm->e[x], but if the following attach process fails in ubi_wl_init or ubi_read_volume_table, the whole attach process will fail without executing ubi_wl_close to free the memory under ubi->fm. Fix this by add a new ubi_free_fastmap function in fastmap.c to free the memory allocated for fm. If SLUB_DEBUG and KUNIT are enabled, the following warning messages will show: ubi0: detaching mtd0 ubi0: mtd0 is detached ubi0: default fastmap pool size: 200 ubi0: default fastmap WL pool size: 100 ubi0: attaching mtd0 ubi0: attached by fastmap ubi0: fastmap pool size: 200 ubi0: fastmap WL pool size: 100 ubi0 error: ubi_wl_init [ubi]: no enough physical eraseblocks (4, need 203) ubi0 error: ubi_attach_mtd_dev [ubi]: failed to attach mtd0, error -28 UBI error: cannot attach mtd0 ================================================================= BUG ubi_wl_entry_slab (Tainted: G B O L ): Objects remaining in ubi_wl_entry_slab on __kmem_cache_shutdown() ----------------------------------------------------------------------------- Slab 0xffff2fd23a40cd00 objects=22 used=1 fp=0xffff2fd1d0334fd8 flags=0x883fffc010200(slab|head|section=34|node=0|zone=1|lastcpupid=0x7fff) CPU: 0 PID: 5884 Comm: insmod Tainted: G B O L 5.10.0 #1 Hardware name: LS1043A RDB Board (DT) Call trace: dump_backtrace+0x0/0x198 show_stack+0x18/0x28 dump_stack+0xe8/0x15c slab_err+0x94/0xc0 __kmem_cache_shutdown+0x1fc/0x39c kmem_cache_destroy+0x48/0x138 ubi_init+0x1d4/0xf34 [ubi] do_one_initcall+0xb4/0x24c do_init_module+0x4c/0x1dc load_module+0x212c/0x2260 __se_sys_finit_module+0xb4/0xd8 __arm64_sys_finit_module+0x18/0x28 el0_svc_common.constprop.0+0x78/0x1a0 do_el0_svc+0x78/0x90 el0_svc+0x20/0x38 el0_sync_handler+0xf0/0x140 normal+0x3d8/0x400 Object 0xffff2fd1d0334e68 @offset=3688 Allocated in ubi_scan_fastmap+0xf04/0xf40 [ubi] age=80 cpu=0 pid=5884 __slab_alloc.isra.21+0x6c/0xb4 kmem_cache_alloc+0x1e4/0x80c ubi_scan_fastmap+0xf04/0xf40 [ubi] ubi_attach+0x1f0/0x3a8 [ubi] ubi_attach_mtd_dev+0x810/0xbc8 [ubi] ubi_init+0x238/0xf34 [ubi] do_one_initcall+0xb4/0x24c do_init_module+0x4c/0x1dc load_module+0x212c/0x2260 __se_sys_finit_module+0xb4/0xd8 __arm64_sys_finit_module+0x18/0x28 el0_svc_common.constprop.0+0x78/0x1a0 do_el0_svc+0x78/0x90 el0_svc+0x20/0x38 el0_sync_handler+0xf0/0x140 normal+0x3d8/0x400 Link: https://bugzilla.kernel.org/show_bug.cgi?id=220744 Signed-off-by: Liyuan Pang <pangliyuan1@huawei.com> Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com> Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
committed by
Richard Weinberger
parent
77530d1a78
commit
d133e30aab
@@ -1600,7 +1600,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
|
||||
|
||||
err = ubi_read_volume_table(ubi, ai);
|
||||
if (err)
|
||||
goto out_ai;
|
||||
goto out_fm;
|
||||
|
||||
err = ubi_wl_init(ubi, ai);
|
||||
if (err)
|
||||
@@ -1642,6 +1642,8 @@ out_wl:
|
||||
out_vtbl:
|
||||
ubi_free_all_volumes(ubi);
|
||||
vfree(ubi->vtbl);
|
||||
out_fm:
|
||||
ubi_free_fastmap(ubi);
|
||||
out_ai:
|
||||
destroy_ai(ai);
|
||||
return err;
|
||||
|
||||
@@ -530,8 +530,6 @@ int ubi_is_erase_work(struct ubi_work *wrk)
|
||||
|
||||
static void ubi_fastmap_close(struct ubi_device *ubi)
|
||||
{
|
||||
int i;
|
||||
|
||||
return_unused_pool_pebs(ubi, &ubi->fm_pool);
|
||||
return_unused_pool_pebs(ubi, &ubi->fm_wl_pool);
|
||||
|
||||
@@ -540,11 +538,7 @@ static void ubi_fastmap_close(struct ubi_device *ubi)
|
||||
ubi->fm_anchor = NULL;
|
||||
}
|
||||
|
||||
if (ubi->fm) {
|
||||
for (i = 0; i < ubi->fm->used_blocks; i++)
|
||||
kfree(ubi->fm->e[i]);
|
||||
}
|
||||
kfree(ubi->fm);
|
||||
ubi_free_fastmap(ubi);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -969,10 +969,22 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
struct ubi_attach_info *scan_ai);
|
||||
int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count);
|
||||
void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol);
|
||||
static inline void ubi_free_fastmap(struct ubi_device *ubi)
|
||||
{
|
||||
if (ubi->fm) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ubi->fm->used_blocks; i++)
|
||||
kmem_cache_free(ubi_wl_entry_slab, ubi->fm->e[i]);
|
||||
kfree(ubi->fm);
|
||||
ubi->fm = NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; }
|
||||
static inline int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) { return 0; }
|
||||
static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {}
|
||||
static inline void ubi_free_fastmap(struct ubi_device *ubi) { }
|
||||
#endif
|
||||
|
||||
/* block.c */
|
||||
|
||||
Reference in New Issue
Block a user