[PATCH 08/10] ovl: cache dirty overlayfs' inode
From: Josef Bacik
Date: Tue Oct 27 2026 - 17:11:38 EST
From: Chengguang Xu <cgxu519@xxxxxxxxxxxx>
An overlay inode is dropped with its last reference, dirty or not. Its
upper inode may well have dirty data at that point, and once the overlay
inode is gone nothing says that this data came from this overlay.
Only drop clean inodes. A dirty one stays in the cache until it has been
written back, and is then reclaimed from the lru list. One which was
unlinked is still dropped at once, so that its space is freed.
Signed-off-by: Chengguang Xu <cgxu519@xxxxxxxxxxxx>
[josef: an inode under writeback isn't clean either, no need to look for an
upper inode, rebased, new commit message]
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
fs/overlayfs/super.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 0aec7059e9da..954648d41700 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -364,11 +364,27 @@ static int ovl_write_inode(struct inode *inode, struct writeback_control *wbc)
return ret;
}
+/*
+ * In iput_final(), clean inode will drop directly and dirty inode will
+ * keep in the cache until write back to sync dirty data then add to lru
+ * list to wait reclaim.
+ *
+ * An inode under writeback has its dirty flags cleared, and only I_SYNC pins
+ * it. It is not clean: ovl_write_inode() may be about to mark it dirty again,
+ * which does nothing for an inode which is being freed.
+ */
+static int ovl_drop_inode(struct inode *inode)
+{
+ if (!(inode_state_read(inode) & (I_DIRTY_ALL | I_SYNC)))
+ return 1;
+ return inode_generic_drop(inode);
+}
+
static const struct super_operations ovl_super_operations = {
.alloc_inode = ovl_alloc_inode,
.free_inode = ovl_free_inode,
.destroy_inode = ovl_destroy_inode,
- .drop_inode = inode_just_drop,
+ .drop_inode = ovl_drop_inode,
.put_super = ovl_put_super,
.write_inode = ovl_write_inode,
.sync_fs = ovl_sync_fs,
--
2.55.0