Backport fixes for UBI
cover Backport fixes for UBI
While looking at recent UBI patches I found these two commits that I believe are worth backporting.
We're not using fastmap so I don't care much about the leak there, but reducing wear is always good to take
Thanks!
---
Cheng Ming Lin (1):
mtd: ubi: skip programming unused bits in ubi headers
Liyuan Pang (1):
ubi: fastmap: fix ubi->fm memory leak
drivers/mtd/ubi/attach.c | 4 +++- drivers/mtd/ubi/fastmap-wl.c | 8 +------- drivers/mtd/ubi/io.c | 10 ++++++++++ drivers/mtd/ubi/ubi.h | 12 ++++++++++++ 4 files changed, 26 insertions(+), 8 deletions(-)
---
base-commit: 98c5a5b9f23ede08be1dcd8be0a13b32fbe2b462
change-id: 20260818-ubi-backports-2f5d76dedbed
Best regards,
Signature · 1 line
Dominique Martinet <[email protected]>
PATCH 1/2 mtd: ubi: skip programming unused bits in ubi headers
From: Cheng Ming Lin <[email protected]>
This patch prevents unnecessary programming of bits in ec_hdr and vid_hdr that are not used or read during normal UBI operation. These unused bits are typcially already set to 1 in erased flash and do not need to be explicitly programmed to 0 if they are not used.
Programming such unused areas offers no functional benefit and may result in unnecessary flash wear, reducing the overall lifetime of the device. By skipping these writes, we preserve the flash state as much as possible and minimize wear caused by redundant operations.
This change ensures that only necessary fields are written when preparing UBI headers, improving flash efficiency without affecting functionality.
Additionally, the Kioxia TC58NVG1S3HTA00 datasheet (page 63) also notes that continuous program/erase cycling with a high percentage of '0' bits in the data pattern can accelerate block endurance degradation. This further supports avoiding large 0x00 patterns.
--- drivers/mtd/ubi/io.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/mtd/ubi/io.c +10 -0
@@ -868,6 +868,8 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,return -EROFS ; } +memset ((char *)ec_hdr +UBI_EC_HDR_SIZE ,0xFF , ubi->ec_hdr_alsize -UBI_EC_HDR_SIZE ); + err =ubi_io_write (ubi, ec_hdr, pnum,0 , ubi->ec_hdr_alsize);return err; }
@@ -1150,6 +1152,14 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,return -EROFS ; } +if (ubi->vid_hdr_shift) { +memset ((char *)p,0xFF , ubi->vid_hdr_shift); +memset ((char *)p + ubi->vid_hdr_shift +UBI_VID_HDR_SIZE ,0xFF , + ubi->vid_hdr_alsize - (ubi->vid_hdr_shift +UBI_VID_HDR_SIZE )); + }else { +memset ((char *)p +UBI_VID_HDR_SIZE ,0xFF , ubi->vid_hdr_alsize -UBI_VID_HDR_SIZE ); + } + err =ubi_io_write (ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize);return err;
Signature · 1 line
2.55.0.dirty
Re: [PATCH v6.12.y 1/2] mtd: ubi: skip programming unused bits in ubi headers
Quoted 28 lines · Dominique Martinet
From: Cheng Ming Lin <[email protected]>
This patch prevents unnecessary programming of bits in
ec_hdrandvid_hdrthat are not used or read during normal UBI operation. These unused bits are typcially already set to 1 in erased flash and do not need to be explicitly programmed to 0 if they are not used.Programming such unused areas offers no functional benefit and may result in unnecessary flash wear, reducing the overall lifetime of the device. By skipping these writes, we preserve the flash state as much as possible and minimize wear caused by redundant operations.
This change ensures that only necessary fields are written when preparing UBI headers, improving flash efficiency without affecting functionality.
Additionally, the Kioxia TC58NVG1S3HTA00 datasheet (page 63) also notes that continuous program/erase cycling with a high percentage of '0' bits in the data pattern can accelerate block endurance degradation. This further supports avoiding large
0x00patterns.Signed-off-by Cheng Ming Lin <[email protected]>Reviewed-by Miquel Raynal <[email protected]>Reviewed-by Zhihao Cheng <[email protected]>Signed-off-by Richard Weinberger <[email protected]>(cherry picked from commit 77530d1a78ca5c274e37d6494a965223672630b2)Signed-off-by Dominique Martinet <[email protected]>
Quoted 4 lines
--- drivers/mtd/ubi/io.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
Quoted 29 lines
drivers/mtd/ubi/io.c +10
-0@@ -868,6 +868,8 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,return -EROFS ; } +memset ((char *)ec_hdr +UBI_EC_HDR_SIZE ,0xFF , ubi->ec_hdr_alsize -UBI_EC_HDR_SIZE ); + err =ubi_io_write (ubi, ec_hdr, pnum,0 , ubi->ec_hdr_alsize);return err; }@@ -1150,6 +1152,14 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,return -EROFS ; } +if (ubi->vid_hdr_shift) { +memset ((char *)p,0xFF , ubi->vid_hdr_shift); +memset ((char *)p + ubi->vid_hdr_shift +UBI_VID_HDR_SIZE ,0xFF , + ubi->vid_hdr_alsize - (ubi->vid_hdr_shift +UBI_VID_HDR_SIZE )); + }else { +memset ((char *)p +UBI_VID_HDR_SIZE ,0xFF , ubi->vid_hdr_alsize -UBI_VID_HDR_SIZE ); + } + err =ubi_io_write (ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize);return err;
PATCH 2/2 ubi: fastmap: fix ubi->fm memory leak
In reply to Dominique MartinetFrom: Liyuan Pang <[email protected]>
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
--- drivers/mtd/ubi/attach.c | 4 +++- drivers/mtd/ubi/fastmap-wl.c | 8 +------- drivers/mtd/ubi/ubi.h | 12 ++++++++++++ 3 files changed, 16 insertions(+), 8 deletions(-)
drivers/mtd/ubi/attach.c +3 -1
@@ -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 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) out_vtbl:ubi_free_all_volumes (ubi);vfree (ubi->vtbl); +out_fm: +ubi_free_fastmap (ubi); out_ai:destroy_ai (ai);return err;
drivers/mtd/ubi/fastmap-wl.c +1 -7
@@ -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); }/**
drivers/mtd/ubi/ubi.h +12 -0
@@ -970,10 +970,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 */
Signature · 1 line
2.55.0.dirty
Re: [PATCH v6.12.y 2/2] ubi: fastmap: fix ubi->fm memory leak
Quoted 75 lines · Dominique Martinet
From: Liyuan Pang <[email protected]>
The problem is that
scan_fast()allocate memory forubi->fmand ubi->fm->e[x], but if the following attach process fails inubi_wl_initorubi_read_volume_table, the whole attach process will fail without executingubi_wl_closeto free the memory underubi->fm.Fix this by add a new
ubi_free_fastmapfunction infastmap.cto free the memory allocated for fm.If
SLUB_DEBUGand 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
=================================================================
BUGubi_wl_entry_slab(Tainted: G B O L ): Objects remaining inubi_wl_entry_slabon__kmem_cache_shutdown()
-----------------------------------------------------------------------------Slab
0xffff2fd23a40cd00objects=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/0x400Signed-off-by Liyuan Pang <[email protected]>Reviewed-by Zhihao Cheng <[email protected]>Signed-off-by Richard Weinberger <[email protected]>(cherry picked from commit d133e30aabc7c8eb8206827f8fbe0f3679adb911)Signed-off-by Dominique Martinet <[email protected]>
Quoted 6 lines
--- drivers/mtd/ubi/attach.c | 4 +++- drivers/mtd/ubi/fastmap-wl.c | 8 +------- drivers/mtd/ubi/ubi.h | 12 ++++++++++++ 3 files changed, 16 insertions(+), 8 deletions(-)
Quoted 76 lines
drivers/mtd/ubi/attach.c +3
-1@@ -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 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) out_vtbl:ubi_free_all_volumes (ubi);vfree (ubi->vtbl); +out_fm: +ubi_free_fastmap (ubi); out_ai:destroy_ai (ai);return err;drivers/mtd/ubi/fastmap-wl.c +1
-7@@ -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); }/** drivers/mtd/ubi/ubi.h +12
-0@@ -970,10 +970,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 */
Quoted 2 lines · Dominique Martinet
While looking at recent UBI patches I found these two commits that I believe are worth backporting.
Queued for 6.18 and 6.12, thanks - 6.18 is missing both as well, so it gets them first.
Signature · 2 lines
Thanks, Sasha
Richard Weinberger
maintainer----- Ursprüngliche Mail -----
Quoted 9 lines
Von: "Dominique Martinet" <[email protected]> While looking at recent UBI patches I found these two commits that I believe are worth backporting.
We're not using fastmap so I don't care much about the leak there, but reducing wear is always good to take
Thanks!
Quoted 7 lines
Signed-off-by Dominique Martinet <[email protected]>---
Cheng Ming Lin (1):
mtd: ubi: skip programming unused bits in ubi headersLiyuan Pang (1):
ubi: fastmap: fix ubi->fm memory leak
While porting these back is not wrong, I have a hard time to see how the current stables rules apply here.
"mtd: ubi: skip programming unused bits in ubi headers" does not fix anything. It's a pure optimization for future flashes, UBI worked since ever without this change.
"ubi: fastmap: fix ubi->fm memory leak" fixes a memory leak, yes. But only in a failure path at attach time. Userspace cannot trigger this.
Thanks,
//richard
Richard Weinberger wrote on Wed, Aug 19, 2026 at 12:48:28PM +0200:
Quoted 2 lines
While porting these back is not wrong, I have a hard time to see how the current stables rules apply here.
Thank you for looking into this!
I'm honestly fuzzy on stable backport "rules", but in practice I see all sort of things get in (admitely sometimes new features/refactor just because it makes an actual fix easier to backport, but also quite a few leaks on failures like the second patch and other general improvements), so after noticing someone else submitted 6.12 contiguous read improvements recently[1] so I assumed such backports would be welcome... But ultimately I think it's up to you, so happy to see the patches dropped if you prefer.
[1] https://lore.kernel.org/r/[email protected]
Quoted 3 lines
"mtd: ubi: skip programming unused bits in ubi headers" does not fix anything. It's a pure optimization for future flashes, UBI worked since ever without this change.
I might have misunderstood something about this patch, but while UBI works fine I believe this would increase the longevity of more than just "future flashes"
I've burned out 2 times 1MB (4 erase blocks) from the NAND I have on hand (winbond W25N04LW) using either random data + erase (nandtest) or a patched version writing zeroes + erase, and writing many zeroes failed the erase blocks about 40-50% faster (85 thousands cycles vs 132 thousands until the first erase failure, 121/175 until erase stopped working with many retries)
This obviously is a tiny sample size and not concrete proof, and this patch won't have such a big impact because the area is small, but I believe this patch will still improve the endurance a tiny bit for at least our model, which was the motivation for me to pick this up.
Of course, there's also a chance that something breaks from it so I can perfectly understand if you prefer not to backport it; you're in a much better place than me to draw the line.
Thanks,
Signature · 1 line
Dominique Martinet | Asmadeus