[Concept,12/15] ext4l: Implement iput() to evict deleted inodes

Message ID 20251230234134.906477-13-sjg@u-boot.org
State New
Headers
Series ext4l: Infrastructure and fixes for write support (part K) |

Commit Message

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

Implement iput() to properly handle inode reference counting and
eviction. When the reference count drops to zero and the inode has no
links (i_nlink == 0), call ext4_evict_inode() to free the inode's data
blocks and the inode itself.

This is required for unlink operations to properly free filesystem
resources.

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

 fs/ext4l/ext4_uboot.h |  4 ++--
 fs/ext4l/stub.c       | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+), 2 deletions(-)
  

Patch

diff --git a/fs/ext4l/ext4_uboot.h b/fs/ext4l/ext4_uboot.h
index 5c66e35662d..18ea2b1bcd4 100644
--- a/fs/ext4l/ext4_uboot.h
+++ b/fs/ext4l/ext4_uboot.h
@@ -491,8 +491,8 @@  int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode,
 /* RCU barrier - stub */
 #define rcu_barrier()		do { } while (0)
 
-/* inode/dentry operations - stubs */
-#define iput(inode)		do { } while (0)
+/* inode/dentry operations */
+void iput(struct inode *inode);
 
 /* current task - from linux/sched.h */
 #include <linux/sched.h>
diff --git a/fs/ext4l/stub.c b/fs/ext4l/stub.c
index ce68ec28b20..2b7618df64c 100644
--- a/fs/ext4l/stub.c
+++ b/fs/ext4l/stub.c
@@ -587,6 +587,29 @@  struct dentry *d_make_root(struct inode *inode)
 	return de;
 }
 
+/**
+ * iput() - Release a reference to an inode
+ * @inode: Inode to release
+ *
+ * Decrements the inode reference count. When the reference count reaches
+ * zero and the inode has no links, the inode is evicted (freed).
+ */
+void iput(struct inode *inode)
+{
+	if (!inode)
+		return;
+
+	if (atomic_dec_and_test(&inode->i_count)) {
+		/* Last reference - check if inode should be evicted */
+		if (inode->i_nlink == 0 && inode->i_sb &&
+		    inode->i_sb->s_op && inode->i_sb->s_op->evict_inode) {
+			inode->i_sb->s_op->evict_inode(inode);
+			/* Sync dirty buffers after eviction */
+			bh_cache_sync();
+		}
+	}
+}
+
 /* percpu init rwsem */
 int percpu_init_rwsem(struct percpu_rw_semaphore *sem)
 {