Skip to contentSkip to conversation

knfsd: Introduction

PATCH New NeilBrown 5 participants 22 messages Jul 25, 2006 – Jul 28, 2006

Subsystems (3)
lore
Share & tools
lore

NeilBrown

author
#0 lore raw

PATCH 1/1 knfsd: Introduction

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'

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#1 lore raw

PATCH 1/1 knfsd: knfsd: Add some missing newlines in printks

From: Greg Banks <[email protected]>

### Diffstat output

 ./fs/nfsd/export.c       |    2 +-
 ./fs/nfsd/nfs4callback.c |    2 +-
 ./fs/nfsd/nfs4proc.c     |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/export.c +1 -1
diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
@@ -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) {
fs/nfsd/nfs4callback.c +1 -1
diff .prev/fs/nfsd/nfs4callback.c ./fs/nfsd/nfs4callback.c
@@ -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; \
 	} \
fs/nfsd/nfs4proc.c +1 -1
diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
@@ -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;
 		}
 	}
author
#2 lore raw

PATCH 1/1 knfsd: knfsd: Remove an unused variable from e_show().

In reply to NeilBrown

From: Greg Banks <[email protected]>

### Diffstat output

 ./fs/nfsd/export.c |    2 --
 1 file changed, 2 deletions(-)
fs/nfsd/export.c +0 -2
diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
@@ -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;

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#3 lore raw

Re: [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().

On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
...

Quoted 4 lines

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c

fs/nfsd/export.c +0 -0
@@ -1178,7 +1178,6 @@ static int e_show(struct seq_file *m, vo

...

Quoted 1 line

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.

Signature · 11 lines
If I have trouble installing Linux, something is wrong. Very wrong.
		- Linus Torvalds

-------------------------------------------------------------------------
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  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
author
#4 lore raw

Re: [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().

Quoted 7 lines · On Tuesday July 25, [email protected] wrote:

On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
...

Quoted 4 lines

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c

fs/nfsd/export.c +0 -0
@@ -1178,7 +1178,6 @@ static int e_show(struct seq_file *m, vo

...

Quoted 8 lines
Quoted 1 line

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

#5 lore raw

Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().

Quoted 13 lines · Neil Brown
Quoted 12 lines · On Tuesday July 25, [email protected] wrote:

On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
...

Quoted 4 lines

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c

fs/nfsd/export.c +0 -0
@@ -1178,7 +1178,6 @@ static int e_show(struct seq_file *m, vo

...

Quoted 1 line

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:

Quoted 8 lines
Quoted 3 lines

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.

Signature · 13 lines
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  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
#6 lore raw

Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().

In reply to Neil Brown
Quoted 10 lines · Neil Brown
Quoted 2 lines · On Tuesday July 25, [email protected] 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.

---

 fs/nfsd/export.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/export.c +3 -3
Index: linux/fs/nfsd/export.c
===================================================================
@@ -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.

Signature · 13 lines
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  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
author Acked-by
#7 lore raw

Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().

Quoted 5 lines · On Tuesday July 25, [email protected] wrote:
Quoted 4 lines · Neil Brown
Quoted 2 lines · On Tuesday July 25, [email protected] wrote:

On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
...

Quoted 8 lines
Quoted 6 lines

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!

Quoted 5 lines

--

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

NeilBrown

Quoted 54 lines

---

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

Index: linux/fs/nfsd/export.c
===================================================================

fs/nfsd/export.c +3 -3
@@ -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.

Signature · 13 lines
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  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
#8 lore raw

Re: [NFS] [PATCH 002 of 9] knfsd: knfsd: Remove an unused variable from e_show().

In reply to Greg Banks
Quoted 5 lines · Greg Banks
Quoted 4 lines · Neil Brown
Quoted 2 lines · On Tuesday July 25, [email protected] wrote:

On Tue, Jul 25, 2006 at 11:54:32AM +1000, NeilBrown wrote:
...

Quoted 8 lines
Quoted 6 lines

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.

---

 fs/nfsd/export.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/export.c +3 -3
Index: linus-git/fs/nfsd/export.c
===================================================================
@@ -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.

Signature · 13 lines
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  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
author
#9 lore raw

PATCH 1/1 knfsd: knfsd: Remove an unused variable from auth_unix_lookup()

In reply to NeilBrown

From: Greg Banks <[email protected]>

### Diffstat output

 ./net/sunrpc/svcauth_unix.c |    5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)
net/sunrpc/svcauth_unix.c +1 -4
diff .prev/net/sunrpc/svcauth_unix.c ./net/sunrpc/svcauth_unix.c
@@ -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)

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#10 lore raw

PATCH 1/1 knfsd: Add a callback for when last rpc thread finishes.

In reply to NeilBrown

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.

### 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(-)
fs/lockd/svc.c +1 -1
diff .prev/fs/lockd/svc.c ./fs/lockd/svc.c
@@ -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;
fs/nfsd/nfssvc.c +18 -22
diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
@@ -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 --;
 
include/linux/sunrpc/svc.h +7 -1
diff .prev/include/linux/sunrpc/svc.h ./include/linux/sunrpc/svc.h
@@ -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 *);
net/sunrpc/svc.c +6 -1
diff .prev/net/sunrpc/svc.c ./net/sunrpc/svc.c
@@ -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,

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#11 lore raw

PATCH 1/1 knfsd: Be more selective in which sockets lockd listens on.

In reply to NeilBrown

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.

### 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(-)
fs/lockd/clntlock.c +1 -1
diff .prev/fs/lockd/clntlock.c ./fs/lockd/clntlock.c
@@ -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. */
fs/lockd/svc.c +40 -7

94 lines not on this page · raw message

fs/nfs/super.c +4 -2
diff .prev/fs/nfs/super.c ./fs/nfs/super.c
@@ -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;
 }
 
fs/nfsd/nfssvc.c +10 -6
diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
@@ -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 --;
 
include/linux/lockd/bind.h +1 -1
diff .prev/include/linux/lockd/bind.h ./include/linux/lockd/bind.h
@@ -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 */

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#12 lore raw

Re: [NFS] [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on.

fs/lockd/svc.c lockd(struct svc_rqst *rqstp) · line 117

Quoted 5 lines · NeilBrown
fs/lockd/svc.c +1 -0
@@ -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?

Quoted 8 lines
fs/lockd/svc.c +2 -1
@@ -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;

...

fs/lockd/svc.c lockd_up(void) · line 285

Quoted 4 lines
fs/lockd/svc.c +1 -0
+	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()?

fs/nfsd/nfssvc.c static int killsig = 0; /* signal that w · line 139

Quoted 10 lines

diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c

fs/nfsd/nfssvc.c +3 -0
@@ -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.

author
#13 lore raw

Re: [NFS] [PATCH 005 of 9] knfsd: Be more selective in which sockets lockd listens on.

Quoted 9 lines · On Wednesday July 26, [email protected] wrote:

fs/lockd/svc.c lockd(struct svc_rqst *rqstp) · line 117

Quoted 5 lines · NeilBrown
fs/lockd/svc.c +1 -0
@@ -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.

Quoted 12 lines
Quoted 9 lines
fs/lockd/svc.c +2 -1
@@ -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;

...

Quoted 7 lines

fs/lockd/svc.c lockd_up(void) · line 285

Quoted 4 lines
fs/lockd/svc.c +1 -0
+	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.

Quoted 3 lines

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

Quoted 15 lines

fs/nfsd/nfssvc.c static int killsig = 0; /* signal that w · line 139

Quoted 11 lines

diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c

fs/nfsd/nfssvc.c +3 -0
@@ -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 (?).

Quoted 2 lines

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

author
#14 lore raw

PATCH 1/1 knfsd: Remove nfsd_versbits as intermediate storage for desired versions.

In reply to NeilBrown

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.

### 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(-)
fs/nfsd/nfsctl.c +8 -10
diff .prev/fs/nfsd/nfsctl.c ./fs/nfsd/nfsctl.c
@@ -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 = " ";
 		}
fs/nfsd/nfssvc.c +50 -43

118 lines not on this page · raw message

include/linux/nfsd/nfsd.h +4 -0
diff .prev/include/linux/nfsd/nfsd.h ./include/linux/nfsd/nfsd.h
@@ -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
include/linux/nfsd/syscall.h +0 -17
diff .prev/include/linux/nfsd/syscall.h ./include/linux/nfsd/syscall.h
@@ -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 */

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#15 lore raw

Re: [NFS] [PATCH 006 of 9] knfsd: Remove nfsd_versbits as intermediate storage for desired versions.

fs/nfsd/nfssvc.c struct svc_program nfsd_program = { · line 123

Quoted 4 lines · NeilBrown
fs/nfsd/nfssvc.c +4 -0
+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.

author
#16 lore raw

PATCH 1/1 knfsd: Separate out some parts of nfsd_svc, which start nfs servers.

In reply to NeilBrown

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

Some of these new functions will have multiple callers soon.

### Diffstat output

 ./fs/nfsd/nfssvc.c |   82 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 25 deletions(-)
fs/nfsd/nfssvc.c +57 -25
diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
@@ -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--;

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#17 lore raw

Re: [PATCH 007 of 9] knfsd: Separate out some parts of nfsd_svc, which start nfs servers.

Quoted 5 lines · On Tue, 25 Jul 2006 11:54:57 +1000 NeilBrown <[email protected]> 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?

Quoted 12 lines
fs/nfsd/nfssvc.c +12 -0
+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,

fs/nfsd/nfssvc.c void nfsd_reset_versions(void) · line 220

Quoted 10 lines
fs/nfsd/nfssvc.c +10 -0
+			       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;
+}
+

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#18 lore raw

PATCH 1/1 knfsd: Define new nfsdfs file: portlist - contains list of ports.

In reply to NeilBrown

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.

### Diffstat output

 ./fs/nfsd/nfsctl.c               |   19 +++++++++++++++++++
 ./include/linux/sunrpc/svcsock.h |    1 +
 ./net/sunrpc/svcsock.c           |   37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+)
fs/nfsd/nfsctl.c +19 -0
diff .prev/fs/nfsd/nfsctl.c ./fs/nfsd/nfsctl.c
@@ -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},
include/linux/sunrpc/svcsock.h +1 -0
diff .prev/include/linux/sunrpc/svcsock.h ./include/linux/sunrpc/svcsock.h
@@ -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 */
net/sunrpc/svcsock.c +37 -0
diff .prev/net/sunrpc/svcsock.c ./net/sunrpc/svcsock.c
@@ -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

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#19 lore raw

PATCH 1/1 knfsd: Allow sockets to be passed to nfsd via 'portlist'

In reply to NeilBrown

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

### 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(-)
fs/nfsd/nfsctl.c +50 -9
diff .prev/fs/nfsd/nfsctl.c ./fs/nfsd/nfsctl.c
@@ -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
fs/nfsd/nfssvc.c +1 -3
diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
@@ -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;
include/linux/nfsd/nfsd.h +1 -0
diff .prev/include/linux/nfsd/nfsd.h ./include/linux/nfsd/nfsd.h
@@ -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);
 
 
 /* 
include/linux/sunrpc/svcsock.h +5 -1
diff .prev/include/linux/sunrpc/svcsock.h ./include/linux/sunrpc/svcsock.h
@@ -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 */
net/sunrpc/svcsock.c +45 -4

82 lines not on this page · raw message

-------------------------------------------------------------------------
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 - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#20 lore raw

Re: [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'

Quoted 8 lines · On Tue, 25 Jul 2006 11:55:08 +1000 NeilBrown <[email protected]> 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?

Quoted 51 lines

static ssize_t write_ports(struct file *file, char *buf, size_t size) {

fs/nfsd/nfsctl.c +39 -9
-	/* 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)

fs/nfsd/nfsctl.c static ssize_t write_versions(struct fil · line 479

Quoted 10 lines
fs/nfsd/nfsctl.c +9 -0
+			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 ;)

#21 lore raw

Re: [NFS] [PATCH 009 of 9] knfsd: Allow sockets to be passed to nfsd via 'portlist'

In reply to NeilBrown
Quoted 10 lines · NeilBrown
fs/nfsd/nfsctl.c +10 -0
+		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--;

....

fs/nfsd/nfssvc.c static inline int nfsd_create_serv(void) · line 215

Quoted 6 lines
fs/nfsd/nfssvc.c +0 -2
@@ -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.

Quoted 14 lines
net/sunrpc/svcsock.c +2 -2
@@ -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) {

net/sunrpc/svcsock.c int one_sock_name(char *buf, struct svc_ · line 469

Quoted 10 lines
net/sunrpc/svcsock.c +6 -1
 		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.