Branch data Line data Source code
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 : 0 : void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) 36 : : { 37 : : unsigned long init = 0; 38 : : unsigned int i; 39 : : 40 : 0 : rt->timeo = timeo; 41 : : 42 : 0 : if (timeo > RPC_RTO_INIT) 43 : 0 : init = (timeo - RPC_RTO_INIT) << 3; 44 : 0 : for (i = 0; i < 5; i++) { 45 : 0 : rt->srtt[i] = init; 46 : 0 : rt->sdrtt[i] = RPC_RTO_INIT; 47 : 0 : rt->ntimeouts[i] = 0; 48 : : } 49 : 0 : } 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 : 0 : void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m) 62 : : { 63 : : long *srtt, *sdrtt; 64 : : 65 : 0 : if (timer-- == 0) 66 : : return; 67 : : 68 : : /* jiffies wrapped; ignore this one */ 69 : 0 : if (m < 0) 70 : : return; 71 : : 72 : 0 : if (m == 0) 73 : : m = 1L; 74 : : 75 : 0 : srtt = (long *)&rt->srtt[timer]; 76 : 0 : m -= *srtt >> 3; 77 : 0 : *srtt += m; 78 : : 79 : 0 : if (m < 0) 80 : 0 : m = -m; 81 : : 82 : 0 : sdrtt = (long *)&rt->sdrtt[timer]; 83 : 0 : m -= *sdrtt >> 2; 84 : 0 : *sdrtt += m; 85 : : 86 : : /* Set lower bound on the variance */ 87 : 0 : if (*sdrtt < RPC_RTO_MIN) 88 : 0 : *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 : 0 : unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer) 111 : : { 112 : : unsigned long res; 113 : : 114 : 0 : if (timer-- == 0) 115 : 0 : return rt->timeo; 116 : : 117 : 0 : res = ((rt->srtt[timer] + 7) >> 3) + rt->sdrtt[timer]; 118 : 0 : if (res > RPC_RTO_MAX) 119 : : res = RPC_RTO_MAX; 120 : : 121 : 0 : return res; 122 : : } 123 : : EXPORT_SYMBOL_GPL(rpc_calc_rto);