diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/fs/nfs/dir.c 05-rpc-slot-table/fs/nfs/dir.c --- 00-stock/fs/nfs/dir.c 2002-11-28 18:53:15.000000000 -0500 +++ 05-rpc-slot-table/fs/nfs/dir.c 2004-01-29 21:48:58.000000000 -0500 @@ -1065,6 +1065,7 @@ go_ahead: nfs_zap_caches(new_dir); nfs_zap_caches(old_dir); + NFS_CACHEINV(old_inode); error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, new_dir, &new_dentry->d_name); out: diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/fs/nfs/direct.c 05-rpc-slot-table/fs/nfs/direct.c --- 00-stock/fs/nfs/direct.c 2004-01-29 18:29:12.000000000 -0500 +++ 05-rpc-slot-table/fs/nfs/direct.c 2004-01-29 21:50:00.000000000 -0500 @@ -356,6 +356,8 @@ nfs_direct_IO(int rw, struct file *file, struct inode *inode = dentry->d_inode; loff_t offset = (loff_t) blocknr << inode->i_blkbits; + up(&inode->i_sem); + switch (rw) { case READ: dfprintk(VFS, @@ -377,6 +379,8 @@ nfs_direct_IO(int rw, struct file *file, break; } + down(&inode->i_sem); + dfprintk(VFS, "NFS: direct_IO result = %d\n", result); return result; } diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/fs/nfs/file.c 05-rpc-slot-table/fs/nfs/file.c --- 00-stock/fs/nfs/file.c 2003-08-25 07:44:43.000000000 -0400 +++ 05-rpc-slot-table/fs/nfs/file.c 2004-01-29 18:41:21.000000000 -0500 @@ -81,7 +81,7 @@ nfs_file_flush(struct file *file) if (file->f_mode & FMODE_READ) nfs_pagein_inode(inode, 0, 0); - status = nfs_wb_file(inode, file); + status = nfs_wb_all(inode); if (!status) { status = file->f_error; file->f_error = 0; @@ -136,7 +136,7 @@ nfs_fsync(struct file *file, struct dent dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino); lock_kernel(); - status = nfs_wb_file(inode, file); + status = nfs_wb_all(inode); if (!status) { status = file->f_error; file->f_error = 0; diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/fs/nfs/inode.c 05-rpc-slot-table/fs/nfs/inode.c --- 00-stock/fs/nfs/inode.c 2002-11-28 18:53:15.000000000 -0500 +++ 05-rpc-slot-table/fs/nfs/inode.c 2004-01-29 18:40:41.000000000 -0500 @@ -121,7 +121,7 @@ nfs_write_inode(struct inode *inode, int { int flags = sync ? FLUSH_WAIT : 0; - nfs_sync_file(inode, NULL, 0, 0, flags); + nfs_sync_file(inode, 0, 0, flags); } static void diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/fs/nfs/pagelist.c 05-rpc-slot-table/fs/nfs/pagelist.c --- 00-stock/fs/nfs/pagelist.c 2003-06-13 10:51:37.000000000 -0400 +++ 05-rpc-slot-table/fs/nfs/pagelist.c 2004-01-29 18:36:50.000000000 -0500 @@ -364,7 +364,6 @@ nfs_scan_lru_timeout(struct list_head *h * nfs_scan_list - Scan a list for matching requests * @head: One of the NFS inode request lists * @dst: Destination list - * @file: if set, ensure we match requests from this file * @idx_start: lower bound of page->index to scan * @npages: idx_start + npages sets the upper bound to scan. * @@ -376,7 +375,6 @@ nfs_scan_lru_timeout(struct list_head *h */ int nfs_scan_list(struct list_head *head, struct list_head *dst, - struct file *file, unsigned long idx_start, unsigned int npages) { struct list_head *pos, *tmp; @@ -395,9 +393,6 @@ nfs_scan_list(struct list_head *head, st req = nfs_list_entry(pos); - if (file && req->wb_file != file) - continue; - pg_idx = page_index(req->wb_page); if (pg_idx < idx_start) continue; diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/fs/nfs/read.c 05-rpc-slot-table/fs/nfs/read.c --- 00-stock/fs/nfs/read.c 2003-06-13 10:51:37.000000000 -0400 +++ 05-rpc-slot-table/fs/nfs/read.c 2004-01-29 18:36:50.000000000 -0500 @@ -371,7 +371,7 @@ static int nfs_scan_read(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) { int res; - res = nfs_scan_list(&inode->u.nfs_i.read, dst, NULL, idx_start, npages); + res = nfs_scan_list(&inode->u.nfs_i.read, dst, idx_start, npages); inode->u.nfs_i.nread -= res; if ((inode->u.nfs_i.nread == 0) != list_empty(&inode->u.nfs_i.read)) printk(KERN_ERR "NFS: desynchronized value of nfs_i.nread.\n"); diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/fs/nfs/write.c 05-rpc-slot-table/fs/nfs/write.c --- 00-stock/fs/nfs/write.c 2003-11-28 13:26:21.000000000 -0500 +++ 05-rpc-slot-table/fs/nfs/write.c 2004-01-29 18:39:35.000000000 -0500 @@ -445,7 +445,7 @@ nfs_mark_request_commit(struct nfs_page * Interruptible by signals only if mounted with intr flag. */ static int -nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_start, unsigned int npages) +nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages) { struct list_head *p, *head; unsigned long idx_end; @@ -464,9 +464,6 @@ nfs_wait_on_requests(struct inode *inode unsigned long pg_idx; struct nfs_page *req = nfs_inode_wb_entry(p); - if (file && req->wb_file != file) - continue; - pg_idx = page_index(req->wb_page); if (pg_idx < idx_start) break; @@ -538,7 +535,6 @@ nfs_scan_lru_dirty(struct nfs_server *se * nfs_scan_dirty - Scan an inode for dirty requests * @inode: NFS inode to scan * @dst: destination list - * @file: if set, ensure we match requests from this file * @idx_start: lower bound of page->index to scan. * @npages: idx_start + npages sets the upper bound to scan. * @@ -546,10 +542,10 @@ nfs_scan_lru_dirty(struct nfs_server *se * The requests are *not* checked to ensure that they form a contiguous set. */ static int -nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages) +nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) { int res; - res = nfs_scan_list(&inode->u.nfs_i.dirty, dst, file, idx_start, npages); + res = nfs_scan_list(&inode->u.nfs_i.dirty, dst, idx_start, npages); inode->u.nfs_i.ndirty -= res; if ((inode->u.nfs_i.ndirty == 0) != list_empty(&inode->u.nfs_i.dirty)) printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n"); @@ -577,7 +573,7 @@ nfs_scan_lru_commit_timeout(struct nfs_s npages = nfs_scan_lru_timeout(&server->lru_commit, dst, 1); if (npages) { inode = nfs_list_entry(dst->next)->wb_inode; - npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, NULL, 0, 0); + npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, 0, 0); inode->u.nfs_i.ncommit -= npages; } return npages; @@ -604,7 +600,7 @@ nfs_scan_lru_commit(struct nfs_server *s npages = nfs_scan_lru(&server->lru_commit, dst, 1); if (npages) { inode = nfs_list_entry(dst->next)->wb_inode; - npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, NULL, 0, 0); + npages += nfs_scan_list(&inode->u.nfs_i.commit, dst, 0, 0); inode->u.nfs_i.ncommit -= npages; } return npages; @@ -614,7 +610,6 @@ nfs_scan_lru_commit(struct nfs_server *s * nfs_scan_commit - Scan an inode for commit requests * @inode: NFS inode to scan * @dst: destination list - * @file: if set, ensure we collect requests from this file only. * @idx_start: lower bound of page->index to scan. * @npages: idx_start + npages sets the upper bound to scan. * @@ -622,10 +617,10 @@ nfs_scan_lru_commit(struct nfs_server *s * The requests are *not* checked to ensure that they form a contiguous set. */ static int -nfs_scan_commit(struct inode *inode, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages) +nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) { int res; - res = nfs_scan_list(&inode->u.nfs_i.commit, dst, file, idx_start, npages); + res = nfs_scan_list(&inode->u.nfs_i.commit, dst, idx_start, npages); inode->u.nfs_i.ncommit -= res; if ((inode->u.nfs_i.ncommit == 0) != list_empty(&inode->u.nfs_i.commit)) printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); @@ -753,12 +748,12 @@ nfs_strategy(struct inode *inode) #ifdef CONFIG_NFS_V3 if (NFS_PROTO(inode)->version == 2) { if (dirty >= NFS_STRATEGY_PAGES * wpages) - nfs_flush_file(inode, NULL, 0, 0, 0); + nfs_flush_file(inode, 0, 0, 0); } else if (dirty >= wpages) - nfs_flush_file(inode, NULL, 0, 0, 0); + nfs_flush_file(inode, 0, 0, 0); #else if (dirty >= NFS_STRATEGY_PAGES * wpages) - nfs_flush_file(inode, NULL, 0, 0, 0); + nfs_flush_file(inode, 0, 0, 0); #endif } @@ -1250,7 +1245,7 @@ nfs_commit_done(struct rpc_task *task) } #endif -int nfs_flush_file(struct inode *inode, struct file *file, unsigned long idx_start, +int nfs_flush_file(struct inode *inode, unsigned long idx_start, unsigned int npages, int how) { LIST_HEAD(head); @@ -1258,7 +1253,7 @@ int nfs_flush_file(struct inode *inode, error = 0; spin_lock(&nfs_wreq_lock); - res = nfs_scan_dirty(inode, &head, file, idx_start, npages); + res = nfs_scan_dirty(inode, &head, idx_start, npages); spin_unlock(&nfs_wreq_lock); if (res) error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how); @@ -1268,7 +1263,7 @@ int nfs_flush_file(struct inode *inode, } #ifdef CONFIG_NFS_V3 -int nfs_commit_file(struct inode *inode, struct file *file, unsigned long idx_start, +int nfs_commit_file(struct inode *inode, unsigned long idx_start, unsigned int npages, int how) { LIST_HEAD(head); @@ -1276,7 +1271,7 @@ int nfs_commit_file(struct inode *inode, error = 0; spin_lock(&nfs_wreq_lock); - res = nfs_scan_commit(inode, &head, file, idx_start, npages); + res = nfs_scan_commit(inode, &head, idx_start, npages); spin_unlock(&nfs_wreq_lock); if (res) error = nfs_commit_list(&head, how); @@ -1286,7 +1281,7 @@ int nfs_commit_file(struct inode *inode, } #endif -int nfs_sync_file(struct inode *inode, struct file *file, unsigned long idx_start, +int nfs_sync_file(struct inode *inode, unsigned long idx_start, unsigned int npages, int how) { int error, @@ -1295,18 +1290,15 @@ int nfs_sync_file(struct inode *inode, s wait = how & FLUSH_WAIT; how &= ~FLUSH_WAIT; - if (!inode && file) - inode = file->f_dentry->d_inode; - do { error = 0; if (wait) - error = nfs_wait_on_requests(inode, file, idx_start, npages); + error = nfs_wait_on_requests(inode, idx_start, npages); if (error == 0) - error = nfs_flush_file(inode, file, idx_start, npages, how); + error = nfs_flush_file(inode, idx_start, npages, how); #ifdef CONFIG_NFS_V3 if (error == 0) - error = nfs_commit_file(inode, file, idx_start, npages, how); + error = nfs_commit_file(inode, idx_start, npages, how); #endif } while (error > 0); return error; diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/include/linux/nfs_fs.h 05-rpc-slot-table/include/linux/nfs_fs.h --- 00-stock/include/linux/nfs_fs.h 2003-08-25 07:44:44.000000000 -0400 +++ 05-rpc-slot-table/include/linux/nfs_fs.h 2004-01-29 22:18:13.000000000 -0500 @@ -209,13 +209,13 @@ extern int nfs_updatepage(struct file * * Try to write back everything synchronously (but check the * return value!) */ -extern int nfs_sync_file(struct inode *, struct file *, unsigned long, unsigned int, int); -extern int nfs_flush_file(struct inode *, struct file *, unsigned long, unsigned int, int); +extern int nfs_sync_file(struct inode *, unsigned long, unsigned int, int); +extern int nfs_flush_file(struct inode *, unsigned long, unsigned int, int); extern int nfs_flush_list(struct list_head *, int, int); extern int nfs_scan_lru_dirty(struct nfs_server *, struct list_head *); extern int nfs_scan_lru_dirty_timeout(struct nfs_server *, struct list_head *); #ifdef CONFIG_NFS_V3 -extern int nfs_commit_file(struct inode *, struct file *, unsigned long, unsigned int, int); +extern int nfs_commit_file(struct inode *, unsigned long, unsigned int, int); extern int nfs_commit_list(struct list_head *, int); extern int nfs_scan_lru_commit(struct nfs_server *, struct list_head *); extern int nfs_scan_lru_commit_timeout(struct nfs_server *, struct list_head *); @@ -236,7 +236,7 @@ nfs_have_writebacks(struct inode *inode) static inline int nfs_wb_all(struct inode *inode) { - int error = nfs_sync_file(inode, 0, 0, 0, FLUSH_WAIT); + int error = nfs_sync_file(inode, 0, 0, FLUSH_WAIT); return (error < 0) ? error : 0; } @@ -246,17 +246,7 @@ nfs_wb_all(struct inode *inode) static inline int nfs_wb_page(struct inode *inode, struct page* page) { - int error = nfs_sync_file(inode, 0, page_index(page), 1, FLUSH_WAIT | FLUSH_STABLE); - return (error < 0) ? error : 0; -} - -/* - * Write back all pending writes for one user.. - */ -static inline int -nfs_wb_file(struct inode *inode, struct file *file) -{ - int error = nfs_sync_file(inode, file, 0, 0, FLUSH_WAIT); + int error = nfs_sync_file(inode, page_index(page), 1, FLUSH_WAIT | FLUSH_STABLE); return (error < 0) ? error : 0; } diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/include/linux/nfs_page.h 05-rpc-slot-table/include/linux/nfs_page.h --- 00-stock/include/linux/nfs_page.h 2002-08-02 20:39:45.000000000 -0400 +++ 05-rpc-slot-table/include/linux/nfs_page.h 2004-01-29 22:22:07.000000000 -0500 @@ -53,7 +53,7 @@ extern void nfs_list_add_request(struct extern int nfs_scan_lru(struct list_head *, struct list_head *, int); extern int nfs_scan_lru_timeout(struct list_head *, struct list_head *, int); extern int nfs_scan_list(struct list_head *, struct list_head *, - struct file *, unsigned long, unsigned int); + unsigned long, unsigned int); extern int nfs_coalesce_requests(struct list_head *, struct list_head *, unsigned int); extern int nfs_wait_on_request(struct nfs_page *); diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/include/linux/sunrpc/debug.h 05-rpc-slot-table/include/linux/sunrpc/debug.h --- 00-stock/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 00-stock/include/linux/sunrpc/xprt.h 05-rpc-slot-table/include/linux/sunrpc/xprt.h --- 00-stock/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 00-stock/net/sunrpc/auth_unix.c 05-rpc-slot-table/net/sunrpc/auth_unix.c --- 00-stock/net/sunrpc/auth_unix.c 2001-08-16 12:39:37.000000000 -0400 +++ 05-rpc-slot-table/net/sunrpc/auth_unix.c 2004-01-29 22:46:06.000000000 -0500 @@ -12,6 +12,7 @@ #include #include #include +#include #define NFS_NGROUPS 16 struct unx_cred { @@ -169,19 +170,14 @@ unx_marshal(struct rpc_task *task, u32 * struct rpc_clnt *clnt = task->tk_client; struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred; u32 *base, *hold; - int i, n; + int i; *p++ = htonl(RPC_AUTH_UNIX); base = p++; *p++ = htonl(jiffies/HZ); - /* - * Copy the UTS nodename captured when the client was created. - */ - n = clnt->cl_nodelen; - *p++ = htonl(n); - memcpy(p, clnt->cl_nodename, n); - p += (n + 3) >> 2; + /* Copy the UTS nodename captured when the client was created */ + p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen); /* Note: we don't use real uid if it involves raising priviledge */ if (ruid && cred->uc_uid != 0 && cred->uc_gid != 0) { diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/net/sunrpc/clnt.c 05-rpc-slot-table/net/sunrpc/clnt.c --- 00-stock/net/sunrpc/clnt.c 2003-11-28 13:26:21.000000000 -0500 +++ 05-rpc-slot-table/net/sunrpc/clnt.c 2004-01-29 21:51:03.000000000 -0500 @@ -524,9 +524,6 @@ call_encode(struct rpc_task *task) rcvbuf->page_len = 0; rcvbuf->len = bufsiz; - /* Zero buffer so we have automatic zero-padding of opaque & string */ - memset(task->tk_buffer, 0, bufsiz); - /* Encode header and provided arguments */ encode = rpcproc_encode(clnt, task->tk_msg.rpc_proc); if (!(p = call_header(task))) { diff -X /home/cel/src/linux/dont-diff -Naurp 00-stock/net/sunrpc/sunrpc_syms.c 05-rpc-slot-table/net/sunrpc/sunrpc_syms.c --- 00-stock/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 00-stock/net/sunrpc/sysctl.c 05-rpc-slot-table/net/sunrpc/sysctl.c --- 00-stock/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 00-stock/net/sunrpc/xprt.c 05-rpc-slot-table/net/sunrpc/xprt.c --- 00-stock/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); } }