linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 000 of 9] knfsd: Introduction
@ 2006-07-25  1:54 NeilBrown
  2006-07-25  1:54 ` [PATCH 001 of 9] knfsd: knfsd: Add some missing newlines in printks NeilBrown
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel

Following are 9 patches for knfsd in 2.6-18-rc1-mm2
They should be held for 2.6.19.

They comprise
 3 trivial cleanups from Greg Banks
 Some fixes/cleanups to socket/version selection code.
 Adding a 'portlist' file to the 'nfsd' filesystem.
  This can be used to open and close sockets used by the nfs server.
  New sockets are created in user-space and passed down by writing
   an 'fd' number.
  Old sockets are closed by finding the appropriate name in 'portlist'
  and writing it back to 'portlist' preceded by a '-'.

nfs-utils-1.0.9 can work with 'portlist' to e.g. control which
protocol (udp or tcp) is used.  However it has other problems:
 rpc.nfsd 0
will no longer stop all nfsd threads.  So there will be a 1.0.10 shortly.

NeilBrown

 [PATCH 001 of 9] knfsd: knfsd: Add some missing newlines in printks
 [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
 [PATCH 003 of 9] knfsd: knfsd: Remove an unused variable from auth_unix_lookup()
 [PATCH 004 of 9] knfsd: Add a callback for when last rpc thread finishes.
 [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on.
 [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions.
 [PATCH 007 of 9] knfsd: Separate out some parts of nfsd_svc, which start nfs servers.
 [PATCH 008 of 9] knfsd: Define new nfsdfs file: portlist - contains list of ports.
 [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 001 of 9] knfsd: knfsd: Add some missing newlines in printks
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction 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
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: Greg Banks <gnb@melbourne.sgi.com>

Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/export.c       |    2 +-
 ./fs/nfsd/nfs4callback.c |    2 +-
 ./fs/nfsd/nfs4proc.c     |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
--- .prev/fs/nfsd/export.c	2006-07-24 14:33:06.000000000 +1000
+++ ./fs/nfsd/export.c	2006-07-24 14:33:06.000000000 +1000
@@ -370,7 +370,7 @@ static int check_export(struct inode *in
 	 */
 	if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
 	    !(flags & NFSEXP_FSID)) {
-		dprintk("exp_export: export of non-dev fs without fsid");
+		dprintk("exp_export: export of non-dev fs without fsid\n");
 		return -EINVAL;
 	}
 	if (!inode->i_sb->s_export_op) {

diff .prev/fs/nfsd/nfs4callback.c ./fs/nfsd/nfs4callback.c
--- .prev/fs/nfsd/nfs4callback.c	2006-07-24 14:33:06.000000000 +1000
+++ ./fs/nfsd/nfs4callback.c	2006-07-24 14:33:06.000000000 +1000
@@ -131,7 +131,7 @@ xdr_error:                              
 #define READ_BUF(nbytes)  do { \
 	p = xdr_inline_decode(xdr, nbytes); \
 	if (!p) { \
-		dprintk("NFSD: %s: reply buffer overflowed in line %d.", \
+		dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \
 			__FUNCTION__, __LINE__); \
 		return -EIO; \
 	} \

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-07-24 14:33:06.000000000 +1000
+++ ./fs/nfsd/nfs4proc.c	2006-07-24 14:33:06.000000000 +1000
@@ -600,7 +600,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
 			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
 		nfs4_unlock_state();
 		if (status) {
-			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!");
+			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
 			return status;
 		}
 	}

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction 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  4:10   ` Josef Sipek
  2006-07-25  1:54 ` [PATCH 003 of 9] knfsd: knfsd: Remove an unused variable from auth_unix_lookup() NeilBrown
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: Greg Banks <gnb@melbourne.sgi.com>

Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/export.c |    2 --
 1 file changed, 2 deletions(-)

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
--- .prev/fs/nfsd/export.c	2006-07-24 14:33:06.000000000 +1000
+++ ./fs/nfsd/export.c	2006-07-24 14:33:26.000000000 +1000
@@ -1178,7 +1178,6 @@ static int e_show(struct seq_file *m, vo
 {
 	struct cache_head *cp = p;
 	struct svc_export *exp = container_of(cp, struct svc_export, h);
-	svc_client *clp;
 
 	if (p == (void *)1) {
 		seq_puts(m, "# Version 1.1\n");
@@ -1186,7 +1185,6 @@ static int e_show(struct seq_file *m, vo
 		return 0;
 	}
 
-	clp = exp->ex_client;
 	cache_get(&exp->h);
 	if (cache_check(&svc_export_cache, &exp->h, NULL))
 		return 0;

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 003 of 9] knfsd: knfsd: Remove an unused variable from auth_unix_lookup()
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
  2006-07-25  1:54 ` [PATCH 001 of 9] knfsd: knfsd: Add some missing newlines in printks 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  1:54 ` [PATCH 004 of 9] knfsd: Add a callback for when last rpc thread finishes NeilBrown
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: Greg Banks <gnb@melbourne.sgi.com>

Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./net/sunrpc/svcauth_unix.c |    5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff .prev/net/sunrpc/svcauth_unix.c ./net/sunrpc/svcauth_unix.c
--- .prev/net/sunrpc/svcauth_unix.c	2006-07-24 14:33:40.000000000 +1000
+++ ./net/sunrpc/svcauth_unix.c	2006-07-24 14:33:40.000000000 +1000
@@ -348,12 +348,9 @@ int auth_unix_forget_old(struct auth_dom
 
 struct auth_domain *auth_unix_lookup(struct in_addr addr)
 {
-	struct ip_map key, *ipm;
+	struct ip_map *ipm;
 	struct auth_domain *rv;
 
-	strcpy(key.m_class, "nfsd");
-	key.m_addr = addr;
-
 	ipm = ip_map_lookup("nfsd", addr);
 
 	if (!ipm)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 004 of 9] knfsd: Add a callback for when last rpc thread finishes.
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
                   ` (2 preceding siblings ...)
  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 005 of 9] knfsd: Be more selective in which sockets lockd listens on NeilBrown
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


nfsd has some cleanup that it wants to do when the last thread
exits, and there will shortly be some more.
So collect this all into one place and define a callback for
an rpc service to call when the service is about to be destroyed.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/lockd/svc.c             |    2 +-
 ./fs/nfsd/nfssvc.c           |   40 ++++++++++++++++++----------------------
 ./include/linux/sunrpc/svc.h |    8 +++++++-
 ./net/sunrpc/svc.c           |    7 ++++++-
 4 files changed, 32 insertions(+), 25 deletions(-)

diff .prev/fs/lockd/svc.c ./fs/lockd/svc.c
--- .prev/fs/lockd/svc.c	2006-07-24 14:55:00.000000000 +1000
+++ ./fs/lockd/svc.c	2006-07-24 15:13:40.000000000 +1000
@@ -236,7 +236,7 @@ lockd_up(void)
 			"lockd_up: no pid, %d users??\n", nlmsvc_users);
 
 	error = -ENOMEM;
-	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE);
+	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
 	if (!serv) {
 		printk(KERN_WARNING "lockd_up: create service failed\n");
 		goto out;

diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
--- .prev/fs/nfsd/nfssvc.c	2006-07-24 14:50:53.000000000 +1000
+++ ./fs/nfsd/nfssvc.c	2006-07-24 15:14:31.000000000 +1000
@@ -130,11 +130,25 @@ int nfsd_nrthreads(void)
 		return nfsd_serv->sv_nrthreads;
 }
 
+static int killsig = 0; /* signal that was used to kill last nfsd */
+static void nfsd_last_thread(struct svc_serv *serv)
+{
+	/* When last nfsd thread exits we need to do some clean-up */
+	nfsd_serv = NULL;
+	nfsd_racache_shutdown();
+	nfs4_state_shutdown();
+
+	printk(KERN_WARNING "nfsd: last server has exited\n");
+	if (killsig != SIG_NOCLEAN) {
+		printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
+		nfsd_export_flush();
+	}
+}
 int
 nfsd_svc(unsigned short port, int nrservs)
 {
 	int	error;
-	int	none_left, found_one, i;
+	int	found_one, i;
 	struct list_head *victim;
 	
 	lock_kernel();
@@ -197,7 +211,8 @@ nfsd_svc(unsigned short port, int nrserv
 
 		atomic_set(&nfsd_busy, 0);
 		error = -ENOMEM;
-		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
+		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE,
+				       nfsd_last_thread);
 		if (nfsd_serv == NULL)
 			goto out;
 		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
@@ -231,13 +246,7 @@ nfsd_svc(unsigned short port, int nrserv
 		nrservs++;
 	}
  failure:
-	none_left = (nfsd_serv->sv_nrthreads == 1);
 	svc_destroy(nfsd_serv);		/* Release server */
-	if (none_left) {
-		nfsd_serv = NULL;
-		nfsd_racache_shutdown();
-		nfs4_state_shutdown();
-	}
  out:
 	unlock_kernel();
 	return error;
@@ -353,7 +362,7 @@ nfsd(struct svc_rqst *rqstp)
 			if (sigismember(&current->pending.signal, signo) &&
 			    !sigismember(&current->blocked, signo))
 				break;
-		err = signo;
+		killsig = signo;
 	}
 	/* Clear signals before calling lockd_down() and svc_exit_thread() */
 	flush_signals(current);
@@ -362,19 +371,6 @@ nfsd(struct svc_rqst *rqstp)
 
 	/* Release lockd */
 	lockd_down();
-
-	/* Check if this is last thread */
-	if (serv->sv_nrthreads==1) {
-		
-		printk(KERN_WARNING "nfsd: last server has exited\n");
-		if (err != SIG_NOCLEAN) {
-			printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
-			nfsd_export_flush();
-		}
-		nfsd_serv = NULL;
-	        nfsd_racache_shutdown();	/* release read-ahead cache */
-		nfs4_state_shutdown();
-	}
 	list_del(&me.list);
 	nfsdstats.th_cnt --;
 

diff .prev/include/linux/sunrpc/svc.h ./include/linux/sunrpc/svc.h
--- .prev/include/linux/sunrpc/svc.h	2006-07-24 14:42:06.000000000 +1000
+++ ./include/linux/sunrpc/svc.h	2006-07-24 15:13:40.000000000 +1000
@@ -42,6 +42,11 @@ struct svc_serv {
 	int			sv_tmpcnt;	/* count of temporary sockets */
 
 	char *			sv_name;	/* service name */
+
+	void			(*sv_shutdown)(struct svc_serv *serv);
+						/* Callback to use when last thread
+						 * exits.
+						 */
 };
 
 /*
@@ -311,7 +316,8 @@ typedef void		(*svc_thread_fn)(struct sv
 /*
  * Function prototypes.
  */
-struct svc_serv *  svc_create(struct svc_program *, unsigned int);
+struct svc_serv *  svc_create(struct svc_program *, unsigned int,
+			      void (*shutdown)(struct svc_serv*));
 int		   svc_create_thread(svc_thread_fn, struct svc_serv *);
 void		   svc_exit_thread(struct svc_rqst *);
 void		   svc_destroy(struct svc_serv *);

diff .prev/net/sunrpc/svc.c ./net/sunrpc/svc.c
--- .prev/net/sunrpc/svc.c	2006-07-24 14:40:46.000000000 +1000
+++ ./net/sunrpc/svc.c	2006-07-24 15:13:40.000000000 +1000
@@ -26,7 +26,8 @@
  * Create an RPC service
  */
 struct svc_serv *
-svc_create(struct svc_program *prog, unsigned int bufsize)
+svc_create(struct svc_program *prog, unsigned int bufsize,
+	   void (*shutdown)(struct svc_serv *serv))
 {
 	struct svc_serv	*serv;
 	int vers;
@@ -40,6 +41,7 @@ svc_create(struct svc_program *prog, uns
 	serv->sv_nrthreads = 1;
 	serv->sv_stats     = prog->pg_stats;
 	serv->sv_bufsz	   = bufsize? bufsize : 4096;
+	serv->sv_shutdown  = shutdown;
 	xdrsize = 0;
 	while (prog) {
 		prog->pg_lovers = prog->pg_nvers-1;
@@ -92,6 +94,9 @@ svc_destroy(struct svc_serv *serv)
 				  sk_list);
 		svc_delete_socket(svsk);
 	}
+	if (serv->sv_shutdown)
+		serv->sv_shutdown(serv);
+
 	while (!list_empty(&serv->sv_permsocks)) {
 		svsk = list_entry(serv->sv_permsocks.next,
 				  struct svc_sock,

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on.
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
                   ` (3 preceding siblings ...)
  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-26 19:17   ` [NFS] " J. Bruce Fields
  2006-07-25  1:54 ` [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions NeilBrown
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


Currently lockd listens on UDP always, and TCP if CONFIG_NFSD_TCP 
is set.

However as lockd performs services of the client as well, this is a
problem.  If CONFIG_NfSD_TCP is not set, and a tcp mount is used, the
server will not be able to call back to lockd.

So:
 - add an option to lockd_up saying which protocol is needed
 - Always open sockets for which an explicit port was given, otherwise
   only open a socket of the type required
 - Change nfsd to do one lockd_up per socket rather than one per thread.

This
 - removes the dependancy on CONFIG_NFSD_TCP
 - means that lockd may open sockets other than at startup
 - means that lockd will *not* listen on UDP if the only
   mounts are TCP mount (and nfsd hasn't started).

The latter is the only one that concerns me at all - I don't know if
this might be a problem with some servers.


Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/lockd/clntlock.c        |    2 -
 ./fs/lockd/svc.c             |   47 ++++++++++++++++++++++++++++++++++++-------
 ./fs/nfs/super.c             |    6 +++--
 ./fs/nfsd/nfssvc.c           |   16 +++++++++-----
 ./include/linux/lockd/bind.h |    2 -
 5 files changed, 56 insertions(+), 17 deletions(-)

diff .prev/fs/lockd/clntlock.c ./fs/lockd/clntlock.c
--- .prev/fs/lockd/clntlock.c	2006-07-24 15:15:04.000000000 +1000
+++ ./fs/lockd/clntlock.c	2006-07-24 15:15:04.000000000 +1000
@@ -202,7 +202,7 @@ reclaimer(void *ptr)
 	/* This one ensures that our parent doesn't terminate while the
 	 * reclaim is in progress */
 	lock_kernel();
-	lockd_up();
+	lockd_up(0);
 
 	nlmclnt_prepare_reclaim(host);
 	/* First, reclaim all locks that have been marked. */

diff .prev/fs/lockd/svc.c ./fs/lockd/svc.c
--- .prev/fs/lockd/svc.c	2006-07-24 15:13:40.000000000 +1000
+++ ./fs/lockd/svc.c	2006-07-24 15:15:04.000000000 +1000
@@ -31,6 +31,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/svcsock.h>
+#include <net/ip.h>
 #include <linux/lockd/lockd.h>
 #include <linux/nfs.h>
 
@@ -46,6 +47,7 @@ EXPORT_SYMBOL(nlmsvc_ops);
 static DEFINE_MUTEX(nlmsvc_mutex);
 static unsigned int		nlmsvc_users;
 static pid_t			nlmsvc_pid;
+static struct svc_serv		*nlmsvc_serv;
 int				nlmsvc_grace_period;
 unsigned long			nlmsvc_timeout;
 
@@ -112,6 +114,7 @@ lockd(struct svc_rqst *rqstp)
 	 * Let our maker know we're running.
 	 */
 	nlmsvc_pid = current->pid;
+	nlmsvc_serv = serv;
 	complete(&lockd_start_done);
 
 	daemonize("lockd");
@@ -189,6 +192,7 @@ lockd(struct svc_rqst *rqstp)
 			nlmsvc_invalidate_all();
 		nlm_shutdown_hosts();
 		nlmsvc_pid = 0;
+		nlmsvc_serv = NULL;
 	} else
 		printk(KERN_DEBUG
 			"lockd: new process, skipping host shutdown\n");
@@ -205,11 +209,42 @@ lockd(struct svc_rqst *rqstp)
 	module_put_and_exit(0);
 }
 
+
+static int find_socket(struct svc_serv *serv, int proto)
+{
+	struct svc_sock *svsk;
+	int found = 0;
+	list_for_each_entry(svsk, &serv->sv_permsocks, sk_list)
+		if (svsk->sk_sk->sk_protocol == proto) {
+			found = 1;
+			break;
+		}
+	return found;
+}
+
+static int make_socks(struct svc_serv *serv, int proto)
+{
+	/* Make any sockets that are needed but not present.
+	 * If nlm_udpport or nlm_tcpport were set as module
+	 * options, make those sockets unconditionally
+	 */
+	int err = 0;
+	if (proto == IPPROTO_UDP || nlm_udpport)
+		if (!find_socket(serv, IPPROTO_UDP))
+			err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport);
+	if (err)
+		return err;
+	if (proto == IPPROTO_TCP || nlm_tcpport)
+		if (!find_socket(serv, IPPROTO_TCP))
+			err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport);
+	return err;
+}
+
 /*
  * Bring up the lockd process if it's not already up.
  */
 int
-lockd_up(void)
+lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
 {
 	static int		warned;
 	struct svc_serv *	serv;
@@ -224,8 +259,10 @@ lockd_up(void)
 	/*
 	 * Check whether we're already up and running.
 	 */
-	if (nlmsvc_pid)
+	if (nlmsvc_pid) {
+		error = make_socks(nlmsvc_serv, proto);
 		goto out;
+	}
 
 	/*
 	 * Sanity check: if there's no pid,
@@ -242,11 +279,7 @@ lockd_up(void)
 		goto out;
 	}
 
-	if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0 
-#ifdef CONFIG_NFSD_TCP
-	 || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0
-#endif
-		) {
+	if ((error = make_socks(serv, proto)) < 0) {
 		if (warned++ == 0) 
 			printk(KERN_WARNING
 				"lockd_up: makesock failed, error=%d\n", error);

diff .prev/fs/nfs/super.c ./fs/nfs/super.c
--- .prev/fs/nfs/super.c	2006-07-24 15:15:04.000000000 +1000
+++ ./fs/nfs/super.c	2006-07-24 15:15:04.000000000 +1000
@@ -869,7 +869,8 @@ nfs_fill_super(struct super_block *sb, s
 
 	/* Start lockd here, before we might error out */
 	if (!(server->flags & NFS_MOUNT_NONLM))
-		lockd_up();
+		lockd_up((server->flags & NFS_MOUNT_TCP)
+			 ? IPPROTO_TCP : IPPROTO_UDP);
 
 	server->namelen  = data->namlen;
 	server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
@@ -1112,7 +1113,8 @@ static struct super_block *nfs_clone_sb(
 	nfs_copy_fh(&server->fh, data->fh);
 	sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
 	if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM))
-		lockd_up();
+		lockd_up((server->flags & NFS_MOUNT_TCP)
+			 ? IPPROTO_TCP : IPPROTO_UDP);
 	return sb;
 }
 

diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
--- .prev/fs/nfsd/nfssvc.c	2006-07-24 15:14:31.000000000 +1000
+++ ./fs/nfsd/nfssvc.c	2006-07-24 15:15:04.000000000 +1000
@@ -134,6 +134,9 @@ static int killsig = 0; /* signal that w
 static void nfsd_last_thread(struct svc_serv *serv)
 {
 	/* When last nfsd thread exits we need to do some clean-up */
+	struct svc_sock *svsk;
+	list_for_each_entry(svsk, &serv->sv_permsocks, sk_list)
+		lockd_down();
 	nfsd_serv = NULL;
 	nfsd_racache_shutdown();
 	nfs4_state_shutdown();
@@ -218,11 +221,16 @@ nfsd_svc(unsigned short port, int nrserv
 		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
 		if (error < 0)
 			goto failure;
-
+		error = lockd_up(IPPROTO_UDP);
+		if (error < 0)
+			goto failure;
 #ifdef CONFIG_NFSD_TCP
 		error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
 		if (error < 0)
 			goto failure;
+		error = lockd_up(IPPROTO_TCP);
+		if (error < 0)
+			goto failure;
 #endif
 		do_gettimeofday(&nfssvc_boot);		/* record boot time */
 	} else
@@ -306,8 +314,6 @@ nfsd(struct svc_rqst *rqstp)
 
 	nfsdstats.th_cnt++;
 
-	lockd_up();				/* start lockd */
-
 	me.task = current;
 	list_add(&me.list, &nfsd_list);
 
@@ -364,13 +370,11 @@ nfsd(struct svc_rqst *rqstp)
 				break;
 		killsig = signo;
 	}
-	/* Clear signals before calling lockd_down() and svc_exit_thread() */
+	/* Clear signals before calling svc_exit_thread() */
 	flush_signals(current);
 
 	lock_kernel();
 
-	/* Release lockd */
-	lockd_down();
 	list_del(&me.list);
 	nfsdstats.th_cnt --;
 

diff .prev/include/linux/lockd/bind.h ./include/linux/lockd/bind.h
--- .prev/include/linux/lockd/bind.h	2006-07-24 15:15:04.000000000 +1000
+++ ./include/linux/lockd/bind.h	2006-07-24 15:15:04.000000000 +1000
@@ -30,7 +30,7 @@ extern struct nlmsvc_binding *	nlmsvc_op
  * Functions exported by the lockd module
  */
 extern int	nlmclnt_proc(struct inode *, int, struct file_lock *);
-extern int	lockd_up(void);
+extern int	lockd_up(int proto);
 extern void	lockd_down(void);
 
 #endif /* LINUX_LOCKD_BIND_H */

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions.
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
                   ` (4 preceding siblings ...)
  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: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
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


We have an array 'nfsd_version' which lists the available versions
of nfsd, and 'nfsd_versions' (poor choice there :-() which lists
the currently active versions.

Then we have a bitmap - nfsd_versbits which says which versions are
wanted.  The bits in this bitset cause content to be copied from
nfsd_version to nfsd_versions when nfsd starts.

This patch removes nfsd_versbits and moves information directly from
nfsd_version to nfsd_versions when requests for version changes arrive.

Note that this doesn't make it possible to change versions while the
server is running.  This is because serv->sv_xdrsize is calculated when
a service is created, and used when threads are created, and xdrsize
depends on the active versions.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfsctl.c             |   18 +++----
 ./fs/nfsd/nfssvc.c             |   93 ++++++++++++++++++++++-------------------
 ./include/linux/nfsd/nfsd.h    |    4 +
 ./include/linux/nfsd/syscall.h |   17 -------
 4 files changed, 62 insertions(+), 70 deletions(-)

diff .prev/fs/nfsd/nfsctl.c ./fs/nfsd/nfsctl.c
--- .prev/fs/nfsd/nfsctl.c	2006-07-24 15:17:36.000000000 +1000
+++ ./fs/nfsd/nfsctl.c	2006-07-24 15:17:36.000000000 +1000
@@ -35,8 +35,6 @@
 
 #include <asm/uaccess.h>
 
-unsigned int nfsd_versbits = ~0;
-
 /*
  *	We have a single directory with 9 nodes in it.
  */
@@ -372,6 +370,10 @@ static ssize_t write_versions(struct fil
 
 	if (size>0) {
 		if (nfsd_serv)
+			/* Cannot change versions without updating
+			 * nfsd_serv->sv_xdrsize, and reallocing
+			 * rq_argp and rq_resp
+			 */
 			return -EBUSY;
 		if (buf[size-1] != '\n')
 			return -EINVAL;
@@ -390,10 +392,7 @@ static ssize_t write_versions(struct fil
 			case 2:
 			case 3:
 			case 4:
-				if (sign != '-')
-					NFSCTL_VERSET(nfsd_versbits, num);
-				else
-					NFSCTL_VERUNSET(nfsd_versbits, num);
+				nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
 				break;
 			default:
 				return -EINVAL;
@@ -404,16 +403,15 @@ static ssize_t write_versions(struct fil
 		/* If all get turned off, turn them back on, as
 		 * having no versions is BAD
 		 */
-		if ((nfsd_versbits & NFSCTL_VERALL)==0)
-			nfsd_versbits = NFSCTL_VERALL;
+		nfsd_reset_versions();
 	}
 	/* Now write current state into reply buffer */
 	len = 0;
 	sep = "";
 	for (num=2 ; num <= 4 ; num++)
-		if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) {
+		if (nfsd_vers(num, NFSD_AVAIL)) {
 			len += sprintf(buf+len, "%s%c%d", sep,
-				       NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-',
+				       nfsd_vers(num, NFSD_TEST)?'+':'-',
 				       num);
 			sep = " ";
 		}

diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
--- .prev/fs/nfsd/nfssvc.c	2006-07-24 15:15:04.000000000 +1000
+++ ./fs/nfsd/nfssvc.c	2006-07-24 15:17:36.000000000 +1000
@@ -117,6 +117,32 @@ struct svc_program		nfsd_program = {
 
 };
 
+int nfsd_vers(int vers, enum vers_op change)
+{
+	if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
+		return -1;
+	switch(change) {
+	case NFSD_SET:
+		nfsd_versions[vers] = nfsd_version[vers];
+		break;
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+		if (vers < NFSD_ACL_NRVERS)
+			nfsd_acl_version[vers] = nfsd_acl_version[vers];
+#endif
+	case NFSD_CLEAR:
+		nfsd_versions[vers] = NULL;
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+		if (vers < NFSD_ACL_NRVERS)
+			nfsd_acl_version[vers] = NULL;
+#endif
+		break;
+	case NFSD_TEST:
+		return nfsd_versions[vers] != NULL;
+	case NFSD_AVAIL:
+		return nfsd_version[vers] != NULL;
+	}
+	return 0;
+}
 /*
  * Maximum number of nfsd processes
  */
@@ -147,16 +173,36 @@ static void nfsd_last_thread(struct svc_
 		nfsd_export_flush();
 	}
 }
+
+void nfsd_reset_versions(void)
+{
+	int found_one = 0;
+	int i;
+
+	for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
+		if (nfsd_program.pg_vers[i])
+			found_one = 1;
+	}
+
+	if (!found_one) {
+		for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
+			nfsd_program.pg_vers[i] = nfsd_version[i];
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+		for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
+			nfsd_acl_program.pg_vers[i] =
+				nfsd_acl_version[i];
+#endif
+	}
+}
+
 int
 nfsd_svc(unsigned short port, int nrservs)
 {
 	int	error;
-	int	found_one, i;
 	struct list_head *victim;
 	
 	lock_kernel();
-	dprintk("nfsd: creating service: vers 0x%x\n",
-		nfsd_versbits);
+	dprintk("nfsd: creating service\n");
 	error = -EINVAL;
 	if (nrservs <= 0)
 		nrservs = 0;
@@ -171,46 +217,7 @@ nfsd_svc(unsigned short port, int nrserv
 	if (error<0)
 		goto out;
 	if (!nfsd_serv) {
-		/*
-		 * Use the nfsd_ctlbits to define which
-		 * versions that will be advertised.
-		 * If nfsd_ctlbits doesn't list any version,
-		 * export them all.
-		 */
-		found_one = 0;
-
-		for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
-			if (NFSCTL_VERISSET(nfsd_versbits, i)) {
-				nfsd_program.pg_vers[i] = nfsd_version[i];
-				found_one = 1;
-			} else
-				nfsd_program.pg_vers[i] = NULL;
-		}
-
-		if (!found_one) {
-			for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
-				nfsd_program.pg_vers[i] = nfsd_version[i];
-		}
-
-
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-		found_one = 0;
-
-		for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
-			if (NFSCTL_VERISSET(nfsd_versbits, i)) {
-				nfsd_acl_program.pg_vers[i] =
-					nfsd_acl_version[i];
-				found_one = 1;
-			} else
-				nfsd_acl_program.pg_vers[i] = NULL;
-		}
-
-		if (!found_one) {
-			for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
-				nfsd_acl_program.pg_vers[i] =
-					nfsd_acl_version[i];
-		}
-#endif
+		nfsd_reset_versions();
 
 		atomic_set(&nfsd_busy, 0);
 		error = -ENOMEM;

diff .prev/include/linux/nfsd/nfsd.h ./include/linux/nfsd/nfsd.h
--- .prev/include/linux/nfsd/nfsd.h	2006-07-24 15:17:36.000000000 +1000
+++ ./include/linux/nfsd/nfsd.h	2006-07-24 15:17:36.000000000 +1000
@@ -140,6 +140,10 @@ struct posix_acl *nfsd_get_posix_acl(str
 int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
 #endif
 
+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);
+
 
 /* 
  * NFSv4 State

diff .prev/include/linux/nfsd/syscall.h ./include/linux/nfsd/syscall.h
--- .prev/include/linux/nfsd/syscall.h	2006-07-24 15:17:36.000000000 +1000
+++ ./include/linux/nfsd/syscall.h	2006-07-24 15:17:36.000000000 +1000
@@ -38,21 +38,6 @@
 #define NFSCTL_GETFD		7	/* get an fh by path (used by mountd) */
 #define	NFSCTL_GETFS		8	/* get an fh by path with max FH len */
 
-/*
- * Macros used to set version
- */
-#define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |=  (1 << (_v)))
-#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
-#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
-
-#if defined(CONFIG_NFSD_V4)
-#define	NFSCTL_VERALL	(0x1c /* 0b011100 */)
-#elif defined(CONFIG_NFSD_V3)
-#define	NFSCTL_VERALL	(0x0c /* 0b001100 */)
-#else
-#define	NFSCTL_VERALL	(0x04 /* 0b000100 */)
-#endif
-
 /* SVC */
 struct nfsctl_svc {
 	unsigned short		svc_port;
@@ -134,8 +119,6 @@ extern int		exp_delclient(struct nfsctl_
 extern int		exp_export(struct nfsctl_export *nxp);
 extern int		exp_unexport(struct nfsctl_export *nxp);
 
-extern unsigned int nfsd_versbits;
-
 #endif /* __KERNEL__ */
 
 #endif /* NFSD_SYSCALL_H */

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 007 of 9] knfsd: Separate out some parts of nfsd_svc, which start nfs servers.
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
                   ` (5 preceding siblings ...)
  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  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 ` [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist' NeilBrown
  8 siblings, 1 reply; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


Separate out the code for creating a new service, and for creating
initial sockets.

Some of these new functions will have multiple callers soon.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfssvc.c |   82 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 25 deletions(-)

diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
--- .prev/fs/nfsd/nfssvc.c	2006-07-24 15:17:36.000000000 +1000
+++ ./fs/nfsd/nfssvc.c	2006-07-24 15:20:39.000000000 +1000
@@ -195,6 +195,53 @@ void nfsd_reset_versions(void)
 	}
 }
 
+
+static inline int nfsd_create_serv(void)
+{
+	int err = 0;
+	lock_kernel();
+	if (nfsd_serv) {
+		nfsd_serv->sv_nrthreads++;
+		unlock_kernel();
+		return 0;
+	}
+
+	atomic_set(&nfsd_busy, 0);
+	nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE,
+			       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;
+}
+
+static inline int nfsd_init_socks(int port)
+{
+	int error;
+	if (!list_empty(&nfsd_serv->sv_permsocks))
+		return 0;
+
+	error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
+	if (error < 0)
+		return error;
+	error = lockd_up(IPPROTO_UDP);
+	if (error < 0)
+		return error;
+
+#ifdef CONFIG_NFSD_TCP
+	error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
+	if (error < 0)
+		return error;
+	error = lockd_up(IPPROTO_TCP);
+	if (error < 0)
+		return error;
+#endif
+	return 0;
+}
+
 int
 nfsd_svc(unsigned short port, int nrservs)
 {
@@ -216,32 +263,17 @@ nfsd_svc(unsigned short port, int nrserv
 	error = nfs4_state_start();
 	if (error<0)
 		goto out;
-	if (!nfsd_serv) {
-		nfsd_reset_versions();
 
-		atomic_set(&nfsd_busy, 0);
-		error = -ENOMEM;
-		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE,
-				       nfsd_last_thread);
-		if (nfsd_serv == NULL)
-			goto out;
-		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
-		if (error < 0)
-			goto failure;
-		error = lockd_up(IPPROTO_UDP);
-		if (error < 0)
-			goto failure;
-#ifdef CONFIG_NFSD_TCP
-		error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
-		if (error < 0)
-			goto failure;
-		error = lockd_up(IPPROTO_TCP);
-		if (error < 0)
-			goto failure;
-#endif
-		do_gettimeofday(&nfssvc_boot);		/* record boot time */
-	} else
-		nfsd_serv->sv_nrthreads++;
+	nfsd_reset_versions();
+
+	error = nfsd_create_serv();
+
+	if (error)
+		goto out;
+	error = nfsd_init_socks(port);
+	if (error)
+		goto failure;
+
 	nrservs -= (nfsd_serv->sv_nrthreads-1);
 	while (nrservs > 0) {
 		nrservs--;

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 008 of 9] knfsd: Define new nfsdfs file: portlist - contains list of ports.
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
                   ` (6 preceding siblings ...)
  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:55 ` NeilBrown
  2006-07-25  1:55 ` [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist' NeilBrown
  8 siblings, 0 replies; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:55 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


This file will list all ports that nfsd has open.
Default when TCP enabled will be
   ipv4 udp 0.0.0.0 2049
   ipv4 tcp 0.0.0.0 2049

Later, the list of ports will be settable.

'portlist' chosen rather than 'ports', to avoid unnecessary confusion with
non-mainline patches which created 'ports' with different semantics.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfsctl.c               |   19 +++++++++++++++++++
 ./include/linux/sunrpc/svcsock.h |    1 +
 ./net/sunrpc/svcsock.c           |   37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+)

diff .prev/fs/nfsd/nfsctl.c ./fs/nfsd/nfsctl.c
--- .prev/fs/nfsd/nfsctl.c	2006-07-24 15:17:36.000000000 +1000
+++ ./fs/nfsd/nfsctl.c	2006-07-24 15:21:44.000000000 +1000
@@ -27,6 +27,7 @@
 #include <linux/nfs.h>
 #include <linux/nfsd_idmap.h>
 #include <linux/sunrpc/svc.h>
+#include <linux/sunrpc/svcsock.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/cache.h>
 #include <linux/nfsd/xdr.h>
@@ -51,6 +52,7 @@ enum {
 	NFSD_Fh,
 	NFSD_Threads,
 	NFSD_Versions,
+	NFSD_Ports,
 	/*
 	 * The below MUST come last.  Otherwise we leave a hole in nfsd_files[]
 	 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
@@ -74,6 +76,7 @@ static ssize_t write_getfs(struct file *
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 static ssize_t write_threads(struct file *file, char *buf, size_t size);
 static ssize_t write_versions(struct file *file, char *buf, size_t size);
+static ssize_t write_ports(struct file *file, char *buf, size_t size);
 #ifdef CONFIG_NFSD_V4
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
@@ -90,6 +93,7 @@ static ssize_t (*write_op[])(struct file
 	[NFSD_Fh] = write_filehandle,
 	[NFSD_Threads] = write_threads,
 	[NFSD_Versions] = write_versions,
+	[NFSD_Ports] = write_ports,
 #ifdef CONFIG_NFSD_V4
 	[NFSD_Leasetime] = write_leasetime,
 	[NFSD_RecoveryDir] = write_recoverydir,
@@ -419,6 +423,20 @@ static ssize_t write_versions(struct fil
 	return len;
 }
 
+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
+	 */
+	int len = 0;
+	lock_kernel();
+	if (nfsd_serv)
+		len = svc_sock_names(buf, nfsd_serv);
+	unlock_kernel();
+	return len;
+}
+
 #ifdef CONFIG_NFSD_V4
 extern time_t nfs4_leasetime(void);
 
@@ -482,6 +500,7 @@ static int nfsd_fill_super(struct super_
 		[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
+		[NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
 #ifdef CONFIG_NFSD_V4
 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},

diff .prev/include/linux/sunrpc/svcsock.h ./include/linux/sunrpc/svcsock.h
--- .prev/include/linux/sunrpc/svcsock.h	2006-07-24 15:21:44.000000000 +1000
+++ ./include/linux/sunrpc/svcsock.h	2006-07-24 15:21:44.000000000 +1000
@@ -61,5 +61,6 @@ 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);
 
 #endif /* SUNRPC_SVCSOCK_H */

diff .prev/net/sunrpc/svcsock.c ./net/sunrpc/svcsock.c
--- .prev/net/sunrpc/svcsock.c	2006-07-24 15:21:44.000000000 +1000
+++ ./net/sunrpc/svcsock.c	2006-07-24 15:21:44.000000000 +1000
@@ -429,6 +429,43 @@ out:
 }
 
 /*
+ * Report socket names for nfsdfs
+ */
+int one_sock_name(char *buf, struct svc_sock *svsk)
+{
+	int len;
+	switch(svsk->sk_sk->sk_family) {
+	case AF_INET:
+		len = sprintf(buf, "ipv4 %s %u.%u.%u.%u %d\n",
+			      svsk->sk_sk->sk_protocol==IPPROTO_UDP?
+			      "udp" : "tcp",
+			      NIPQUAD(inet_sk(svsk->sk_sk)->rcv_saddr),
+			      inet_sk(svsk->sk_sk)->num);
+		break;
+	default: len = sprintf(buf, "*unknown-%d*\n",
+			       svsk->sk_sk->sk_family);
+	}
+	return len;
+}
+
+int
+svc_sock_names(char *buf, struct svc_serv *serv)
+{
+	struct svc_sock *svsk;
+	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;
+	}
+	spin_unlock(&serv->sv_lock);
+	return len;
+}
+EXPORT_SYMBOL(svc_sock_names);
+
+/*
  * Check input queue length
  */
 static int

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'
  2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
                   ` (7 preceding siblings ...)
  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-26  6:53   ` Andrew Morton
  2006-07-26 20:41   ` [NFS] " J. Bruce Fields
  8 siblings, 2 replies; 22+ messages in thread
From: NeilBrown @ 2006-07-25  1:55 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


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);

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
  2006-07-25  1:54 ` [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show() NeilBrown
@ 2006-07-25  4:10   ` Josef Sipek
  2006-07-25  4:20     ` Neil Brown
  0 siblings, 1 reply; 22+ messages in thread
From: Josef Sipek @ 2006-07-25  4:10 UTC (permalink / raw)
  To: NeilBrown; +Cc: Andrew Morton, nfs, linux-kernel

On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
...
> diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
> --- .prev/fs/nfsd/export.c	2006-07-24 14:33:06.000000000 +1000
> +++ ./fs/nfsd/export.c	2006-07-24 14:33:26.000000000 +1000
> @@ -1178,7 +1178,6 @@ static int e_show(struct seq_file *m, vo
...
>  	if (p == (void *)1) {

I'm not an NFS expert, but the above makes me want to puke. Isn't there a
cleaner way of doing whatever needs to be done without:

1) hard-coding a constant
2) comparing a variable to an arbitrary pointer

Josef Sipek.

-- 
If I have trouble installing Linux, something is wrong. Very wrong.
		- Linus Torvalds

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
  2006-07-25  4:10   ` Josef Sipek
@ 2006-07-25  4:20     ` Neil Brown
  2006-07-25  4:24       ` [NFS] " Greg Banks
  2006-07-25  4:32       ` Greg Banks
  0 siblings, 2 replies; 22+ messages in thread
From: Neil Brown @ 2006-07-25  4:20 UTC (permalink / raw)
  To: Josef Sipek; +Cc: Andrew Morton, nfs, linux-kernel

On Tuesday July 25, jsipek@fsl.cs.sunysb.edu wrote:
> On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
> ...
> > diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
> > --- .prev/fs/nfsd/export.c	2006-07-24 14:33:06.000000000 +1000
> > +++ ./fs/nfsd/export.c	2006-07-24 14:33:26.000000000 +1000
> > @@ -1178,7 +1178,6 @@ static int e_show(struct seq_file *m, vo
> ...
> >  	if (p == (void *)1) {
> 
> I'm not an NFS expert, but the above makes me want to puke. Isn't there a
> cleaner way of doing whatever needs to be done without:
> 
> 1) hard-coding a constant
> 2) comparing a variable to an arbitrary pointer
> 

Probably.  We just need a pointer value that is definitely not a
pointer to a valid cache_head object, and is not NULL.
(void*)1 seems a reasonable choice, but maybe #defineing something
would help.

Patches welcome.

NeilBrown

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
  2006-07-25  4:20     ` Neil Brown
@ 2006-07-25  4:24       ` Greg Banks
  2006-07-25  4:32       ` Greg Banks
  1 sibling, 0 replies; 22+ messages in thread
From: Greg Banks @ 2006-07-25  4:24 UTC (permalink / raw)
  To: Neil Brown
  Cc: Josef Sipek, Andrew Morton, Linux NFS Mailing List,
	Linux Kernel Mailing List

On Tue, 2006-07-25 at 14:20, Neil Brown wrote:
> On Tuesday July 25, jsipek@fsl.cs.sunysb.edu wrote:
> > On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
> > ...
> > > diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
> > > --- .prev/fs/nfsd/export.c	2006-07-24 14:33:06.000000000 +1000
> > > +++ ./fs/nfsd/export.c	2006-07-24 14:33:26.000000000 +1000
> > > @@ -1178,7 +1178,6 @@ static int e_show(struct seq_file *m, vo
> > ...
> > >  	if (p == (void *)1) {
> > 
> > I'm not an NFS expert, but the above makes me want to puke. Isn't there a
> > cleaner way of doing whatever needs to be done without:
> > 
> > 1) hard-coding a constant
> > 2) comparing a variable to an arbitrary pointer
> > 
> 
> Probably.  We just need a pointer value that is definitely not a
> pointer to a valid cache_head object, and is not NULL.
> (void*)1 seems a reasonable choice, but maybe #defineing something
> would help.

include/linux/seq_file.h:

#define SEQ_START_TOKEN ((void *)1)

Greg.
-- 
Greg Banks, R&D Software Engineer, SGI Australian Software Group.
I don't speak for SGI.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
  2006-07-25  4:20     ` Neil Brown
  2006-07-25  4:24       ` [NFS] " Greg Banks
@ 2006-07-25  4:32       ` Greg Banks
  2006-07-25  4:36         ` Neil Brown
  2006-07-25  5:53         ` Greg Banks
  1 sibling, 2 replies; 22+ messages in thread
From: Greg Banks @ 2006-07-25  4:32 UTC (permalink / raw)
  To: Neil Brown
  Cc: Josef Sipek, Andrew Morton, Linux NFS Mailing List,
	Linux Kernel Mailing List

On Tue, 2006-07-25 at 14:20, Neil Brown wrote:
> On Tuesday July 25, jsipek@fsl.cs.sunysb.edu wrote:
> > On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
> > ...
> 
> Probably.  We just need a pointer value that is definitely not a
> pointer to a valid cache_head object, and is not NULL.
> (void*)1 seems a reasonable choice, but maybe #defineing something
> would help.
> 
> Patches welcome.

This trivial patch compiles.
--

knfsd: Use SEQ_START_TOKEN instead of hardcoded magic (void*)1.

Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
---

 fs/nfsd/export.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

Index: linux/fs/nfsd/export.c
===================================================================
--- linux.orig/fs/nfsd/export.c	2006-07-25 14:28:03.000000000 +1000
+++ linux/fs/nfsd/export.c	2006-07-25 14:29:14.526574385 +1000
@@ -1086,7 +1086,7 @@ static void *e_start(struct seq_file *m,
 	exp_readlock();
 	read_lock(&svc_export_cache.hash_lock);
 	if (!n--)
-		return (void*)1;
+		return SEQ_START_TOKEN;
 	hash = n >> 32;
 	export = n & ((1LL<<32) - 1);
 
@@ -1110,7 +1110,7 @@ static void *e_next(struct seq_file *m, 
 	struct cache_head *ch = p;
 	int hash = (*pos >> 32);
 
-	if (p == (void*)1)
+	if (p == SEQ_START_TOKEN)
 		hash = 0;
 	else if (ch->next == NULL) {
 		hash++;
@@ -1180,7 +1180,7 @@ static int e_show(struct seq_file *m, vo
 	struct svc_export *exp = container_of(cp, struct svc_export, h);
 	svc_client *clp;
 
-	if (p == (void*)1) {
+	if (p == SEQ_START_TOKEN) {
 		seq_puts(m, "# Version 1.1\n");
 		seq_puts(m, "# Path Client(Flags) # IPs\n");
 		return 0;



Greg.
-- 
Greg Banks, R&D Software Engineer, SGI Australian Software Group.
I don't speak for SGI.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
  2006-07-25  4:32       ` Greg Banks
@ 2006-07-25  4:36         ` Neil Brown
  2006-07-25  5:53         ` Greg Banks
  1 sibling, 0 replies; 22+ messages in thread
From: Neil Brown @ 2006-07-25  4:36 UTC (permalink / raw)
  To: Greg Banks
  Cc: Andrew Morton, Linux NFS Mailing List, Josef Sipek,
	Linux Kernel Mailing List

On Tuesday July 25, gnb@melbourne.sgi.com wrote:
> On Tue, 2006-07-25 at 14:20, Neil Brown wrote:
> > On Tuesday July 25, jsipek@fsl.cs.sunysb.edu wrote:
> > > On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
> > > ...
> > 
> > Probably.  We just need a pointer value that is definitely not a
> > pointer to a valid cache_head object, and is not NULL.
> > (void*)1 seems a reasonable choice, but maybe #defineing something
> > would help.
> > 
> > Patches welcome.
> 
> This trivial patch compiles.

Cool... you learn something new every day!
> --
> 
> knfsd: Use SEQ_START_TOKEN instead of hardcoded magic (void*)1.
> 
> Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
Acked-by: NeilBrown <neilb@suse.de>

NeilBrown


> ---
> 
>  fs/nfsd/export.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> Index: linux/fs/nfsd/export.c
> ===================================================================
> --- linux.orig/fs/nfsd/export.c	2006-07-25 14:28:03.000000000 +1000
> +++ linux/fs/nfsd/export.c	2006-07-25 14:29:14.526574385 +1000
> @@ -1086,7 +1086,7 @@ static void *e_start(struct seq_file *m,
>  	exp_readlock();
>  	read_lock(&svc_export_cache.hash_lock);
>  	if (!n--)
> -		return (void*)1;
> +		return SEQ_START_TOKEN;
>  	hash = n >> 32;
>  	export = n & ((1LL<<32) - 1);
>  
> @@ -1110,7 +1110,7 @@ static void *e_next(struct seq_file *m, 
>  	struct cache_head *ch = p;
>  	int hash = (*pos >> 32);
>  
> -	if (p == (void*)1)
> +	if (p == SEQ_START_TOKEN)
>  		hash = 0;
>  	else if (ch->next == NULL) {
>  		hash++;
> @@ -1180,7 +1180,7 @@ static int e_show(struct seq_file *m, vo
>  	struct svc_export *exp = container_of(cp, struct svc_export, h);
>  	svc_client *clp;
>  
> -	if (p == (void*)1) {
> +	if (p == SEQ_START_TOKEN) {
>  		seq_puts(m, "# Version 1.1\n");
>  		seq_puts(m, "# Path Client(Flags) # IPs\n");
>  		return 0;
> 
> 
> 
> Greg.
> -- 
> Greg Banks, R&D Software Engineer, SGI Australian Software Group.
> I don't speak for SGI.
> 
> 
> 
> -------------------------------------------------------------------------
> 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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().
  2006-07-25  4:32       ` Greg Banks
  2006-07-25  4:36         ` Neil Brown
@ 2006-07-25  5:53         ` Greg Banks
  1 sibling, 0 replies; 22+ messages in thread
From: Greg Banks @ 2006-07-25  5:53 UTC (permalink / raw)
  To: Neil Brown
  Cc: Andrew Morton, Linux NFS Mailing List, Josef Sipek,
	Linux Kernel Mailing List

On Tue, 2006-07-25 at 14:32, Greg Banks wrote:
> On Tue, 2006-07-25 at 14:20, Neil Brown wrote:
> > On Tuesday July 25, jsipek@fsl.cs.sunysb.edu wrote:
> > > On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
> > > ...
> > 
> > Probably.  We just need a pointer value that is definitely not a
> > pointer to a valid cache_head object, and is not NULL.
> > (void*)1 seems a reasonable choice, but maybe #defineing something
> > would help.
> > 
> > Patches welcome.
> 
> This trivial patch compiles.

But only applies to sles10 <sigh>.  Here's the version
which applies to today's GIT.
--

knfsd: Use SEQ_START_TOKEN instead of hardcoded magic (void*)1.

Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
---

 fs/nfsd/export.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

Index: linus-git/fs/nfsd/export.c
===================================================================
--- linus-git.orig/fs/nfsd/export.c	2006-07-25 14:55:28.000000000 +1000
+++ linus-git/fs/nfsd/export.c	2006-07-25 15:40:03.987257265 +1000
@@ -1086,7 +1086,7 @@ static void *e_start(struct seq_file *m,
 	exp_readlock();
 	read_lock(&svc_export_cache.hash_lock);
 	if (!n--)
-		return (void *)1;
+		return SEQ_START_TOKEN;
 	hash = n >> 32;
 	export = n & ((1LL<<32) - 1);
 
@@ -1110,7 +1110,7 @@ static void *e_next(struct seq_file *m, 
 	struct cache_head *ch = p;
 	int hash = (*pos >> 32);
 
-	if (p == (void *)1)
+	if (p == SEQ_START_TOKEN)
 		hash = 0;
 	else if (ch->next == NULL) {
 		hash++;
@@ -1179,7 +1179,7 @@ static int e_show(struct seq_file *m, vo
 	struct cache_head *cp = p;
 	struct svc_export *exp = container_of(cp, struct svc_export, h);
 
-	if (p == (void *)1) {
+	if (p == SEQ_START_TOKEN) {
 		seq_puts(m, "# Version 1.1\n");
 		seq_puts(m, "# Path Client(Flags) # IPs\n");
 		return 0;


Greg.
-- 
Greg Banks, R&D Software Engineer, SGI Australian Software Group.
I don't speak for SGI.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 007 of 9] knfsd: Separate out some parts of nfsd_svc, which start nfs servers.
  2006-07-25  1:54 ` [PATCH 007 of 9] knfsd: Separate out some parts of nfsd_svc, which start nfs servers NeilBrown
@ 2006-07-26  6:42   ` Andrew Morton
  0 siblings, 0 replies; 22+ messages in thread
From: Andrew Morton @ 2006-07-26  6:42 UTC (permalink / raw)
  To: NeilBrown; +Cc: nfs, linux-kernel

On Tue, 25 Jul 2006 11:54:57 +1000
NeilBrown <neilb@suse.de> wrote:

> 
> Separate out the code for creating a new service, and for creating
> initial sockets.
> 
> Some of these new functions will have multiple callers soon.

In which case they shouldn't be inlined, hmm?

> +static inline int nfsd_create_serv(void)
> +{
> +	int err = 0;
> +	lock_kernel();
> +	if (nfsd_serv) {
> +		nfsd_serv->sv_nrthreads++;
> +		unlock_kernel();
> +		return 0;
> +	}
> +
> +	atomic_set(&nfsd_busy, 0);
> +	nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE,
> +			       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;
> +}
> +


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'
  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
  1 sibling, 0 replies; 22+ messages in thread
From: Andrew Morton @ 2006-07-26  6:53 UTC (permalink / raw)
  To: NeilBrown; +Cc: nfs, linux-kernel

On Tue, 25 Jul 2006 11:55:08 +1000
NeilBrown <neilb@suse.de> wrote:

> 
> 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 '-'.
> 

ick.  Is that the best API we can come up with?

It's a privileged operation, but heck.  Do we perform validation on the fd
to make sure that it's refers to a socket and not to /dev/fb0?

>  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;
>  }

<checks>

OK, simple_transaction_get() guarantees that *buf is null-terminated.  It
might be worth a comment to stop code-reviewers from freaking out ;)


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on.
  2006-07-25  1:54 ` [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on NeilBrown
@ 2006-07-26 19:17   ` J. Bruce Fields
  2006-07-28  2:32     ` Neil Brown
  0 siblings, 1 reply; 22+ messages in thread
From: J. Bruce Fields @ 2006-07-26 19:17 UTC (permalink / raw)
  To: NeilBrown; +Cc: Andrew Morton, nfs, linux-kernel

On Tue, Jul 25, 2006 at 11:54:47AM +1000, NeilBrown wrote:
> @@ -112,6 +114,7 @@ lockd(struct svc_rqst *rqstp)
>  	 * Let our maker know we're running.
>  	 */
>  	nlmsvc_pid = current->pid;
> +	nlmsvc_serv = serv;

Nitpick: any reason not to just get rid of the local variable "serv"
after that?

> @@ -224,8 +259,10 @@ lockd_up(void)
>  	/*
>  	 * Check whether we're already up and running.
>  	 */
> -	if (nlmsvc_pid)
> +	if (nlmsvc_pid) {
> +		error = make_socks(nlmsvc_serv, proto);
>  		goto out;

...

> +	if ((error = make_socks(serv, proto)) < 0) {
>  		if (warned++ == 0) 
>  			printk(KERN_WARNING
>  				"lockd_up: makesock failed, error=%d\n", error);

The warning is printk'ed a little inconsistently.  (If we care, maybe it
should just go inside make_socks?)

By the way, why don't most callers use the error returned from
lockd_up()?

> diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
> --- .prev/fs/nfsd/nfssvc.c	2006-07-24 15:14:31.000000000 +1000
> +++ ./fs/nfsd/nfssvc.c	2006-07-24 15:15:04.000000000 +1000
> @@ -134,6 +134,9 @@ static int killsig = 0; /* signal that w
>  static void nfsd_last_thread(struct svc_serv *serv)
>  {
>  	/* When last nfsd thread exits we need to do some clean-up */
> +	struct svc_sock *svsk;
> +	list_for_each_entry(svsk, &serv->sv_permsocks, sk_list)
> +		lockd_down();

So I guess it's a minor point, but: we take the trouble to only open tcp
or udp sockets as necessary, but then won't close them down till all the
mounts and nfsd's go away at which point we close them all down.

Would it be that bad just to always listen on both?

--b.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions.
  2006-07-25  1:54 ` [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions NeilBrown
@ 2006-07-26 19:34   ` J. Bruce Fields
  0 siblings, 0 replies; 22+ messages in thread
From: J. Bruce Fields @ 2006-07-26 19:34 UTC (permalink / raw)
  To: NeilBrown; +Cc: Andrew Morton, nfs, linux-kernel

On Tue, Jul 25, 2006 at 11:54:52AM +1000, NeilBrown wrote:
> +int nfsd_vers(int vers, enum vers_op change)
> +{
> +	if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
> +		return -1;

This isn't actually used; remove it or make it a BUG_ON()?

--b.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'
  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   ` J. Bruce Fields
  1 sibling, 0 replies; 22+ messages in thread
From: J. Bruce Fields @ 2006-07-26 20:41 UTC (permalink / raw)
  To: NeilBrown; +Cc: Andrew Morton, nfs, linux-kernel

On Tue, Jul 25, 2006 at 11:55:08AM +1000, NeilBrown wrote:
> +		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--;
....
> @@ -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++;

I don't understand these sv_nrthreads changes.

> @@ -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);

Am I missing something, or do we end up missing a lockd_down() in this
case?  (Because nfsd_last_thread() isn't going to be calling
lockd_down() for this thread now that we've removed it from
sv_permsocks).

--b.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [NFS] [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on.
  2006-07-26 19:17   ` [NFS] " J. Bruce Fields
@ 2006-07-28  2:32     ` Neil Brown
  0 siblings, 0 replies; 22+ messages in thread
From: Neil Brown @ 2006-07-28  2:32 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: Andrew Morton, Steve Dickson, nfs, linux-kernel

On Wednesday July 26, bfields@fieldses.org wrote:
> On Tue, Jul 25, 2006 at 11:54:47AM +1000, NeilBrown wrote:
> > @@ -112,6 +114,7 @@ lockd(struct svc_rqst *rqstp)
> >  	 * Let our maker know we're running.
> >  	 */
> >  	nlmsvc_pid = current->pid;
> > +	nlmsvc_serv = serv;
> 
> Nitpick: any reason not to just get rid of the local variable "serv"
> after that?

Well... it is used two more times in that function.... but in both
those cases it isn't really needed because we pass it to a function that
also gets rqstp, serv is always rqstp->rq_server.  So there is room
for cleaning up there ... patch to follow.

> 
> > @@ -224,8 +259,10 @@ lockd_up(void)
> >  	/*
> >  	 * Check whether we're already up and running.
> >  	 */
> > -	if (nlmsvc_pid)
> > +	if (nlmsvc_pid) {
> > +		error = make_socks(nlmsvc_serv, proto);
> >  		goto out;
> 
> ...
> 
> > +	if ((error = make_socks(serv, proto)) < 0) {
> >  		if (warned++ == 0) 
> >  			printk(KERN_WARNING
> >  				"lockd_up: makesock failed, error=%d\n", error);
> 
> The warning is printk'ed a little inconsistently.  (If we care, maybe it
> should just go inside make_socks?)

So.  Do we care?  That's a hard one...  I guess we do.  I'll move the
message into make_socks.

> 
> By the way, why don't most callers use the error returned from
> lockd_up()?

Most?  I could 2 out of 5.
One of those is just getting an extra ref-count so it cannot fail.
The other - in nfsctl - is simply carelessness on my part.
I should fix that.... patch to follow.

However...
 One would expect that if lockd_up fails, a matching lockd_down
wouldn't be needed.  However nlmsvc_users is unconditionally
increased by lockd_up.  That's a worry.

 - The nfs client will only call lockd_down if lockd_up succeeded.
 - NFSD currently will call lockd_down either way.
 - The lockd reclaimer ignores the return value and always calls
    lockd_down.

So the most common usage is to always call lockd_down, but I cannot
help feeling that is wrong.  And 'fixing' the client code to do it
that way would make it very ugly....

Patch to follow :-)

> 
> > diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
> > --- .prev/fs/nfsd/nfssvc.c	2006-07-24 15:14:31.000000000 +1000
> > +++ ./fs/nfsd/nfssvc.c	2006-07-24 15:15:04.000000000 +1000
> > @@ -134,6 +134,9 @@ static int killsig = 0; /* signal that w
> >  static void nfsd_last_thread(struct svc_serv *serv)
> >  {
> >  	/* When last nfsd thread exits we need to do some clean-up */
> > +	struct svc_sock *svsk;
> > +	list_for_each_entry(svsk, &serv->sv_permsocks, sk_list)
> > +		lockd_down();
> 
> So I guess it's a minor point, but: we take the trouble to only open tcp
> or udp sockets as necessary, but then won't close them down till all the
> mounts and nfsd's go away at which point we close them all down.

I thought about making that cleaner but couldn't quite motivate myself
to do it.... and it can always be done later (?).

> 
> Would it be that bad just to always listen on both?

Some people seem to want to only listen on one.
Why?  Maybe a security thing?  
So once you have opened a protocol once, the "horse has bolted" and
closing it is no big deal?

dunno... any else go opinions on this?

Steve?

NeilBrown

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2006-07-28  2:33 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-07-25  1:54 [PATCH 000 of 9] knfsd: Introduction NeilBrown
2006-07-25  1:54 ` [PATCH 001 of 9] knfsd: knfsd: Add some missing newlines in printks NeilBrown
2006-07-25  1:54 ` [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show() NeilBrown
2006-07-25  4:10   ` Josef Sipek
2006-07-25  4:20     ` Neil Brown
2006-07-25  4:24       ` [NFS] " Greg Banks
2006-07-25  4:32       ` Greg Banks
2006-07-25  4:36         ` Neil Brown
2006-07-25  5:53         ` 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 ` [PATCH 004 of 9] knfsd: Add a callback for when last rpc thread finishes NeilBrown
2006-07-25  1:54 ` [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on NeilBrown
2006-07-26 19:17   ` [NFS] " J. Bruce Fields
2006-07-28  2:32     ` Neil Brown
2006-07-25  1:54 ` [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions 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-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 ` [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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).