Branch data Line data Source code
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 : : #include <linux/module.h>
21 : :
22 : : #include <linux/sunrpc/clnt.h>
23 : :
24 : : #define RPC_RTO_MAX (60*HZ)
25 : : #define RPC_RTO_INIT (HZ/5)
26 : : #define RPC_RTO_MIN (HZ/10)
27 : :
28 : : /**
29 : : * rpc_init_rtt - Initialize an RPC RTT estimator context
30 : : * @rt: context to initialize
31 : : * @timeo: initial timeout value, in jiffies
32 : : *
33 : : */
34 : 0 : void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo)
35 : : {
36 : : unsigned long init = 0;
37 : : unsigned int i;
38 : :
39 : 0 : rt->timeo = timeo;
40 : :
41 [ # # ]: 0 : if (timeo > RPC_RTO_INIT)
42 : 0 : init = (timeo - RPC_RTO_INIT) << 3;
43 [ # # ]: 0 : for (i = 0; i < 5; i++) {
44 : 0 : rt->srtt[i] = init;
45 : 0 : rt->sdrtt[i] = RPC_RTO_INIT;
46 : 0 : rt->ntimeouts[i] = 0;
47 : : }
48 : 0 : }
49 : : EXPORT_SYMBOL_GPL(rpc_init_rtt);
50 : :
51 : : /**
52 : : * rpc_update_rtt - Update an RPC RTT estimator context
53 : : * @rt: context to update
54 : : * @timer: timer array index (request type)
55 : : * @m: recent actual RTT, in jiffies
56 : : *
57 : : * NB: When computing the smoothed RTT and standard deviation,
58 : : * be careful not to produce negative intermediate results.
59 : : */
60 : 0 : void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m)
61 : : {
62 : : long *srtt, *sdrtt;
63 : :
64 [ # # ]: 0 : if (timer-- == 0)
65 : : return;
66 : :
67 : : /* jiffies wrapped; ignore this one */
68 [ # # ]: 0 : if (m < 0)
69 : : return;
70 : :
71 [ # # ]: 0 : if (m == 0)
72 : : m = 1L;
73 : :
74 : 0 : srtt = (long *)&rt->srtt[timer];
75 : 0 : m -= *srtt >> 3;
76 : 0 : *srtt += m;
77 : :
78 [ # # ]: 0 : if (m < 0)
79 : 0 : m = -m;
80 : :
81 : 0 : sdrtt = (long *)&rt->sdrtt[timer];
82 : 0 : m -= *sdrtt >> 2;
83 : 0 : *sdrtt += m;
84 : :
85 : : /* Set lower bound on the variance */
86 [ # # ]: 0 : if (*sdrtt < RPC_RTO_MIN)
87 : 0 : *sdrtt = RPC_RTO_MIN;
88 : : }
89 : : EXPORT_SYMBOL_GPL(rpc_update_rtt);
90 : :
91 : : /**
92 : : * rpc_calc_rto - Provide an estimated timeout value
93 : : * @rt: context to use for calculation
94 : : * @timer: timer array index (request type)
95 : : *
96 : : * Estimate RTO for an NFS RPC sent via an unreliable datagram. Use
97 : : * the mean and mean deviation of RTT for the appropriate type of RPC
98 : : * for frequently issued RPCs, and a fixed default for the others.
99 : : *
100 : : * The justification for doing "other" this way is that these RPCs
101 : : * happen so infrequently that timer estimation would probably be
102 : : * stale. Also, since many of these RPCs are non-idempotent, a
103 : : * conservative timeout is desired.
104 : : *
105 : : * getattr, lookup,
106 : : * read, write, commit - A+4D
107 : : * other - timeo
108 : : */
109 : 0 : unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer)
110 : : {
111 : : unsigned long res;
112 : :
113 [ # # ]: 0 : if (timer-- == 0)
114 : 0 : return rt->timeo;
115 : :
116 : 0 : res = ((rt->srtt[timer] + 7) >> 3) + rt->sdrtt[timer];
117 [ # # ]: 0 : if (res > RPC_RTO_MAX)
118 : : res = RPC_RTO_MAX;
119 : :
120 : 0 : return res;
121 : : }
122 : : EXPORT_SYMBOL_GPL(rpc_calc_rto);
|