From: Al Viro <viro@zeniv.linux.org.uk>
To: linux-fsdevel@vger.kernel.org
Cc: linux-nfs@vger.kernel.org, Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>,
David Howells <dhowells@redhat.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>
Subject: [RFC][PATCH] get rid of weirdness around NFS dummy root dentries
Date: Sat, 24 Jan 2026 19:58:33 +0000 [thread overview]
Message-ID: <20260124195833.GN3183987@ZenIV> (raw)
These days (starting from 2013, actually) dcache_shrink_for_umount() is not
bothered by having ->s_root spliced onto one of the secondary trees, so the reason
for having a weird alias for root directory (manually removed from the alias list
of directory inode, which violates all kinds of assumptions) no longer applies.
Just use the dentry we are about to return as ->s_root, if it hasn't been
set already. And don't bother with manual security_d_instantiate(), while we are
at it - d_obtain_root() has already done that.
NOTE: if root of the first mount does get spliced onto the bigger subtree
of subsequent mount, it will keep the resulting chain of ancestors pinned in dcache
for as long as any of mounts exist. That won't affect the "is the filesystem busy"
logics, though; just that after
mount foo:/bar/baz/barf /path1
mount foo:/bar/ /path2
ls /path2/baz/barf
umount /path1
we'll get the dentries of /path2/baz and /path2/baz/barf stay in dcache (unhashed
if invalidated, etc.) until /path2 is also unmounted, rather than having only the
dummy root pinned.
AFAICS, it works and unless there are other reasons why need it, it would
be nice to get rid of that wart.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index f13d25d95b85..2ac8404e1a15 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -32,35 +32,6 @@
#define NFSDBG_FACILITY NFSDBG_CLIENT
-/*
- * Set the superblock root dentry.
- * Note that this function frees the inode in case of error.
- */
-static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
-{
- /* The mntroot acts as the dummy root dentry for this superblock */
- if (sb->s_root == NULL) {
- sb->s_root = d_make_root(inode);
- if (sb->s_root == NULL)
- return -ENOMEM;
- ihold(inode);
- /*
- * Ensure that this dentry is invisible to d_find_alias().
- * Otherwise, it may be spliced into the tree by
- * d_splice_alias if a parent directory from the same
- * filesystem gets mounted at a later time.
- * This again causes shrink_dcache_for_umount_subtree() to
- * Oops, since the test for IS_ROOT() will fail.
- */
- spin_lock(&d_inode(sb->s_root)->i_lock);
- spin_lock(&sb->s_root->d_lock);
- hlist_del_init(&sb->s_root->d_u.d_alias);
- spin_unlock(&sb->s_root->d_lock);
- spin_unlock(&d_inode(sb->s_root)->i_lock);
- }
- return 0;
-}
-
/*
* get a root dentry from the root filehandle
*/
@@ -99,10 +70,6 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
goto out_fattr;
}
- error = nfs_superblock_set_dummy_root(s, inode);
- if (error != 0)
- goto out_fattr;
-
/* root dentries normally start off anonymous and get spliced in later
* if the dentry tree reaches them; however if the dentry already
* exists, we'll pick it up at this point and use it as the root
@@ -115,7 +82,6 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
goto out_fattr;
}
- security_d_instantiate(root, inode);
spin_lock(&root->d_lock);
if (IS_ROOT(root) && !root->d_fsdata &&
!(root->d_flags & DCACHE_NFSFS_RENAMED)) {
@@ -123,6 +89,8 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
name = NULL;
}
spin_unlock(&root->d_lock);
+ if (!s->s_root)
+ s->s_root = dget(root);
fc->root = root;
if (server->caps & NFS_CAP_SECURITY_LABEL)
kflags |= SECURITY_LSM_NATIVE_LABELS;
reply other threads:[~2026-01-24 19:56 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260124195833.GN3183987@ZenIV \
--to=viro@zeniv.linux.org.uk \
--cc=anna@kernel.org \
--cc=brauner@kernel.org \
--cc=dhowells@redhat.com \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=trondmy@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox