From cab6fc1b77c3ec4471d7d54ff6db9ad2dd59c2f5 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 20 Dec 2007 14:55:11 -0500 Subject: lockd: Eliminate harmless mixed sign comparison in nlmdbg_cookie2a() The cookie->len field is unsigned, so the loop index variable in nlmdbg_cookie2a() should also be unsigned. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/xdr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 633653b..3e459e1 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -612,8 +612,7 @@ const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie) * called with BKL held. */ static char buf[2*NLM_MAXCOOKIELEN+1]; - int i; - int len = sizeof(buf); + unsigned int i, len = sizeof(buf); char *p = buf; len--; /* allow for trailing \0 */ -- cgit v1.1 From 52c4044d00fe703eb3fb18e0d8dfd1c196eb28be Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 11 Jan 2008 17:09:44 -0500 Subject: NLM: Introduce external nlm_host set-up and tear-down functions We would like to remove the per-lock-operation nlm_lookup_host() call from nlmclnt_proc(). The new architecture pins an nlm_host structure to each NFS client superblock that has the "lock" mount option set. The NFS client passes in the pinned nlm_host structure during each call to nlmclnt_proc(). NFS client unmount processing "puts" the nlm_host so it can be garbage- collected later. This patch introduces externally callable NLM functions that handle mount-time nlm_host set up and tear-down. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/clntlock.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'fs/lockd') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index d070b18..9a8f4f4 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -41,6 +41,54 @@ struct nlm_wait { static LIST_HEAD(nlm_blocked); +/** + * nlmclnt_init - Set up per-NFS mount point lockd data structures + * @server_name: server's hostname + * @server_address: server's network address + * @server_addrlen: length of server's address + * @protocol: transport protocol lockd should use + * @nfs_version: NFS protocol version for this mount point + * + * Returns pointer to an appropriate nlm_host struct, + * or an ERR_PTR value. + */ +struct nlm_host *nlmclnt_init(const char *server_name, + const struct sockaddr *server_address, + size_t server_addrlen, + unsigned short protocol, u32 nfs_version) +{ + struct nlm_host *host; + u32 nlm_version = (nfs_version == 2) ? 1 : 4; + int status; + + status = lockd_up(protocol); + if (status < 0) + return ERR_PTR(status); + + host = nlmclnt_lookup_host((struct sockaddr_in *)server_address, + protocol, nlm_version, + server_name, strlen(server_name)); + if (host == NULL) { + lockd_down(); + return ERR_PTR(-ENOLCK); + } + + return host; +} +EXPORT_SYMBOL_GPL(nlmclnt_init); + +/** + * nlmclnt_done - Release resources allocated by nlmclnt_init() + * @host: nlm_host structure reserved by nlmclnt_init() + * + */ +void nlmclnt_done(struct nlm_host *host) +{ + nlm_release_host(host); + lockd_down(); +} +EXPORT_SYMBOL_GPL(nlmclnt_done); + /* * Queue up a lock for blocking so that the GRANTED request can see it */ -- cgit v1.1 From 1093a60ef34bb12010fe7ea4b780bee1c57cfbbe Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 11 Jan 2008 17:09:59 -0500 Subject: NLM/NFS: Use cached nlm_host when calling nlmclnt_proc() Now that each NFS mount point caches its own nlm_host structure, it can be passed to nlmclnt_proc() for each lock request. By pinning an nlm_host for each mount point, we trade the overhead of looking up or creating a fresh nlm_host struct during every NLM procedure call for a little extra memory. We also restrict the nlmclnt_proc symbol to limit the use of this call to in-tree modules. Note that nlm_lookup_host() (just removed from the client's per-request NLM processing) could also trigger an nlm_host garbage collection. Now client-side nlm_host garbage collection occurs only during NFS mount processing. Since the NFS client now holds a reference on these nlm_host structures, they wouldn't have been affected by garbage collection anyway. Given that nlm_lookup_host() reorders the global nlm_host chain after every successful lookup, and that a garbage collection could be triggered during the call, we've removed a significant amount of per-NLM-request CPU processing overhead. Sidebar: there are only a few remaining references to the internals of NFS inodes in the client-side NLM code. The only references I found are related to extracting or comparing the inode's file handle via NFS_FH(). One is in nlmclnt_grant(); the other is in nlmclnt_setlockargs(). Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index a10343b..b1a4dba 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -145,34 +145,21 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req) BUG_ON(req->a_args.lock.fl.fl_ops != NULL); } -/* - * This is the main entry point for the NLM client. +/** + * nlmclnt_proc - Perform a single client-side lock request + * @host: address of a valid nlm_host context representing the NLM server + * @cmd: fcntl-style file lock operation to perform + * @fl: address of arguments for the lock operation + * */ -int -nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) +int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl) { - struct rpc_clnt *client = NFS_CLIENT(inode); - struct sockaddr_in addr; - struct nfs_server *nfssrv = NFS_SERVER(inode); - struct nlm_host *host; struct nlm_rqst *call; sigset_t oldset; unsigned long flags; - int status, vers; - - vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; - if (NFS_PROTO(inode)->version > 3) { - printk(KERN_NOTICE "NFSv4 file locking not implemented!\n"); - return -ENOLCK; - } - - rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr)); - host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers, - nfssrv->nfs_client->cl_hostname, - strlen(nfssrv->nfs_client->cl_hostname)); - if (host == NULL) - return -ENOLCK; + int status; + nlm_get_host(host); call = nlm_alloc_call(host); if (call == NULL) return -ENOMEM; @@ -219,7 +206,7 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) dprintk("lockd: clnt proc returns %d\n", status); return status; } -EXPORT_SYMBOL(nlmclnt_proc); +EXPORT_SYMBOL_GPL(nlmclnt_proc); /* * Allocate an NLM RPC call struct -- cgit v1.1 From 883bb163f84e0a54b29846c61621f52db3f27393 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 15 Jan 2008 16:04:20 -0500 Subject: NLM: Introduce an arguments structure for nlmclnt_init() Clean up: pass 5 arguments to nlmclnt_init() in a structure similar to the new nfs_client_initdata structure. Signed-off-by: Chuck Lever --- fs/lockd/clntlock.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 9a8f4f4..0b45fd3 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -43,31 +43,25 @@ static LIST_HEAD(nlm_blocked); /** * nlmclnt_init - Set up per-NFS mount point lockd data structures - * @server_name: server's hostname - * @server_address: server's network address - * @server_addrlen: length of server's address - * @protocol: transport protocol lockd should use - * @nfs_version: NFS protocol version for this mount point + * @nlm_init: pointer to arguments structure * * Returns pointer to an appropriate nlm_host struct, * or an ERR_PTR value. */ -struct nlm_host *nlmclnt_init(const char *server_name, - const struct sockaddr *server_address, - size_t server_addrlen, - unsigned short protocol, u32 nfs_version) +struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) { struct nlm_host *host; - u32 nlm_version = (nfs_version == 2) ? 1 : 4; + u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; int status; - status = lockd_up(protocol); + status = lockd_up(nlm_init->protocol); if (status < 0) return ERR_PTR(status); - host = nlmclnt_lookup_host((struct sockaddr_in *)server_address, - protocol, nlm_version, - server_name, strlen(server_name)); + host = nlmclnt_lookup_host((struct sockaddr_in *)nlm_init->address, + nlm_init->protocol, nlm_version, + nlm_init->hostname, + strlen(nlm_init->hostname)); if (host == NULL) { lockd_down(); return ERR_PTR(-ENOLCK); -- cgit v1.1 From 65fdf7d264213a9a8de44f9a20e002a26c267a76 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 11 Jan 2008 17:41:29 -0500 Subject: NLM: Fix a bogus 'return' in nlmclnt_rpc_release Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index b1a4dba..b6b74a6 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -244,7 +244,7 @@ void nlm_release_call(struct nlm_rqst *call) static void nlmclnt_rpc_release(void *data) { - return nlm_release_call(data); + nlm_release_call(data); } static int nlm_wait_on_grace(wait_queue_head_t *queue) -- cgit v1.1 From 48df020aa17ac95a012ff765b0086ede5996b320 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 1 Nov 2007 16:56:53 -0400 Subject: NLM: Fix sign of length of NLM variable length strings According to The Open Group's NLM specification, NLM callers are variable length strings. XDR variable length strings use an unsigned 32 bit length. And internally, negative string lengths are not meaningful for the Linux NLM implementation. Clean up: Make nlm_lock.len and nlm_reboot.len unsigned integers. This makes the sign of NLM string lengths consistent with the sign of xdr_netobj lengths. Signed-off-by: Chuck Lever Acked-By: NeilBrown Signed-off-by: J. Bruce Fields --- fs/lockd/host.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 572601e9..ebec009 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -34,10 +34,10 @@ static DEFINE_MUTEX(nlm_host_mutex); static void nlm_gc_hosts(void); static struct nsm_handle * __nsm_find(const struct sockaddr_in *, - const char *, int, int); + const char *, unsigned int, int); static struct nsm_handle * nsm_find(const struct sockaddr_in *sin, const char *hostname, - int hostname_len); + unsigned int hostname_len); /* * Common host lookup routine for server & client @@ -45,7 +45,8 @@ static struct nsm_handle * nsm_find(const struct sockaddr_in *sin, static struct nlm_host * nlm_lookup_host(int server, const struct sockaddr_in *sin, int proto, int version, const char *hostname, - int hostname_len, const struct sockaddr_in *ssin) + unsigned int hostname_len, + const struct sockaddr_in *ssin) { struct hlist_head *chain; struct hlist_node *pos; @@ -176,7 +177,7 @@ nlm_destroy_host(struct nlm_host *host) */ struct nlm_host * nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version, - const char *hostname, int hostname_len) + const char *hostname, unsigned int hostname_len) { struct sockaddr_in ssin = {0}; @@ -189,7 +190,7 @@ nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version, */ struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *rqstp, - const char *hostname, int hostname_len) + const char *hostname, unsigned int hostname_len) { struct sockaddr_in ssin = {0}; @@ -307,7 +308,8 @@ void nlm_release_host(struct nlm_host *host) * Release all resources held by that peer. */ void nlm_host_rebooted(const struct sockaddr_in *sin, - const char *hostname, int hostname_len, + const char *hostname, + unsigned int hostname_len, u32 new_state) { struct hlist_head *chain; @@ -449,7 +451,7 @@ static DEFINE_MUTEX(nsm_mutex); static struct nsm_handle * __nsm_find(const struct sockaddr_in *sin, - const char *hostname, int hostname_len, + const char *hostname, unsigned int hostname_len, int create) { struct nsm_handle *nsm = NULL; @@ -503,7 +505,8 @@ out: } static struct nsm_handle * -nsm_find(const struct sockaddr_in *sin, const char *hostname, int hostname_len) +nsm_find(const struct sockaddr_in *sin, const char *hostname, + unsigned int hostname_len) { return __nsm_find(sin, hostname, hostname_len, 1); } -- cgit v1.1 From b7e6b86948df8d08d420558212e09eb449be9bfa Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Mon, 26 Nov 2007 13:35:11 -0500 Subject: lockd: fix reference count leaks in async locking case In a number of places where we wish only to translate nlm_drop_reply to rpc_drop_reply errors we instead return early with rpc_drop_reply, skipping some important end-of-function cleanup. This results in reference count leaks when lockd is doing posix locking on GFS2. Signed-off-by: Oleg Drokin Signed-off-by: J. Bruce Fields --- fs/lockd/svc4proc.c | 20 ++++++++++++-------- fs/lockd/svcproc.c | 22 +++++++++++++--------- 2 files changed, 25 insertions(+), 17 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index bf27b6c..385437e 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -84,6 +84,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; + int rc = rpc_success; dprintk("lockd: TEST4 called\n"); resp->cookie = argp->cookie; @@ -91,7 +92,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Don't accept test requests during grace period */ if (nlmsvc_grace_period) { resp->status = nlm_lck_denied_grace_period; - return rpc_success; + return rc; } /* Obtain client and file */ @@ -101,12 +102,13 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Now check for conflicting locks */ resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie); if (resp->status == nlm_drop_reply) - return rpc_drop_reply; + rc = rpc_drop_reply; + else + dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); - dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); nlm_release_host(host); nlm_release_file(file); - return rpc_success; + return rc; } static __be32 @@ -115,6 +117,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; + int rc = rpc_success; dprintk("lockd: LOCK called\n"); @@ -123,7 +126,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Don't accept new lock requests during grace period */ if (nlmsvc_grace_period && !argp->reclaim) { resp->status = nlm_lck_denied_grace_period; - return rpc_success; + return rc; } /* Obtain client and file */ @@ -146,12 +149,13 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, resp->status = nlmsvc_lock(rqstp, file, &argp->lock, argp->block, &argp->cookie); if (resp->status == nlm_drop_reply) - return rpc_drop_reply; + rc = rpc_drop_reply; + else + dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); - dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); nlm_release_host(host); nlm_release_file(file); - return rpc_success; + return rc; } static __be32 diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 9cd5c8b..88379cc 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -113,6 +113,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; + int rc = rpc_success; dprintk("lockd: TEST called\n"); resp->cookie = argp->cookie; @@ -120,7 +121,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Don't accept test requests during grace period */ if (nlmsvc_grace_period) { resp->status = nlm_lck_denied_grace_period; - return rpc_success; + return rc; } /* Obtain client and file */ @@ -130,13 +131,14 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Now check for conflicting locks */ resp->status = cast_status(nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie)); if (resp->status == nlm_drop_reply) - return rpc_drop_reply; + rc = rpc_drop_reply; + else + dprintk("lockd: TEST status %d vers %d\n", + ntohl(resp->status), rqstp->rq_vers); - dprintk("lockd: TEST status %d vers %d\n", - ntohl(resp->status), rqstp->rq_vers); nlm_release_host(host); nlm_release_file(file); - return rpc_success; + return rc; } static __be32 @@ -145,6 +147,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; + int rc = rpc_success; dprintk("lockd: LOCK called\n"); @@ -153,7 +156,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Don't accept new lock requests during grace period */ if (nlmsvc_grace_period && !argp->reclaim) { resp->status = nlm_lck_denied_grace_period; - return rpc_success; + return rc; } /* Obtain client and file */ @@ -176,12 +179,13 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, argp->block, &argp->cookie)); if (resp->status == nlm_drop_reply) - return rpc_drop_reply; + rc = rpc_drop_reply; + else + dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); - dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); nlm_release_host(host); nlm_release_file(file); - return rpc_success; + return rc; } static __be32 -- cgit v1.1 From 29dbf546159f5701e11de26fa2da5c4a962e0f83 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Thu, 29 Nov 2007 14:02:21 -0500 Subject: lockd: fix a leak in nlmsvc_testlock asynchronous request handling Without the patch, there is a leakage of nlmblock structure refcount that holds a reference nlmfile structure, that holds a reference to struct file, when async GETFL is used (-EINPROGRESS return from file_ops->lock()), and also in some error cases. Fix up a style nit while we're here. Signed-off-by: Oleg Drokin Signed-off-by: J. Bruce Fields --- fs/lockd/svclock.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index d120ec39..84c4d5e 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -501,25 +501,29 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, block, block->b_flags, block->b_fl); if (block->b_flags & B_TIMED_OUT) { nlmsvc_unlink_block(block); - return nlm_lck_denied; + ret = nlm_lck_denied; + goto out; } if (block->b_flags & B_GOT_CALLBACK) { if (block->b_fl != NULL && block->b_fl->fl_type != F_UNLCK) { lock->fl = *block->b_fl; goto conf_lock; - } - else { + } else { nlmsvc_unlink_block(block); - return nlm_granted; + ret = nlm_granted; + goto out; } } - return nlm_drop_reply; + ret = nlm_drop_reply; + goto out; } error = vfs_test_lock(file->f_file, &lock->fl); - if (error == -EINPROGRESS) - return nlmsvc_defer_lock_rqst(rqstp, block); + if (error == -EINPROGRESS) { + ret = nlmsvc_defer_lock_rqst(rqstp, block); + goto out; + } if (error) { ret = nlm_lck_denied_nolocks; goto out; -- cgit v1.1 From 54ca95eb362d6988a577965ffb77c08702adb890 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 11 Jan 2008 21:57:35 -0500 Subject: Leak in nlmsvc_testlock for async GETFL case Fix nlm_block leak for the case of supplied blocking lock info. Signed-off-by: Oleg Drokin Signed-off-by: J. Bruce Fields --- fs/lockd/svclock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 84c4d5e..2f4d8fa 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -505,12 +505,12 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, goto out; } if (block->b_flags & B_GOT_CALLBACK) { + nlmsvc_unlink_block(block); if (block->b_fl != NULL && block->b_fl->fl_type != F_UNLCK) { lock->fl = *block->b_fl; goto conf_lock; } else { - nlmsvc_unlink_block(block); ret = nlm_granted; goto out; } -- cgit v1.1 From d7c9f1ed972b4a468dd24a2457721704dfe9ca70 Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Sun, 30 Dec 2007 21:07:44 -0600 Subject: svc: Change services to use new svc_create_xprt service Modify the various kernel RPC svcs to use the svc_create_xprt service. Signed-off-by: Tom Tucker Acked-by: Neil Brown Reviewed-by: Chuck Lever Reviewed-by: Greg Banks Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 82e2192..8686915 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -219,13 +219,12 @@ lockd(struct svc_rqst *rqstp) module_put_and_exit(0); } - -static int find_socket(struct svc_serv *serv, int proto) +static int find_xprt(struct svc_serv *serv, char *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) { + if (strcmp(svsk->sk_xprt.xpt_class->xcl_name, proto) == 0) { found = 1; break; } @@ -243,13 +242,13 @@ static int make_socks(struct svc_serv *serv, int proto) int err = 0; if (proto == IPPROTO_UDP || nlm_udpport) - if (!find_socket(serv, IPPROTO_UDP)) - err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport, - SVC_SOCK_DEFAULTS); + if (!find_xprt(serv, "udp")) + err = svc_create_xprt(serv, "udp", nlm_udpport, + SVC_SOCK_DEFAULTS); if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) - if (!find_socket(serv, IPPROTO_TCP)) - err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport, - SVC_SOCK_DEFAULTS); + if (!find_xprt(serv, "tcp")) + err = svc_create_xprt(serv, "tcp", nlm_tcpport, + SVC_SOCK_DEFAULTS); if (err >= 0) { warned = 0; -- cgit v1.1 From 7a18208383ab3f3ce4a1f4e0536acc9372523d81 Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Sun, 30 Dec 2007 21:07:53 -0600 Subject: svc: Make close transport independent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move sk_list and sk_ready to svc_xprt. This involves close because these lists are walked by svcs when closing all their transports. So I combined the moving of these lists to svc_xprt with making close transport independent. The svc_force_sock_close has been changed to svc_close_all and takes a list as an argument. This removes some svc internals knowledge from the svcs. This code races with module removal and transport addition. Thanks to Simon Holm Thøgersen for a compile fix. Signed-off-by: Tom Tucker Acked-by: Neil Brown Reviewed-by: Chuck Lever Reviewed-by: Greg Banks Signed-off-by: J. Bruce Fields Cc: Simon Holm Thøgersen --- fs/lockd/svc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 8686915..a8e79a9 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -221,10 +221,10 @@ lockd(struct svc_rqst *rqstp) static int find_xprt(struct svc_serv *serv, char *proto) { - struct svc_sock *svsk; + struct svc_xprt *xprt; int found = 0; - list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) - if (strcmp(svsk->sk_xprt.xpt_class->xcl_name, proto) == 0) { + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) + if (strcmp(xprt->xpt_class->xcl_name, proto) == 0) { found = 1; break; } -- cgit v1.1 From 7fcb98d58cb4d18af6386f71025fc5192f25fbca Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Sun, 30 Dec 2007 21:08:33 -0600 Subject: svc: Add svc API that queries for a transport instance Add a new svc function that allows a service to query whether a transport instance has already been created. This is used in lockd to determine whether or not a transport needs to be created when a lockd instance is brought up. Specifying 0 for the address family or port is effectively a wild-card, and will result in matching the first transport in the service's list that has a matching class name. Signed-off-by: Tom Tucker Acked-by: Neil Brown Reviewed-by: Chuck Lever Reviewed-by: Greg Banks Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index a8e79a9..470af01 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -219,18 +219,6 @@ lockd(struct svc_rqst *rqstp) module_put_and_exit(0); } -static int find_xprt(struct svc_serv *serv, char *proto) -{ - struct svc_xprt *xprt; - int found = 0; - list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) - if (strcmp(xprt->xpt_class->xcl_name, proto) == 0) { - found = 1; - break; - } - return found; -} - /* * Make any sockets that are needed but not present. * If nlm_udpport or nlm_tcpport were set as module @@ -242,11 +230,11 @@ static int make_socks(struct svc_serv *serv, int proto) int err = 0; if (proto == IPPROTO_UDP || nlm_udpport) - if (!find_xprt(serv, "udp")) + if (!svc_find_xprt(serv, "udp", 0, 0)) err = svc_create_xprt(serv, "udp", nlm_udpport, SVC_SOCK_DEFAULTS); if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) - if (!find_xprt(serv, "tcp")) + if (!svc_find_xprt(serv, "tcp", 0, 0)) err = svc_create_xprt(serv, "tcp", nlm_tcpport, SVC_SOCK_DEFAULTS); -- cgit v1.1 From a217813f9067b785241cb7f31956e51d2071703a Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Sun, 30 Dec 2007 21:08:35 -0600 Subject: knfsd: Support adding transports by writing portlist file Update the write handler for the portlist file to allow creating new listening endpoints on a transport. The general form of the string is: For example: echo "tcp 2049" > /proc/fs/nfsd/portlist This is intended to support the creation of a listening endpoint for RDMA transports without adding #ifdef code to the nfssvc.c file. Transports can also be removed as follows: '-' For example: echo "-tcp 2049" > /proc/fs/nfsd/portlist Attempting to add a listener with an invalid transport string results in EPROTONOSUPPORT and a perror string of "Protocol not supported". Attempting to remove an non-existent listener (.e.g. bad proto or port) results in ENOTCONN and a perror string of "Transport endpoint is not connected" Signed-off-by: Tom Tucker Acked-by: Neil Brown Reviewed-by: Chuck Lever Reviewed-by: Greg Banks Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 470af01..0822646 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -227,17 +227,25 @@ lockd(struct svc_rqst *rqstp) static int make_socks(struct svc_serv *serv, int proto) { static int warned; + struct svc_xprt *xprt; int err = 0; - if (proto == IPPROTO_UDP || nlm_udpport) - if (!svc_find_xprt(serv, "udp", 0, 0)) + if (proto == IPPROTO_UDP || nlm_udpport) { + xprt = svc_find_xprt(serv, "udp", 0, 0); + if (!xprt) err = svc_create_xprt(serv, "udp", nlm_udpport, SVC_SOCK_DEFAULTS); - if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) - if (!svc_find_xprt(serv, "tcp", 0, 0)) + else + svc_xprt_put(xprt); + } + if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) { + xprt = svc_find_xprt(serv, "tcp", 0, 0); + if (!xprt) err = svc_create_xprt(serv, "tcp", nlm_tcpport, SVC_SOCK_DEFAULTS); - + else + svc_xprt_put(xprt); + } if (err >= 0) { warned = 0; err = 0; -- cgit v1.1 From 50431d94e732ba71b66a83c5435890728e313095 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 31 Aug 2007 17:09:33 -0400 Subject: lockd: minor log message fix Wendy Cheng noticed that function name doesn't agree here. Signed-off-by: J. Bruce Fields Cc: Wendy Cheng --- fs/lockd/svcsubs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 84ebba3..dbbefbc 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -87,7 +87,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, unsigned int hash; __be32 nfserr; - nlm_debug_print_fh("nlm_file_lookup", f); + nlm_debug_print_fh("nlm_lookup_file", f); hash = file_hash(f); -- cgit v1.1 From d801b861681116ea23a7fb87a70bf463d29c8b9c Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 29 Jan 2008 10:30:55 -0500 Subject: NLM: tear down RPC clients in nlm_shutdown_hosts It's possible for a RPC to outlive the lockd daemon that created it, so we need to make sure that all RPC's are killed when lockd is coming down. When nlm_shutdown_hosts is called, kill off all RPC tasks associated with the host. Since we need to wait until they have all gone away, we might as well just shut down the RPC client altogether. Signed-off-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/lockd/host.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/host.c b/fs/lockd/host.c index ebec009..ca6b16f 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -379,8 +379,13 @@ nlm_shutdown_hosts(void) /* First, make all hosts eligible for gc */ dprintk("lockd: nuking all hosts...\n"); for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { - hlist_for_each_entry(host, pos, chain, h_hash) + hlist_for_each_entry(host, pos, chain, h_hash) { host->h_expires = jiffies - 1; + if (host->h_rpcclnt) { + rpc_shutdown_client(host->h_rpcclnt); + host->h_rpcclnt = NULL; + } + } } /* Then, perform a garbage collection pass */ -- cgit v1.1