From: Chuck Lever Date: Fri, 15 May 2026 15:35:10 +0000 (-0400) Subject: nfs: Avoid transient zeroed case capability bits during probe X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c6eb07d3da833c351993ab8582c27073afe295e6;p=thirdparty%2Flinux.git nfs: Avoid transient zeroed case capability bits during probe nfs_probe_fsinfo() clears NFS_CAP_CASE_INSENSITIVE and NFS_CAP_CASE_NONPRESERVING ahead of the synchronous pathconf RPC and sets them again only after the reply arrives. The code path is gated by clp->rpc_ops->version < 4 and is therefore reached on NFSv2/v3 remount via nfs_reconfigure(), which calls nfs_probe_server() against a live mount. Concurrent readers walking server->caps can observe the cleared state for the duration of the round-trip and report the wrong case-sensitivity attributes. Compute the post-probe capability mask on the stack and assign it to server->caps in a single store so readers see either the stale value or the freshly computed one, never an intermediate zero. Preserve the original behaviour of dropping the bits when the pathconf RPC itself fails. The analogous transient zero on the NFSv4 path lives in nfs4_server_capabilities() and is left for a separate fix. Reported-by: sashiko-bot Closes: https://sashiko.dev/#/patchset/20260507-case-sensitivity-v14-0-e62cc8200435@oracle.com?part=10 Signed-off-by: Chuck Lever Link: https://patch.msgid.link/20260515153515.362266-3-cel@kernel.org Signed-off-by: Christian Brauner --- diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 3db2f18315b87..28b66bb0dd337 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -937,20 +937,23 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str pathinfo.fattr = fattr; nfs_fattr_init(fattr); - /* Clear before probing so a failed RPC does not retain stale bits. */ - if (clp->rpc_ops->version < 4) - server->caps &= ~(NFS_CAP_CASE_INSENSITIVE | - NFS_CAP_CASE_NONPRESERVING); - if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) { if (server->namelen == 0) server->namelen = pathinfo.max_namelen; if (clp->rpc_ops->version < 4) { + unsigned int caps = server->caps; + + caps &= ~(NFS_CAP_CASE_INSENSITIVE | + NFS_CAP_CASE_NONPRESERVING); if (pathinfo.case_insensitive) - server->caps |= NFS_CAP_CASE_INSENSITIVE; + caps |= NFS_CAP_CASE_INSENSITIVE; if (!pathinfo.case_preserving) - server->caps |= NFS_CAP_CASE_NONPRESERVING; + caps |= NFS_CAP_CASE_NONPRESERVING; + server->caps = caps; } + } else if (clp->rpc_ops->version < 4) { + server->caps &= ~(NFS_CAP_CASE_INSENSITIVE | + NFS_CAP_CASE_NONPRESERVING); } if (clp->rpc_ops->discover_trunking != NULL &&