xref: /openbmc/linux/net/sunrpc/timer.c (revision 58e16d792a6a8c6b750f637a4649967fcac853dc)
1*457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * linux/net/sunrpc/timer.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Estimate RPC request round trip time.
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Based on packet round-trip and variance estimator algorithms described
81da177e4SLinus Torvalds  * in appendix A of "Congestion Avoidance and Control" by Van Jacobson
91da177e4SLinus Torvalds  * and Michael J. Karels (ACM Computer Communication Review; Proceedings
101da177e4SLinus Torvalds  * of the Sigcomm '88 Symposium in Stanford, CA, August, 1988).
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  * This RTT estimator is used only for RPC over datagram protocols.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
151da177e4SLinus Torvalds  */
161da177e4SLinus Torvalds 
171da177e4SLinus Torvalds #include <asm/param.h>
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds #include <linux/types.h>
201da177e4SLinus Torvalds #include <linux/unistd.h>
2112444809S\"Talpey, Thomas\ #include <linux/module.h>
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h>
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #define RPC_RTO_MAX (60*HZ)
261da177e4SLinus Torvalds #define RPC_RTO_INIT (HZ/5)
271da177e4SLinus Torvalds #define RPC_RTO_MIN (HZ/10)
281da177e4SLinus Torvalds 
29c05988cdSChuck Lever /**
30c05988cdSChuck Lever  * rpc_init_rtt - Initialize an RPC RTT estimator context
31c05988cdSChuck Lever  * @rt: context to initialize
32c05988cdSChuck Lever  * @timeo: initial timeout value, in jiffies
33c05988cdSChuck Lever  *
34c05988cdSChuck Lever  */
rpc_init_rtt(struct rpc_rtt * rt,unsigned long timeo)35c05988cdSChuck Lever void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo)
361da177e4SLinus Torvalds {
371da177e4SLinus Torvalds 	unsigned long init = 0;
3895c96174SEric Dumazet 	unsigned int i;
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds 	rt->timeo = timeo;
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds 	if (timeo > RPC_RTO_INIT)
431da177e4SLinus Torvalds 		init = (timeo - RPC_RTO_INIT) << 3;
441da177e4SLinus Torvalds 	for (i = 0; i < 5; i++) {
451da177e4SLinus Torvalds 		rt->srtt[i] = init;
461da177e4SLinus Torvalds 		rt->sdrtt[i] = RPC_RTO_INIT;
471da177e4SLinus Torvalds 		rt->ntimeouts[i] = 0;
481da177e4SLinus Torvalds 	}
491da177e4SLinus Torvalds }
5012444809S\"Talpey, Thomas\ EXPORT_SYMBOL_GPL(rpc_init_rtt);
511da177e4SLinus Torvalds 
52c05988cdSChuck Lever /**
53c05988cdSChuck Lever  * rpc_update_rtt - Update an RPC RTT estimator context
54c05988cdSChuck Lever  * @rt: context to update
55c05988cdSChuck Lever  * @timer: timer array index (request type)
56c05988cdSChuck Lever  * @m: recent actual RTT, in jiffies
57c05988cdSChuck Lever  *
581da177e4SLinus Torvalds  * NB: When computing the smoothed RTT and standard deviation,
591da177e4SLinus Torvalds  *     be careful not to produce negative intermediate results.
601da177e4SLinus Torvalds  */
rpc_update_rtt(struct rpc_rtt * rt,unsigned int timer,long m)6195c96174SEric Dumazet void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds 	long *srtt, *sdrtt;
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds 	if (timer-- == 0)
661da177e4SLinus Torvalds 		return;
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds 	/* jiffies wrapped; ignore this one */
691da177e4SLinus Torvalds 	if (m < 0)
701da177e4SLinus Torvalds 		return;
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds 	if (m == 0)
731da177e4SLinus Torvalds 		m = 1L;
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds 	srtt = (long *)&rt->srtt[timer];
761da177e4SLinus Torvalds 	m -= *srtt >> 3;
771da177e4SLinus Torvalds 	*srtt += m;
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds 	if (m < 0)
801da177e4SLinus Torvalds 		m = -m;
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds 	sdrtt = (long *)&rt->sdrtt[timer];
831da177e4SLinus Torvalds 	m -= *sdrtt >> 2;
841da177e4SLinus Torvalds 	*sdrtt += m;
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds 	/* Set lower bound on the variance */
871da177e4SLinus Torvalds 	if (*sdrtt < RPC_RTO_MIN)
881da177e4SLinus Torvalds 		*sdrtt = RPC_RTO_MIN;
891da177e4SLinus Torvalds }
9012444809S\"Talpey, Thomas\ EXPORT_SYMBOL_GPL(rpc_update_rtt);
911da177e4SLinus Torvalds 
92c05988cdSChuck Lever /**
93c05988cdSChuck Lever  * rpc_calc_rto - Provide an estimated timeout value
94c05988cdSChuck Lever  * @rt: context to use for calculation
95c05988cdSChuck Lever  * @timer: timer array index (request type)
96c05988cdSChuck Lever  *
97c05988cdSChuck Lever  * Estimate RTO for an NFS RPC sent via an unreliable datagram.  Use
98c05988cdSChuck Lever  * the mean and mean deviation of RTT for the appropriate type of RPC
99c05988cdSChuck Lever  * for frequently issued RPCs, and a fixed default for the others.
100c05988cdSChuck Lever  *
101c05988cdSChuck Lever  * The justification for doing "other" this way is that these RPCs
102c05988cdSChuck Lever  * happen so infrequently that timer estimation would probably be
103c05988cdSChuck Lever  * stale.  Also, since many of these RPCs are non-idempotent, a
104c05988cdSChuck Lever  * conservative timeout is desired.
105c05988cdSChuck Lever  *
1061da177e4SLinus Torvalds  * getattr, lookup,
1071da177e4SLinus Torvalds  * read, write, commit     - A+4D
1081da177e4SLinus Torvalds  * other                   - timeo
1091da177e4SLinus Torvalds  */
rpc_calc_rto(struct rpc_rtt * rt,unsigned int timer)11095c96174SEric Dumazet unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer)
1111da177e4SLinus Torvalds {
1121da177e4SLinus Torvalds 	unsigned long res;
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	if (timer-- == 0)
1151da177e4SLinus Torvalds 		return rt->timeo;
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds 	res = ((rt->srtt[timer] + 7) >> 3) + rt->sdrtt[timer];
1181da177e4SLinus Torvalds 	if (res > RPC_RTO_MAX)
1191da177e4SLinus Torvalds 		res = RPC_RTO_MAX;
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds 	return res;
1221da177e4SLinus Torvalds }
12312444809S\"Talpey, Thomas\ EXPORT_SYMBOL_GPL(rpc_calc_rto);
124