diff -X /home/cel/src/linux/dont-diff -Naurp 04-call_encode/include/linux/sunrpc/debug.h 05-rpc-slot-table/include/linux/sunrpc/debug.h --- 04-call_encode/include/linux/sunrpc/debug.h 2001-11-22 14:46:19.000000000 -0500 +++ 05-rpc-slot-table/include/linux/sunrpc/debug.h 2004-01-29 21:56:42.000000000 -0500 @@ -90,6 +90,8 @@ enum { CTL_NFSDEBUG, CTL_NFSDDEBUG, CTL_NLMDEBUG, + CTL_SLOTTABLE_UDP, + CTL_SLOTTABLE_TCP, }; #endif /* _LINUX_SUNRPC_DEBUG_H_ */ diff -X /home/cel/src/linux/dont-diff -Naurp 04-call_encode/include/linux/sunrpc/xprt.h 05-rpc-slot-table/include/linux/sunrpc/xprt.h --- 04-call_encode/include/linux/sunrpc/xprt.h 2003-11-28 13:26:21.000000000 -0500 +++ 05-rpc-slot-table/include/linux/sunrpc/xprt.h 2004-01-29 21:56:42.000000000 -0500 @@ -28,16 +28,18 @@ * * Upper procedures may check whether a request would block waiting for * a free RPC slot by using the RPC_CONGESTED() macro. - * - * Note: on machines with low memory we should probably use a smaller - * MAXREQS value: At 32 outstanding reqs with 8 megs of RAM, fragment - * reassembly will frequently run out of memory. */ -#define RPC_MAXCONG (16) -#define RPC_MAXREQS RPC_MAXCONG -#define RPC_CWNDSCALE (256) -#define RPC_MAXCWND (RPC_MAXCONG * RPC_CWNDSCALE) +extern unsigned int xprt_udp_slot_table_entries; +extern unsigned int xprt_tcp_slot_table_entries; + +#define RPC_MIN_SLOT_TABLE (2U) +#define RPC_DEF_SLOT_TABLE (16U) +#define RPC_MAX_SLOT_TABLE (128U) + +#define RPC_CWNDSHIFT (8U) +#define RPC_CWNDSCALE (1U << RPC_CWNDSHIFT) #define RPC_INITCWND RPC_CWNDSCALE +#define RPC_MAXCWND(xprt) ((xprt)->max_reqs << RPC_CWNDSHIFT) #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) /* Default timeout values */ @@ -146,7 +148,7 @@ struct rpc_xprt { struct rpc_wait_queue pending; /* requests in flight */ struct rpc_wait_queue backlog; /* waiting for slot */ struct rpc_rqst * free; /* free slots */ - struct rpc_rqst slot[RPC_MAXREQS]; + unsigned int max_reqs; /* total slots */ unsigned long sockstate; /* Socket state */ unsigned char shutdown : 1, /* being shut down */ nocong : 1, /* no congestion control */ diff -X /home/cel/src/linux/dont-diff -Naurp 04-call_encode/net/sunrpc/sunrpc_syms.c 05-rpc-slot-table/net/sunrpc/sunrpc_syms.c --- 04-call_encode/net/sunrpc/sunrpc_syms.c 2003-06-13 10:51:39.000000000 -0400 +++ 05-rpc-slot-table/net/sunrpc/sunrpc_syms.c 2004-01-29 21:51:56.000000000 -0500 @@ -55,6 +55,8 @@ EXPORT_SYMBOL(rpc_setbufsize); EXPORT_SYMBOL(xprt_create_proto); EXPORT_SYMBOL(xprt_destroy); EXPORT_SYMBOL(xprt_set_timeout); +EXPORT_SYMBOL(xprt_udp_slot_table_entries); +EXPORT_SYMBOL(xprt_tcp_slot_table_entries); /* Client credential cache */ EXPORT_SYMBOL(rpcauth_register); diff -X /home/cel/src/linux/dont-diff -Naurp 04-call_encode/net/sunrpc/sysctl.c 05-rpc-slot-table/net/sunrpc/sysctl.c --- 04-call_encode/net/sunrpc/sysctl.c 2003-06-13 10:51:39.000000000 -0400 +++ 05-rpc-slot-table/net/sunrpc/sysctl.c 2004-01-29 21:51:56.000000000 -0500 @@ -1,7 +1,7 @@ /* * linux/net/sunrpc/sysctl.c * - * Sysctl interface to sunrpc module. This is for debugging only now. + * Sysctl interface to sunrpc module. * * I would prefer to register the sunrpc table below sys/net, but that's * impossible at the moment. @@ -20,6 +20,7 @@ #include #include #include +#include /* * Declare the debug flags here @@ -115,6 +116,9 @@ done: return 0; } +static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE; +static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE; + #define DIRENTRY(nam1, nam2, child) \ {CTL_##nam1, #nam2, NULL, 0, 0555, child } #define DBGENTRY(nam1, nam2) \ @@ -126,6 +130,14 @@ static ctl_table debug_table[] = { DBGENTRY(NFS, nfs), DBGENTRY(NFSD, nfsd), DBGENTRY(NLM, nlm), + { CTL_SLOTTABLE_UDP, "udp_slot_table_entries", + &xprt_udp_slot_table_entries, sizeof(unsigned int), 0644, NULL, + &proc_dointvec_minmax, &sysctl_intvec, NULL, + &min_slot_table_size, &max_slot_table_size }, + { CTL_SLOTTABLE_TCP, "tcp_slot_table_entries", + &xprt_tcp_slot_table_entries, sizeof(unsigned int), 0644, NULL, + &proc_dointvec_minmax, &sysctl_intvec, NULL, + &min_slot_table_size, &max_slot_table_size }, {0} }; diff -X /home/cel/src/linux/dont-diff -Naurp 04-call_encode/net/sunrpc/xprt.c 05-rpc-slot-table/net/sunrpc/xprt.c --- 04-call_encode/net/sunrpc/xprt.c 2003-11-28 13:26:21.000000000 -0500 +++ 05-rpc-slot-table/net/sunrpc/xprt.c 2004-01-29 21:51:56.000000000 -0500 @@ -343,8 +343,8 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, /* The (cwnd >> 1) term makes sure * the result gets rounded properly. */ cwnd += (RPC_CWNDSCALE * RPC_CWNDSCALE + (cwnd >> 1)) / cwnd; - if (cwnd > RPC_MAXCWND) - cwnd = RPC_MAXCWND; + if (cwnd > RPC_MAXCWND(xprt)) + cwnd = RPC_MAXCWND(xprt); __xprt_lock_write_next(xprt); } else if (result == -ETIMEDOUT) { cwnd >>= 1; @@ -1373,6 +1373,9 @@ xprt_set_timeout(struct rpc_timeout *to, to->to_exponential = 0; } +unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; +unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE << 2; + /* * Initialize an RPC client */ @@ -1380,21 +1383,28 @@ static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to) { struct rpc_xprt *xprt; - struct rpc_rqst *req; + unsigned int entries, xprt_size; + struct rpc_rqst *req; int i; dprintk("RPC: setting up %s transport...\n", proto == IPPROTO_UDP? "UDP" : "TCP"); - if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) + entries = (proto == IPPROTO_TCP)? + xprt_tcp_slot_table_entries : xprt_udp_slot_table_entries; + xprt_size = sizeof(struct rpc_xprt) + sizeof(struct rpc_rqst) * entries; + + if ((xprt = kmalloc(xprt_size, GFP_KERNEL)) == NULL) return NULL; - memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */ + memset(xprt, 0, xprt_size); + xprt->free = (struct rpc_rqst *)(xprt + 1); + xprt->max_reqs = entries; xprt->addr = *ap; xprt->prot = proto; xprt->stream = (proto == IPPROTO_TCP)? 1 : 0; if (xprt->stream) { - xprt->cwnd = RPC_MAXCWND; + xprt->cwnd = RPC_MAXCWND(xprt); xprt->nocong = 1; } else xprt->cwnd = RPC_INITCWND; @@ -1417,15 +1427,17 @@ xprt_setup(int proto, struct sockaddr_in INIT_RPC_WAITQ(&xprt->backlog, "xprt_backlog"); /* initialize free list */ - for (i = 0, req = xprt->slot; i < RPC_MAXREQS-1; i++, req++) + entries--; + req = xprt->free; + for (i = 0; i < entries; i++, req++) req->rq_next = req + 1; req->rq_next = NULL; - xprt->free = xprt->slot; /* Check whether we want to use a reserved port */ xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; - dprintk("RPC: created transport %p\n", xprt); + dprintk("RPC: created transport %p with %u slots\n", xprt, + xprt->max_reqs); return xprt; } @@ -1507,11 +1519,11 @@ xprt_sock_setbufsize(struct rpc_xprt *xp return; if (xprt->rcvsize) { sk->userlocks |= SOCK_RCVBUF_LOCK; - sk->rcvbuf = xprt->rcvsize * RPC_MAXCONG * 2; + sk->rcvbuf = xprt->rcvsize * xprt->max_reqs * 2; } if (xprt->sndsize) { sk->userlocks |= SOCK_SNDBUF_LOCK; - sk->sndbuf = xprt->sndsize * RPC_MAXCONG * 2; + sk->sndbuf = xprt->sndsize * xprt->max_reqs * 2; sk->write_space(sk); } }