You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
[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>
This commit is contained in:
committed by
Linus Torvalds
parent
80212d59e3
commit
b41b66d63c
+45
-4
@@ -31,6 +31,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/file.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/ip.h>
|
||||
@@ -451,9 +452,9 @@ static int one_sock_name(char *buf, struct svc_sock *svsk)
|
||||
}
|
||||
|
||||
int
|
||||
svc_sock_names(char *buf, struct svc_serv *serv)
|
||||
svc_sock_names(char *buf, struct svc_serv *serv, char *toclose)
|
||||
{
|
||||
struct svc_sock *svsk;
|
||||
struct svc_sock *svsk, *closesk = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (!serv)
|
||||
@@ -461,9 +462,14 @@ svc_sock_names(char *buf, struct svc_serv *serv)
|
||||
spin_lock(&serv->sv_lock);
|
||||
list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) {
|
||||
int onelen = one_sock_name(buf+len, svsk);
|
||||
len += onelen;
|
||||
if (toclose && strcmp(toclose, buf+len) == 0)
|
||||
closesk = svsk;
|
||||
else
|
||||
len += onelen;
|
||||
}
|
||||
spin_unlock(&serv->sv_lock);
|
||||
if (closesk)
|
||||
svc_delete_socket(closesk);
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL(svc_sock_names);
|
||||
@@ -1407,6 +1413,38 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock,
|
||||
return svsk;
|
||||
}
|
||||
|
||||
int svc_addsock(struct svc_serv *serv,
|
||||
int fd,
|
||||
char *name_return,
|
||||
int *proto)
|
||||
{
|
||||
int err = 0;
|
||||
struct socket *so = sockfd_lookup(fd, &err);
|
||||
struct svc_sock *svsk = NULL;
|
||||
|
||||
if (!so)
|
||||
return err;
|
||||
if (so->sk->sk_family != AF_INET)
|
||||
err = -EAFNOSUPPORT;
|
||||
else if (so->sk->sk_protocol != IPPROTO_TCP &&
|
||||
so->sk->sk_protocol != IPPROTO_UDP)
|
||||
err = -EPROTONOSUPPORT;
|
||||
else if (so->state > SS_UNCONNECTED)
|
||||
err = -EISCONN;
|
||||
else {
|
||||
svsk = svc_setup_socket(serv, so, &err, 1);
|
||||
if (svsk)
|
||||
err = 0;
|
||||
}
|
||||
if (err) {
|
||||
sockfd_put(so);
|
||||
return err;
|
||||
}
|
||||
if (proto) *proto = so->sk->sk_protocol;
|
||||
return one_sock_name(name_return, svsk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(svc_addsock);
|
||||
|
||||
/*
|
||||
* Create socket for RPC service.
|
||||
*/
|
||||
@@ -1482,7 +1520,10 @@ svc_delete_socket(struct svc_sock *svsk)
|
||||
|
||||
if (!svsk->sk_inuse) {
|
||||
spin_unlock_bh(&serv->sv_lock);
|
||||
sock_release(svsk->sk_sock);
|
||||
if (svsk->sk_sock->file)
|
||||
sockfd_put(svsk->sk_sock);
|
||||
else
|
||||
sock_release(svsk->sk_sock);
|
||||
kfree(svsk);
|
||||
} else {
|
||||
spin_unlock_bh(&serv->sv_lock);
|
||||
|
||||
Reference in New Issue
Block a user