[Concept,13/14] linux: ext4l: Make cache init/exit functions reentrant for U-Boot

Message ID 20251230205157.3383926-14-sjg@u-boot.org
State New
Headers
Series ext4l: Linux adaptation patches for ext4 write support |

Commit Message

Simon Glass Dec. 30, 2025, 8:51 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

In U-Boot, filesystems may be mounted and unmounted multiple times in a
single session. The ext4 cache initialization functions would fail on
subsequent mounts because the caches were already initialized but pointers
were not reset on exit.

Add early return checks in init functions when already initialized, and
reset cache pointers to NULL in exit functions to allow clean
reinitialization.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 fs/ext4l/block_validity.c | 10 ++++++++++
 fs/ext4l/extents_status.c |  6 ++++++
 fs/ext4l/mballoc.c        | 13 +++++++++++++
 3 files changed, 29 insertions(+)
  

Patch

diff --git a/fs/ext4l/block_validity.c b/fs/ext4l/block_validity.c
index bff72dcd27c..f110d7ef4c7 100644
--- a/fs/ext4l/block_validity.c
+++ b/fs/ext4l/block_validity.c
@@ -23,6 +23,12 @@  static struct kmem_cache *ext4_system_zone_cachep;
 
 int __init ext4_init_system_zone(void)
 {
+#ifdef __UBOOT__
+	/* Already initialized - skip in multiple mount scenarios */
+	if (ext4_system_zone_cachep)
+		return 0;
+#endif
+
 	ext4_system_zone_cachep = KMEM_CACHE(ext4_system_zone, 0);
 	if (ext4_system_zone_cachep == NULL)
 		return -ENOMEM;
@@ -33,6 +39,10 @@  void ext4_exit_system_zone(void)
 {
 	rcu_barrier();
 	kmem_cache_destroy(ext4_system_zone_cachep);
+#ifdef __UBOOT__
+	/* Reset pointer for clean reinitialization */
+	ext4_system_zone_cachep = NULL;
+#endif
 }
 
 static inline int can_merge(struct ext4_system_zone *entry1,
diff --git a/fs/ext4l/extents_status.c b/fs/ext4l/extents_status.c
index a3ab26624e7..f557c7c23c2 100644
--- a/fs/ext4l/extents_status.c
+++ b/fs/ext4l/extents_status.c
@@ -189,6 +189,12 @@  static int __revise_pending(struct inode *inode, ext4_lblk_t lblk,
 
 int __init ext4_init_es(void)
 {
+#ifdef __UBOOT__
+	/* Already initialized - skip in multiple mount scenarios */
+	if (ext4_es_cachep)
+		return 0;
+#endif
+
 	ext4_es_cachep = KMEM_CACHE(extent_status, SLAB_RECLAIM_ACCOUNT);
 	if (ext4_es_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/ext4l/mballoc.c b/fs/ext4l/mballoc.c
index 1d44d9b5cb6..47863efd1cb 100644
--- a/fs/ext4l/mballoc.c
+++ b/fs/ext4l/mballoc.c
@@ -4008,6 +4008,12 @@  void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid)
 
 int __init ext4_init_mballoc(void)
 {
+#ifdef __UBOOT__
+	/* Already initialized - skip in multiple mount scenarios */
+	if (ext4_pspace_cachep)
+		return 0;
+#endif
+
 	ext4_pspace_cachep = KMEM_CACHE(ext4_prealloc_space,
 					SLAB_RECLAIM_ACCOUNT);
 	if (ext4_pspace_cachep == NULL)
@@ -4044,6 +4050,13 @@  void ext4_exit_mballoc(void)
 	kmem_cache_destroy(ext4_ac_cachep);
 	kmem_cache_destroy(ext4_free_data_cachep);
 	ext4_groupinfo_destroy_slabs();
+
+#ifdef __UBOOT__
+	/* Reset pointers for clean reinitialization */
+	ext4_pspace_cachep = NULL;
+	ext4_ac_cachep = NULL;
+	ext4_free_data_cachep = NULL;
+#endif
 }
 
 #define EXT4_MB_BITMAP_MARKED_CHECK 0x0001