timer.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. #include <asm/param.h>
  16. #include <linux/types.h>
  17. #include <linux/unistd.h>
  18. #include <linux/module.h>
  19. #include <linux/sunrpc/clnt.h>
  20. #define RPC_RTO_MAX (60*HZ)
  21. #define RPC_RTO_INIT (HZ/5)
  22. #define RPC_RTO_MIN (HZ/10)
  23. /**
  24. * rpc_init_rtt - Initialize an RPC RTT estimator context
  25. * @rt: context to initialize
  26. * @timeo: initial timeout value, in jiffies
  27. *
  28. */
  29. void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo)
  30. {
  31. unsigned long init = 0;
  32. unsigned int i;
  33. rt->timeo = timeo;
  34. if (timeo > RPC_RTO_INIT)
  35. init = (timeo - RPC_RTO_INIT) << 3;
  36. for (i = 0; i < 5; i++) {
  37. rt->srtt[i] = init;
  38. rt->sdrtt[i] = RPC_RTO_INIT;
  39. rt->ntimeouts[i] = 0;
  40. }
  41. }
  42. EXPORT_SYMBOL_GPL(rpc_init_rtt);
  43. /**
  44. * rpc_update_rtt - Update an RPC RTT estimator context
  45. * @rt: context to update
  46. * @timer: timer array index (request type)
  47. * @m: recent actual RTT, in jiffies
  48. *
  49. * NB: When computing the smoothed RTT and standard deviation,
  50. * be careful not to produce negative intermediate results.
  51. */
  52. void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m)
  53. {
  54. long *srtt, *sdrtt;
  55. if (timer-- == 0)
  56. return;
  57. /* jiffies wrapped; ignore this one */
  58. if (m < 0)
  59. return;
  60. if (m == 0)
  61. m = 1L;
  62. srtt = (long *)&rt->srtt[timer];
  63. m -= *srtt >> 3;
  64. *srtt += m;
  65. if (m < 0)
  66. m = -m;
  67. sdrtt = (long *)&rt->sdrtt[timer];
  68. m -= *sdrtt >> 2;
  69. *sdrtt += m;
  70. /* Set lower bound on the variance */
  71. if (*sdrtt < RPC_RTO_MIN)
  72. *sdrtt = RPC_RTO_MIN;
  73. }
  74. EXPORT_SYMBOL_GPL(rpc_update_rtt);
  75. /**
  76. * rpc_calc_rto - Provide an estimated timeout value
  77. * @rt: context to use for calculation
  78. * @timer: timer array index (request type)
  79. *
  80. * Estimate RTO for an NFS RPC sent via an unreliable datagram. Use
  81. * the mean and mean deviation of RTT for the appropriate type of RPC
  82. * for frequently issued RPCs, and a fixed default for the others.
  83. *
  84. * The justification for doing "other" this way is that these RPCs
  85. * happen so infrequently that timer estimation would probably be
  86. * stale. Also, since many of these RPCs are non-idempotent, a
  87. * conservative timeout is desired.
  88. *
  89. * getattr, lookup,
  90. * read, write, commit - A+4D
  91. * other - timeo
  92. */
  93. unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer)
  94. {
  95. unsigned long res;
  96. if (timer-- == 0)
  97. return rt->timeo;
  98. res = ((rt->srtt[timer] + 7) >> 3) + rt->sdrtt[timer];
  99. if (res > RPC_RTO_MAX)
  100. res = RPC_RTO_MAX;
  101. return res;
  102. }
  103. EXPORT_SYMBOL_GPL(rpc_calc_rto);