^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/net/sunrpc/timer.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Estimate RPC request round trip time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on packet round-trip and variance estimator algorithms described
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * in appendix A of "Congestion Avoidance and Control" by Van Jacobson
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * and Michael J. Karels (ACM Computer Communication Review; Proceedings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * of the Sigcomm '88 Symposium in Stanford, CA, August, 1988).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This RTT estimator is used only for RPC over datagram protocols.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/param.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/sunrpc/clnt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define RPC_RTO_MAX (60*HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define RPC_RTO_INIT (HZ/5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define RPC_RTO_MIN (HZ/10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * rpc_init_rtt - Initialize an RPC RTT estimator context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @rt: context to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @timeo: initial timeout value, in jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long init = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) rt->timeo = timeo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (timeo > RPC_RTO_INIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) init = (timeo - RPC_RTO_INIT) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) rt->srtt[i] = init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) rt->sdrtt[i] = RPC_RTO_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) rt->ntimeouts[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) EXPORT_SYMBOL_GPL(rpc_init_rtt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * rpc_update_rtt - Update an RPC RTT estimator context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @rt: context to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * @timer: timer array index (request type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * @m: recent actual RTT, in jiffies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * NB: When computing the smoothed RTT and standard deviation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * be careful not to produce negative intermediate results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) long *srtt, *sdrtt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (timer-- == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* jiffies wrapped; ignore this one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (m < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (m == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) m = 1L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) srtt = (long *)&rt->srtt[timer];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) m -= *srtt >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *srtt += m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (m < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) m = -m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) sdrtt = (long *)&rt->sdrtt[timer];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) m -= *sdrtt >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *sdrtt += m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Set lower bound on the variance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (*sdrtt < RPC_RTO_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *sdrtt = RPC_RTO_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) EXPORT_SYMBOL_GPL(rpc_update_rtt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * rpc_calc_rto - Provide an estimated timeout value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @rt: context to use for calculation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @timer: timer array index (request type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Estimate RTO for an NFS RPC sent via an unreliable datagram. Use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * the mean and mean deviation of RTT for the appropriate type of RPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * for frequently issued RPCs, and a fixed default for the others.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * The justification for doing "other" this way is that these RPCs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * happen so infrequently that timer estimation would probably be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * stale. Also, since many of these RPCs are non-idempotent, a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * conservative timeout is desired.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * getattr, lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * read, write, commit - A+4D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * other - timeo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned long res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (timer-- == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return rt->timeo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) res = ((rt->srtt[timer] + 7) >> 3) + rt->sdrtt[timer];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (res > RPC_RTO_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) res = RPC_RTO_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) EXPORT_SYMBOL_GPL(rpc_calc_rto);