Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[platform/kernel/linux-starfive.git] / net / sunrpc / timer.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * linux/net/sunrpc/timer.c
4  *
5  * Estimate RPC request round trip time.
6  *
7  * Based on packet round-trip and variance estimator algorithms described
8  * in appendix A of "Congestion Avoidance and Control" by Van Jacobson
9  * and Michael J. Karels (ACM Computer Communication Review; Proceedings
10  * of the Sigcomm '88 Symposium in Stanford, CA, August, 1988).
11  *
12  * This RTT estimator is used only for RPC over datagram protocols.
13  *
14  * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
15  */
16
17 #include <asm/param.h>
18
19 #include <linux/types.h>
20 #include <linux/unistd.h>
21 #include <linux/module.h>
22
23 #include <linux/sunrpc/clnt.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 /**
30  * rpc_init_rtt - Initialize an RPC RTT estimator context
31  * @rt: context to initialize
32  * @timeo: initial timeout value, in jiffies
33  *
34  */
35 void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo)
36 {
37         unsigned long init = 0;
38         unsigned int i;
39
40         rt->timeo = timeo;
41
42         if (timeo > RPC_RTO_INIT)
43                 init = (timeo - RPC_RTO_INIT) << 3;
44         for (i = 0; i < 5; i++) {
45                 rt->srtt[i] = init;
46                 rt->sdrtt[i] = RPC_RTO_INIT;
47                 rt->ntimeouts[i] = 0;
48         }
49 }
50 EXPORT_SYMBOL_GPL(rpc_init_rtt);
51
52 /**
53  * rpc_update_rtt - Update an RPC RTT estimator context
54  * @rt: context to update
55  * @timer: timer array index (request type)
56  * @m: recent actual RTT, in jiffies
57  *
58  * NB: When computing the smoothed RTT and standard deviation,
59  *     be careful not to produce negative intermediate results.
60  */
61 void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m)
62 {
63         long *srtt, *sdrtt;
64
65         if (timer-- == 0)
66                 return;
67
68         /* jiffies wrapped; ignore this one */
69         if (m < 0)
70                 return;
71
72         if (m == 0)
73                 m = 1L;
74
75         srtt = (long *)&rt->srtt[timer];
76         m -= *srtt >> 3;
77         *srtt += m;
78
79         if (m < 0)
80                 m = -m;
81
82         sdrtt = (long *)&rt->sdrtt[timer];
83         m -= *sdrtt >> 2;
84         *sdrtt += m;
85
86         /* Set lower bound on the variance */
87         if (*sdrtt < RPC_RTO_MIN)
88                 *sdrtt = RPC_RTO_MIN;
89 }
90 EXPORT_SYMBOL_GPL(rpc_update_rtt);
91
92 /**
93  * rpc_calc_rto - Provide an estimated timeout value
94  * @rt: context to use for calculation
95  * @timer: timer array index (request type)
96  *
97  * Estimate RTO for an NFS RPC sent via an unreliable datagram.  Use
98  * the mean and mean deviation of RTT for the appropriate type of RPC
99  * for frequently issued RPCs, and a fixed default for the others.
100  *
101  * The justification for doing "other" this way is that these RPCs
102  * happen so infrequently that timer estimation would probably be
103  * stale.  Also, since many of these RPCs are non-idempotent, a
104  * conservative timeout is desired.
105  *
106  * getattr, lookup,
107  * read, write, commit     - A+4D
108  * other                   - timeo
109  */
110 unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer)
111 {
112         unsigned long res;
113
114         if (timer-- == 0)
115                 return rt->timeo;
116
117         res = ((rt->srtt[timer] + 7) >> 3) + rt->sdrtt[timer];
118         if (res > RPC_RTO_MAX)
119                 res = RPC_RTO_MAX;
120
121         return res;
122 }
123 EXPORT_SYMBOL_GPL(rpc_calc_rto);