aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-22 15:55:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-22 15:55:50 -0400
commit7e0338c0de18c50f09aea1fbef45110cf7d64a3c (patch)
tree30a935c1f6eee7125a9fbb802a33292b1f7268fa /net
parentdf36b439c5fedefe013d4449cb6a50d15e2f4d70 (diff)
parent47fcb03fefee2501e79176932a4184fc24d6f8ec (diff)
Merge branch 'for-2.6.31' of git://fieldses.org/git/linux-nfsd
* 'for-2.6.31' of git://fieldses.org/git/linux-nfsd: (60 commits) SUNRPC: Fix the TCP server's send buffer accounting nfsd41: Backchannel: minorversion support for the back channel nfsd41: Backchannel: cleanup nfs4.0 callback encode routines nfsd41: Remove ip address collision detection case nfsd: optimise the starting of zero threads when none are running. nfsd: don't take nfsd_mutex twice when setting number of threads. nfsd41: sanity check client drc maxreqs nfsd41: move channel attributes from nfsd4_session to a nfsd4_channel_attr struct NFS: kill off complicated macro 'PROC' sunrpc: potential memory leak in function rdma_read_xdr nfsd: minor nfsd_vfs_write cleanup nfsd: Pull write-gathering code out of nfsd_vfs_write nfsd: track last inode only in use_wgather case sunrpc: align cache_clean work's timer nfsd: Use write gathering only with NFSv2 NFSv4: kill off complicated macro 'PROC' NFSv4: do exact check about attribute specified knfsd: remove unreported filehandle stats counters knfsd: fix reply cache memory corruption knfsd: reply cache cleanups ...
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/cache.c2
-rw-r--r--net/sunrpc/svc_xprt.c57
-rw-r--r--net/sunrpc/svcsock.c122
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c8
4 files changed, 129 insertions, 60 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 20029a79a5de..ff0c23053d2f 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -488,7 +488,7 @@ static void do_cache_clean(struct work_struct *work)
488{ 488{
489 int delay = 5; 489 int delay = 5;
490 if (cache_clean() == -1) 490 if (cache_clean() == -1)
491 delay = 30*HZ; 491 delay = round_jiffies_relative(30*HZ);
492 492
493 if (list_empty(&cache_list)) 493 if (list_empty(&cache_list))
494 delay = 0; 494 delay = 0;
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index c200d92e57e4..6f33d33cc064 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -11,6 +11,7 @@
11#include <net/sock.h> 11#include <net/sock.h>
12#include <linux/sunrpc/stats.h> 12#include <linux/sunrpc/stats.h>
13#include <linux/sunrpc/svc_xprt.h> 13#include <linux/sunrpc/svc_xprt.h>
14#include <linux/sunrpc/svcsock.h>
14 15
15#define RPCDBG_FACILITY RPCDBG_SVCXPRT 16#define RPCDBG_FACILITY RPCDBG_SVCXPRT
16 17
@@ -1097,36 +1098,58 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
1097} 1098}
1098EXPORT_SYMBOL_GPL(svc_find_xprt); 1099EXPORT_SYMBOL_GPL(svc_find_xprt);
1099 1100
1100/* 1101static int svc_one_xprt_name(const struct svc_xprt *xprt,
1101 * Format a buffer with a list of the active transports. A zero for 1102 char *pos, int remaining)
1102 * the buflen parameter disables target buffer overflow checking. 1103{
1104 int len;
1105
1106 len = snprintf(pos, remaining, "%s %u\n",
1107 xprt->xpt_class->xcl_name,
1108 svc_xprt_local_port(xprt));
1109 if (len >= remaining)
1110 return -ENAMETOOLONG;
1111 return len;
1112}
1113
1114/**
1115 * svc_xprt_names - format a buffer with a list of transport names
1116 * @serv: pointer to an RPC service
1117 * @buf: pointer to a buffer to be filled in
1118 * @buflen: length of buffer to be filled in
1119 *
1120 * Fills in @buf with a string containing a list of transport names,
1121 * each name terminated with '\n'.
1122 *
1123 * Returns positive length of the filled-in string on success; otherwise
1124 * a negative errno value is returned if an error occurs.
1103 */ 1125 */
1104int svc_xprt_names(struct svc_serv *serv, char *buf, int buflen) 1126int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen)
1105{ 1127{
1106 struct svc_xprt *xprt; 1128 struct svc_xprt *xprt;
1107 char xprt_str[64]; 1129 int len, totlen;
1108 int totlen = 0; 1130 char *pos;
1109 int len;
1110 1131
1111 /* Sanity check args */ 1132 /* Sanity check args */
1112 if (!serv) 1133 if (!serv)
1113 return 0; 1134 return 0;
1114 1135
1115 spin_lock_bh(&serv->sv_lock); 1136 spin_lock_bh(&serv->sv_lock);
1137
1138 pos = buf;
1139 totlen = 0;
1116 list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { 1140 list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) {
1117 len = snprintf(xprt_str, sizeof(xprt_str), 1141 len = svc_one_xprt_name(xprt, pos, buflen - totlen);
1118 "%s %d\n", xprt->xpt_class->xcl_name, 1142 if (len < 0) {
1119 svc_xprt_local_port(xprt)); 1143 *buf = '\0';
1120 /* If the string was truncated, replace with error string */ 1144 totlen = len;
1121 if (len >= sizeof(xprt_str)) 1145 }
1122 strcpy(xprt_str, "name-too-long\n"); 1146 if (len <= 0)
1123 /* Don't overflow buffer */
1124 len = strlen(xprt_str);
1125 if (buflen && (len + totlen >= buflen))
1126 break; 1147 break;
1127 strcpy(buf+totlen, xprt_str); 1148
1149 pos += len;
1128 totlen += len; 1150 totlen += len;
1129 } 1151 }
1152
1130 spin_unlock_bh(&serv->sv_lock); 1153 spin_unlock_bh(&serv->sv_lock);
1131 return totlen; 1154 return totlen;
1132} 1155}
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index a2a03e500533..23128ee191ae 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -240,42 +240,76 @@ out:
240/* 240/*
241 * Report socket names for nfsdfs 241 * Report socket names for nfsdfs
242 */ 242 */
243static int one_sock_name(char *buf, struct svc_sock *svsk) 243static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
244{ 244{
245 const struct sock *sk = svsk->sk_sk;
246 const char *proto_name = sk->sk_protocol == IPPROTO_UDP ?
247 "udp" : "tcp";
245 int len; 248 int len;
246 249
247 switch(svsk->sk_sk->sk_family) { 250 switch (sk->sk_family) {
248 case AF_INET: 251 case PF_INET:
249 len = sprintf(buf, "ipv4 %s %pI4 %d\n", 252 len = snprintf(buf, remaining, "ipv4 %s %pI4 %d\n",
250 svsk->sk_sk->sk_protocol == IPPROTO_UDP ? 253 proto_name,
251 "udp" : "tcp", 254 &inet_sk(sk)->rcv_saddr,
252 &inet_sk(svsk->sk_sk)->rcv_saddr, 255 inet_sk(sk)->num);
253 inet_sk(svsk->sk_sk)->num); 256 break;
257 case PF_INET6:
258 len = snprintf(buf, remaining, "ipv6 %s %pI6 %d\n",
259 proto_name,
260 &inet6_sk(sk)->rcv_saddr,
261 inet_sk(sk)->num);
254 break; 262 break;
255 default: 263 default:
256 len = sprintf(buf, "*unknown-%d*\n", 264 len = snprintf(buf, remaining, "*unknown-%d*\n",
257 svsk->sk_sk->sk_family); 265 sk->sk_family);
266 }
267
268 if (len >= remaining) {
269 *buf = '\0';
270 return -ENAMETOOLONG;
258 } 271 }
259 return len; 272 return len;
260} 273}
261 274
262int 275/**
263svc_sock_names(char *buf, struct svc_serv *serv, char *toclose) 276 * svc_sock_names - construct a list of listener names in a string
277 * @serv: pointer to RPC service
278 * @buf: pointer to a buffer to fill in with socket names
279 * @buflen: size of the buffer to be filled
280 * @toclose: pointer to '\0'-terminated C string containing the name
281 * of a listener to be closed
282 *
283 * Fills in @buf with a '\n'-separated list of names of listener
284 * sockets. If @toclose is not NULL, the socket named by @toclose
285 * is closed, and is not included in the output list.
286 *
287 * Returns positive length of the socket name string, or a negative
288 * errno value on error.
289 */
290int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen,
291 const char *toclose)
264{ 292{
265 struct svc_sock *svsk, *closesk = NULL; 293 struct svc_sock *svsk, *closesk = NULL;
266 int len = 0; 294 int len = 0;
267 295
268 if (!serv) 296 if (!serv)
269 return 0; 297 return 0;
298
270 spin_lock_bh(&serv->sv_lock); 299 spin_lock_bh(&serv->sv_lock);
271 list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { 300 list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) {
272 int onelen = one_sock_name(buf+len, svsk); 301 int onelen = svc_one_sock_name(svsk, buf + len, buflen - len);
273 if (toclose && strcmp(toclose, buf+len) == 0) 302 if (onelen < 0) {
303 len = onelen;
304 break;
305 }
306 if (toclose && strcmp(toclose, buf + len) == 0)
274 closesk = svsk; 307 closesk = svsk;
275 else 308 else
276 len += onelen; 309 len += onelen;
277 } 310 }
278 spin_unlock_bh(&serv->sv_lock); 311 spin_unlock_bh(&serv->sv_lock);
312
279 if (closesk) 313 if (closesk)
280 /* Should unregister with portmap, but you cannot 314 /* Should unregister with portmap, but you cannot
281 * unregister just one protocol... 315 * unregister just one protocol...
@@ -346,6 +380,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
346 sock->sk->sk_sndbuf = snd * 2; 380 sock->sk->sk_sndbuf = snd * 2;
347 sock->sk->sk_rcvbuf = rcv * 2; 381 sock->sk->sk_rcvbuf = rcv * 2;
348 sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK; 382 sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK;
383 sock->sk->sk_write_space(sock->sk);
349 release_sock(sock->sk); 384 release_sock(sock->sk);
350#endif 385#endif
351} 386}
@@ -387,6 +422,15 @@ static void svc_write_space(struct sock *sk)
387 } 422 }
388} 423}
389 424
425static void svc_tcp_write_space(struct sock *sk)
426{
427 struct socket *sock = sk->sk_socket;
428
429 if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock)
430 clear_bit(SOCK_NOSPACE, &sock->flags);
431 svc_write_space(sk);
432}
433
390/* 434/*
391 * Copy the UDP datagram's destination address to the rqstp structure. 435 * Copy the UDP datagram's destination address to the rqstp structure.
392 * The 'destination' address in this case is the address to which the 436 * The 'destination' address in this case is the address to which the
@@ -427,13 +471,14 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
427 long all[SVC_PKTINFO_SPACE / sizeof(long)]; 471 long all[SVC_PKTINFO_SPACE / sizeof(long)];
428 } buffer; 472 } buffer;
429 struct cmsghdr *cmh = &buffer.hdr; 473 struct cmsghdr *cmh = &buffer.hdr;
430 int err, len;
431 struct msghdr msg = { 474 struct msghdr msg = {
432 .msg_name = svc_addr(rqstp), 475 .msg_name = svc_addr(rqstp),
433 .msg_control = cmh, 476 .msg_control = cmh,
434 .msg_controllen = sizeof(buffer), 477 .msg_controllen = sizeof(buffer),
435 .msg_flags = MSG_DONTWAIT, 478 .msg_flags = MSG_DONTWAIT,
436 }; 479 };
480 size_t len;
481 int err;
437 482
438 if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) 483 if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags))
439 /* udp sockets need large rcvbuf as all pending 484 /* udp sockets need large rcvbuf as all pending
@@ -465,8 +510,8 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
465 return -EAGAIN; 510 return -EAGAIN;
466 } 511 }
467 len = svc_addr_len(svc_addr(rqstp)); 512 len = svc_addr_len(svc_addr(rqstp));
468 if (len < 0) 513 if (len == 0)
469 return len; 514 return -EAFNOSUPPORT;
470 rqstp->rq_addrlen = len; 515 rqstp->rq_addrlen = len;
471 if (skb->tstamp.tv64 == 0) { 516 if (skb->tstamp.tv64 == 0) {
472 skb->tstamp = ktime_get_real(); 517 skb->tstamp = ktime_get_real();
@@ -980,25 +1025,16 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
980static int svc_tcp_has_wspace(struct svc_xprt *xprt) 1025static int svc_tcp_has_wspace(struct svc_xprt *xprt)
981{ 1026{
982 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); 1027 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
983 struct svc_serv *serv = svsk->sk_xprt.xpt_server; 1028 struct svc_serv *serv = svsk->sk_xprt.xpt_server;
984 int required; 1029 int required;
985 int wspace;
986 1030
987 /* 1031 if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
988 * Set the SOCK_NOSPACE flag before checking the available 1032 return 1;
989 * sock space. 1033 required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
990 */ 1034 if (sk_stream_wspace(svsk->sk_sk) >= required)
1035 return 1;
991 set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); 1036 set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
992 required = atomic_read(&svsk->sk_xprt.xpt_reserved) + serv->sv_max_mesg; 1037 return 0;
993 wspace = sk_stream_wspace(svsk->sk_sk);
994
995 if (wspace < sk_stream_min_wspace(svsk->sk_sk))
996 return 0;
997 if (required * 2 > wspace)
998 return 0;
999
1000 clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
1001 return 1;
1002} 1038}
1003 1039
1004static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, 1040static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
@@ -1054,7 +1090,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
1054 dprintk("setting up TCP socket for reading\n"); 1090 dprintk("setting up TCP socket for reading\n");
1055 sk->sk_state_change = svc_tcp_state_change; 1091 sk->sk_state_change = svc_tcp_state_change;
1056 sk->sk_data_ready = svc_tcp_data_ready; 1092 sk->sk_data_ready = svc_tcp_data_ready;
1057 sk->sk_write_space = svc_write_space; 1093 sk->sk_write_space = svc_tcp_write_space;
1058 1094
1059 svsk->sk_reclen = 0; 1095 svsk->sk_reclen = 0;
1060 svsk->sk_tcplen = 0; 1096 svsk->sk_tcplen = 0;
@@ -1148,9 +1184,19 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
1148 return svsk; 1184 return svsk;
1149} 1185}
1150 1186
1151int svc_addsock(struct svc_serv *serv, 1187/**
1152 int fd, 1188 * svc_addsock - add a listener socket to an RPC service
1153 char *name_return) 1189 * @serv: pointer to RPC service to which to add a new listener
1190 * @fd: file descriptor of the new listener
1191 * @name_return: pointer to buffer to fill in with name of listener
1192 * @len: size of the buffer
1193 *
1194 * Fills in socket name and returns positive length of name if successful.
1195 * Name is terminated with '\n'. On error, returns a negative errno
1196 * value.
1197 */
1198int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
1199 const size_t len)
1154{ 1200{
1155 int err = 0; 1201 int err = 0;
1156 struct socket *so = sockfd_lookup(fd, &err); 1202 struct socket *so = sockfd_lookup(fd, &err);
@@ -1190,7 +1236,7 @@ int svc_addsock(struct svc_serv *serv,
1190 sockfd_put(so); 1236 sockfd_put(so);
1191 return err; 1237 return err;
1192 } 1238 }
1193 return one_sock_name(name_return, svsk); 1239 return svc_one_sock_name(svsk, name_return, len);
1194} 1240}
1195EXPORT_SYMBOL_GPL(svc_addsock); 1241EXPORT_SYMBOL_GPL(svc_addsock);
1196 1242
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 42a6f9f20285..9e884383134f 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -397,14 +397,14 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt,
397 if (!ch) 397 if (!ch)
398 return 0; 398 return 0;
399 399
400 /* Allocate temporary reply and chunk maps */
401 rpl_map = svc_rdma_get_req_map();
402 chl_map = svc_rdma_get_req_map();
403
404 svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count); 400 svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count);
405 if (ch_count > RPCSVC_MAXPAGES) 401 if (ch_count > RPCSVC_MAXPAGES)
406 return -EINVAL; 402 return -EINVAL;
407 403
404 /* Allocate temporary reply and chunk maps */
405 rpl_map = svc_rdma_get_req_map();
406 chl_map = svc_rdma_get_req_map();
407
408 if (!xprt->sc_frmr_pg_list_len) 408 if (!xprt->sc_frmr_pg_list_len)
409 sge_count = map_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp, 409 sge_count = map_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp,
410 rpl_map, chl_map, ch_count, 410 rpl_map, chl_map, ch_count,