timer.c 2.9 KB

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