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); 124