[PATCH v2 1/2] ceph: mark the superblock active after mounting

From: Xiubo Li via B4 Relay

Date: Wed Aug 26 2026 - 01:24:22 EST


From: Xiubo Li <xiubo.li@xxxxxxxxx>

ceph_get_tree() calls sget_fc() directly and so never goes through
vfs_get_super(), which is what sets SB_ACTIVE after fill_super for
filesystems that use it. Before commit 82995cc6c5ae ("libceph, rbd,
ceph: convert to use the new mount API") the flag used to be set by
get_sb_nodev(), which did this for ceph, but the conversion dropped it.

SB_ACTIVE is required for iput_final() to retain an inode on the
inode LRU instead of evicting it once its last reference goes away.
This has gone unnoticed because ceph sets inode_just_drop() for
->drop_inode, which always asks for eviction, so the retain branch in
iput_final() was never reachable. The next patch makes ->drop_inode()
able to retain inodes, and that needs the flag to actually work.

Set it once the mount is up, like nfs_get_tree() does.

Fixes: 82995cc6c5ae ("libceph, rbd, ceph: convert to use the new mount API")
Signed-off-by: Xiubo Li <xiubo.li@xxxxxxxxx>
---
fs/ceph/super.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 518ee63d55fb..6573285d704a 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -1381,6 +1381,15 @@ static int ceph_get_tree(struct fs_context *fc)
doutc(fsc->client, "root %p inode %p ino %llx.%llx\n", res,
d_inode(res), ceph_vinop(d_inode(res)));
fc->root = fsc->sb->s_root;
+
+ /*
+ * The mount is up. sget_fc() leaves SB_ACTIVE unset, and, unlike
+ * filesystems that go through vfs_get_super(), nothing else sets
+ * it here, so iput_final() would always evict an inode whose
+ * ->drop_inode() asks to retain it. Set it like nfs_get_tree()
+ * does.
+ */
+ sb->s_flags |= SB_ACTIVE;
return 0;

out_splat:

--
2.53.0