aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2021-11-02 00:21:31 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2021-11-18 22:03:11 +0000
commite785923ade1b23dda1004978abc5b239f7882b8d (patch)
treea45fc038338c01e34a3c9e9b4ad01e5c46f7c8ef
parentc6d3831e54921c55c8297f5fcccf31f62b8bf324 (diff)
downloadsrc-e785923ade1b23dda1004978abc5b239f7882b8d.tar.gz
src-e785923ade1b23dda1004978abc5b239f7882b8d.zip
nfscl: Use a smaller initial delay time for NFSERR_DELAY
For NFS RPCs that receive a NFSERR_DELAY reply, the delay time is initially 1sec and then increases exponentially to NFS_TRYLATERDEL. It was found that this delay time is excessive for some NFSv4 servers, which work well with a 1msec delay. A 1sec delay resulted in very slow performance for Remove and Rename when delegations and pNFS were enabled. This patch decreases the initial delay time to 1msec. Found during a recent IETF NFSv4 working group testing event. (cherry picked from commit 5a95a6e8e4d9e947b3bb4b4755a7242e1ddd72e7)
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c
index d583b1c80c3c..12c2787b1eda 100644
--- a/sys/fs/nfs/nfs_commonkrpc.c
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -107,6 +107,10 @@ static int nfs_reconnects;
static int nfs3_jukebox_delay = 10;
static int nfs_skip_wcc_data_onerr = 1;
static int nfs_dsretries = 2;
+static struct timespec nfs_trylater_max = {
+ .tv_sec = NFS_TRYLATERDEL,
+ .tv_nsec = 0,
+};
SYSCTL_DECL(_vfs_nfs);
@@ -541,12 +545,10 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *dssep)
{
uint32_t retseq, retval, slotseq, *tl;
- time_t waituntil;
int i = 0, j = 0, opcnt, set_sigset = 0, slot;
int error = 0, usegssname = 0, secflavour = AUTH_SYS;
int freeslot, maxslot, reterr, slotpos, timeo;
u_int16_t procnum;
- u_int trylater_delay = 1;
struct nfs_feedback_arg nf;
struct timeval timo;
AUTH *auth;
@@ -558,7 +560,11 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
struct ucred *authcred;
struct nfsclsession *sep;
uint8_t sessionid[NFSX_V4SESSIONID];
+ struct timespec trylater_delay, ts, waituntil;
+ /* Initially 1msec. */
+ trylater_delay.tv_sec = 0;
+ trylater_delay.tv_nsec = 1000000;
sep = dssep;
if (xidp != NULL)
*xidp = 0;
@@ -1075,12 +1081,19 @@ tryagain:
(nd->nd_repstat == NFSERR_DELAY &&
(nd->nd_flag & ND_NFSV4) == 0) ||
nd->nd_repstat == NFSERR_RESOURCE) {
- if (trylater_delay > NFS_TRYLATERDEL)
- trylater_delay = NFS_TRYLATERDEL;
- waituntil = NFSD_MONOSEC + trylater_delay;
- while (NFSD_MONOSEC < waituntil)
- (void) nfs_catnap(PZERO, 0, "nfstry");
- trylater_delay *= 2;
+ /* Clip at NFS_TRYLATERDEL. */
+ if (timespeccmp(&trylater_delay,
+ &nfs_trylater_max, >))
+ trylater_delay = nfs_trylater_max;
+ getnanouptime(&waituntil);
+ timespecadd(&waituntil, &trylater_delay,
+ &waituntil);
+ do {
+ nfs_catnap(PZERO, 0, "nfstry");
+ getnanouptime(&ts);
+ } while (timespeccmp(&ts, &waituntil, <));
+ timespecadd(&trylater_delay, &trylater_delay,
+ &trylater_delay); /* Double each time. */
if (slot != -1) {
mtx_lock(&sep->nfsess_mtx);
sep->nfsess_slotseq[slot]++;