2005-04-17 02:20:36 +04:00
/*
* linux / net / sunrpc / timer . c
*
* Estimate RPC request round trip time .
*
* Based on packet round - trip and variance estimator algorithms described
* in appendix A of " Congestion Avoidance and Control " by Van Jacobson
* and Michael J . Karels ( ACM Computer Communication Review ; Proceedings
* of the Sigcomm ' 88 Symposium in Stanford , CA , August , 1988 ) .
*
* This RTT estimator is used only for RPC over datagram protocols .
*
* Copyright ( C ) 2002 Trond Myklebust < trond . myklebust @ fys . uio . no >
*/
# include <asm/param.h>
# include <linux/types.h>
# include <linux/unistd.h>
2007-09-10 21:45:36 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/sunrpc/clnt.h>
# define RPC_RTO_MAX (60*HZ)
# define RPC_RTO_INIT (HZ / 5)
# define RPC_RTO_MIN (HZ / 10)
2009-08-09 23:09:47 +04:00
/**
* rpc_init_rtt - Initialize an RPC RTT estimator context
* @ rt : context to initialize
* @ timeo : initial timeout value , in jiffies
*
*/
void rpc_init_rtt ( struct rpc_rtt * rt , unsigned long timeo )
2005-04-17 02:20:36 +04:00
{
unsigned long init = 0 ;
2012-04-15 09:58:06 +04:00
unsigned int i ;
2005-04-17 02:20:36 +04:00
rt - > timeo = timeo ;
if ( timeo > RPC_RTO_INIT )
init = ( timeo - RPC_RTO_INIT ) < < 3 ;
for ( i = 0 ; i < 5 ; i + + ) {
rt - > srtt [ i ] = init ;
rt - > sdrtt [ i ] = RPC_RTO_INIT ;
rt - > ntimeouts [ i ] = 0 ;
}
}
2007-09-10 21:45:36 +04:00
EXPORT_SYMBOL_GPL ( rpc_init_rtt ) ;
2005-04-17 02:20:36 +04:00
2009-08-09 23:09:47 +04:00
/**
* rpc_update_rtt - Update an RPC RTT estimator context
* @ rt : context to update
* @ timer : timer array index ( request type )
* @ m : recent actual RTT , in jiffies
*
2005-04-17 02:20:36 +04:00
* NB : When computing the smoothed RTT and standard deviation ,
* be careful not to produce negative intermediate results .
*/
2012-04-15 09:58:06 +04:00
void rpc_update_rtt ( struct rpc_rtt * rt , unsigned int timer , long m )
2005-04-17 02:20:36 +04:00
{
long * srtt , * sdrtt ;
if ( timer - - = = 0 )
return ;
/* jiffies wrapped; ignore this one */
if ( m < 0 )
return ;
if ( m = = 0 )
m = 1L ;
srtt = ( long * ) & rt - > srtt [ timer ] ;
m - = * srtt > > 3 ;
* srtt + = m ;
if ( m < 0 )
m = - m ;
sdrtt = ( long * ) & rt - > sdrtt [ timer ] ;
m - = * sdrtt > > 2 ;
* sdrtt + = m ;
/* Set lower bound on the variance */
if ( * sdrtt < RPC_RTO_MIN )
* sdrtt = RPC_RTO_MIN ;
}
2007-09-10 21:45:36 +04:00
EXPORT_SYMBOL_GPL ( rpc_update_rtt ) ;
2005-04-17 02:20:36 +04:00
2009-08-09 23:09:47 +04:00
/**
* rpc_calc_rto - Provide an estimated timeout value
* @ rt : context to use for calculation
* @ timer : timer array index ( request type )
*
* Estimate RTO for an NFS RPC sent via an unreliable datagram . Use
* the mean and mean deviation of RTT for the appropriate type of RPC
* for frequently issued RPCs , and a fixed default for the others .
*
* The justification for doing " other " this way is that these RPCs
* happen so infrequently that timer estimation would probably be
* stale . Also , since many of these RPCs are non - idempotent , a
* conservative timeout is desired .
*
2005-04-17 02:20:36 +04:00
* getattr , lookup ,
* read , write , commit - A + 4 D
* other - timeo
*/
2012-04-15 09:58:06 +04:00
unsigned long rpc_calc_rto ( struct rpc_rtt * rt , unsigned int timer )
2005-04-17 02:20:36 +04:00
{
unsigned long res ;
if ( timer - - = = 0 )
return rt - > timeo ;
res = ( ( rt - > srtt [ timer ] + 7 ) > > 3 ) + rt - > sdrtt [ timer ] ;
if ( res > RPC_RTO_MAX )
res = RPC_RTO_MAX ;
return res ;
}
2007-09-10 21:45:36 +04:00
EXPORT_SYMBOL_GPL ( rpc_calc_rto ) ;