| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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> | 
| \"Talpey, Thomas\ | 1244480 | 2007-09-10 13:45:36 -0400 | [diff] [blame] | 20 | #include <linux/module.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 |  | 
 | 22 | #include <linux/sunrpc/clnt.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 23 |  | 
 | 24 | #define RPC_RTO_MAX (60*HZ) | 
 | 25 | #define RPC_RTO_INIT (HZ/5) | 
 | 26 | #define RPC_RTO_MIN (HZ/10) | 
 | 27 |  | 
| Chuck Lever | c05988c | 2009-08-09 15:09:47 -0400 | [diff] [blame] | 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 | void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 35 | { | 
 | 36 | 	unsigned long init = 0; | 
 | 37 | 	unsigned 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 | } | 
| \"Talpey, Thomas\ | 1244480 | 2007-09-10 13:45:36 -0400 | [diff] [blame] | 49 | EXPORT_SYMBOL_GPL(rpc_init_rtt); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 50 |  | 
| Chuck Lever | c05988c | 2009-08-09 15:09:47 -0400 | [diff] [blame] | 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 |  * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 57 |  * NB: When computing the smoothed RTT and standard deviation, | 
 | 58 |  *     be careful not to produce negative intermediate results. | 
 | 59 |  */ | 
| Chuck Lever | c05988c | 2009-08-09 15:09:47 -0400 | [diff] [blame] | 60 | void rpc_update_rtt(struct rpc_rtt *rt, unsigned timer, long m) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | } | 
| \"Talpey, Thomas\ | 1244480 | 2007-09-10 13:45:36 -0400 | [diff] [blame] | 89 | EXPORT_SYMBOL_GPL(rpc_update_rtt); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 |  | 
| Chuck Lever | c05988c | 2009-08-09 15:09:47 -0400 | [diff] [blame] | 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 |  * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 |  * getattr, lookup, | 
 | 106 |  * read, write, commit     - A+4D | 
 | 107 |  * other                   - timeo | 
 | 108 |  */ | 
| Chuck Lever | c05988c | 2009-08-09 15:09:47 -0400 | [diff] [blame] | 109 | unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned timer) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | } | 
| \"Talpey, Thomas\ | 1244480 | 2007-09-10 13:45:36 -0400 | [diff] [blame] | 122 | EXPORT_SYMBOL_GPL(rpc_calc_rto); |