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