1 #include <linux/version.h>
2 #include <linux/types.h>
3 #include <linux/unistd.h>
4 
5 #include <linux/sunrpc/clnt.h>
6 #include <linux/sunrpc/xprt.h>
7 #include <linux/sunrpc/timer.h>
8 
9 #define RPC_RTO_MAX (60*HZ)
10 #define RPC_RTO_INIT (HZ/5)
11 #define RPC_RTO_MIN (HZ/10)
12 
13 void
rpc_init_rtt(struct rpc_rtt * rt,long timeo)14 rpc_init_rtt(struct rpc_rtt *rt, long timeo)
15 {
16 	long t = (timeo - RPC_RTO_INIT) << 3;
17 	int i;
18 	rt->timeo = timeo;
19 	if (t < 0)
20 		t = 0;
21 	for (i = 0; i < 5; i++) {
22 		rt->srtt[i] = t;
23 		rt->sdrtt[i] = RPC_RTO_INIT;
24 	}
25 	memset(rt->ntimeouts, 0, sizeof(rt->ntimeouts));
26 }
27 
28 void
rpc_update_rtt(struct rpc_rtt * rt,int timer,long m)29 rpc_update_rtt(struct rpc_rtt *rt, int timer, long m)
30 {
31 	long *srtt, *sdrtt;
32 
33 	if (timer-- == 0)
34 		return;
35 
36 	if (m == 0)
37 		m = 1;
38 	srtt = &rt->srtt[timer];
39 	m -= *srtt >> 3;
40 	*srtt += m;
41 	if (m < 0)
42 		m = -m;
43 	sdrtt = &rt->sdrtt[timer];
44 	m -= *sdrtt >> 2;
45 	*sdrtt += m;
46 	/* Set lower bound on the variance */
47 	if (*sdrtt < RPC_RTO_MIN)
48 		*sdrtt = RPC_RTO_MIN;
49 }
50 
51 /*
52  * Estimate rto for an nfs rpc sent via. an unreliable datagram.
53  * Use the mean and mean deviation of rtt for the appropriate type of rpc
54  * for the frequent rpcs and a default for the others.
55  * The justification for doing "other" this way is that these rpcs
56  * happen so infrequently that timer est. would probably be stale.
57  * Also, since many of these rpcs are
58  * non-idempotent, a conservative timeout is desired.
59  * getattr, lookup,
60  * read, write, commit     - A+4D
61  * other                   - timeo
62  */
63 
64 long
rpc_calc_rto(struct rpc_rtt * rt,int timer)65 rpc_calc_rto(struct rpc_rtt *rt, int timer)
66 {
67 	long res;
68 	if (timer-- == 0)
69 		return rt->timeo;
70 	res = (rt->srtt[timer] >> 3) + rt->sdrtt[timer];
71 	if (res > RPC_RTO_MAX)
72 		res = RPC_RTO_MAX;
73 	return res;
74 }
75