From: Jeff Layton <jlayton@kernel.org>
To: "Steve Dickson" <steved@redhat.com>,
"Mantas Mikulėnas" <grawity@gmail.com>
Cc: Chuck Lever <cel@kernel.org>,
linux-nfs@vger.kernel.org, Jeff Layton <jlayton@kernel.org>
Subject: [PATCH nfs-utils v3 01/11] mountd: factor out the per-path export attribute computation
Date: Mon, 14 Sep 2026 09:14:10 -0400 [thread overview]
Message-ID: <20260914-nl-crossmnt-v3-1-a984a6c94829@kernel.org> (raw)
In-Reply-To: <20260914-nl-crossmnt-v3-0-a984a6c94829@kernel.org>
dump_to_cache() adjusts the export flags, fsid and uuid before handing
them to the kernel, because the upcall path may be a crossmnt submount
rather than the exported path itself. Pull that into
export_attrs_build() so the netlink downcall can use it too.
No functional change.
Assisted-by: LLM
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
support/export/cache.c | 143 ++++++++++++++++++++++++++++++-------------------
1 file changed, 88 insertions(+), 55 deletions(-)
diff --git a/support/export/cache.c b/support/export/cache.c
index 059f48a7069f..e8b13409ad7a 100644
--- a/support/export/cache.c
+++ b/support/export/cache.c
@@ -1072,6 +1072,86 @@ static void write_xprtsec(char **bp, int *blen, struct exportent *ep)
qword_addint(bp, blen, p->info->number);
}
+static int can_reexport_via_fsidnum(struct exportent *exp, struct statfs *st)
+{
+ if (st->f_type != 0x6969 /* NFS_SUPER_MAGIC */)
+ return 0;
+
+ return exp->e_reexport == REEXP_PREDEFINED_FSIDNUM ||
+ exp->e_reexport == REEXP_AUTO_FSIDNUM;
+}
+
+/* What to hand the kernel for one (path, export) pair */
+struct export_attrs {
+ int flags;
+ uint32_t fsidnum;
+ int sec_mask; /* mask for the per-flavor flags */
+ int sec_extra; /* extra per-flavor flags */
+ char uuid[16];
+ bool have_uuid;
+};
+
+/*
+ * An upcall path may be a submount below the exported one, when the export
+ * is marked crossmnt. Such a submount is a filesystem in its own right, so
+ * it must not inherit the parent's fsid= or uuid= - if it does, both end up
+ * claiming the same filehandles and the client sees ESTALE.
+ *
+ * Returns 0, or -1 with errno set if @path cannot be exported at all.
+ */
+static int export_attrs_build(struct export_attrs *ea, char *path,
+ struct exportent *exp)
+{
+ int different_fs = strcmp(path, exp->e_path) != 0;
+ int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
+ int do_fsidnum = 0;
+
+ memset(ea, 0, sizeof(*ea));
+ ea->fsidnum = exp->e_fsid;
+
+ if (different_fs) {
+ struct statfs st;
+
+ if (nfsd_path_statfs(path, &st)) {
+ xlog(L_WARNING, "unable to statfs %s", path);
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* A re-exported submount gets an fsid= of its own instead */
+ if (can_reexport_via_fsidnum(exp, &st)) {
+ do_fsidnum = 1;
+ flag_mask = ~0;
+ }
+ }
+
+ if (do_fsidnum) {
+ uint32_t search_fsidnum = 0;
+
+ if (exp->e_reexport != REEXP_NONE &&
+ reexpdb_fsidnum_by_path(path, &search_fsidnum,
+ exp->e_reexport == REEXP_AUTO_FSIDNUM) == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ ea->fsidnum = search_fsidnum;
+ ea->flags = exp->e_flags | NFSEXP_FSID;
+ ea->sec_extra = NFSEXP_FSID;
+ } else {
+ ea->flags = exp->e_flags & flag_mask;
+ }
+ ea->sec_mask = flag_mask;
+
+ if (exp->e_uuid && !different_fs) {
+ get_uuid(exp->e_uuid, 16, ea->uuid);
+ ea->have_uuid = true;
+ } else if ((exp->e_flags & flag_mask & NFSEXP_FSID) == 0) {
+ ea->have_uuid = uuid_by_path(path, 0, 16, ea->uuid);
+ }
+
+ return 0;
+}
+
/*
* Netlink-based svc_export cache support.
*
@@ -2501,15 +2581,6 @@ static void cache_sunrpc_nl_process(void)
cache_nl_process_unix_gid();
}
-static int can_reexport_via_fsidnum(struct exportent *exp, struct statfs *st)
-{
- if (st->f_type != 0x6969 /* NFS_SUPER_MAGIC */)
- return 0;
-
- return exp->e_reexport == REEXP_PREDEFINED_FSIDNUM ||
- exp->e_reexport == REEXP_AUTO_FSIDNUM;
-}
-
static int dump_to_cache(int f, char *buf, int blen, char *domain,
char *path, struct exportent *exp, int ttl)
{
@@ -2524,60 +2595,22 @@ static int dump_to_cache(int f, char *buf, int blen, char *domain,
qword_add(&bp, &blen, domain);
qword_add(&bp, &blen, path);
if (exp) {
- int different_fs = strcmp(path, exp->e_path) != 0;
- int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
- int rc, do_fsidnum = 0;
- uint32_t fsidnum = exp->e_fsid;
-
- if (different_fs) {
- struct statfs st;
-
- rc = nfsd_path_statfs(path, &st);
- if (rc) {
- xlog(L_WARNING, "unable to statfs %s", path);
- errno = EINVAL;
- return -1;
- }
+ struct export_attrs ea;
- if (can_reexport_via_fsidnum(exp, &st)) {
- do_fsidnum = 1;
- flag_mask = ~0;
- }
- }
+ if (export_attrs_build(&ea, path, exp) < 0)
+ return -1;
qword_adduint(&bp, &blen, now + exp->e_ttl);
-
- if (do_fsidnum) {
- uint32_t search_fsidnum = 0;
- if (exp->e_reexport != REEXP_NONE && reexpdb_fsidnum_by_path(path, &search_fsidnum,
- exp->e_reexport == REEXP_AUTO_FSIDNUM) == 0) {
- errno = EINVAL;
- return -1;
- }
- fsidnum = search_fsidnum;
- qword_addint(&bp, &blen, exp->e_flags | NFSEXP_FSID);
- } else {
- qword_addint(&bp, &blen, exp->e_flags & flag_mask);
- }
-
+ qword_addint(&bp, &blen, ea.flags);
qword_addint(&bp, &blen, exp->e_anonuid);
qword_addint(&bp, &blen, exp->e_anongid);
- qword_addint(&bp, &blen, fsidnum);
+ qword_addint(&bp, &blen, ea.fsidnum);
write_fsloc(&bp, &blen, exp);
- write_secinfo(&bp, &blen, exp, flag_mask, do_fsidnum ? NFSEXP_FSID : 0);
- if (exp->e_uuid == NULL || different_fs) {
- char u[16];
- if ((exp->e_flags & flag_mask & NFSEXP_FSID) == 0 &&
- uuid_by_path(path, 0, 16, u)) {
- qword_add(&bp, &blen, "uuid");
- qword_addhex(&bp, &blen, u, 16);
- }
- } else {
- char u[16];
- get_uuid(exp->e_uuid, 16, u);
+ write_secinfo(&bp, &blen, exp, ea.sec_mask, ea.sec_extra);
+ if (ea.have_uuid) {
qword_add(&bp, &blen, "uuid");
- qword_addhex(&bp, &blen, u, 16);
+ qword_addhex(&bp, &blen, ea.uuid, 16);
}
write_xprtsec(&bp, &blen, exp);
xlog(D_AUTH, "granted access to %s for %s",
--
2.55.0
next prev parent reply other threads:[~2026-09-14 13:14 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-14 13:14 [PATCH nfs-utils v3 00/11] mountd: bugfixes for up/downcall interfaces Jeff Layton
2026-09-14 13:14 ` Jeff Layton [this message]
2026-09-14 13:14 ` [PATCH nfs-utils v3 02/11] mountd: handle unmountable paths and junctions in the netlink downcall Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 03/11] mountd: answer requests the kernel rejects on " Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 04/11] mountd: don't leak the parent export's fsid onto crossmnt submounts Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 05/11] mountd: retry unresolvable fsid lookups on the netlink downcall Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 06/11] mountd: bound the junction path before copying it into e_path Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 07/11] mountd: give each worker its own netlink command socket Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 08/11] mountd: retry export attributes that fail to resolve for a passing reason Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 09/11] mountd: drop a deferred fsid lookup once it has been answered Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 10/11] mountd: bound the retry queues Jeff Layton
2026-09-14 13:14 ` [PATCH nfs-utils v3 11/11] mountd: don't warn about pipefs submounts nobody asked to export Jeff Layton
2026-09-15 9:24 ` [PATCH nfs-utils v3 00/11] mountd: bugfixes for up/downcall interfaces Mantas Mikulėnas
2026-09-17 7:21 ` Steve Dickson
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=20260914-nl-crossmnt-v3-1-a984a6c94829@kernel.org \
--to=jlayton@kernel.org \
--cc=cel@kernel.org \
--cc=grawity@gmail.com \
--cc=linux-nfs@vger.kernel.org \
--cc=steved@redhat.com \
/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