From 25dde935988bc0cc2991cedbea90a2ce65066d54 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 11 Sep 2026 11:00:02 -0400 Subject: [PATCH 1/4] NFSv4: Fix a regression in the handling of CB_RECALL_ANY When the flag NFS_DELEGATION_RETURN was replaced by the server->delegations_return list, the test in nfs_mark_return_if_closed_delegation() was replaced by one that stops all further marking of delegations for return when closed as soon as the server->delegations_return list is non-empty, breaking CB_RECALL_ANY behaviour. While the intention at the time was probably to check if delegation->entry was non-empty in order to emulate the effect of the NFS_DELEGATION_RETURN test, that is no longer an option, since delegation->entry is also used for the LRU list. By just removing the offending check altogether, the patch can end up moving delegations from the server->delegations_delayed list prematurely, triggering an early retry. However that should be mostly harmless behaviour. Fixes: 0ebe655bd033 ("NFS: add a separate delegation return list") Cc: stable@vger.kernel.org Reviewed-by: Christoph Hellwig Signed-off-by: Trond Myklebust --- fs/nfs/delegation.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index ab3e441464a6..ad774316f716 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -934,8 +934,7 @@ nfs_mark_return_if_closed_delegation(struct nfs_server *server, { struct inode *inode; - if (!list_empty_careful(&server->delegations_return) || - test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) + if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) return; spin_lock(&delegation->lock); inode = delegation->inode; From a0db57fee35ece5603f852df1b665e01e0556f65 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 26 Aug 2026 10:34:15 -0400 Subject: [PATCH 2/4] xprtrdma: Fix Write chunk payload corruption on a short reply header An NFSv3 server may return READ3resok with attributes_follow set to FALSE. The client has already reserved enough head iovec space for the largest possible reply header, so such a reply falls 84 bytes short of that estimate. rpcrdma_inline_fixup() points the head iovec at the received message but leaves its length at the reserved size, so it runs past the header into stale receive buffer content. xdr_realign_pages() then shifts those bytes into the page list, and the READ returns transport data where READ payload belongs. nfs3_read_done() records the shorter header size, so on an ordinary NFSv3 mount, only the first READ is corrupted. However, the FlexFiles layout driver installs its own completion callback, so every READ from a data server is corrupt. To address this, reduce the head iovec to the header bytes actually received when a Write chunk carries the READ payload. An auth flavor that transforms the payload cannot use a Write chunk, so scoping it to Write chunks leaves krb5[ip] alone. Fixes: cb0ae1fbb2f5 ("xprtrdma: Do not update {head, tail}.iov_len in rpcrdma_inline_fixup()") Reported-by: Rakesh Bhargava Closes: https://lore.kernel.org/linux-nfs/SA6PR06MB104695205126871E29444567A8BA02@SA6PR06MB10469.namprd06.prod.outlook.com/ Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- net/sunrpc/xprtrdma/rpc_rdma.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 1285f04cdac1..ba8bdca8a49f 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -1243,9 +1243,19 @@ rpcrdma_decode_msg(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep, /* Build the RPC reply's Payload stream in rqst->rq_rcv_buf */ base = (char *)xdr_inline_decode(xdr, 0); - rpclen = xdr_stream_remaining(xdr); + rpclen = rep->rr_hdrbuf.len - xdr_stream_pos(xdr); + if (writelist) + rpclen &= ~3; + if (unlikely(!rpclen)) + return -EIO; + if (writelist && rpclen < rqst->rq_rcv_buf.head[0].iov_len) { + rqst->rq_rcv_buf.head[0].iov_len = rpclen; + rqst->rq_private_buf.head[0].iov_len = rpclen; + } + r_xprt->rx_stats.fixup_copy_count += - rpcrdma_inline_fixup(rqst, base, rpclen, writelist & 3); + rpcrdma_inline_fixup(rqst, base, rpclen, + xdr_pad_size(writelist)); r_xprt->rx_stats.total_rdma_reply += writelist; return rpclen + xdr_align_size(writelist); From 72233aabc78cd0415c850641bc2a6e4fea23173f Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 16 Sep 2026 16:43:36 -0400 Subject: [PATCH 3/4] NFS: use TCP for MOUNT when xprtsec= selects TLS An NFSv2 or NFSv3 text mount that specifies xprtsec= but no mountproto= crashes in nfs_init_timeout_values(): RIP: 0010:nfs_init_timeout_values+0x10a/0x110 [nfs] Call Trace: nfs_mount+0x1c3/0x330 [nfs] nfs_try_get_tree+0x1e5/0x460 [nfs] nfs_get_tree+0x64d/0x6d0 [nfs] vfs_get_tree+0x2b/0xe0 vfs_cmd_create+0x5f/0xd0 vfs_fsconfig_locked+0x50/0x130 __se_sys_fsconfig+0x2f9/0x3a0 nfs_validate_transport_protocol() sets nfs_server.protocol to XPRT_TRANSPORT_TCP_TLS when xprtsec= is present, but the switch in nfs_set_mount_transport_protocol() has no case for that value. mount_server.protocol stays zero, and nfs_init_timeout_values() calls BUG() on a transport it does not recognize. mount.nfs always appends mountproto= after probing the server's rpcbind, so only a caller that bypasses it, such as "mount -i" or a program that drives fsconfig() directly, reaches the crash. Select TCP for MOUNT when the NFS transport is XPRT_TRANSPORT_TCP_TLS. nfs_mount() requests no transport security, so MOUNT already runs over plain TCP whenever mount.nfs supplies mountproto=tcp. Fixes: c8407f2e560c ("NFS: Add an "xprtsec=" NFS mount option") Signed-off-by: Chuck Lever Reviewed-by: Prabhakar Pujeri Signed-off-by: Trond Myklebust --- fs/nfs/fs_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index 1967de7d1dff..a7393ff05494 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c @@ -402,6 +402,7 @@ static void nfs_set_mount_transport_protocol(struct nfs_fs_context *ctx) ctx->mount_server.protocol = XPRT_TRANSPORT_UDP; break; case XPRT_TRANSPORT_TCP: + case XPRT_TRANSPORT_TCP_TLS: case XPRT_TRANSPORT_RDMA: ctx->mount_server.protocol = XPRT_TRANSPORT_TCP; } From 211cda4fdf33011cee39f8970c4625b207142d6b Mon Sep 17 00:00:00 2001 From: Jimmy Zuber Date: Tue, 22 Sep 2026 17:56:56 +0000 Subject: [PATCH 4/4] NFS: Fix stale negative cache on failed nfs_mkdir() Since commit 8376583b84a1 ("nfs: change mkdir inode_operation to return alternate dentry if needed"), nfs_mkdir() no longer drops the dentry on RPC failure. A negative cache value can then result in spurious ENOENT results for further operations within that directory, such as open or stat. We observed this breaking some applications where an EEXIST on mkdir caused the application to assume the directory to exist, only to fail operations within that directory due to the retained negative cache entry. The other create paths, nfs_create() and nfs_mknod(), still drop the dentry on failure. This patch restores the previous behavior. Fixes: 8376583b84a1 ("nfs: change mkdir inode_operation to return alternate dentry if needed") Cc: stable@vger.kernel.org # v6.15+ Signed-off-by: Jimmy Zuber Reviewed-by: NeilBrown Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 49394123bd09..a26c459ffb04 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2490,6 +2490,8 @@ struct dentry *nfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, trace_nfs_mkdir_enter(dir, dentry); ret = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); trace_nfs_mkdir_exit(dir, dentry, PTR_ERR_OR_ZERO(ret)); + if (IS_ERR(ret)) + d_drop(dentry); return ret; } EXPORT_SYMBOL_GPL(nfs_mkdir);