diff options
Diffstat (limited to 'net/sunrpc/timer.c')
-rw-r--r-- | net/sunrpc/timer.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/net/sunrpc/timer.c b/net/sunrpc/timer.c new file mode 100644 index 000000000000..bcbdf6430d5c --- /dev/null +++ b/net/sunrpc/timer.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * linux/net/sunrpc/timer.c | ||
3 | * | ||
4 | * Estimate RPC request round trip time. | ||
5 | * | ||
6 | * Based on packet round-trip and variance estimator algorithms described | ||
7 | * in appendix A of "Congestion Avoidance and Control" by Van Jacobson | ||
8 | * and Michael J. Karels (ACM Computer Communication Review; Proceedings | ||
9 | * of the Sigcomm '88 Symposium in Stanford, CA, August, 1988). | ||
10 | * | ||
11 | * This RTT estimator is used only for RPC over datagram protocols. | ||
12 | * | ||
13 | * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no> | ||
14 | */ | ||
15 | |||
16 | #include <asm/param.h> | ||
17 | |||
18 | #include <linux/types.h> | ||
19 | #include <linux/unistd.h> | ||
20 | |||
21 | #include <linux/sunrpc/clnt.h> | ||
22 | #include <linux/sunrpc/xprt.h> | ||
23 | #include <linux/sunrpc/timer.h> | ||
24 | |||
25 | #define RPC_RTO_MAX (60*HZ) | ||
26 | #define RPC_RTO_INIT (HZ/5) | ||
27 | #define RPC_RTO_MIN (HZ/10) | ||
28 | |||
29 | void | ||
30 | rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) | ||
31 | { | ||
32 | unsigned long init = 0; | ||
33 | unsigned i; | ||
34 | |||
35 | rt->timeo = timeo; | ||
36 | |||
37 | if (timeo > RPC_RTO_INIT) | ||
38 | init = (timeo - RPC_RTO_INIT) << 3; | ||
39 | for (i = 0; i < 5; i++) { | ||
40 | rt->srtt[i] = init; | ||
41 | rt->sdrtt[i] = RPC_RTO_INIT; | ||
42 | rt->ntimeouts[i] = 0; | ||
43 | } | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * NB: When computing the smoothed RTT and standard deviation, | ||
48 | * be careful not to produce negative intermediate results. | ||
49 | */ | ||
50 | void | ||
51 | rpc_update_rtt(struct rpc_rtt *rt, unsigned timer, long m) | ||
52 | { | ||
53 | long *srtt, *sdrtt; | ||
54 | |||
55 | if (timer-- == 0) | ||
56 | return; | ||
57 | |||
58 | /* jiffies wrapped; ignore this one */ | ||
59 | if (m < 0) | ||
60 | return; | ||
61 | |||
62 | if (m == 0) | ||
63 | m = 1L; | ||
64 | |||
65 | srtt = (long *)&rt->srtt[timer]; | ||
66 | m -= *srtt >> 3; | ||
67 | *srtt += m; | ||
68 | |||
69 | if (m < 0) | ||
70 | m = -m; | ||
71 | |||
72 | sdrtt = (long *)&rt->sdrtt[timer]; | ||
73 | m -= *sdrtt >> 2; | ||
74 | *sdrtt += m; | ||
75 | |||
76 | /* Set lower bound on the variance */ | ||
77 | if (*sdrtt < RPC_RTO_MIN) | ||
78 | *sdrtt = RPC_RTO_MIN; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Estimate rto for an nfs rpc sent via. an unreliable datagram. | ||
83 | * Use the mean and mean deviation of rtt for the appropriate type of rpc | ||
84 | * for the frequent rpcs and a default for the others. | ||
85 | * The justification for doing "other" this way is that these rpcs | ||
86 | * happen so infrequently that timer est. would probably be stale. | ||
87 | * Also, since many of these rpcs are | ||
88 | * non-idempotent, a conservative timeout is desired. | ||
89 | * getattr, lookup, | ||
90 | * read, write, commit - A+4D | ||
91 | * other - timeo | ||
92 | */ | ||
93 | |||
94 | unsigned long | ||
95 | rpc_calc_rto(struct rpc_rtt *rt, unsigned timer) | ||
96 | { | ||
97 | unsigned long res; | ||
98 | |||
99 | if (timer-- == 0) | ||
100 | return rt->timeo; | ||
101 | |||
102 | res = ((rt->srtt[timer] + 7) >> 3) + rt->sdrtt[timer]; | ||
103 | if (res > RPC_RTO_MAX) | ||
104 | res = RPC_RTO_MAX; | ||
105 | |||
106 | return res; | ||
107 | } | ||