The patch titled knfsd: be more selective in which sockets lockd listens on has been added to the -mm tree. Its filename is knfsd-be-more-selective-in-which-sockets-lockd-listens-on.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: knfsd: be more selective in which sockets lockd listens on From: NeilBrown <neilb@xxxxxxx> 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@xxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- 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 -puN fs/lockd/clntlock.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on fs/lockd/clntlock.c --- a/fs/lockd/clntlock.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on +++ a/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. */ diff -puN fs/lockd/svc.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on fs/lockd/svc.c --- a/fs/lockd/svc.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on +++ a/fs/lockd/svc.c @@ -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 -puN fs/nfsd/nfssvc.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on fs/nfsd/nfssvc.c --- a/fs/nfsd/nfssvc.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on +++ a/fs/nfsd/nfssvc.c @@ -134,6 +134,9 @@ static int killsig; /* signal that was u 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 -puN fs/nfs/super.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on fs/nfs/super.c --- a/fs/nfs/super.c~knfsd-be-more-selective-in-which-sockets-lockd-listens-on +++ a/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; } diff -puN include/linux/lockd/bind.h~knfsd-be-more-selective-in-which-sockets-lockd-listens-on include/linux/lockd/bind.h --- a/include/linux/lockd/bind.h~knfsd-be-more-selective-in-which-sockets-lockd-listens-on +++ a/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 */ _ Patches currently in -mm which might be from neilb@xxxxxxx are ext3-avoid-triggering-ext3_error-on-bad-nfs-file-handle.patch ext3-avoid-triggering-ext3_error-on-bad-nfs-file-handle-fix.patch git-klibc.patch ext3-reject-filehandles-referring-to-special-files.patch ext2-reject-file-handles-with-bad-inode-numbers-early.patch knfsd-knfsd-add-some-missing-newlines-in-printks.patch knfsd-knfsd-remove-an-unused-variable-from-e_show.patch knfsd-knfsd-remove-an-unused-variable-from-auth_unix_lookup.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes-tidy.patch knfsd-be-more-selective-in-which-sockets-lockd-listens-on.patch knfsd-remove-nfsd_versbits-as-intermediate-storage-for-desired-versions.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers-tweaks.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports-tidy.patch knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist.patch md-dm-reduce-stack-usage-with-stacked-block-devices.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html