nfsd: reset write verifier when async COPY writeback fails
Subsystems (3)
Chuck Lever
maintainerPATCH v2 1/1 nfsd: reset write verifier when async COPY writeback fails
From: Chuck Lever <[email protected]>
Async COPY captures nn->writeverf at request time and reports it to the client via CB_OFFLOAD after the worker kthread completes. When the post-copy vfs_fsync_range() or filemap_check_wb_err() in _nfsd_copy_file_range() reports an error, the worker correctly leaves NFSD4_COPY_F_COMMITTED clear so that CB_OFFLOAD encodes wr_stable_how as NFS_UNSTABLE, but the server's write verifier is not rotated.
A client that receives NFS_UNSTABLE in CB_OFFLOAD follows up with COMMIT to make the copied data durable. With the verifier unchanged, COMMIT returns the same value the client just received via CB_OFFLOAD, and the client concludes the copy is durable -- silently dropping the data whose writeback in fact failed. This violates the UNSTABLE+COMMIT durability contract (RFC 7862 section 15.1, RFC 8881 section 18.32) and matches the bug just fixed in nfsd_vfs_write() and nfsd_commit().
Rotate nn->writeverf at the writeback-failure site. The async COPY worker has no svc_rqst, so commit_reset_write_verifier() is not available here; calling nfsd_reset_write_verifier() directly mirrors the trace-less reset already used by nfsd_file_check_write_error() for the same purpose. Filter out -EAGAIN and -ESTALE, matching commit_reset_write_verifier(), since neither indicates a durable-storage failure.
--- fs/nfsd/nfs4proc.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfsd/nfs4proc.c +2 -0
@@ -1972,6 +1972,8 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy, status =filemap_check_wb_err (dst->f_mapping, since);if (!status)set_bit (NFSD4_COPY_F_COMMITTED , ©->cp_flags); +else if (status != -EAGAIN && status != -ESTALE ) +nfsd_reset_write_verifier (copy->cp_nn); }return bytes_copied; }
Signature · 1 line
2.54.0
Quoted 40 lines · Chuck Lever
From: Chuck Lever <[email protected]>
Async COPY captures
nn->writeverfat request time and reports it to the client viaCB_OFFLOADafter the worker kthread completes. When the post-copyvfs_fsync_range()orfilemap_check_wb_err()in_nfsd_copy_file_range()reports an error, the worker correctly leavesNFSD4_COPY_F_COMMITTEDclear so thatCB_OFFLOADencodeswr_stable_howasNFS_UNSTABLE, but the server's write verifier is not rotated.A client that receives
NFS_UNSTABLEinCB_OFFLOADfollows up with COMMIT to make the copied data durable. With the verifier unchanged, COMMIT returns the same value the client just received viaCB_OFFLOAD, and the client concludes the copy is durable -- silently dropping the data whose writeback in fact failed. This violates the UNSTABLE+COMMIT durability contract (RFC 7862 section 15.1, RFC 8881 section 18.32) and matches the bug just fixed innfsd_vfs_write()andnfsd_commit().Rotate
nn->writeverfat the writeback-failure site. The async COPY worker has nosvc_rqst, socommit_reset_write_verifier()is not available here; callingnfsd_reset_write_verifier()directly mirrors the trace-less reset already used bynfsd_file_check_write_error()for the same purpose. Filter out-EAGAINand-ESTALE, matchingcommit_reset_write_verifier(), since neither indicates a durable-storage failure.Fixes eac0b17a77fb ("NFSD add vfs_fsync after async copy is done")Assisted-by kres:claude-opus-4-7Signed-off-by Chuck Lever <[email protected]>--- fs/nfsd/nfs4proc.c | 2 ++ 1 file changed, 2 insertions(+)fs/nfsd/nfs4proc.c +0
-0
fs/nfsd/nfs4proc.c static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy, · line 1979
Quoted 8 lines
fs/nfsd/nfs4proc.c +2
-0@@ -1972,6 +1972,8 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy, status =filemap_check_wb_err (dst->f_mapping, since);if (!status)set_bit (NFSD4_COPY_F_COMMITTED , ©->cp_flags); +else if (status != -EAGAIN && status != -ESTALE ) +nfsd_reset_write_verifier (copy->cp_nn); }return bytes_copied; }