From: NeilBrown <neilb@suse.de>
To: Andrew Morton <akpm@osdl.org>
Cc: nfs@lists.sourceforge.net, linux-kernel@vger.kernel.org
Subject: [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'
Date: Tue, 25 Jul 2006 11:55:08 +1000 [thread overview]
Message-ID: <1060725015508.22007@suse.de> (raw)
In-Reply-To: 20060725114207.21779.patches@notabene
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>
### Diffstat output
./fs/nfsd/nfsctl.c | 59 +++++++++++++++++++++++++++++++++------
./fs/nfsd/nfssvc.c | 4 --
./include/linux/nfsd/nfsd.h | 1
./include/linux/sunrpc/svcsock.h | 6 +++
./net/sunrpc/svcsock.c | 49 +++++++++++++++++++++++++++++---
5 files changed, 102 insertions(+), 17 deletions(-)
diff .prev/fs/nfsd/nfsctl.c ./fs/nfsd/nfsctl.c
--- .prev/fs/nfsd/nfsctl.c 2006-07-24 15:49:51.000000000 +1000
+++ ./fs/nfsd/nfsctl.c 2006-07-24 17:24:17.000000000 +1000
@@ -23,9 +23,11 @@
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/ctype.h>
#include <linux/nfs.h>
#include <linux/nfsd_idmap.h>
+#include <linux/lockd/bind.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/nfsd/nfsd.h>
@@ -425,16 +427,55 @@ static ssize_t write_versions(struct fil
static ssize_t write_ports(struct file *file, char *buf, size_t size)
{
- /* for now, ignore what was written and just
- * return known ports
- * AF proto address port
+ if (size == 0) {
+ int len = 0;
+ lock_kernel();
+ if (nfsd_serv)
+ len = svc_sock_names(buf, nfsd_serv, NULL);
+ unlock_kernel();
+ return len;
+ }
+ /* Either a single 'fd' number is written, in which
+ * case it must be for a socket of a supported family/protocol,
+ * and we use it as an nfsd socket, or
+ * A '-' followed by the 'name' of a socket in which case
+ * we close the socket.
*/
- int len = 0;
- lock_kernel();
- if (nfsd_serv)
- len = svc_sock_names(buf, nfsd_serv);
- unlock_kernel();
- return len;
+ if (isdigit(buf[0])) {
+ char *mesg = buf;
+ int fd;
+ int err;
+ err = get_int(&mesg, &fd);
+ if (err)
+ return -EINVAL;
+ if (fd < 0)
+ return -EINVAL;
+ err = nfsd_create_serv();
+ if (!err) {
+ int proto = 0;
+ err = svc_addsock(nfsd_serv, fd, buf, &proto);
+ /* Decrease the count, but don't shutdown the
+ * the service
+ */
+ if (err >= 0)
+ lockd_up(proto);
+ nfsd_serv->sv_nrthreads--;
+ }
+ return err;
+ }
+ if (buf[0] == '-') {
+ char *toclose = kstrdup(buf+1, GFP_KERNEL);
+ int len = 0;
+ if (!toclose)
+ return -ENOMEM;
+ lock_kernel();
+ if (nfsd_serv)
+ len = svc_sock_names(buf, nfsd_serv, toclose);
+ unlock_kernel();
+ kfree(toclose);
+ return len;
+ }
+ return -EINVAL;
}
#ifdef CONFIG_NFSD_V4
diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
--- .prev/fs/nfsd/nfssvc.c 2006-07-24 15:49:51.000000000 +1000
+++ ./fs/nfsd/nfssvc.c 2006-07-24 15:53:37.000000000 +1000
@@ -196,7 +196,7 @@ void nfsd_reset_versions(void)
}
-static inline int nfsd_create_serv(void)
+int nfsd_create_serv(void)
{
int err = 0;
lock_kernel();
@@ -211,8 +211,6 @@ static inline int nfsd_create_serv(void)
nfsd_last_thread);
if (nfsd_serv == NULL)
err = -ENOMEM;
- else
- nfsd_serv->sv_nrthreads++;
unlock_kernel();
do_gettimeofday(&nfssvc_boot); /* record boot time */
return err;
diff .prev/include/linux/nfsd/nfsd.h ./include/linux/nfsd/nfsd.h
--- .prev/include/linux/nfsd/nfsd.h 2006-07-24 15:49:51.000000000 +1000
+++ ./include/linux/nfsd/nfsd.h 2006-07-24 15:22:49.000000000 +1000
@@ -143,6 +143,7 @@ int nfsd_set_posix_acl(struct svc_fh *,
enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
int nfsd_vers(int vers, enum vers_op change);
void nfsd_reset_versions(void);
+int nfsd_create_serv(void);
/*
diff .prev/include/linux/sunrpc/svcsock.h ./include/linux/sunrpc/svcsock.h
--- .prev/include/linux/sunrpc/svcsock.h 2006-07-24 15:49:51.000000000 +1000
+++ ./include/linux/sunrpc/svcsock.h 2006-07-24 15:22:49.000000000 +1000
@@ -61,6 +61,10 @@ int svc_recv(struct svc_serv *, struct
int svc_send(struct svc_rqst *);
void svc_drop(struct svc_rqst *);
void svc_sock_update_bufs(struct svc_serv *serv);
-int svc_sock_names(char *buf, struct svc_serv *serv);
+int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);
+int svc_addsock(struct svc_serv *serv,
+ int fd,
+ char *name_return,
+ int *proto);
#endif /* SUNRPC_SVCSOCK_H */
diff .prev/net/sunrpc/svcsock.c ./net/sunrpc/svcsock.c
--- .prev/net/sunrpc/svcsock.c 2006-07-24 15:49:51.000000000 +1000
+++ ./net/sunrpc/svcsock.c 2006-07-25 11:25:50.000000000 +1000
@@ -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>
@@ -449,18 +450,23 @@ int one_sock_name(char *buf, struct svc_
}
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) return 0;
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);
@@ -1415,6 +1421,38 @@ svc_setup_socket(struct svc_serv *serv,
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.
*/
@@ -1492,7 +1530,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);
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
WARNING: multiple messages have this Message-ID (diff)
From: NeilBrown <neilb@suse.de>
To: Andrew Morton <akpm@osdl.org>
Cc: nfs@lists.sourceforge.net, linux-kernel@vger.kernel.org
Subject: [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'
Date: Tue, 25 Jul 2006 11:55:08 +1000 [thread overview]
Message-ID: <1060725015508.22007@suse.de> (raw)
In-Reply-To: 20060725114207.21779.patches@notabene
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>
### Diffstat output
./fs/nfsd/nfsctl.c | 59 +++++++++++++++++++++++++++++++++------
./fs/nfsd/nfssvc.c | 4 --
./include/linux/nfsd/nfsd.h | 1
./include/linux/sunrpc/svcsock.h | 6 +++
./net/sunrpc/svcsock.c | 49 +++++++++++++++++++++++++++++---
5 files changed, 102 insertions(+), 17 deletions(-)
diff .prev/fs/nfsd/nfsctl.c ./fs/nfsd/nfsctl.c
--- .prev/fs/nfsd/nfsctl.c 2006-07-24 15:49:51.000000000 +1000
+++ ./fs/nfsd/nfsctl.c 2006-07-24 17:24:17.000000000 +1000
@@ -23,9 +23,11 @@
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/ctype.h>
#include <linux/nfs.h>
#include <linux/nfsd_idmap.h>
+#include <linux/lockd/bind.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/nfsd/nfsd.h>
@@ -425,16 +427,55 @@ static ssize_t write_versions(struct fil
static ssize_t write_ports(struct file *file, char *buf, size_t size)
{
- /* for now, ignore what was written and just
- * return known ports
- * AF proto address port
+ if (size == 0) {
+ int len = 0;
+ lock_kernel();
+ if (nfsd_serv)
+ len = svc_sock_names(buf, nfsd_serv, NULL);
+ unlock_kernel();
+ return len;
+ }
+ /* Either a single 'fd' number is written, in which
+ * case it must be for a socket of a supported family/protocol,
+ * and we use it as an nfsd socket, or
+ * A '-' followed by the 'name' of a socket in which case
+ * we close the socket.
*/
- int len = 0;
- lock_kernel();
- if (nfsd_serv)
- len = svc_sock_names(buf, nfsd_serv);
- unlock_kernel();
- return len;
+ if (isdigit(buf[0])) {
+ char *mesg = buf;
+ int fd;
+ int err;
+ err = get_int(&mesg, &fd);
+ if (err)
+ return -EINVAL;
+ if (fd < 0)
+ return -EINVAL;
+ err = nfsd_create_serv();
+ if (!err) {
+ int proto = 0;
+ err = svc_addsock(nfsd_serv, fd, buf, &proto);
+ /* Decrease the count, but don't shutdown the
+ * the service
+ */
+ if (err >= 0)
+ lockd_up(proto);
+ nfsd_serv->sv_nrthreads--;
+ }
+ return err;
+ }
+ if (buf[0] == '-') {
+ char *toclose = kstrdup(buf+1, GFP_KERNEL);
+ int len = 0;
+ if (!toclose)
+ return -ENOMEM;
+ lock_kernel();
+ if (nfsd_serv)
+ len = svc_sock_names(buf, nfsd_serv, toclose);
+ unlock_kernel();
+ kfree(toclose);
+ return len;
+ }
+ return -EINVAL;
}
#ifdef CONFIG_NFSD_V4
diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
--- .prev/fs/nfsd/nfssvc.c 2006-07-24 15:49:51.000000000 +1000
+++ ./fs/nfsd/nfssvc.c 2006-07-24 15:53:37.000000000 +1000
@@ -196,7 +196,7 @@ void nfsd_reset_versions(void)
}
-static inline int nfsd_create_serv(void)
+int nfsd_create_serv(void)
{
int err = 0;
lock_kernel();
@@ -211,8 +211,6 @@ static inline int nfsd_create_serv(void)
nfsd_last_thread);
if (nfsd_serv == NULL)
err = -ENOMEM;
- else
- nfsd_serv->sv_nrthreads++;
unlock_kernel();
do_gettimeofday(&nfssvc_boot); /* record boot time */
return err;
diff .prev/include/linux/nfsd/nfsd.h ./include/linux/nfsd/nfsd.h
--- .prev/include/linux/nfsd/nfsd.h 2006-07-24 15:49:51.000000000 +1000
+++ ./include/linux/nfsd/nfsd.h 2006-07-24 15:22:49.000000000 +1000
@@ -143,6 +143,7 @@ int nfsd_set_posix_acl(struct svc_fh *,
enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
int nfsd_vers(int vers, enum vers_op change);
void nfsd_reset_versions(void);
+int nfsd_create_serv(void);
/*
diff .prev/include/linux/sunrpc/svcsock.h ./include/linux/sunrpc/svcsock.h
--- .prev/include/linux/sunrpc/svcsock.h 2006-07-24 15:49:51.000000000 +1000
+++ ./include/linux/sunrpc/svcsock.h 2006-07-24 15:22:49.000000000 +1000
@@ -61,6 +61,10 @@ int svc_recv(struct svc_serv *, struct
int svc_send(struct svc_rqst *);
void svc_drop(struct svc_rqst *);
void svc_sock_update_bufs(struct svc_serv *serv);
-int svc_sock_names(char *buf, struct svc_serv *serv);
+int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);
+int svc_addsock(struct svc_serv *serv,
+ int fd,
+ char *name_return,
+ int *proto);
#endif /* SUNRPC_SVCSOCK_H */
diff .prev/net/sunrpc/svcsock.c ./net/sunrpc/svcsock.c
--- .prev/net/sunrpc/svcsock.c 2006-07-24 15:49:51.000000000 +1000
+++ ./net/sunrpc/svcsock.c 2006-07-25 11:25:50.000000000 +1000
@@ -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>
@@ -449,18 +450,23 @@ int one_sock_name(char *buf, struct svc_
}
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) return 0;
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);
@@ -1415,6 +1421,38 @@ svc_setup_socket(struct svc_serv *serv,
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.
*/
@@ -1492,7 +1530,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);
next prev parent reply other threads:[~2006-07-25 1:55 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-07-25 1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-25 1:54 ` [PATCH 001 of 9] knfsd: knfsd: Add some missing newlines in printks NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-25 1:54 ` [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show() NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-25 4:10 ` Josef Sipek
2006-07-25 4:10 ` Josef Sipek
2006-07-25 4:20 ` Neil Brown
2006-07-25 4:20 ` Neil Brown
2006-07-25 4:24 ` Greg Banks
2006-07-25 4:24 ` [NFS] " Greg Banks
2006-07-25 4:32 ` Greg Banks
2006-07-25 4:32 ` [NFS] " Greg Banks
2006-07-25 4:36 ` Neil Brown
2006-07-25 4:36 ` [NFS] " Neil Brown
2006-07-25 5:53 ` Greg Banks
2006-07-25 5:53 ` [NFS] " Greg Banks
2006-07-25 1:54 ` [PATCH 003 of 9] knfsd: knfsd: Remove an unused variable from auth_unix_lookup() NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-25 1:54 ` [PATCH 004 of 9] knfsd: Add a callback for when last rpc thread finishes NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-25 1:54 ` [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-26 19:17 ` [NFS] " J. Bruce Fields
2006-07-28 2:32 ` Neil Brown
2006-07-28 2:32 ` [NFS] " Neil Brown
2006-07-25 1:54 ` [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-26 19:34 ` [NFS] " J. Bruce Fields
2006-07-25 1:54 ` [PATCH 007 of 9] knfsd: Separate out some parts of nfsd_svc, which start nfs servers NeilBrown
2006-07-25 1:54 ` NeilBrown
2006-07-26 6:42 ` Andrew Morton
2006-07-26 6:42 ` Andrew Morton
2006-07-25 1:55 ` [PATCH 008 of 9] knfsd: Define new nfsdfs file: portlist - contains list of ports NeilBrown
2006-07-25 1:55 ` NeilBrown
2006-07-25 1:55 ` NeilBrown [this message]
2006-07-25 1:55 ` [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist' NeilBrown
2006-07-26 6:53 ` Andrew Morton
2006-07-26 20:41 ` [NFS] " J. Bruce Fields
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1060725015508.22007@suse.de \
--to=neilb@suse.de \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nfs@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.