Skip to content

Commit 75acacb

Browse files
committed
NFSD: Trace boot verifier resets
According to commit bbf2f09 ("nfsd: Reset the boot verifier on all write I/O errors"), the Linux NFS server forces all clients to resend pending unstable writes if any server-side write or commit operation encounters an error (say, ENOSPC). This is a rare and quite exceptional event that could require administrative recovery action, so it should be made trace-able. Example trace event: nfsd-938 [002] 7174.945558: nfsd_writeverf_reset: boot_time= 61cc920d xid=0xdcd62036 error=-28 new verifier=0x08aecc6142515904 Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 3988a57 commit 75acacb

2 files changed

Lines changed: 38 additions & 3 deletions

File tree

fs/nfsd/trace.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,34 @@ DEFINE_EVENT(nfsd_net_class, nfsd_##name, \
574574
DEFINE_NET_EVENT(grace_start);
575575
DEFINE_NET_EVENT(grace_complete);
576576

577+
TRACE_EVENT(nfsd_writeverf_reset,
578+
TP_PROTO(
579+
const struct nfsd_net *nn,
580+
const struct svc_rqst *rqstp,
581+
int error
582+
),
583+
TP_ARGS(nn, rqstp, error),
584+
TP_STRUCT__entry(
585+
__field(unsigned long long, boot_time)
586+
__field(u32, xid)
587+
__field(int, error)
588+
__array(unsigned char, verifier, NFS4_VERIFIER_SIZE)
589+
),
590+
TP_fast_assign(
591+
__entry->boot_time = nn->boot_time;
592+
__entry->xid = be32_to_cpu(rqstp->rq_xid);
593+
__entry->error = error;
594+
595+
/* avoid seqlock inside TP_fast_assign */
596+
memcpy(__entry->verifier, nn->writeverf,
597+
NFS4_VERIFIER_SIZE);
598+
),
599+
TP_printk("boot_time=%16llx xid=0x%08x error=%d new verifier=0x%s",
600+
__entry->boot_time, __entry->xid, __entry->error,
601+
__print_hex_str(__entry->verifier, NFS4_VERIFIER_SIZE)
602+
)
603+
);
604+
577605
TRACE_EVENT(nfsd_clid_cred_mismatch,
578606
TP_PROTO(
579607
const struct nfs4_client *clp,

fs/nfsd/vfs.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -553,14 +553,17 @@ __be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
553553
if (!status)
554554
status = commit_inode_metadata(file_inode(src));
555555
if (status < 0) {
556+
struct nfsd_net *nn = net_generic(nf_dst->nf_net,
557+
nfsd_net_id);
558+
556559
trace_nfsd_clone_file_range_err(rqstp,
557560
&nfsd4_get_cstate(rqstp)->save_fh,
558561
src_pos,
559562
&nfsd4_get_cstate(rqstp)->current_fh,
560563
dst_pos,
561564
count, status);
562-
nfsd_reset_write_verifier(net_generic(nf_dst->nf_net,
563-
nfsd_net_id));
565+
nfsd_reset_write_verifier(nn);
566+
trace_nfsd_writeverf_reset(nn, rqstp, status);
564567
ret = nfserrno(status);
565568
}
566569
}
@@ -1017,6 +1020,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
10171020
host_err = vfs_iter_write(file, &iter, &pos, flags);
10181021
if (host_err < 0) {
10191022
nfsd_reset_write_verifier(nn);
1023+
trace_nfsd_writeverf_reset(nn, rqstp, host_err);
10201024
goto out_nfserr;
10211025
}
10221026
*cnt = host_err;
@@ -1028,8 +1032,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
10281032

10291033
if (stable && use_wgather) {
10301034
host_err = wait_for_concurrent_writes(file);
1031-
if (host_err < 0)
1035+
if (host_err < 0) {
10321036
nfsd_reset_write_verifier(nn);
1037+
trace_nfsd_writeverf_reset(nn, rqstp, host_err);
1038+
}
10331039
}
10341040

10351041
out_nfserr:
@@ -1151,6 +1157,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
11511157
break;
11521158
default:
11531159
nfsd_reset_write_verifier(nn);
1160+
trace_nfsd_writeverf_reset(nn, rqstp, err2);
11541161
}
11551162
err = nfserrno(err2);
11561163
} else

0 commit comments

Comments
 (0)