diff options
| author | NeilBrown <neilb@suse.de> | 2006-10-02 05:17:48 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:18 -0400 |
| commit | b41b66d63c730cc45a1024e1f1e67439e507e40f (patch) | |
| tree | 85f623c087a90ccf08a8264c638df5504f972c0d /net | |
| parent | 80212d59e32a8a8e030c2ddc5861d8ff70542c56 (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')
| -rw-r--r-- | net/sunrpc/svcsock.c | 49 |
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 | ||
| 453 | int | 454 | int |
| 454 | svc_sock_names(char *buf, struct svc_serv *serv) | 455 | svc_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 | } |
| 469 | EXPORT_SYMBOL(svc_sock_names); | 475 | EXPORT_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 | ||
| 1416 | int 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 | } | ||
| 1446 | EXPORT_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); |
