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 08/11] mountd: retry export attributes that fail to resolve for a passing reason
Date: Mon, 14 Sep 2026 09:14:17 -0400 [thread overview]
Message-ID: <20260914-nl-crossmnt-v3-8-a984a6c94829@kernel.org> (raw)
In-Reply-To: <20260914-nl-crossmnt-v3-0-a984a6c94829@kernel.org>
export_attrs_build() answers -1 both for a filesystem that can never be
exported and for one it could not measure this time:
- nfsd_path_statfs() on a re-exported NFS mount can give ETIMEDOUT with
"softerr", or EIO with plain "soft"
- fsidnum_get_by_path() returns the same false whether fsidd is
restarting, answered with nonsense, or has no fsid for the path
Both then set errno to EINVAL, so both downcalls deny the path for
default_ttl. An fsidd restart takes a working re-export offline until the
negative entry expires.
Report EAGAIN for the cases we cannot decide and keep EINVAL for the rest.
The netlink path turns EAGAIN into EXPORT_RETRY, and nfsd_export() leaves
the request for the next upcall, which is what both already do when
is_mountpoint() fails oddly.
statfs errors are sorted with path_lookup_error(), the same test
is_mountpoint() callers use, plus two that are decidable even though it
does not name them:
- ENOSYS: a filesystem with no statfs will never answer
- 0: a chrooted worker thread ran the stat and its errno never reached
us, which is how the is_mountpoint() callers already read it
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Assisted-by: LLM
---
support/export/cache.c | 41 ++++++++++++++++++++++++++++++++++++++---
1 file changed, 38 insertions(+), 3 deletions(-)
diff --git a/support/export/cache.c b/support/export/cache.c
index cbe3df83b0eb..290ce09bb66e 100644
--- a/support/export/cache.c
+++ b/support/export/cache.c
@@ -1145,7 +1145,9 @@ struct export_attrs {
* 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.
+ * Returns 0, or -1 with errno set: EAGAIN if we could not work the attributes
+ * out this time and the caller should ask again, anything else if @path is
+ * genuinely not exportable.
*/
static int export_attrs_build(struct export_attrs *ea, char *path,
struct exportent *exp)
@@ -1161,8 +1163,24 @@ static int export_attrs_build(struct export_attrs *ea, char *path,
struct statfs st;
if (nfsd_path_statfs(path, &st)) {
+ int err = errno;
+
xlog(L_WARNING, "unable to statfs %s", path);
- errno = EINVAL;
+ /*
+ * A strange error - the ETIMEDOUT a "softerr" NFS
+ * re-export gives, or the EIO a plain "soft" one gives
+ * - leaves us unable to say whether the path is
+ * exportable, so ask again later. Two errors are not
+ * of that kind: ENOSYS, because a filesystem with no
+ * statfs will never answer, and 0, which means a
+ * chrooted worker thread ran the statfs and we never
+ * saw its errno - is_mountpoint() callers read that as
+ * definitive too.
+ */
+ if (err != 0 && err != ENOSYS && !path_lookup_error(err))
+ errno = EAGAIN;
+ else
+ errno = EINVAL;
return -1;
}
@@ -1179,7 +1197,13 @@ static int export_attrs_build(struct export_attrs *ea, char *path,
if (exp->e_reexport != REEXP_NONE &&
reexpdb_fsidnum_by_path(path, &search_fsidnum,
exp->e_reexport == REEXP_AUTO_FSIDNUM) == 0) {
- errno = EINVAL;
+ /*
+ * fsidnum_get_by_path() answers the same way whether
+ * fsidd is unreachable, gave us nonsense, or has no
+ * fsid for this path. A restarting fsidd must not
+ * deny a working re-export, so ask again later.
+ */
+ errno = EAGAIN;
return -1;
}
ea->fsidnum = search_fsidnum;
@@ -1845,6 +1869,10 @@ static enum export_result nl_add_export_req(struct nl_msg *msg, char *dom,
}
if (epp && export_attrs_build(&ea, path, epp) < 0) {
+ if (errno == EAGAIN) {
+ res = EXPORT_RETRY;
+ goto out;
+ }
xlog(explicit_export ? L_WARNING : D_GENERAL,
"Cannot export %s, possibly unsupported"
" filesystem or fsid= required", path);
@@ -3637,6 +3665,13 @@ static void nfsd_export(int f)
NULL, 60);
} else if (dump_to_cache(f, buf, sizeof(buf), dom, path,
&found->m_export, 0) < 0) {
+ /*
+ * We could not work out the attributes this time.
+ * Leave the request for the next upcall rather than
+ * denying an export that is probably fine.
+ */
+ if (errno == EAGAIN)
+ goto out;
xlog(L_WARNING,
"Cannot export %s, possibly unsupported filesystem"
" or fsid= required", path);
--
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 ` [PATCH nfs-utils v3 01/11] mountd: factor out the per-path export attribute computation Jeff Layton
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 ` Jeff Layton [this message]
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-8-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