aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-10-02 05:17:48 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:18 -0400
commitb41b66d63c730cc45a1024e1f1e67439e507e40f (patch)
tree85f623c087a90ccf08a8264c638df5504f972c0d /net/sunrpc
parent80212d59e32a8a8e030c2ddc5861d8ff70542c56 (diff)
[PATCH] knfsd: allow sockets to be passed to nfsd via 'portlist'
Userspace should create and bind a socket (but not connectted) and write the 'fd' to portlist. This will cause the nfs server to listen on that socket. To close a socket, the name of the socket - as read from 'portlist' can be written to 'portlist' with a preceding '-'. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/svcsock.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 3ee4b78742b1..c6be67a86ae7 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -31,6 +31,7 @@
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/netdevice.h> 32#include <linux/netdevice.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <linux/file.h>
34#include <net/sock.h> 35#include <net/sock.h>
35#include <net/checksum.h> 36#include <net/checksum.h>
36#include <net/ip.h> 37#include <net/ip.h>
@@ -451,9 +452,9 @@ static int one_sock_name(char *buf, struct svc_sock *svsk)
451} 452}
452 453
453int 454int
454svc_sock_names(char *buf, struct svc_serv *serv) 455svc_sock_names(char *buf, struct svc_serv *serv, char *toclose)
455{ 456{
456 struct svc_sock *svsk; 457 struct svc_sock *svsk, *closesk = NULL;
457 int len = 0; 458 int len = 0;
458 459
459 if (!serv) 460 if (!serv)
@@ -461,9 +462,14 @@ svc_sock_names(char *buf, struct svc_serv *serv)
461 spin_lock(&serv->sv_lock); 462 spin_lock(&serv->sv_lock);
462 list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) { 463 list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) {
463 int onelen = one_sock_name(buf+len, svsk); 464 int onelen = one_sock_name(buf+len, svsk);
464 len += onelen; 465 if (toclose && strcmp(toclose, buf+len) == 0)
466 closesk = svsk;
467 else
468 len += onelen;
465 } 469 }
466 spin_unlock(&serv->sv_lock); 470 spin_unlock(&serv->sv_lock);
471 if (closesk)
472 svc_delete_socket(closesk);
467 return len; 473 return len;
468} 474}
469EXPORT_SYMBOL(svc_sock_names); 475EXPORT_SYMBOL(svc_sock_names);
@@ -1407,6 +1413,38 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock,
1407 return svsk; 1413 return svsk;
1408} 1414}
1409 1415
1416int svc_addsock(struct svc_serv *serv,
1417 int fd,
1418 char *name_return,
1419 int *proto)
1420{
1421 int err = 0;
1422 struct socket *so = sockfd_lookup(fd, &err);
1423 struct svc_sock *svsk = NULL;
1424
1425 if (!so)
1426 return err;
1427 if (so->sk->sk_family != AF_INET)
1428 err = -EAFNOSUPPORT;
1429 else if (so->sk->sk_protocol != IPPROTO_TCP &&
1430 so->sk->sk_protocol != IPPROTO_UDP)
1431 err = -EPROTONOSUPPORT;
1432 else if (so->state > SS_UNCONNECTED)
1433 err = -EISCONN;
1434 else {
1435 svsk = svc_setup_socket(serv, so, &err, 1);
1436 if (svsk)
1437 err = 0;
1438 }
1439 if (err) {
1440 sockfd_put(so);
1441 return err;
1442 }
1443 if (proto) *proto = so->sk->sk_protocol;
1444 return one_sock_name(name_return, svsk);
1445}
1446EXPORT_SYMBOL_GPL(svc_addsock);
1447
1410/* 1448/*
1411 * Create socket for RPC service. 1449 * Create socket for RPC service.
1412 */ 1450 */
@@ -1482,7 +1520,10 @@ svc_delete_socket(struct svc_sock *svsk)
1482 1520
1483 if (!svsk->sk_inuse) { 1521 if (!svsk->sk_inuse) {
1484 spin_unlock_bh(&serv->sv_lock); 1522 spin_unlock_bh(&serv->sv_lock);
1485 sock_release(svsk->sk_sock); 1523 if (svsk->sk_sock->file)
1524 sockfd_put(svsk->sk_sock);
1525 else
1526 sock_release(svsk->sk_sock);
1486 kfree(svsk); 1527 kfree(svsk);
1487 } else { 1528 } else {
1488 spin_unlock_bh(&serv->sv_lock); 1529 spin_unlock_bh(&serv->sv_lock);