Re: [PATCH 7.2.y] nfsd: fix all-zero stateid in CB_OFFLOAD for async COPY

From: Jeff Layton

Date: Thu Oct 15 2026 - 13:28:18 EST


On Thu, 2026-10-15 at 11:53 +1100, Lubos Rendek wrote:
> [ There is no upstream commit: this fixes the 7.2.y backport of
> d0beaee498e1. Mainline fixed the problem as part of the async COPY
> rework in commit f307b4f7ed17 ("nfsd: split nfsd4_copy into transient
> and durable async copy objects"), which is too risky to backport. ]
>
> Since commit 14b978e8d05c ("nfsd: fix stale s2s_cp_stateids IDR entry
> for async COPY"), nfsd4_copy() calls dup_copy_fields() before the copy
> stateid is created and then writes the new stateid only into the COPY
> result. The async copy's own cp_res.cb_stateid stays zero, so
> nfsd4_send_cb_offload() sends CB_OFFLOAD with an all-zero stateid. The
> client cannot match it to its pending COPY and waits forever in
> nfs42_proc_copy().
>
> Also copy the new stateid into async_copy->cp_res.cb_stateid. Calling
> dup_copy_fields() after nfs4_init_copy_state() instead is not an
> option, because dup_copy_fields() also copies cp_stateid and would
> overwrite the stateid that the backport moved to the async copy.
>
> Tested on 7.2.10 with an NFSv4.2 server-side COPY between two
> exports: with this change the copy completes and CB_OFFLOAD carries
> the same stateid as the COPY reply. Without it, cp(1) hangs on 7.2.4
> and 7.2.9; the affected code in nfsd4_copy() is the same in 7.2.10.
>
> Fixes: 14b978e8d05c ("nfsd: fix stale s2s_cp_stateids IDR entry for async COPY")
> Closes: https://lore.kernel.org/stable/7cc824c4-632d-49df-ae5e-cfcbb5bf76ad@xxxxxxxxxxx/
> Assisted-by: Claude:claude-opus-5-5
> Signed-off-by: Lubos Rendek <l.rendek@xxxxxxxxxxx>
> ---
> fs/nfsd/nfs4proc.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index 939749709..7c2955796 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -2243,6 +2243,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> goto out_dec_async_copy_err;
> memcpy(&result->cb_stateid, &async_copy->cp_stateid.cs_stid,
> sizeof(result->cb_stateid));
> + memcpy(&async_copy->cp_res.cb_stateid, &async_copy->cp_stateid.cs_stid,
> + sizeof(async_copy->cp_res.cb_stateid));
> if ((READ_ONCE(copy->nf_dst->nf_file->f_mode) &
> FMODE_NOCMTIME) != 0)
> async_copy->attr_update = true;

Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>