Commit ff3cc6a0 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] increase socket buffer for RPC over UDP

Make RPC over UDP use a socket buffer size that is large enough to fit
all the messages. Congestion control is in any case handled by the Van
Jacobson algoritm, and we need to work around a bug in
ip_build_xmit_slow() w.r.t. fragmentation when there is insufficient
buffer memory to fit the entire message.
parent 0be53f27
...@@ -425,7 +425,8 @@ int nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int sile ...@@ -425,7 +425,8 @@ int nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int sile
goto failure_kill_reqlist; goto failure_kill_reqlist;
} }
/* We're airborne */ /* We're airborne Set socket buffersize */
rpc_setbufsize(clnt, server->wsize + 100, server->rsize + 100);
/* Check whether to start the lockd process */ /* Check whether to start the lockd process */
if (!(server->flags & NFS_MOUNT_NONLM)) if (!(server->flags & NFS_MOUNT_NONLM))
......
...@@ -127,6 +127,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, ...@@ -127,6 +127,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
void rpc_restart_call(struct rpc_task *); void rpc_restart_call(struct rpc_task *);
void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset); void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset); void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
static __inline__ static __inline__
int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags) int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
......
...@@ -122,6 +122,9 @@ struct rpc_xprt { ...@@ -122,6 +122,9 @@ struct rpc_xprt {
unsigned long cong; /* current congestion */ unsigned long cong; /* current congestion */
unsigned long cwnd; /* congestion window */ unsigned long cwnd; /* congestion window */
unsigned int rcvsize, /* socket receive buffer size */
sndsize; /* socket send buffer size */
struct rpc_wait_queue sending; /* requests waiting to send */ struct rpc_wait_queue sending; /* requests waiting to send */
struct rpc_wait_queue resend; /* requests waiting to resend */ struct rpc_wait_queue resend; /* requests waiting to resend */
struct rpc_wait_queue pending; /* requests in flight */ struct rpc_wait_queue pending; /* requests in flight */
...@@ -177,6 +180,7 @@ int xprt_adjust_timeout(struct rpc_timeout *); ...@@ -177,6 +180,7 @@ int xprt_adjust_timeout(struct rpc_timeout *);
void xprt_release(struct rpc_task *); void xprt_release(struct rpc_task *);
void xprt_reconnect(struct rpc_task *); void xprt_reconnect(struct rpc_task *);
int xprt_clear_backlog(struct rpc_xprt *); int xprt_clear_backlog(struct rpc_xprt *);
void xprt_sock_setbufsize(struct rpc_xprt *);
#define XPRT_CONNECT 0 #define XPRT_CONNECT 0
......
...@@ -335,6 +335,20 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) ...@@ -335,6 +335,20 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
rpcproc_count(task->tk_client, task->tk_msg.rpc_proc)++; rpcproc_count(task->tk_client, task->tk_msg.rpc_proc)++;
} }
void
rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
{
struct rpc_xprt *xprt = clnt->cl_xprt;
xprt->sndsize = 0;
if (sndsize)
xprt->sndsize = sndsize + RPC_SLACK_SPACE;
xprt->rcvsize = 0;
if (rcvsize)
xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
xprt_sock_setbufsize(xprt);
}
/* /*
* Restart an (async) RPC call. Usually called from within the * Restart an (async) RPC call. Usually called from within the
* exit handler. * exit handler.
......
...@@ -50,6 +50,7 @@ EXPORT_SYMBOL(rpc_clnt_sigmask); ...@@ -50,6 +50,7 @@ EXPORT_SYMBOL(rpc_clnt_sigmask);
EXPORT_SYMBOL(rpc_clnt_sigunmask); EXPORT_SYMBOL(rpc_clnt_sigunmask);
EXPORT_SYMBOL(rpc_delay); EXPORT_SYMBOL(rpc_delay);
EXPORT_SYMBOL(rpc_restart_call); EXPORT_SYMBOL(rpc_restart_call);
EXPORT_SYMBOL(rpc_setbufsize);
/* Client transport */ /* Client transport */
EXPORT_SYMBOL(xprt_create_proto); EXPORT_SYMBOL(xprt_create_proto);
......
...@@ -1420,6 +1420,27 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock) ...@@ -1420,6 +1420,27 @@ xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
return 0; return 0;
} }
/*
* Set socket buffer length
*/
void
xprt_sock_setbufsize(struct rpc_xprt *xprt)
{
struct sock *sk = xprt->inet;
if (xprt->stream)
return;
if (xprt->rcvsize) {
sk->userlocks |= SOCK_RCVBUF_LOCK;
sk->rcvbuf = xprt->rcvsize * RPC_MAXCONG * 2;
}
if (xprt->sndsize) {
sk->userlocks |= SOCK_SNDBUF_LOCK;
sk->sndbuf = xprt->sndsize * RPC_MAXCONG * 2;
sk->write_space(sk);
}
}
/* /*
* Create a client socket given the protocol and peer address. * Create a client socket given the protocol and peer address.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment