diff options
Diffstat (limited to 'fs/lockd')
-rw-r--r-- | fs/lockd/clntlock.c | 58 | ||||
-rw-r--r-- | fs/lockd/clntproc.c | 17 | ||||
-rw-r--r-- | fs/lockd/host.c | 325 | ||||
-rw-r--r-- | fs/lockd/mon.c | 77 | ||||
-rw-r--r-- | fs/lockd/svc.c | 19 | ||||
-rw-r--r-- | fs/lockd/svc4proc.c | 85 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 207 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 89 | ||||
-rw-r--r-- | fs/lockd/svcshare.c | 24 | ||||
-rw-r--r-- | fs/lockd/svcsubs.c | 183 | ||||
-rw-r--r-- | fs/lockd/xdr.c | 76 | ||||
-rw-r--r-- | fs/lockd/xdr4.c | 80 |
12 files changed, 713 insertions, 527 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 87e1d03..b85a0ad 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -100,12 +100,12 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) /* * The server lockd has called us back to tell us the lock was granted */ -u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) +__be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) { const struct file_lock *fl = &lock->fl; const struct nfs_fh *fh = &lock->fh; struct nlm_wait *block; - u32 res = nlm_lck_denied; + __be32 res = nlm_lck_denied; /* * Look up blocked request based on arguments. @@ -144,42 +144,12 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) */ /* - * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, - * that we mark locks for reclaiming, and that we bump the pseudo NSM state. - */ -static void nlmclnt_prepare_reclaim(struct nlm_host *host) -{ - down_write(&host->h_rwsem); - host->h_monitored = 0; - host->h_state++; - host->h_nextrebind = 0; - nlm_rebind_host(host); - - /* - * Mark the locks for reclaiming. - */ - list_splice_init(&host->h_granted, &host->h_reclaim); - - dprintk("NLM: reclaiming locks for host %s\n", host->h_name); -} - -static void nlmclnt_finish_reclaim(struct nlm_host *host) -{ - host->h_reclaiming = 0; - up_write(&host->h_rwsem); - dprintk("NLM: done reclaiming locks for host %s", host->h_name); -} - -/* * Reclaim all locks on server host. We do this by spawning a separate * reclaimer thread. */ void -nlmclnt_recovery(struct nlm_host *host, u32 newstate) +nlmclnt_recovery(struct nlm_host *host) { - if (host->h_nsmstate == newstate) - return; - host->h_nsmstate = newstate; if (!host->h_reclaiming++) { nlm_get_host(host); __module_get(THIS_MODULE); @@ -199,18 +169,30 @@ reclaimer(void *ptr) daemonize("%s-reclaim", host->h_name); allow_signal(SIGKILL); + down_write(&host->h_rwsem); + /* This one ensures that our parent doesn't terminate while the * reclaim is in progress */ lock_kernel(); lockd_up(0); /* note: this cannot fail as lockd is already running */ - nlmclnt_prepare_reclaim(host); - /* First, reclaim all locks that have been marked. */ + dprintk("lockd: reclaiming locks for host %s", host->h_name); + restart: nsmstate = host->h_nsmstate; + + /* Force a portmap getport - the peer's lockd will + * most likely end up on a different port. + */ + host->h_nextrebind = jiffies; + nlm_rebind_host(host); + + /* First, reclaim all locks that have been granted. */ + list_splice_init(&host->h_granted, &host->h_reclaim); list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { list_del_init(&fl->fl_u.nfs_fl.list); + /* Why are we leaking memory here? --okir */ if (signalled()) continue; if (nlmclnt_reclaim(host, fl) != 0) @@ -218,11 +200,13 @@ restart: list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); if (host->h_nsmstate != nsmstate) { /* Argh! The server rebooted again! */ - list_splice_init(&host->h_granted, &host->h_reclaim); goto restart; } } - nlmclnt_finish_reclaim(host); + + host->h_reclaiming = 0; + up_write(&host->h_rwsem); + dprintk("NLM: done reclaiming locks for host %s", host->h_name); /* Now, wake up all processes that sleep on a blocked lock */ list_for_each_entry(block, &nlm_blocked, b_list) { diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 0116729..3d84f60 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -36,14 +36,14 @@ static const struct rpc_call_ops nlmclnt_cancel_ops; /* * Cookie counter for NLM requests */ -static u32 nlm_cookie = 0x1234; +static atomic_t nlm_cookie = ATOMIC_INIT(0x1234); -static inline void nlmclnt_next_cookie(struct nlm_cookie *c) +void nlmclnt_next_cookie(struct nlm_cookie *c) { - memcpy(c->data, &nlm_cookie, 4); - memset(c->data+4, 0, 4); + u32 cookie = atomic_inc_return(&nlm_cookie); + + memcpy(c->data, &cookie, 4); c->len=4; - nlm_cookie++; } static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner) @@ -153,6 +153,7 @@ nlmclnt_proc(struct inode *inode, 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; @@ -166,7 +167,9 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) } rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr)); - host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers); + 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; @@ -499,7 +502,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) unsigned char fl_flags = fl->fl_flags; int status = -ENOLCK; - if (!host->h_monitored && nsm_monitor(host) < 0) { + if (nsm_monitor(host) < 0) { printk(KERN_NOTICE "lockd: failed to monitor %s\n", host->h_name); goto out; diff --git a/fs/lockd/host.c b/fs/lockd/host.c index a0d0b58..fb24a97 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -27,46 +27,60 @@ #define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ) #define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ) -static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH]; +static struct hlist_head nlm_hosts[NLM_HOST_NRHASH]; static unsigned long next_gc; static int nrhosts; 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); /* * Find an NLM server handle in the cache. If there is none, create it. */ struct nlm_host * -nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version) +nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version, + const char *hostname, int hostname_len) { - return nlm_lookup_host(0, sin, proto, version); + return nlm_lookup_host(0, sin, proto, version, + hostname, hostname_len); } /* * Find an NLM client handle in the cache. If there is none, create it. */ struct nlm_host * -nlmsvc_lookup_host(struct svc_rqst *rqstp) +nlmsvc_lookup_host(struct svc_rqst *rqstp, + const char *hostname, int hostname_len) { return nlm_lookup_host(1, &rqstp->rq_addr, - rqstp->rq_prot, rqstp->rq_vers); + rqstp->rq_prot, rqstp->rq_vers, + hostname, hostname_len); } /* * Common host lookup routine for server & client */ struct nlm_host * -nlm_lookup_host(int server, struct sockaddr_in *sin, - int proto, int version) +nlm_lookup_host(int server, const struct sockaddr_in *sin, + int proto, int version, + const char *hostname, + int hostname_len) { - struct nlm_host *host, **hp; - u32 addr; + struct hlist_head *chain; + struct hlist_node *pos; + struct nlm_host *host; + struct nsm_handle *nsm = NULL; int hash; - dprintk("lockd: nlm_lookup_host(%08x, p=%d, v=%d)\n", - (unsigned)(sin? ntohl(sin->sin_addr.s_addr) : 0), proto, version); + dprintk("lockd: nlm_lookup_host(%u.%u.%u.%u, p=%d, v=%d, my role=%s, name=%.*s)\n", + NIPQUAD(sin->sin_addr.s_addr), proto, version, + server? "server" : "client", + hostname_len, + hostname? hostname : "<none>"); + hash = NLM_ADDRHASH(sin->sin_addr.s_addr); @@ -76,7 +90,22 @@ nlm_lookup_host(int server, struct sockaddr_in *sin, if (time_after_eq(jiffies, next_gc)) nlm_gc_hosts(); - for (hp = &nlm_hosts[hash]; (host = *hp) != 0; hp = &host->h_next) { + /* We may keep several nlm_host objects for a peer, because each + * nlm_host is identified by + * (address, protocol, version, server/client) + * We could probably simplify this a little by putting all those + * different NLM rpc_clients into one single nlm_host object. + * This would allow us to have one nlm_host per address. + */ + chain = &nlm_hosts[hash]; + hlist_for_each_entry(host, pos, chain, h_hash) { + if (!nlm_cmp_addr(&host->h_addr, sin)) + continue; + + /* See if we have an NSM handle for this client */ + if (!nsm) + nsm = host->h_nsmhandle; + if (host->h_proto != proto) continue; if (host->h_version != version) @@ -84,28 +113,30 @@ nlm_lookup_host(int server, struct sockaddr_in *sin, if (host->h_server != server) continue; - if (nlm_cmp_addr(&host->h_addr, sin)) { - if (hp != nlm_hosts + hash) { - *hp = host->h_next; - host->h_next = nlm_hosts[hash]; - nlm_hosts[hash] = host; - } - nlm_get_host(host); - mutex_unlock(&nlm_host_mutex); - return host; - } - } + /* Move to head of hash chain. */ + hlist_del(&host->h_hash); + hlist_add_head(&host->h_hash, chain); - /* Ooops, no host found, create it */ - dprintk("lockd: creating host entry\n"); + nlm_get_host(host); + goto out; + } + if (nsm) + atomic_inc(&nsm->sm_count); - host = kzalloc(sizeof(*host), GFP_KERNEL); - if (!host) - goto nohost; + host = NULL; - addr = sin->sin_addr.s_addr; - sprintf(host->h_name, "%u.%u.%u.%u", NIPQUAD(addr)); + /* Sadly, the host isn't in our hash table yet. See if + * we have an NSM handle for it. If not, create one. + */ + if (!nsm && !(nsm = nsm_find(sin, hostname, hostname_len))) + goto out; + host = kzalloc(sizeof(*host), GFP_KERNEL); + if (!host) { + nsm_release(nsm); + goto out; + } + host->h_name = nsm->sm_name; host->h_addr = *sin; host->h_addr.sin_port = 0; /* ouch! */ host->h_version = version; @@ -119,9 +150,9 @@ nlm_lookup_host(int server, struct sockaddr_in *sin, init_rwsem(&host->h_rwsem); host->h_state = 0; /* pseudo NSM state */ host->h_nsmstate = 0; /* real NSM state */ + host->h_nsmhandle = nsm; host->h_server = server; - host->h_next = nlm_hosts[hash]; - nlm_hosts[hash] = host; + hlist_add_head(&host->h_hash, chain); INIT_LIST_HEAD(&host->h_lockowners); spin_lock_init(&host->h_lock); INIT_LIST_HEAD(&host->h_granted); @@ -130,35 +161,39 @@ nlm_lookup_host(int server, struct sockaddr_in *sin, if (++nrhosts > NLM_HOST_MAX) next_gc = 0; -nohost: +out: mutex_unlock(&nlm_host_mutex); return host; } -struct nlm_host * -nlm_find_client(void) +/* + * Destroy a host + */ +static void +nlm_destroy_host(struct nlm_host *host) { - /* find a nlm_host for a client for which h_killed == 0. - * and return it + struct rpc_clnt *clnt; + + BUG_ON(!list_empty(&host->h_lockowners)); + BUG_ON(atomic_read(&host->h_count)); + + /* + * Release NSM handle and unmonitor host. */ - int hash; - mutex_lock(&nlm_host_mutex); - for (hash = 0 ; hash < NLM_HOST_NRHASH; hash++) { - struct nlm_host *host, **hp; - for (hp = &nlm_hosts[hash]; (host = *hp) != 0; hp = &host->h_next) { - if (host->h_server && - host->h_killed == 0) { - nlm_get_host(host); - mutex_unlock(&nlm_host_mutex); - return host; - } + nsm_unmonitor(host); + + if ((clnt = host->h_rpcclnt) != NULL) { + if (atomic_read(&clnt->cl_users)) { + printk(KERN_WARNING + "lockd: active RPC handle\n"); + clnt->cl_dead = 1; + } else { + rpc_destroy_client(host->h_rpcclnt); } } - mutex_unlock(&nlm_host_mutex); - return NULL; + kfree(host); } - /* * Create the NLM RPC client for an NLM peer */ @@ -260,22 +295,82 @@ void nlm_release_host(struct nlm_host *host) } /* + * We were notified that the host indicated by address &sin + * has rebooted. + * Release all resources held by that peer. + */ +void nlm_host_rebooted(const struct sockaddr_in *sin, + const char *hostname, int hostname_len, + u32 new_state) +{ + struct hlist_head *chain; + struct hlist_node *pos; + struct nsm_handle *nsm; + struct nlm_host *host; + + dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n", + hostname, NIPQUAD(sin->sin_addr)); + + /* Find the NSM handle for this peer */ + if (!(nsm = __nsm_find(sin, hostname, hostname_len, 0))) + return; + + /* When reclaiming locks on this peer, make sure that + * we set up a new notification */ + nsm->sm_monitored = 0; + + /* Mark all hosts tied to this NSM state as having rebooted. + * We run the loop repeatedly, because we drop the host table + * lock for this. + * To avoid processing a host several times, we match the nsmstate. + */ +again: mutex_lock(&nlm_host_mutex); + for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { + hlist_for_each_entry(host, pos, chain, h_hash) { + if (host->h_nsmhandle == nsm + && host->h_nsmstate != new_state) { + host->h_nsmstate = new_state; + host->h_state++; + + nlm_get_host(host); + mutex_unlock(&nlm_host_mutex); + + if (host->h_server) { + /* We're server for this guy, just ditch + * all the locks he held. */ + nlmsvc_free_host_resources(host); + } else { + /* He's the server, initiate lock recovery. */ + nlmclnt_recovery(host); + } + + nlm_release_host(host); + goto again; + } + } + } + + mutex_unlock(&nlm_host_mutex); +} + +/* * Shut down the hosts module. * Note that this routine is called only at server shutdown time. */ void nlm_shutdown_hosts(void) { + struct hlist_head *chain; + struct hlist_node *pos; struct nlm_host *host; - int i; dprintk("lockd: shutting down host module\n"); mutex_lock(&nlm_host_mutex); /* First, make all hosts eligible for gc */ dprintk("lockd: nuking all hosts...\n"); - for (i = 0; i < NLM_HOST_NRHASH; i++) { - for (host = nlm_hosts[i]; host; host = host->h_next) + for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { + hlist_for_each_entry(host, pos, chain, h_hash) host->h_expires = jiffies - 1; } @@ -287,8 +382,8 @@ nlm_shutdown_hosts(void) if (nrhosts) { printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); dprintk("lockd: %d hosts left:\n", nrhosts); - for (i = 0; i < NLM_HOST_NRHASH; i++) { - for (host = nlm_hosts[i]; host; host = host->h_next) { + for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { + hlist_for_each_entry(host, pos, chain, h_hash) { dprintk(" %s (cnt %d use %d exp %ld)\n", host->h_name, atomic_read(&host->h_count), host->h_inuse, host->h_expires); @@ -305,45 +400,32 @@ nlm_shutdown_hosts(void) static void nlm_gc_hosts(void) { - struct nlm_host **q, *host; - struct rpc_clnt *clnt; - int i; + struct hlist_head *chain; + struct hlist_node *pos, *next; + struct nlm_host *host; dprintk("lockd: host garbage collection\n"); - for (i = 0; i < NLM_HOST_NRHASH; i++) { - for (host = nlm_hosts[i]; host; host = host->h_next) + for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { + hlist_for_each_entry(host, pos, chain, h_hash) host->h_inuse = 0; } /* Mark all hosts that hold locks, blocks or shares */ nlmsvc_mark_resources(); - for (i = 0; i < NLM_HOST_NRHASH; i++) { - q = &nlm_hosts[i]; - while ((host = *q) != NULL) { + for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { + hlist_for_each_entry_safe(host, pos, next, chain, h_hash) { if (atomic_read(&host->h_count) || host->h_inuse || time_before(jiffies, host->h_expires)) { dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", host->h_name, atomic_read(&host->h_count), host->h_inuse, host->h_expires); - q = &host->h_next; continue; } dprintk("lockd: delete host %s\n", host->h_name); - *q = host->h_next; - /* Don't unmonitor hosts that have been invalidated */ - if (host->h_monitored && !host->h_killed) - nsm_unmonitor(host); - if ((clnt = host->h_rpcclnt) != NULL) { - if (atomic_read(&clnt->cl_users)) { - printk(KERN_WARNING - "lockd: active RPC handle\n"); - clnt->cl_dead = 1; - } else { - rpc_destroy_client(host->h_rpcclnt); - } - } - kfree(host); + hlist_del_init(&host->h_hash); + + nlm_destroy_host(host); nrhosts--; } } @@ -351,3 +433,88 @@ nlm_gc_hosts(void) next_gc = jiffies + NLM_HOST_COLLECT; } + +/* + * Manage NSM handles + */ +static LIST_HEAD(nsm_handles); +static DEFINE_MUTEX(nsm_mutex); + +static struct nsm_handle * +__nsm_find(const struct sockaddr_in *sin, + const char *hostname, int hostname_len, + int create) +{ + struct nsm_handle *nsm = NULL; + struct list_head *pos; + + if (!sin) + return NULL; + + if (hostname && memchr(hostname, '/', hostname_len) != NULL) { + if (printk_ratelimit()) { + printk(KERN_WARNING "Invalid hostname \"%.*s\" " + "in NFS lock request\n", + hostname_len, hostname); + } + return NULL; + } + + mutex_lock(&nsm_mutex); + list_for_each(pos, &nsm_handles) { + nsm = list_entry(pos, struct nsm_handle, sm_link); + + if (hostname && nsm_use_hostnames) { + if (strlen(nsm->sm_name) != hostname_len + || memcmp(nsm->sm_name, hostname, hostname_len)) + continue; + } else if (!nlm_cmp_addr(&nsm->sm_addr, sin)) + continue; + atomic_inc(&nsm->sm_count); + goto out; + } + + if (!create) { + nsm = NULL; + goto out; + } + + nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL); + if (nsm != NULL) { + nsm->sm_addr = *sin; + nsm->sm_name = (char *) (nsm + 1); + memcpy(nsm->sm_name, hostname, hostname_len); + nsm->sm_name[hostname_len] = '\0'; + atomic_set(&nsm->sm_count, 1); + + list_add(&nsm->sm_link, &nsm_handles); + } + +out: + mutex_unlock(&nsm_mutex); + return nsm; +} + +struct nsm_handle * +nsm_find(const struct sockaddr_in *sin, const char *hostname, int hostname_len) +{ + return __nsm_find(sin, hostname, hostname_len, 1); +} + +/* + * Release an NSM handle + */ +void +nsm_release(struct nsm_handle *nsm) +{ + if (!nsm) + return; + if (atomic_dec_and_test(&nsm->sm_count)) { + mutex_lock(&nsm_mutex); + if (atomic_read(&nsm->sm_count) == 0) { + list_del(&nsm->sm_link); + kfree(nsm); + } + mutex_unlock(&nsm_mutex); + } +} diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index a816b92..eb243ed 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -24,13 +24,13 @@ static struct rpc_program nsm_program; /* * Local NSM state */ -u32 nsm_local_state; +int nsm_local_state; /* * Common procedure for SM_MON/SM_UNMON calls */ static int -nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) +nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) { struct rpc_clnt *clnt; int status; @@ -46,10 +46,11 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) goto out; } - args.addr = host->h_addr.sin_addr.s_addr; - args.proto= (host->h_proto<<1) | host->h_server; + memset(&args, 0, sizeof(args)); + args.mon_name = nsm->sm_name; + args.addr = nsm->sm_addr.sin_addr.s_addr; args.prog = NLM_PROGRAM; - args.vers = host->h_version; + args.vers = 3; args.proc = NLMPROC_NSM_NOTIFY; memset(res, 0, sizeof(*res)); @@ -70,17 +71,22 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) int nsm_monitor(struct nlm_host *host) { + struct nsm_handle *nsm = host->h_nsmhandle; struct nsm_res res; int status; dprintk("lockd: nsm_monitor(%s)\n", host->h_name); + BUG_ON(nsm == NULL); - status = nsm_mon_unmon(host, SM_MON, &res); + if (nsm->sm_monitored) + return 0; + + status = nsm_mon_unmon(nsm, SM_MON, &res); if (status < 0 || res.status != 0) printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); else - host->h_monitored = 1; + nsm->sm_monitored = 1; return status; } @@ -90,16 +96,26 @@ nsm_monitor(struct nlm_host *host) int nsm_unmonitor(struct nlm_host *host) { + struct nsm_handle *nsm = host->h_nsmhandle; struct nsm_res res; - int status; - - dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); - - status = nsm_mon_unmon(host, SM_UNMON, &res); - if (status < 0) - printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", host->h_name); - else - host->h_monitored = 0; + int status = 0; + + if (nsm == NULL) + return 0; + host->h_nsmhandle = NULL; + + if (atomic_read(&nsm->sm_count) == 1 + && nsm->sm_monitored && !nsm->sm_sticky) { + dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); + + status = nsm_mon_unmon(nsm, SM_UNMON, &res); + if (status < 0) + printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", + host->h_name); + else + nsm->sm_monitored = 0; + } + nsm_release(nsm); return status; } @@ -132,10 +148,10 @@ nsm_create(void) * XDR functions for NSM. */ -static u32 * -xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +static __be32 * +xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { - char buffer[20]; + char buffer[20], *name; /* * Use the dotted-quad IP address of the remote host as @@ -143,8 +159,13 @@ xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) * hostname first for whatever remote hostname it receives, * so this works alright. */ - sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); - if (!(p = xdr_encode_string(p, buffer)) + if (nsm_use_hostnames) { + name = argp->mon_name; + } else { + sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); + name = buffer; + } + if (!(p = xdr_encode_string(p, name)) || !(p = xdr_encode_string(p, utsname()->nodename))) return ERR_PTR(-EIO); *p++ = htonl(argp->prog); @@ -155,21 +176,23 @@ xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) } static int -xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { p = xdr_encode_common(rqstp, p, argp); if (IS_ERR(p)) return PTR_ERR(p); + + /* Surprise - there may even be room for an IPv6 address now */ *p++ = argp->addr; - *p++ = argp->vers; - *p++ = argp->proto; + *p++ = 0; + *p++ = 0; *p++ = 0; rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); return 0; } static int -xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) +xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) { p = xdr_encode_common(rqstp, p, argp); if (IS_ERR(p)) @@ -179,7 +202,7 @@ xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) } static int -xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) +xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) { resp->status = ntohl(*p++); resp->state = ntohl(*p++); @@ -189,7 +212,7 @@ xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) } static int -xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) +xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) { resp->state = ntohl(*p++); return 0; diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 3cc369e..6341392 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -33,6 +33,7 @@ #include <linux/sunrpc/svcsock.h> #include <net/ip.h> #include <linux/lockd/lockd.h> +#include <linux/lockd/sm_inter.h> #include <linux/nfs.h> #define NLMDBG_FACILITY NLMDBG_SVC @@ -61,6 +62,7 @@ static DECLARE_WAIT_QUEUE_HEAD(lockd_exit); static unsigned long nlm_grace_period; static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO; static int nlm_udpport, nlm_tcpport; +int nsm_use_hostnames = 0; /* * Constants needed for the sysctl interface. @@ -395,6 +397,22 @@ static ctl_table nlm_sysctls[] = { .extra1 = (int *) &nlm_port_min, .extra2 = (int *) &nlm_port_max, }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "nsm_use_hostnames", + .data = &nsm_use_hostnames, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "nsm_local_state", + .data = &nsm_local_state, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0 } }; @@ -483,6 +501,7 @@ module_param_call(nlm_udpport, param_set_port, param_get_int, &nlm_udpport, 0644); module_param_call(nlm_tcpport, param_set_port, param_get_int, &nlm_tcpport, 0644); +module_param(nsm_use_hostnames, bool, 0644); /* * Initialising and terminating the module. diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index a2dd9cc..0ce5c81 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -24,22 +24,22 @@ /* * Obtain client and file from arguments */ -static u32 +static __be32 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host **hostp, struct nlm_file **filp) { struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; - u32 error = 0; + __be32 error = 0; /* nfsd callbacks must have been installed for this procedure */ if (!nlmsvc_ops) return nlm_lck_denied_nolocks; /* Obtain host handle */ - if (!(host = nlmsvc_lookup_host(rqstp)) - || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0)) + if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) + || (argp->monitor && nsm_monitor(host) < 0)) goto no_locks; *hostp = host; @@ -68,7 +68,7 @@ no_locks: /* * NULL: Test for presence of service */ -static int +static __be32 nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { dprintk("lockd: NULL called\n"); @@ -78,7 +78,7 @@ nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) /* * TEST: Check for conflicting lock */ -static int +static __be32 nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -96,7 +96,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now check for conflicting locks */ resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); @@ -107,7 +107,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -126,7 +126,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; #if 0 /* If supplied state doesn't match current state, we assume it's @@ -150,7 +150,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -169,7 +169,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Try to cancel request. */ resp->status = nlmsvc_cancel_blocked(file, &argp->lock); @@ -183,7 +183,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNLOCK: release a lock */ -static int +static __be32 nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -202,7 +202,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to remove the lock */ resp->status = nlmsvc_unlock(file, &argp->lock); @@ -217,7 +217,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, * GRANTED: A server calls us to tell that a process' lock request * was granted */ -static int +static __be32 nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -253,14 +253,16 @@ static const struct rpc_call_ops nlm4svc_callback_ops = { * because we send the callback before the reply proper. I hope this * doesn't break any clients. */ -static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, - int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) +static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, + __be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) { struct nlm_host *host; struct nlm_rqst *call; - int stat; + __be32 stat; - host = nlmsvc_lookup_host(rqstp); + host = nlmsvc_lookup_host(rqstp, + argp->lock.caller, + argp->lock.len); if (host == NULL) return rpc_system_err; @@ -280,35 +282,35 @@ static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *a return rpc_success; } -static int nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: TEST_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test); } -static int nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: LOCK_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock); } -static int nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: CANCEL_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel); } -static int nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: UNLOCK_MSG called\n"); return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock); } -static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: GRANTED_MSG called\n"); @@ -318,7 +320,7 @@ static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *arg /* * SHARE: create a DOS share or alter existing share. */ -static int +static __be32 nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -337,7 +339,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to create the share */ resp->status = nlmsvc_share_file(host, file, argp); @@ -351,7 +353,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNSHARE: Release a DOS share. */ -static int +static __be32 nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -370,7 +372,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to lock the file */ resp->status = nlmsvc_unshare_file(host, file, argp); @@ -384,7 +386,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* * NM_LOCK: Create an unmonitored lock */ -static int +static __be32 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -397,7 +399,7 @@ nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* * FREE_ALL: Release all locks and shares held by client */ -static int +static __be32 nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -415,15 +417,11 @@ nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, /* * SM_NOTIFY: private callback from statd (not part of official NLM proto) */ -static int +static __be32 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, void *resp) { struct sockaddr_in saddr = rqstp->rq_addr; - int vers = argp->vers; - int prot = argp->proto >> 1; - - struct nlm_host *host; dprintk("lockd: SM_NOTIFY called\n"); if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) @@ -438,28 +436,17 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, /* Obtain the host pointer for this NFS server and try to * reclaim all locks we hold on this server. */ + memset(&saddr, 0, sizeof(saddr)); saddr.sin_addr.s_addr = argp->addr; + nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); - if ((argp->proto & 1)==0) { - if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) { - nlmclnt_recovery(host, argp->state); - nlm_release_host(host); - } - } else { - /* If we run on an NFS server, delete all locks held by the client */ - - if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) { - nlmsvc_free_host_resources(host); - nlm_release_host(host); - } - } return rpc_success; } /* * client sent a GRANTED_RES, let's remove the associated block */ -static int +static __be32 nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, void *resp) { @@ -468,7 +455,7 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, dprintk("lockd: GRANTED_RES called\n"); - nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status); + nlmsvc_grant_reply(&argp->cookie, argp->status); return rpc_success; } diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 93c00ee..7e219b9 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -40,7 +40,7 @@ static void nlmsvc_release_block(struct nlm_block *block); static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); -static int nlmsvc_remove_block(struct nlm_block *block); +static void nlmsvc_remove_block(struct nlm_block *block); static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); static void nlmsvc_freegrantargs(struct nlm_rqst *call); @@ -49,7 +49,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops; /* * The list of blocked locks to retry */ -static struct nlm_block * nlm_blocked; +static LIST_HEAD(nlm_blocked); /* * Insert a blocked lock into the global list @@ -57,48 +57,44 @@ static struct nlm_block * nlm_blocked; static void nlmsvc_insert_block(struct nlm_block *block, unsigned long when) { - struct nlm_block **bp, *b; + struct nlm_block *b; + struct list_head *pos; dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when); - kref_get(&block->b_count); - if (block->b_queued) - nlmsvc_remove_block(block); - bp = &nlm_blocked; + if (list_empty(&block->b_list)) { + kref_get(&block->b_count); + } else { + list_del_init(&block->b_list); + } + + pos = &nlm_blocked; if (when != NLM_NEVER) { if ((when += jiffies) == NLM_NEVER) when ++; - while ((b = *bp) && time_before_eq(b->b_when,when) && b->b_when != NLM_NEVER) - bp = &b->b_next; - } else - while ((b = *bp) != 0) - bp = &b->b_next; + list_for_each(pos, &nlm_blocked) { + b = list_entry(pos, struct nlm_block, b_list); + if (time_after(b->b_when,when) || b->b_when == NLM_NEVER) + break; + } + /* On normal exit from the loop, pos == &nlm_blocked, + * so we will be adding to the end of the list - good + */ + } - block->b_queued = 1; + list_add_tail(&block->b_list, pos); block->b_when = when; - block->b_next = b; - *bp = block; } /* * Remove a block from the global list */ -static int +static inline void nlmsvc_remove_block(struct nlm_block *block) { - struct nlm_block **bp, *b; - - if (!block->b_queued) - return 1; - for (bp = &nlm_blocked; (b = *bp) != 0; bp = &b->b_next) { - if (b == block) { - *bp = block->b_next; - block->b_queued = 0; - nlmsvc_release_block(block); - return 1; - } + if (!list_empty(&block->b_list)) { + list_del_init(&block->b_list); + nlmsvc_release_block(block); } - - return 0; } /* @@ -107,14 +103,14 @@ nlmsvc_remove_block(struct nlm_block *block) static struct nlm_block * nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock) { - struct nlm_block **head, *block; + struct nlm_block *block; struct file_lock *fl; dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n", file, lock->fl.fl_pid, (long long)lock->fl.fl_start, (long long)lock->fl.fl_end, lock->fl.fl_type); - for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { + list_for_each_entry(block, &nlm_blocked, b_list) { fl = &block->b_call->a_args.lock.fl; dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", block->b_file, fl->fl_pid, @@ -143,20 +139,20 @@ static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b) * Find a block with a given NLM cookie. */ static inline struct nlm_block * -nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) +nlmsvc_find_block(struct nlm_cookie *cookie) { struct nlm_block *block; - for (block = nlm_blocked; block; block = block->b_next) { - dprintk("cookie: head of blocked queue %p, block %p\n", - nlm_blocked, block); - if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie) - && nlm_cmp_addr(sin, &block->b_host->h_addr)) - break; + list_for_each_entry(block, &nlm_blocked, b_list) { + if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie)) + goto found; } - if (block != NULL) - kref_get(&block->b_count); + return NULL; + +found: + dprintk("nlmsvc_find_block(%s): block=%p\n", nlmdbg_cookie2a(cookie), block); + kref_get(&block->b_count); return block; } @@ -169,6 +165,11 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) * request, but (as I found out later) that's because some implementations * do just this. Never mind the standards comittees, they support our * logging industries. + * + * 10 years later: I hope we can safely ignore these old and broken + * clients by now. Let's fix this so we can uniquely identify an incoming + * GRANTED_RES message by cookie, without having to rely on the client's IP + * address. --okir */ static inline struct nlm_block * nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, @@ -179,7 +180,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_rqst *call = NULL; /* Create host handle for callback */ - host = nlmsvc_lookup_host(rqstp); + host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); if (host == NULL) return NULL; @@ -192,6 +193,8 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, if (block == NULL) goto failed; kref_init(&block->b_count); + INIT_LIST_HEAD(&block->b_list); + INIT_LIST_HEAD(&block->b_flist); if (!nlmsvc_setgrantargs(call, lock)) goto failed_free; @@ -199,7 +202,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, /* Set notifier function for VFS, and init args */ call->a_args.lock.fl.fl_flags |= FL_SLEEP; call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; - call->a_args.cookie = *cookie; /* see above */ + nlmclnt_next_cookie(&call->a_args.cookie); dprintk("lockd: created block %p...\n", block); @@ -210,8 +213,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, file->f_count++; /* Add to file's list of blocks */ - block->b_fnext = file->f_blocks; - file->f_blocks = block; + list_add(&block->b_flist, &file->f_blocks); /* Set up RPC arguments for callback */ block->b_call = call; @@ -248,19 +250,13 @@ static void nlmsvc_free_block(struct kref *kref) { struct nlm_block *block = container_of(kref, struct nlm_block, b_count); struct nlm_file *file = block->b_file; - struct nlm_block **bp; dprintk("lockd: freeing block %p...\n", block); - down(&file->f_sema); /* Remove block from file's list of blocks */ - for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { - if (*bp == block) { - *bp = block->b_fnext; - break; - } - } - up(&file->f_sema); + mutex_lock(&file->f_mutex); + list_del_init(&block->b_flist); + mutex_unlock(&file->f_mutex); nlmsvc_freegrantargs(block->b_call); nlm_release_call(block->b_call); @@ -274,47 +270,32 @@ static void nlmsvc_release_block(struct nlm_block *block) kref_put(&block->b_count, nlmsvc_free_block); } -static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file) -{ - struct nlm_block *block; - - down(&file->f_sema); - for (block = file->f_blocks; block != NULL; block = block->b_fnext) - block->b_host->h_inuse = 1; - up(&file->f_sema); -} - -static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file) +/* + * Loop over all blocks and delete blocks held by + * a matching host. + */ +void nlmsvc_traverse_blocks(struct nlm_host *host, + struct nlm_file *file, + nlm_host_match_fn_t match) { - struct nlm_block *block; + struct nlm_block *block, *next; restart: - down(&file->f_sema); - for (block = file->f_blocks; block != NULL; block = block->b_fnext) { - if (host != NULL && host != block->b_host) + mutex_lock(&file->f_mutex); + list_for_each_entry_safe(block, next, &file->f_blocks, b_flist) { + if (!match(block->b_host, host)) continue; - if (!block->b_queued) + /* Do not destroy blocks that are not on + * the global retry list - why? */ + if (list_empty(&block->b_list)) continue; kref_get(&block->b_count); - up(&file->f_sema); + mutex_unlock(&file->f_mutex); nlmsvc_unlink_block(block); nlmsvc_release_block(block); goto restart; } - up(&file->f_sema); -} - -/* - * Loop over all blocks and perform the action specified. - * (NLM_ACT_CHECK handled by nlmsvc_inspect_file). - */ -void -nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) -{ - if (action == NLM_ACT_MARK) - nlmsvc_act_mark(host, file); - else - nlmsvc_act_unlock(host, file); + mutex_unlock(&file->f_mutex); } /* @@ -353,13 +334,13 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call) * Attempt to establish a lock, and if it can't be granted, block it * if required. */ -u32 +__be32 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) { struct nlm_block *block, *newblock = NULL; int error; - u32 ret; + __be32 ret; dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", file->f_file->f_dentry->d_inode->i_sb->s_id, @@ -373,7 +354,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, lock->fl.fl_flags &= ~FL_SLEEP; again: /* Lock file against concurrent access */ - down(&file->f_sema); + mutex_lock(&file->f_mutex); /* Get existing block (in case client is busy-waiting) */ block = nlmsvc_lookup_block(file, lock); if (block == NULL) { @@ -411,10 +392,10 @@ again: /* If we don't have a block, create and initialize it. Then * retry because we may have slept in kmalloc. */ - /* We have to release f_sema as nlmsvc_create_block may try to + /* We have to release f_mutex as nlmsvc_create_block may try to * to claim it while doing host garbage collection */ if (newblock == NULL) { - up(&file->f_sema); + mutex_unlock(&file->f_mutex); dprintk("lockd: blocking on this lock (allocating).\n"); if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie))) return nlm_lck_denied_nolocks; @@ -424,7 +405,7 @@ again: /* Append to list of blocked */ nlmsvc_insert_block(newblock, NLM_NEVER); out: - up(&file->f_sema); + mutex_unlock(&file->f_mutex); nlmsvc_release_block(newblock); nlmsvc_release_block(block); dprintk("lockd: nlmsvc_lock returned %u\n", ret); @@ -434,7 +415,7 @@ out: /* * Test for presence of a conflicting lock. */ -u32 +__be32 nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, struct nlm_lock *conflock) { @@ -451,6 +432,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, (long long)conflock->fl.fl_start, (long long)conflock->fl.fl_end); conflock->caller = "somehost"; /* FIXME */ + conflock->len = strlen(conflock->caller); conflock->oh.len = 0; /* don't return OH info */ conflock->svid = conflock->fl.fl_pid; return nlm_lck_denied; @@ -466,7 +448,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, * afterwards. In this case the block will still be there, and hence * must be removed. */ -u32 +__be32 nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) { int error; @@ -494,7 +476,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) * be in progress. * The calling procedure must check whether the file can be closed. */ -u32 +__be32 nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) { struct nlm_block *block; @@ -507,9 +489,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) (long long)lock->fl.fl_start, (long long)lock->fl.fl_end); - down(&file->f_sema); + mutex_lock(&file->f_mutex); block = nlmsvc_lookup_block(file, lock); - up(&file->f_sema); + mutex_unlock(&file->f_mutex); if (block != NULL) { status = nlmsvc_unlink_block(block); nlmsvc_release_block(block); @@ -527,10 +509,10 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) static void nlmsvc_notify_blocked(struct file_lock *fl) { - struct nlm_block **bp, *block; + struct nlm_block *block; dprintk("lockd: VFS unblock notification for block %p\n", fl); - for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) { + list_for_each_entry(block, &nlm_blocked, b_list) { if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { nlmsvc_insert_block(block, 0); svc_wake_up(block->b_daemon); @@ -663,17 +645,14 @@ static const struct rpc_call_ops nlmsvc_grant_ops = { * block. */ void -nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status) +nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status) { struct nlm_block *block; - struct nlm_file *file; - dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", - *(unsigned int *)(cookie->data), - ntohl(rqstp->rq_addr.sin_addr.s_addr), status); - if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr))) + dprintk("grant_reply: looking for cookie %x, s=%d \n", + *(unsigned int *)(cookie->data), status); + if (!(block = nlmsvc_find_block(cookie))) return; - file = block->b_file; if (block) { if (status == NLM_LCK_DENIED_GRACE_PERIOD) { @@ -696,16 +675,19 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status unsigned long nlmsvc_retry_blocked(void) { - struct nlm_block *block; + unsigned long timeout = MAX_SCHEDULE_TIMEOUT; + struct nlm_block *block; + + while (!list_empty(&nlm_blocked)) { + block = list_entry(nlm_blocked.next, struct nlm_block, b_list); - dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", - nlm_blocked, - nlm_blocked? nlm_blocked->b_when : 0); - while ((block = nlm_blocked) != 0) { if (block->b_when == NLM_NEVER) break; - if (time_after(block->b_when,jiffies)) + if (time_after(block->b_when,jiffies)) { + timeout = block->b_when - jiffies; break; + } + dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", block, block->b_when); kref_get(&block->b_count); @@ -713,8 +695,5 @@ nlmsvc_retry_blocked(void) nlmsvc_release_block(block); } - if ((block = nlm_blocked) && block->b_when != NLM_NEVER) - return (block->b_when - jiffies); - - return MAX_SCHEDULE_TIMEOUT; + return timeout; } diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index dbb66a3..32e99a6 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -22,8 +22,8 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT #ifdef CONFIG_LOCKD_V4 -static u32 -cast_to_nlm(u32 status, u32 vers) +static __be32 +cast_to_nlm(__be32 status, u32 vers) { /* Note: status is assumed to be in network byte order !!! */ if (vers != 4){ @@ -52,22 +52,22 @@ cast_to_nlm(u32 status, u32 vers) /* * Obtain client and file from arguments */ -static u32 +static __be32 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host **hostp, struct nlm_file **filp) { struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; - u32 error; + __be32 error = 0; /* nfsd callbacks must have been installed for this procedure */ if (!nlmsvc_ops) return nlm_lck_denied_nolocks; /* Obtain host handle */ - if (!(host = nlmsvc_lookup_host(rqstp)) - || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0)) + if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) + || (argp->monitor && nsm_monitor(host) < 0)) goto no_locks; *hostp = host; @@ -88,13 +88,15 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, no_locks: if (host) nlm_release_host(host); + if (error) + return error; return nlm_lck_denied_nolocks; } /* * NULL: Test for presence of service */ -static int +static __be32 nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) { dprintk("lockd: NULL called\n"); @@ -104,7 +106,7 @@ nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) /* * TEST: Check for conflicting lock */ -static int +static __be32 nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -122,7 +124,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now check for conflicting locks */ resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock)); @@ -134,7 +136,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -153,7 +155,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; #if 0 /* If supplied state doesn't match current state, we assume it's @@ -177,7 +179,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } -static int +static __be32 nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -196,7 +198,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Try to cancel request. */ resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock)); @@ -210,7 +212,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNLOCK: release a lock */ -static int +static __be32 nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -229,7 +231,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to remove the lock */ resp->status = cast_status(nlmsvc_unlock(file, &argp->lock)); @@ -244,7 +246,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, * GRANTED: A server calls us to tell that a process' lock request * was granted */ -static int +static __be32 nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -280,14 +282,16 @@ static const struct rpc_call_ops nlmsvc_callback_ops = { * because we send the callback before the reply proper. I hope this * doesn't break any clients. */ -static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, - int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) +static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, + __be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) { struct nlm_host *host; struct nlm_rqst *call; - int stat; + __be32 stat; - host = nlmsvc_lookup_host(rqstp); + host = nlmsvc_lookup_host(rqstp, + argp->lock.caller, + argp->lock.len); if (host == NULL) return rpc_system_err; @@ -307,28 +311,28 @@ static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *ar return rpc_success; } -static int nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: TEST_MSG called\n"); return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test); } -static int nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: LOCK_MSG called\n"); return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock); } -static int nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { dprintk("lockd: CANCEL_MSG called\n"); return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel); } -static int +static __be32 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -336,7 +340,7 @@ nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock); } -static int +static __be32 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -347,7 +351,7 @@ nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, /* * SHARE: create a DOS share or alter existing share. */ -static int +static __be32 nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -366,7 +370,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to create the share */ resp->status = cast_status(nlmsvc_share_file(host, file, argp)); @@ -380,7 +384,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, /* * UNSHARE: Release a DOS share. */ -static int +static __be32 nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -399,7 +403,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain client and file */ if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) - return rpc_success; + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; /* Now try to unshare the file */ resp->status = cast_status(nlmsvc_unshare_file(host, file, argp)); @@ -413,7 +417,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, /* * NM_LOCK: Create an unmonitored lock */ -static int +static __be32 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_res *resp) { @@ -426,7 +430,7 @@ nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, /* * FREE_ALL: Release all locks and shares held by client */ -static int +static __be32 nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { @@ -444,14 +448,11 @@ nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, /* * SM_NOTIFY: private callback from statd (not part of official NLM proto) */ -static int +static __be32 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, void *resp) { struct sockaddr_in saddr = rqstp->rq_addr; - int vers = argp->vers; - int prot = argp->proto >> 1; - struct nlm_host *host; dprintk("lockd: SM_NOTIFY called\n"); if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) @@ -466,19 +467,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, /* Obtain the host pointer for this NFS server and try to * reclaim all locks we hold on this server. */ + memset(&saddr, 0, sizeof(saddr)); saddr.sin_addr.s_addr = argp->addr; - if ((argp->proto & 1)==0) { - if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) { - nlmclnt_recovery(host, argp->state); - nlm_release_host(host); - } - } else { - /* If we run on an NFS server, delete all locks held by the client */ - if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) { - nlmsvc_free_host_resources(host); - nlm_release_host(host); - } - } + nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); return rpc_success; } @@ -486,7 +477,7 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, /* * client sent a GRANTED_RES, let's remove the associated block */ -static int +static __be32 nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, void *resp) { @@ -495,7 +486,7 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, dprintk("lockd: GRANTED_RES called\n"); - nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status); + nlmsvc_grant_reply(&argp->cookie, argp->status); return rpc_success; } diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c index 27288c8..6220dc2a 100644 --- a/fs/lockd/svcshare.c +++ b/fs/lockd/svcshare.c @@ -23,7 +23,7 @@ nlm_cmp_owner(struct nlm_share *share, struct xdr_netobj *oh) && !memcmp(share->s_owner.data, oh->data, oh->len); } -u32 +__be32 nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file, struct nlm_args *argp) { @@ -64,7 +64,7 @@ update: /* * Delete a share. */ -u32 +__be32 nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file, struct nlm_args *argp) { @@ -85,24 +85,20 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file, } /* - * Traverse all shares for a given file (and host). - * NLM_ACT_CHECK is handled by nlmsvc_inspect_file. + * Traverse all shares for a given file, and delete + * those owned by the given (type of) host */ -void -nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, int action) +void nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, + nlm_host_match_fn_t match) { struct nlm_share *share, **shpp; shpp = &file->f_shares; while ((share = *shpp) != NULL) { - if (action == NLM_ACT_MARK) - share->s_host->h_inuse = 1; - else if (action == NLM_ACT_UNLOCK) { - if (host == NULL || host == share->s_host) { - *shpp = share->s_next; - kfree(share); - continue; - } + if (match(share->s_host, host)) { + *shpp = share->s_next; + kfree(share); + continue; } shpp = &share->s_next; } diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index a92dd98f..e83024e 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -25,9 +25,9 @@ /* * Global file hash table */ -#define FILE_HASH_BITS 5 +#define FILE_HASH_BITS 7 #define FILE_NRHASH (1<<FILE_HASH_BITS) -static struct nlm_file * nlm_files[FILE_NRHASH]; +static struct hlist_head nlm_files[FILE_NRHASH]; static DEFINE_MUTEX(nlm_file_mutex); #ifdef NFSD_DEBUG @@ -78,13 +78,14 @@ static inline unsigned int file_hash(struct nfs_fh *f) * This is not quite right, but for now, we assume the client performs * the proper R/W checking. */ -u32 +__be32 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, struct nfs_fh *f) { + struct hlist_node *pos; struct nlm_file *file; unsigned int hash; - u32 nfserr; + __be32 nfserr; nlm_debug_print_fh("nlm_file_lookup", f); @@ -93,7 +94,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, /* Lock file table */ mutex_lock(&nlm_file_mutex); - for (file = nlm_files[hash]; file; file = file->f_next) + hlist_for_each_entry(file, pos, &nlm_files[hash], f_list) if (!nfs_compare_fh(&file->f_handle, f)) goto found; @@ -105,8 +106,9 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, goto out_unlock; memcpy(&file->f_handle, f, sizeof(struct nfs_fh)); - file->f_hash = hash; - init_MUTEX(&file->f_sema); + mutex_init(&file->f_mutex); + INIT_HLIST_NODE(&file->f_list); + INIT_LIST_HEAD(&file->f_blocks); /* Open the file. Note that this must not sleep for too long, else * we would lock up lockd:-) So no NFS re-exports, folks. @@ -115,12 +117,11 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, * the file. */ if ((nfserr = nlmsvc_ops->fopen(rqstp, f, &file->f_file)) != 0) { - dprintk("lockd: open failed (nfserr %d)\n", ntohl(nfserr)); + dprintk("lockd: open failed (error %d)\n", nfserr); goto out_free; } - file->f_next = nlm_files[hash]; - nlm_files[hash] = file; + hlist_add_head(&file->f_list, &nlm_files[hash]); found: dprintk("lockd: found file %p (count %d)\n", file, file->f_count); @@ -134,12 +135,6 @@ out_unlock: out_free: kfree(file); -#ifdef CONFIG_LOCKD_V4 - if (nfserr == 1) - nfserr = nlm4_stale_fh; - else -#endif - nfserr = nlm_lck_denied; goto out_unlock; } @@ -149,22 +144,14 @@ out_free: static inline void nlm_delete_file(struct nlm_file *file) { - struct nlm_file **fp, *f; - nlm_debug_print_file("closing file", file); - - fp = nlm_files + file->f_hash; - while ((f = *fp) != NULL) { - if (f == file) { - *fp = file->f_next; - nlmsvc_ops->fclose(file->f_file); - kfree(file); - return; - } - fp = &f->f_next; + if (!hlist_unhashed(&file->f_list)) { + hlist_del(&file->f_list); + nlmsvc_ops->fclose(file->f_file); + kfree(file); + } else { + printk(KERN_WARNING "lockd: attempt to release unknown file!\n"); } - - printk(KERN_WARNING "lockd: attempt to release unknown file!\n"); } /* @@ -172,7 +159,8 @@ nlm_delete_file(struct nlm_file *file) * action. */ static int -nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file, int action) +nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file, + nlm_host_match_fn_t match) { struct inode *inode = nlmsvc_file_inode(file); struct file_lock *fl; @@ -186,17 +174,11 @@ again: /* update current lock count */ file->f_locks++; + lockhost = (struct nlm_host *) fl->fl_owner; - if (action == NLM_ACT_MARK) - lockhost->h_inuse = 1; - else if (action == NLM_ACT_CHECK) - return 1; - else if (action == NLM_ACT_UNLOCK) { + if (match(lockhost, host)) { struct file_lock lock = *fl; - if (host && lockhost != host) - continue; - lock.fl_type = F_UNLCK; lock.fl_start = 0; lock.fl_end = OFFSET_MAX; @@ -213,53 +195,66 @@ again: } /* - * Operate on a single file + * Inspect a single file + */ +static inline int +nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, nlm_host_match_fn_t match) +{ + nlmsvc_traverse_blocks(host, file, match); + nlmsvc_traverse_shares(host, file, match); + return nlm_traverse_locks(host, file, match); +} + +/* + * Quick check whether there are still any locks, blocks or + * shares on a given file. */ static inline int -nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, int action) +nlm_file_inuse(struct nlm_file *file) { - if (action == NLM_ACT_CHECK) { - /* Fast path for mark and sweep garbage collection */ - if (file->f_count || file->f_blocks || file->f_shares) + struct inode *inode = nlmsvc_file_inode(file); + struct file_lock *fl; + + if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares) + return 1; + + for (fl = inode->i_flock; fl; fl = fl->fl_next) { + if (fl->fl_lmops == &nlmsvc_lock_operations) return 1; - } else { - nlmsvc_traverse_blocks(host, file, action); - nlmsvc_traverse_shares(host, file, action); } - return nlm_traverse_locks(host, file, action); + file->f_locks = 0; + return 0; } /* * Loop over all files in the file table. */ static int -nlm_traverse_files(struct nlm_host *host, int action) +nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match) { - struct nlm_file *file, **fp; + struct hlist_node *pos, *next; + struct nlm_file *file; int i, ret = 0; mutex_lock(&nlm_file_mutex); for (i = 0; i < FILE_NRHASH; i++) { - fp = nlm_files + i; - while ((file = *fp) != NULL) { + hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) { file->f_count++; mutex_unlock(&nlm_file_mutex); /* Traverse locks, blocks and shares of this file * and update file->f_locks count */ - if (nlm_inspect_file(host, file, action)) + if (nlm_inspect_file(host, file, match)) ret = 1; mutex_lock(&nlm_file_mutex); file->f_count--; /* No more references to this file. Let go of it. */ - if (!file->f_blocks && !file->f_locks + if (list_empty(&file->f_blocks) && !file->f_locks && !file->f_shares && !file->f_count) { - *fp = file->f_next; + hlist_del(&file->f_list); nlmsvc_ops->fclose(file->f_file); kfree(file); - } else { - fp = &file->f_next; } } } @@ -286,23 +281,63 @@ nlm_release_file(struct nlm_file *file) mutex_lock(&nlm_file_mutex); /* If there are no more locks etc, delete the file */ - if(--file->f_count == 0) { - if(!nlm_inspect_file(NULL, file, NLM_ACT_CHECK)) - nlm_delete_file(file); - } + if (--file->f_count == 0 && !nlm_file_inuse(file)) + nlm_delete_file(file); mutex_unlock(&nlm_file_mutex); } /* + * Helpers function for resource traversal + * + * nlmsvc_mark_host: + * used by the garbage collector; simply sets h_inuse. + * Always returns 0. + * + * nlmsvc_same_host: + * returns 1 iff the two hosts match. Used to release + * all resources bound to a specific host. + * + * nlmsvc_is_client: + * returns 1 iff the host is a client. + * Used by nlmsvc_invalidate_all + */ +static int +nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy) +{ + host->h_inuse = 1; + return 0; +} + +static int +nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other) +{ + return host == other; +} + +static int +nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy) +{ + if (host->h_server) { + /* we are destroying locks even though the client + * hasn't asked us too, so don't unmonitor the + * client + */ + if (host->h_nsmhandle) + host->h_nsmhandle->sm_sticky = 1; + return 1; + } else + return 0; +} + +/* * Mark all hosts that still hold resources */ void nlmsvc_mark_resources(void) { dprintk("lockd: nlmsvc_mark_resources\n"); - - nlm_traverse_files(NULL, NLM_ACT_MARK); + nlm_traverse_files(NULL, nlmsvc_mark_host); } /* @@ -313,23 +348,25 @@ nlmsvc_free_host_resources(struct nlm_host *host) { dprintk("lockd: nlmsvc_free_host_resources\n"); - if (nlm_traverse_files(host, NLM_ACT_UNLOCK)) + if (nlm_traverse_files(host, nlmsvc_same_host)) { printk(KERN_WARNING - "lockd: couldn't remove all locks held by %s", + "lockd: couldn't remove all locks held by %s\n", host->h_name); + BUG(); + } } /* - * delete all hosts structs for clients + * Remove all locks held for clients */ void nlmsvc_invalidate_all(void) { - struct nlm_host *host; - while ((host = nlm_find_client()) != NULL) { - nlmsvc_free_host_resources(host); - host->h_expires = 0; - host->h_killed = 1; - nlm_release_host(host); - } + /* Release all locks held by NFS clients. + * Previously, the code would call + * nlmsvc_free_host_resources for each client in + * turn, which is about as inefficient as it gets. + * Now we just do it once in nlm_traverse_files. + */ + nlm_traverse_files(NULL, nlmsvc_is_client); } diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 61c46fa..b7c9492 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -43,7 +43,7 @@ loff_t_to_s32(loff_t offset) /* * XDR functions for basic NLM types */ -static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) +static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c) { unsigned int len; @@ -69,8 +69,8 @@ static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static inline u32 * -nlm_encode_cookie(u32 *p, struct nlm_cookie *c) +static inline __be32 * +nlm_encode_cookie(__be32 *p, struct nlm_cookie *c) { *p++ = htonl(c->len); memcpy(p, c->data, c->len); @@ -78,8 +78,8 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static u32 * -nlm_decode_fh(u32 *p, struct nfs_fh *f) +static __be32 * +nlm_decode_fh(__be32 *p, struct nfs_fh *f) { unsigned int len; @@ -95,8 +95,8 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f) return p + XDR_QUADLEN(NFS2_FHSIZE); } -static inline u32 * -nlm_encode_fh(u32 *p, struct nfs_fh *f) +static inline __be32 * +nlm_encode_fh(__be32 *p, struct nfs_fh *f) { *p++ = htonl(NFS2_FHSIZE); memcpy(p, f->data, NFS2_FHSIZE); @@ -106,20 +106,20 @@ nlm_encode_fh(u32 *p, struct nfs_fh *f) /* * Encode and decode owner handle */ -static inline u32 * -nlm_decode_oh(u32 *p, struct xdr_netobj *oh) +static inline __be32 * +nlm_decode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_decode_netobj(p, oh); } -static inline u32 * -nlm_encode_oh(u32 *p, struct xdr_netobj *oh) +static inline __be32 * +nlm_encode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_encode_netobj(p, oh); } -static u32 * -nlm_decode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm_decode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; s32 start, len, end; @@ -153,8 +153,8 @@ nlm_decode_lock(u32 *p, struct nlm_lock *lock) /* * Encode a lock as part of an NLM call */ -static u32 * -nlm_encode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm_encode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; __s32 start, len; @@ -184,8 +184,8 @@ nlm_encode_lock(u32 *p, struct nlm_lock *lock) /* * Encode result of a TEST/TEST_MSG call */ -static u32 * -nlm_encode_testres(u32 *p, struct nlm_res *resp) +static __be32 * +nlm_encode_testres(__be32 *p, struct nlm_res *resp) { s32 start, len; @@ -221,7 +221,7 @@ nlm_encode_testres(u32 *p, struct nlm_res *resp) * First, the server side XDR functions */ int -nlmsvc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -238,7 +238,7 @@ nlmsvc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_testres(p, resp))) return 0; @@ -246,7 +246,7 @@ nlmsvc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -266,7 +266,7 @@ nlmsvc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -282,7 +282,7 @@ nlmsvc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { if (!(p = nlm_decode_cookie(p, &argp->cookie)) || !(p = nlm_decode_lock(p, &argp->lock))) @@ -292,7 +292,7 @@ nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -313,7 +313,7 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_cookie(p, &resp->cookie))) return 0; @@ -323,7 +323,7 @@ nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_cookie(p, &resp->cookie))) return 0; @@ -332,7 +332,7 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) +nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -344,7 +344,7 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) } int -nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) +nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp) { if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) return 0; @@ -357,7 +357,7 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) } int -nlmsvc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_decode_cookie(p, &resp->cookie))) return 0; @@ -366,13 +366,13 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlmsvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_argsize_check(rqstp, p); } int -nlmsvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } @@ -389,7 +389,7 @@ nlmclt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) #endif static int -nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -403,7 +403,7 @@ nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_decode_cookie(p, &resp->cookie))) return -EIO; @@ -438,7 +438,7 @@ nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) static int -nlmclt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -455,7 +455,7 @@ nlmclt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -470,7 +470,7 @@ nlmclt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlmclt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -483,7 +483,7 @@ nlmclt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_cookie(p, &resp->cookie))) return -EIO; @@ -493,7 +493,7 @@ nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlmclt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_encode_testres(p, resp))) return -EIO; @@ -502,7 +502,7 @@ nlmclt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm_decode_cookie(p, &resp->cookie))) return -EIO; diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 36eb175..f4c0b2b 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -44,8 +44,8 @@ loff_t_to_s64(loff_t offset) /* * XDR functions for basic NLM types */ -static u32 * -nlm4_decode_cookie(u32 *p, struct nlm_cookie *c) +static __be32 * +nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c) { unsigned int len; @@ -71,8 +71,8 @@ nlm4_decode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static u32 * -nlm4_encode_cookie(u32 *p, struct nlm_cookie *c) +static __be32 * +nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c) { *p++ = htonl(c->len); memcpy(p, c->data, c->len); @@ -80,8 +80,8 @@ nlm4_encode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static u32 * -nlm4_decode_fh(u32 *p, struct nfs_fh *f) +static __be32 * +nlm4_decode_fh(__be32 *p, struct nfs_fh *f) { memset(f->data, 0, sizeof(f->data)); f->size = ntohl(*p++); @@ -95,8 +95,8 @@ nlm4_decode_fh(u32 *p, struct nfs_fh *f) return p + XDR_QUADLEN(f->size); } -static u32 * -nlm4_encode_fh(u32 *p, struct nfs_fh *f) +static __be32 * +nlm4_encode_fh(__be32 *p, struct nfs_fh *f) { *p++ = htonl(f->size); if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */ @@ -107,20 +107,20 @@ nlm4_encode_fh(u32 *p, struct nfs_fh *f) /* * Encode and decode owner handle */ -static u32 * -nlm4_decode_oh(u32 *p, struct xdr_netobj *oh) +static __be32 * +nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_decode_netobj(p, oh); } -static u32 * -nlm4_encode_oh(u32 *p, struct xdr_netobj *oh) +static __be32 * +nlm4_encode_oh(__be32 *p, struct xdr_netobj *oh) { return xdr_encode_netobj(p, oh); } -static u32 * -nlm4_decode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm4_decode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; __s64 len, start, end; @@ -153,8 +153,8 @@ nlm4_decode_lock(u32 *p, struct nlm_lock *lock) /* * Encode a lock as part of an NLM call */ -static u32 * -nlm4_encode_lock(u32 *p, struct nlm_lock *lock) +static __be32 * +nlm4_encode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; __s64 start, len; @@ -185,8 +185,8 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock) /* * Encode result of a TEST/TEST_MSG call */ -static u32 * -nlm4_encode_testres(u32 *p, struct nlm_res *resp) +static __be32 * +nlm4_encode_testres(__be32 *p, struct nlm_res *resp) { s64 start, len; @@ -227,7 +227,7 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp) * First, the server side XDR functions */ int -nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -244,7 +244,7 @@ nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_testres(p, resp))) return 0; @@ -252,7 +252,7 @@ nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -272,7 +272,7 @@ nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { u32 exclusive; @@ -288,7 +288,7 @@ nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { if (!(p = nlm4_decode_cookie(p, &argp->cookie)) || !(p = nlm4_decode_lock(p, &argp->lock))) @@ -298,7 +298,7 @@ nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) +nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -319,7 +319,7 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) } int -nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_cookie(p, &resp->cookie))) return 0; @@ -329,7 +329,7 @@ nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_cookie(p, &resp->cookie))) return 0; @@ -338,7 +338,7 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) +nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -350,7 +350,7 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) } int -nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) +nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp) { if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) return 0; @@ -363,7 +363,7 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) } int -nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) +nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_decode_cookie(p, &resp->cookie))) return 0; @@ -372,13 +372,13 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) } int -nlm4svc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_argsize_check(rqstp, p); } int -nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) +nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) { return xdr_ressize_check(rqstp, p); } @@ -388,14 +388,14 @@ nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) */ #ifdef NLMCLNT_SUPPORT_SHARES static int -nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) +nlm4clt_decode_void(struct rpc_rqst *req, __be32 *p, void *ptr) { return 0; } #endif static int -nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -409,7 +409,7 @@ nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_decode_cookie(p, &resp->cookie))) return -EIO; @@ -444,7 +444,7 @@ nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) static int -nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -461,7 +461,7 @@ nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -476,7 +476,7 @@ nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) +nlm4clt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) { struct nlm_lock *lock = &argp->lock; @@ -489,7 +489,7 @@ nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) } static int -nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_cookie(p, &resp->cookie))) return -EIO; @@ -499,7 +499,7 @@ nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_encode_testres(p, resp))) return -EIO; @@ -508,7 +508,7 @@ nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) } static int -nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) +nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) { if (!(p = nlm4_decode_cookie(p, &resp->cookie))) return -EIO; |