aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcsock.c
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/sunrpc/svcsock.c
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/sunrpc/svcsock.c')
-rw-r--r--net/sunrpc/svcsock.c122
1 files changed, 84 insertions, 38 deletions
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