aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/clntlock.c58
-rw-r--r--fs/lockd/clntproc.c17
-rw-r--r--fs/lockd/host.c325
-rw-r--r--fs/lockd/mon.c77
-rw-r--r--fs/lockd/svc.c19
-rw-r--r--fs/lockd/svc4proc.c85
-rw-r--r--fs/lockd/svclock.c207
-rw-r--r--fs/lockd/svcproc.c89
-rw-r--r--fs/lockd/svcshare.c24
-rw-r--r--fs/lockd/svcsubs.c183
-rw-r--r--fs/lockd/xdr.c76
-rw-r--r--fs/lockd/xdr4.c80
12 files changed, 713 insertions, 527 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 87e1d03e8267..b85a0ad2cfb6 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)
100/* 100/*
101 * The server lockd has called us back to tell us the lock was granted 101 * The server lockd has called us back to tell us the lock was granted
102 */ 102 */
103u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) 103__be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
104{ 104{
105 const struct file_lock *fl = &lock->fl; 105 const struct file_lock *fl = &lock->fl;
106 const struct nfs_fh *fh = &lock->fh; 106 const struct nfs_fh *fh = &lock->fh;
107 struct nlm_wait *block; 107 struct nlm_wait *block;
108 u32 res = nlm_lck_denied; 108 __be32 res = nlm_lck_denied;
109 109
110 /* 110 /*
111 * Look up blocked request based on arguments. 111 * Look up blocked request based on arguments.
@@ -144,42 +144,12 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
144 */ 144 */
145 145
146/* 146/*
147 * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number,
148 * that we mark locks for reclaiming, and that we bump the pseudo NSM state.
149 */
150static void nlmclnt_prepare_reclaim(struct nlm_host *host)
151{
152 down_write(&host->h_rwsem);
153 host->h_monitored = 0;
154 host->h_state++;
155 host->h_nextrebind = 0;
156 nlm_rebind_host(host);
157
158 /*
159 * Mark the locks for reclaiming.
160 */
161 list_splice_init(&host->h_granted, &host->h_reclaim);
162
163 dprintk("NLM: reclaiming locks for host %s\n", host->h_name);
164}
165
166static void nlmclnt_finish_reclaim(struct nlm_host *host)
167{
168 host->h_reclaiming = 0;
169 up_write(&host->h_rwsem);
170 dprintk("NLM: done reclaiming locks for host %s", host->h_name);
171}
172
173/*
174 * Reclaim all locks on server host. We do this by spawning a separate 147 * Reclaim all locks on server host. We do this by spawning a separate
175 * reclaimer thread. 148 * reclaimer thread.
176 */ 149 */
177void 150void
178nlmclnt_recovery(struct nlm_host *host, u32 newstate) 151nlmclnt_recovery(struct nlm_host *host)
179{ 152{
180 if (host->h_nsmstate == newstate)
181 return;
182 host->h_nsmstate = newstate;
183 if (!host->h_reclaiming++) { 153 if (!host->h_reclaiming++) {
184 nlm_get_host(host); 154 nlm_get_host(host);
185 __module_get(THIS_MODULE); 155 __module_get(THIS_MODULE);
@@ -199,18 +169,30 @@ reclaimer(void *ptr)
199 daemonize("%s-reclaim", host->h_name); 169 daemonize("%s-reclaim", host->h_name);
200 allow_signal(SIGKILL); 170 allow_signal(SIGKILL);
201 171
172 down_write(&host->h_rwsem);
173
202 /* This one ensures that our parent doesn't terminate while the 174 /* This one ensures that our parent doesn't terminate while the
203 * reclaim is in progress */ 175 * reclaim is in progress */
204 lock_kernel(); 176 lock_kernel();
205 lockd_up(0); /* note: this cannot fail as lockd is already running */ 177 lockd_up(0); /* note: this cannot fail as lockd is already running */
206 178
207 nlmclnt_prepare_reclaim(host); 179 dprintk("lockd: reclaiming locks for host %s", host->h_name);
208 /* First, reclaim all locks that have been marked. */ 180
209restart: 181restart:
210 nsmstate = host->h_nsmstate; 182 nsmstate = host->h_nsmstate;
183
184 /* Force a portmap getport - the peer's lockd will
185 * most likely end up on a different port.
186 */
187 host->h_nextrebind = jiffies;
188 nlm_rebind_host(host);
189
190 /* First, reclaim all locks that have been granted. */
191 list_splice_init(&host->h_granted, &host->h_reclaim);
211 list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { 192 list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
212 list_del_init(&fl->fl_u.nfs_fl.list); 193 list_del_init(&fl->fl_u.nfs_fl.list);
213 194
195 /* Why are we leaking memory here? --okir */
214 if (signalled()) 196 if (signalled())
215 continue; 197 continue;
216 if (nlmclnt_reclaim(host, fl) != 0) 198 if (nlmclnt_reclaim(host, fl) != 0)
@@ -218,11 +200,13 @@ restart:
218 list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); 200 list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
219 if (host->h_nsmstate != nsmstate) { 201 if (host->h_nsmstate != nsmstate) {
220 /* Argh! The server rebooted again! */ 202 /* Argh! The server rebooted again! */
221 list_splice_init(&host->h_granted, &host->h_reclaim);
222 goto restart; 203 goto restart;
223 } 204 }
224 } 205 }
225 nlmclnt_finish_reclaim(host); 206
207 host->h_reclaiming = 0;
208 up_write(&host->h_rwsem);
209 dprintk("NLM: done reclaiming locks for host %s", host->h_name);
226 210
227 /* Now, wake up all processes that sleep on a blocked lock */ 211 /* Now, wake up all processes that sleep on a blocked lock */
228 list_for_each_entry(block, &nlm_blocked, b_list) { 212 list_for_each_entry(block, &nlm_blocked, b_list) {
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 0116729cec5f..3d84f600b633 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -36,14 +36,14 @@ static const struct rpc_call_ops nlmclnt_cancel_ops;
36/* 36/*
37 * Cookie counter for NLM requests 37 * Cookie counter for NLM requests
38 */ 38 */
39static u32 nlm_cookie = 0x1234; 39static atomic_t nlm_cookie = ATOMIC_INIT(0x1234);
40 40
41static inline void nlmclnt_next_cookie(struct nlm_cookie *c) 41void nlmclnt_next_cookie(struct nlm_cookie *c)
42{ 42{
43 memcpy(c->data, &nlm_cookie, 4); 43 u32 cookie = atomic_inc_return(&nlm_cookie);
44 memset(c->data+4, 0, 4); 44
45 memcpy(c->data, &cookie, 4);
45 c->len=4; 46 c->len=4;
46 nlm_cookie++;
47} 47}
48 48
49static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner) 49static 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)
153{ 153{
154 struct rpc_clnt *client = NFS_CLIENT(inode); 154 struct rpc_clnt *client = NFS_CLIENT(inode);
155 struct sockaddr_in addr; 155 struct sockaddr_in addr;
156 struct nfs_server *nfssrv = NFS_SERVER(inode);
156 struct nlm_host *host; 157 struct nlm_host *host;
157 struct nlm_rqst *call; 158 struct nlm_rqst *call;
158 sigset_t oldset; 159 sigset_t oldset;
@@ -166,7 +167,9 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
166 } 167 }
167 168
168 rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr)); 169 rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr));
169 host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers); 170 host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers,
171 nfssrv->nfs_client->cl_hostname,
172 strlen(nfssrv->nfs_client->cl_hostname));
170 if (host == NULL) 173 if (host == NULL)
171 return -ENOLCK; 174 return -ENOLCK;
172 175
@@ -499,7 +502,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
499 unsigned char fl_flags = fl->fl_flags; 502 unsigned char fl_flags = fl->fl_flags;
500 int status = -ENOLCK; 503 int status = -ENOLCK;
501 504
502 if (!host->h_monitored && nsm_monitor(host) < 0) { 505 if (nsm_monitor(host) < 0) {
503 printk(KERN_NOTICE "lockd: failed to monitor %s\n", 506 printk(KERN_NOTICE "lockd: failed to monitor %s\n",
504 host->h_name); 507 host->h_name);
505 goto out; 508 goto out;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index a0d0b58ce7a4..fb24a9730345 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -27,46 +27,60 @@
27#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ) 27#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
28#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ) 28#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ)
29 29
30static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH]; 30static struct hlist_head nlm_hosts[NLM_HOST_NRHASH];
31static unsigned long next_gc; 31static unsigned long next_gc;
32static int nrhosts; 32static int nrhosts;
33static DEFINE_MUTEX(nlm_host_mutex); 33static DEFINE_MUTEX(nlm_host_mutex);
34 34
35 35
36static void nlm_gc_hosts(void); 36static void nlm_gc_hosts(void);
37static struct nsm_handle * __nsm_find(const struct sockaddr_in *,
38 const char *, int, int);
37 39
38/* 40/*
39 * Find an NLM server handle in the cache. If there is none, create it. 41 * Find an NLM server handle in the cache. If there is none, create it.
40 */ 42 */
41struct nlm_host * 43struct nlm_host *
42nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version) 44nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
45 const char *hostname, int hostname_len)
43{ 46{
44 return nlm_lookup_host(0, sin, proto, version); 47 return nlm_lookup_host(0, sin, proto, version,
48 hostname, hostname_len);
45} 49}
46 50
47/* 51/*
48 * Find an NLM client handle in the cache. If there is none, create it. 52 * Find an NLM client handle in the cache. If there is none, create it.
49 */ 53 */
50struct nlm_host * 54struct nlm_host *
51nlmsvc_lookup_host(struct svc_rqst *rqstp) 55nlmsvc_lookup_host(struct svc_rqst *rqstp,
56 const char *hostname, int hostname_len)
52{ 57{
53 return nlm_lookup_host(1, &rqstp->rq_addr, 58 return nlm_lookup_host(1, &rqstp->rq_addr,
54 rqstp->rq_prot, rqstp->rq_vers); 59 rqstp->rq_prot, rqstp->rq_vers,
60 hostname, hostname_len);
55} 61}
56 62
57/* 63/*
58 * Common host lookup routine for server & client 64 * Common host lookup routine for server & client
59 */ 65 */
60struct nlm_host * 66struct nlm_host *
61nlm_lookup_host(int server, struct sockaddr_in *sin, 67nlm_lookup_host(int server, const struct sockaddr_in *sin,
62 int proto, int version) 68 int proto, int version,
69 const char *hostname,
70 int hostname_len)
63{ 71{
64 struct nlm_host *host, **hp; 72 struct hlist_head *chain;
65 u32 addr; 73 struct hlist_node *pos;
74 struct nlm_host *host;
75 struct nsm_handle *nsm = NULL;
66 int hash; 76 int hash;
67 77
68 dprintk("lockd: nlm_lookup_host(%08x, p=%d, v=%d)\n", 78 dprintk("lockd: nlm_lookup_host(%u.%u.%u.%u, p=%d, v=%d, my role=%s, name=%.*s)\n",
69 (unsigned)(sin? ntohl(sin->sin_addr.s_addr) : 0), proto, version); 79 NIPQUAD(sin->sin_addr.s_addr), proto, version,
80 server? "server" : "client",
81 hostname_len,
82 hostname? hostname : "<none>");
83
70 84
71 hash = NLM_ADDRHASH(sin->sin_addr.s_addr); 85 hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
72 86
@@ -76,7 +90,22 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
76 if (time_after_eq(jiffies, next_gc)) 90 if (time_after_eq(jiffies, next_gc))
77 nlm_gc_hosts(); 91 nlm_gc_hosts();
78 92
79 for (hp = &nlm_hosts[hash]; (host = *hp) != 0; hp = &host->h_next) { 93 /* We may keep several nlm_host objects for a peer, because each
94 * nlm_host is identified by
95 * (address, protocol, version, server/client)
96 * We could probably simplify this a little by putting all those
97 * different NLM rpc_clients into one single nlm_host object.
98 * This would allow us to have one nlm_host per address.
99 */
100 chain = &nlm_hosts[hash];
101 hlist_for_each_entry(host, pos, chain, h_hash) {
102 if (!nlm_cmp_addr(&host->h_addr, sin))
103 continue;
104
105 /* See if we have an NSM handle for this client */
106 if (!nsm)
107 nsm = host->h_nsmhandle;
108
80 if (host->h_proto != proto) 109 if (host->h_proto != proto)
81 continue; 110 continue;
82 if (host->h_version != version) 111 if (host->h_version != version)
@@ -84,28 +113,30 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
84 if (host->h_server != server) 113 if (host->h_server != server)
85 continue; 114 continue;
86 115
87 if (nlm_cmp_addr(&host->h_addr, sin)) { 116 /* Move to head of hash chain. */
88 if (hp != nlm_hosts + hash) { 117 hlist_del(&host->h_hash);
89 *hp = host->h_next; 118 hlist_add_head(&host->h_hash, chain);
90 host->h_next = nlm_hosts[hash];
91 nlm_hosts[hash] = host;
92 }
93 nlm_get_host(host);
94 mutex_unlock(&nlm_host_mutex);
95 return host;
96 }
97 }
98 119
99 /* Ooops, no host found, create it */ 120 nlm_get_host(host);
100 dprintk("lockd: creating host entry\n"); 121 goto out;
122 }
123 if (nsm)
124 atomic_inc(&nsm->sm_count);
101 125
102 host = kzalloc(sizeof(*host), GFP_KERNEL); 126 host = NULL;
103 if (!host)
104 goto nohost;
105 127
106 addr = sin->sin_addr.s_addr; 128 /* Sadly, the host isn't in our hash table yet. See if
107 sprintf(host->h_name, "%u.%u.%u.%u", NIPQUAD(addr)); 129 * we have an NSM handle for it. If not, create one.
130 */
131 if (!nsm && !(nsm = nsm_find(sin, hostname, hostname_len)))
132 goto out;
108 133
134 host = kzalloc(sizeof(*host), GFP_KERNEL);
135 if (!host) {
136 nsm_release(nsm);
137 goto out;
138 }
139 host->h_name = nsm->sm_name;
109 host->h_addr = *sin; 140 host->h_addr = *sin;
110 host->h_addr.sin_port = 0; /* ouch! */ 141 host->h_addr.sin_port = 0; /* ouch! */
111 host->h_version = version; 142 host->h_version = version;
@@ -119,9 +150,9 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
119 init_rwsem(&host->h_rwsem); 150 init_rwsem(&host->h_rwsem);
120 host->h_state = 0; /* pseudo NSM state */ 151 host->h_state = 0; /* pseudo NSM state */
121 host->h_nsmstate = 0; /* real NSM state */ 152 host->h_nsmstate = 0; /* real NSM state */
153 host->h_nsmhandle = nsm;
122 host->h_server = server; 154 host->h_server = server;
123 host->h_next = nlm_hosts[hash]; 155 hlist_add_head(&host->h_hash, chain);
124 nlm_hosts[hash] = host;
125 INIT_LIST_HEAD(&host->h_lockowners); 156 INIT_LIST_HEAD(&host->h_lockowners);
126 spin_lock_init(&host->h_lock); 157 spin_lock_init(&host->h_lock);
127 INIT_LIST_HEAD(&host->h_granted); 158 INIT_LIST_HEAD(&host->h_granted);
@@ -130,35 +161,39 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
130 if (++nrhosts > NLM_HOST_MAX) 161 if (++nrhosts > NLM_HOST_MAX)
131 next_gc = 0; 162 next_gc = 0;
132 163
133nohost: 164out:
134 mutex_unlock(&nlm_host_mutex); 165 mutex_unlock(&nlm_host_mutex);
135 return host; 166 return host;
136} 167}
137 168
138struct nlm_host * 169/*
139nlm_find_client(void) 170 * Destroy a host
171 */
172static void
173nlm_destroy_host(struct nlm_host *host)
140{ 174{
141 /* find a nlm_host for a client for which h_killed == 0. 175 struct rpc_clnt *clnt;
142 * and return it 176
177 BUG_ON(!list_empty(&host->h_lockowners));
178 BUG_ON(atomic_read(&host->h_count));
179
180 /*
181 * Release NSM handle and unmonitor host.
143 */ 182 */
144 int hash; 183 nsm_unmonitor(host);
145 mutex_lock(&nlm_host_mutex); 184
146 for (hash = 0 ; hash < NLM_HOST_NRHASH; hash++) { 185 if ((clnt = host->h_rpcclnt) != NULL) {
147 struct nlm_host *host, **hp; 186 if (atomic_read(&clnt->cl_users)) {
148 for (hp = &nlm_hosts[hash]; (host = *hp) != 0; hp = &host->h_next) { 187 printk(KERN_WARNING
149 if (host->h_server && 188 "lockd: active RPC handle\n");
150 host->h_killed == 0) { 189 clnt->cl_dead = 1;
151 nlm_get_host(host); 190 } else {
152 mutex_unlock(&nlm_host_mutex); 191 rpc_destroy_client(host->h_rpcclnt);
153 return host;
154 }
155 } 192 }
156 } 193 }
157 mutex_unlock(&nlm_host_mutex); 194 kfree(host);
158 return NULL;
159} 195}
160 196
161
162/* 197/*
163 * Create the NLM RPC client for an NLM peer 198 * Create the NLM RPC client for an NLM peer
164 */ 199 */
@@ -260,22 +295,82 @@ void nlm_release_host(struct nlm_host *host)
260} 295}
261 296
262/* 297/*
298 * We were notified that the host indicated by address &sin
299 * has rebooted.
300 * Release all resources held by that peer.
301 */
302void nlm_host_rebooted(const struct sockaddr_in *sin,
303 const char *hostname, int hostname_len,
304 u32 new_state)
305{
306 struct hlist_head *chain;
307 struct hlist_node *pos;
308 struct nsm_handle *nsm;
309 struct nlm_host *host;
310
311 dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n",
312 hostname, NIPQUAD(sin->sin_addr));
313
314 /* Find the NSM handle for this peer */
315 if (!(nsm = __nsm_find(sin, hostname, hostname_len, 0)))
316 return;
317
318 /* When reclaiming locks on this peer, make sure that
319 * we set up a new notification */
320 nsm->sm_monitored = 0;
321
322 /* Mark all hosts tied to this NSM state as having rebooted.
323 * We run the loop repeatedly, because we drop the host table
324 * lock for this.
325 * To avoid processing a host several times, we match the nsmstate.
326 */
327again: mutex_lock(&nlm_host_mutex);
328 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
329 hlist_for_each_entry(host, pos, chain, h_hash) {
330 if (host->h_nsmhandle == nsm
331 && host->h_nsmstate != new_state) {
332 host->h_nsmstate = new_state;
333 host->h_state++;
334
335 nlm_get_host(host);
336 mutex_unlock(&nlm_host_mutex);
337
338 if (host->h_server) {
339 /* We're server for this guy, just ditch
340 * all the locks he held. */
341 nlmsvc_free_host_resources(host);
342 } else {
343 /* He's the server, initiate lock recovery. */
344 nlmclnt_recovery(host);
345 }
346
347 nlm_release_host(host);
348 goto again;
349 }
350 }
351 }
352
353 mutex_unlock(&nlm_host_mutex);
354}
355
356/*
263 * Shut down the hosts module. 357 * Shut down the hosts module.
264 * Note that this routine is called only at server shutdown time. 358 * Note that this routine is called only at server shutdown time.
265 */ 359 */
266void 360void
267nlm_shutdown_hosts(void) 361nlm_shutdown_hosts(void)
268{ 362{
363 struct hlist_head *chain;
364 struct hlist_node *pos;
269 struct nlm_host *host; 365 struct nlm_host *host;
270 int i;
271 366
272 dprintk("lockd: shutting down host module\n"); 367 dprintk("lockd: shutting down host module\n");
273 mutex_lock(&nlm_host_mutex); 368 mutex_lock(&nlm_host_mutex);
274 369
275 /* First, make all hosts eligible for gc */ 370 /* First, make all hosts eligible for gc */
276 dprintk("lockd: nuking all hosts...\n"); 371 dprintk("lockd: nuking all hosts...\n");
277 for (i = 0; i < NLM_HOST_NRHASH; i++) { 372 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
278 for (host = nlm_hosts[i]; host; host = host->h_next) 373 hlist_for_each_entry(host, pos, chain, h_hash)
279 host->h_expires = jiffies - 1; 374 host->h_expires = jiffies - 1;
280 } 375 }
281 376
@@ -287,8 +382,8 @@ nlm_shutdown_hosts(void)
287 if (nrhosts) { 382 if (nrhosts) {
288 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); 383 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
289 dprintk("lockd: %d hosts left:\n", nrhosts); 384 dprintk("lockd: %d hosts left:\n", nrhosts);
290 for (i = 0; i < NLM_HOST_NRHASH; i++) { 385 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
291 for (host = nlm_hosts[i]; host; host = host->h_next) { 386 hlist_for_each_entry(host, pos, chain, h_hash) {
292 dprintk(" %s (cnt %d use %d exp %ld)\n", 387 dprintk(" %s (cnt %d use %d exp %ld)\n",
293 host->h_name, atomic_read(&host->h_count), 388 host->h_name, atomic_read(&host->h_count),
294 host->h_inuse, host->h_expires); 389 host->h_inuse, host->h_expires);
@@ -305,45 +400,32 @@ nlm_shutdown_hosts(void)
305static void 400static void
306nlm_gc_hosts(void) 401nlm_gc_hosts(void)
307{ 402{
308 struct nlm_host **q, *host; 403 struct hlist_head *chain;
309 struct rpc_clnt *clnt; 404 struct hlist_node *pos, *next;
310 int i; 405 struct nlm_host *host;
311 406
312 dprintk("lockd: host garbage collection\n"); 407 dprintk("lockd: host garbage collection\n");
313 for (i = 0; i < NLM_HOST_NRHASH; i++) { 408 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
314 for (host = nlm_hosts[i]; host; host = host->h_next) 409 hlist_for_each_entry(host, pos, chain, h_hash)
315 host->h_inuse = 0; 410 host->h_inuse = 0;
316 } 411 }
317 412
318 /* Mark all hosts that hold locks, blocks or shares */ 413 /* Mark all hosts that hold locks, blocks or shares */
319 nlmsvc_mark_resources(); 414 nlmsvc_mark_resources();
320 415
321 for (i = 0; i < NLM_HOST_NRHASH; i++) { 416 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) {
322 q = &nlm_hosts[i]; 417 hlist_for_each_entry_safe(host, pos, next, chain, h_hash) {
323 while ((host = *q) != NULL) {
324 if (atomic_read(&host->h_count) || host->h_inuse 418 if (atomic_read(&host->h_count) || host->h_inuse
325 || time_before(jiffies, host->h_expires)) { 419 || time_before(jiffies, host->h_expires)) {
326 dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", 420 dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n",
327 host->h_name, atomic_read(&host->h_count), 421 host->h_name, atomic_read(&host->h_count),
328 host->h_inuse, host->h_expires); 422 host->h_inuse, host->h_expires);
329 q = &host->h_next;
330 continue; 423 continue;
331 } 424 }
332 dprintk("lockd: delete host %s\n", host->h_name); 425 dprintk("lockd: delete host %s\n", host->h_name);
333 *q = host->h_next; 426 hlist_del_init(&host->h_hash);
334 /* Don't unmonitor hosts that have been invalidated */ 427
335 if (host->h_monitored && !host->h_killed) 428 nlm_destroy_host(host);
336 nsm_unmonitor(host);
337 if ((clnt = host->h_rpcclnt) != NULL) {
338 if (atomic_read(&clnt->cl_users)) {
339 printk(KERN_WARNING
340 "lockd: active RPC handle\n");
341 clnt->cl_dead = 1;
342 } else {
343 rpc_destroy_client(host->h_rpcclnt);
344 }
345 }
346 kfree(host);
347 nrhosts--; 429 nrhosts--;
348 } 430 }
349 } 431 }
@@ -351,3 +433,88 @@ nlm_gc_hosts(void)
351 next_gc = jiffies + NLM_HOST_COLLECT; 433 next_gc = jiffies + NLM_HOST_COLLECT;
352} 434}
353 435
436
437/*
438 * Manage NSM handles
439 */
440static LIST_HEAD(nsm_handles);
441static DEFINE_MUTEX(nsm_mutex);
442
443static struct nsm_handle *
444__nsm_find(const struct sockaddr_in *sin,
445 const char *hostname, int hostname_len,
446 int create)
447{
448 struct nsm_handle *nsm = NULL;
449 struct list_head *pos;
450
451 if (!sin)
452 return NULL;
453
454 if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
455 if (printk_ratelimit()) {
456 printk(KERN_WARNING "Invalid hostname \"%.*s\" "
457 "in NFS lock request\n",
458 hostname_len, hostname);
459 }
460 return NULL;
461 }
462
463 mutex_lock(&nsm_mutex);
464 list_for_each(pos, &nsm_handles) {
465 nsm = list_entry(pos, struct nsm_handle, sm_link);
466
467 if (hostname && nsm_use_hostnames) {
468 if (strlen(nsm->sm_name) != hostname_len
469 || memcmp(nsm->sm_name, hostname, hostname_len))
470 continue;
471 } else if (!nlm_cmp_addr(&nsm->sm_addr, sin))
472 continue;
473 atomic_inc(&nsm->sm_count);
474 goto out;
475 }
476
477 if (!create) {
478 nsm = NULL;
479 goto out;
480 }
481
482 nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
483 if (nsm != NULL) {
484 nsm->sm_addr = *sin;
485 nsm->sm_name = (char *) (nsm + 1);
486 memcpy(nsm->sm_name, hostname, hostname_len);
487 nsm->sm_name[hostname_len] = '\0';
488 atomic_set(&nsm->sm_count, 1);
489
490 list_add(&nsm->sm_link, &nsm_handles);
491 }
492
493out:
494 mutex_unlock(&nsm_mutex);
495 return nsm;
496}
497
498struct nsm_handle *
499nsm_find(const struct sockaddr_in *sin, const char *hostname, int hostname_len)
500{
501 return __nsm_find(sin, hostname, hostname_len, 1);
502}
503
504/*
505 * Release an NSM handle
506 */
507void
508nsm_release(struct nsm_handle *nsm)
509{
510 if (!nsm)
511 return;
512 if (atomic_dec_and_test(&nsm->sm_count)) {
513 mutex_lock(&nsm_mutex);
514 if (atomic_read(&nsm->sm_count) == 0) {
515 list_del(&nsm->sm_link);
516 kfree(nsm);
517 }
518 mutex_unlock(&nsm_mutex);
519 }
520}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index a816b920d431..eb243edf8932 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -24,13 +24,13 @@ static struct rpc_program nsm_program;
24/* 24/*
25 * Local NSM state 25 * Local NSM state
26 */ 26 */
27u32 nsm_local_state; 27int nsm_local_state;
28 28
29/* 29/*
30 * Common procedure for SM_MON/SM_UNMON calls 30 * Common procedure for SM_MON/SM_UNMON calls
31 */ 31 */
32static int 32static int
33nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) 33nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
34{ 34{
35 struct rpc_clnt *clnt; 35 struct rpc_clnt *clnt;
36 int status; 36 int status;
@@ -46,10 +46,11 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
46 goto out; 46 goto out;
47 } 47 }
48 48
49 args.addr = host->h_addr.sin_addr.s_addr; 49 memset(&args, 0, sizeof(args));
50 args.proto= (host->h_proto<<1) | host->h_server; 50 args.mon_name = nsm->sm_name;
51 args.addr = nsm->sm_addr.sin_addr.s_addr;
51 args.prog = NLM_PROGRAM; 52 args.prog = NLM_PROGRAM;
52 args.vers = host->h_version; 53 args.vers = 3;
53 args.proc = NLMPROC_NSM_NOTIFY; 54 args.proc = NLMPROC_NSM_NOTIFY;
54 memset(res, 0, sizeof(*res)); 55 memset(res, 0, sizeof(*res));
55 56
@@ -70,17 +71,22 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
70int 71int
71nsm_monitor(struct nlm_host *host) 72nsm_monitor(struct nlm_host *host)
72{ 73{
74 struct nsm_handle *nsm = host->h_nsmhandle;
73 struct nsm_res res; 75 struct nsm_res res;
74 int status; 76 int status;
75 77
76 dprintk("lockd: nsm_monitor(%s)\n", host->h_name); 78 dprintk("lockd: nsm_monitor(%s)\n", host->h_name);
79 BUG_ON(nsm == NULL);
77 80
78 status = nsm_mon_unmon(host, SM_MON, &res); 81 if (nsm->sm_monitored)
82 return 0;
83
84 status = nsm_mon_unmon(nsm, SM_MON, &res);
79 85
80 if (status < 0 || res.status != 0) 86 if (status < 0 || res.status != 0)
81 printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); 87 printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name);
82 else 88 else
83 host->h_monitored = 1; 89 nsm->sm_monitored = 1;
84 return status; 90 return status;
85} 91}
86 92
@@ -90,16 +96,26 @@ nsm_monitor(struct nlm_host *host)
90int 96int
91nsm_unmonitor(struct nlm_host *host) 97nsm_unmonitor(struct nlm_host *host)
92{ 98{
99 struct nsm_handle *nsm = host->h_nsmhandle;
93 struct nsm_res res; 100 struct nsm_res res;
94 int status; 101 int status = 0;
95 102
96 dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); 103 if (nsm == NULL)
97 104 return 0;
98 status = nsm_mon_unmon(host, SM_UNMON, &res); 105 host->h_nsmhandle = NULL;
99 if (status < 0) 106
100 printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", host->h_name); 107 if (atomic_read(&nsm->sm_count) == 1
101 else 108 && nsm->sm_monitored && !nsm->sm_sticky) {
102 host->h_monitored = 0; 109 dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name);
110
111 status = nsm_mon_unmon(nsm, SM_UNMON, &res);
112 if (status < 0)
113 printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
114 host->h_name);
115 else
116 nsm->sm_monitored = 0;
117 }
118 nsm_release(nsm);
103 return status; 119 return status;
104} 120}
105 121
@@ -132,10 +148,10 @@ nsm_create(void)
132 * XDR functions for NSM. 148 * XDR functions for NSM.
133 */ 149 */
134 150
135static u32 * 151static __be32 *
136xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) 152xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
137{ 153{
138 char buffer[20]; 154 char buffer[20], *name;
139 155
140 /* 156 /*
141 * Use the dotted-quad IP address of the remote host as 157 * 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)
143 * hostname first for whatever remote hostname it receives, 159 * hostname first for whatever remote hostname it receives,
144 * so this works alright. 160 * so this works alright.
145 */ 161 */
146 sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr)); 162 if (nsm_use_hostnames) {
147 if (!(p = xdr_encode_string(p, buffer)) 163 name = argp->mon_name;
164 } else {
165 sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr));
166 name = buffer;
167 }
168 if (!(p = xdr_encode_string(p, name))
148 || !(p = xdr_encode_string(p, utsname()->nodename))) 169 || !(p = xdr_encode_string(p, utsname()->nodename)))
149 return ERR_PTR(-EIO); 170 return ERR_PTR(-EIO);
150 *p++ = htonl(argp->prog); 171 *p++ = htonl(argp->prog);
@@ -155,21 +176,23 @@ xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
155} 176}
156 177
157static int 178static int
158xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) 179xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
159{ 180{
160 p = xdr_encode_common(rqstp, p, argp); 181 p = xdr_encode_common(rqstp, p, argp);
161 if (IS_ERR(p)) 182 if (IS_ERR(p))
162 return PTR_ERR(p); 183 return PTR_ERR(p);
184
185 /* Surprise - there may even be room for an IPv6 address now */
163 *p++ = argp->addr; 186 *p++ = argp->addr;
164 *p++ = argp->vers; 187 *p++ = 0;
165 *p++ = argp->proto; 188 *p++ = 0;
166 *p++ = 0; 189 *p++ = 0;
167 rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); 190 rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
168 return 0; 191 return 0;
169} 192}
170 193
171static int 194static int
172xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp) 195xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
173{ 196{
174 p = xdr_encode_common(rqstp, p, argp); 197 p = xdr_encode_common(rqstp, p, argp);
175 if (IS_ERR(p)) 198 if (IS_ERR(p))
@@ -179,7 +202,7 @@ xdr_encode_unmon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
179} 202}
180 203
181static int 204static int
182xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) 205xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
183{ 206{
184 resp->status = ntohl(*p++); 207 resp->status = ntohl(*p++);
185 resp->state = ntohl(*p++); 208 resp->state = ntohl(*p++);
@@ -189,7 +212,7 @@ xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp)
189} 212}
190 213
191static int 214static int
192xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) 215xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
193{ 216{
194 resp->state = ntohl(*p++); 217 resp->state = ntohl(*p++);
195 return 0; 218 return 0;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 3cc369e5693f..634139232aaf 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -33,6 +33,7 @@
33#include <linux/sunrpc/svcsock.h> 33#include <linux/sunrpc/svcsock.h>
34#include <net/ip.h> 34#include <net/ip.h>
35#include <linux/lockd/lockd.h> 35#include <linux/lockd/lockd.h>
36#include <linux/lockd/sm_inter.h>
36#include <linux/nfs.h> 37#include <linux/nfs.h>
37 38
38#define NLMDBG_FACILITY NLMDBG_SVC 39#define NLMDBG_FACILITY NLMDBG_SVC
@@ -61,6 +62,7 @@ static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
61static unsigned long nlm_grace_period; 62static unsigned long nlm_grace_period;
62static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO; 63static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
63static int nlm_udpport, nlm_tcpport; 64static int nlm_udpport, nlm_tcpport;
65int nsm_use_hostnames = 0;
64 66
65/* 67/*
66 * Constants needed for the sysctl interface. 68 * Constants needed for the sysctl interface.
@@ -395,6 +397,22 @@ static ctl_table nlm_sysctls[] = {
395 .extra1 = (int *) &nlm_port_min, 397 .extra1 = (int *) &nlm_port_min,
396 .extra2 = (int *) &nlm_port_max, 398 .extra2 = (int *) &nlm_port_max,
397 }, 399 },
400 {
401 .ctl_name = CTL_UNNUMBERED,
402 .procname = "nsm_use_hostnames",
403 .data = &nsm_use_hostnames,
404 .maxlen = sizeof(int),
405 .mode = 0644,
406 .proc_handler = &proc_dointvec,
407 },
408 {
409 .ctl_name = CTL_UNNUMBERED,
410 .procname = "nsm_local_state",
411 .data = &nsm_local_state,
412 .maxlen = sizeof(int),
413 .mode = 0644,
414 .proc_handler = &proc_dointvec,
415 },
398 { .ctl_name = 0 } 416 { .ctl_name = 0 }
399}; 417};
400 418
@@ -483,6 +501,7 @@ module_param_call(nlm_udpport, param_set_port, param_get_int,
483 &nlm_udpport, 0644); 501 &nlm_udpport, 0644);
484module_param_call(nlm_tcpport, param_set_port, param_get_int, 502module_param_call(nlm_tcpport, param_set_port, param_get_int,
485 &nlm_tcpport, 0644); 503 &nlm_tcpport, 0644);
504module_param(nsm_use_hostnames, bool, 0644);
486 505
487/* 506/*
488 * Initialising and terminating the module. 507 * Initialising and terminating the module.
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index a2dd9ccb9b32..0ce5c81ff507 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -24,22 +24,22 @@
24/* 24/*
25 * Obtain client and file from arguments 25 * Obtain client and file from arguments
26 */ 26 */
27static u32 27static __be32
28nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, 28nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
29 struct nlm_host **hostp, struct nlm_file **filp) 29 struct nlm_host **hostp, struct nlm_file **filp)
30{ 30{
31 struct nlm_host *host = NULL; 31 struct nlm_host *host = NULL;
32 struct nlm_file *file = NULL; 32 struct nlm_file *file = NULL;
33 struct nlm_lock *lock = &argp->lock; 33 struct nlm_lock *lock = &argp->lock;
34 u32 error = 0; 34 __be32 error = 0;
35 35
36 /* nfsd callbacks must have been installed for this procedure */ 36 /* nfsd callbacks must have been installed for this procedure */
37 if (!nlmsvc_ops) 37 if (!nlmsvc_ops)
38 return nlm_lck_denied_nolocks; 38 return nlm_lck_denied_nolocks;
39 39
40 /* Obtain host handle */ 40 /* Obtain host handle */
41 if (!(host = nlmsvc_lookup_host(rqstp)) 41 if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
42 || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0)) 42 || (argp->monitor && nsm_monitor(host) < 0))
43 goto no_locks; 43 goto no_locks;
44 *hostp = host; 44 *hostp = host;
45 45
@@ -68,7 +68,7 @@ no_locks:
68/* 68/*
69 * NULL: Test for presence of service 69 * NULL: Test for presence of service
70 */ 70 */
71static int 71static __be32
72nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) 72nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
73{ 73{
74 dprintk("lockd: NULL called\n"); 74 dprintk("lockd: NULL called\n");
@@ -78,7 +78,7 @@ nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
78/* 78/*
79 * TEST: Check for conflicting lock 79 * TEST: Check for conflicting lock
80 */ 80 */
81static int 81static __be32
82nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, 82nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
83 struct nlm_res *resp) 83 struct nlm_res *resp)
84{ 84{
@@ -96,7 +96,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
96 96
97 /* Obtain client and file */ 97 /* Obtain client and file */
98 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 98 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
99 return rpc_success; 99 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
100 100
101 /* Now check for conflicting locks */ 101 /* Now check for conflicting locks */
102 resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); 102 resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock);
@@ -107,7 +107,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
107 return rpc_success; 107 return rpc_success;
108} 108}
109 109
110static int 110static __be32
111nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, 111nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
112 struct nlm_res *resp) 112 struct nlm_res *resp)
113{ 113{
@@ -126,7 +126,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
126 126
127 /* Obtain client and file */ 127 /* Obtain client and file */
128 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 128 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
129 return rpc_success; 129 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
130 130
131#if 0 131#if 0
132 /* If supplied state doesn't match current state, we assume it's 132 /* 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,
150 return rpc_success; 150 return rpc_success;
151} 151}
152 152
153static int 153static __be32
154nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, 154nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
155 struct nlm_res *resp) 155 struct nlm_res *resp)
156{ 156{
@@ -169,7 +169,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
169 169
170 /* Obtain client and file */ 170 /* Obtain client and file */
171 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 171 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
172 return rpc_success; 172 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
173 173
174 /* Try to cancel request. */ 174 /* Try to cancel request. */
175 resp->status = nlmsvc_cancel_blocked(file, &argp->lock); 175 resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
@@ -183,7 +183,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
183/* 183/*
184 * UNLOCK: release a lock 184 * UNLOCK: release a lock
185 */ 185 */
186static int 186static __be32
187nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, 187nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
188 struct nlm_res *resp) 188 struct nlm_res *resp)
189{ 189{
@@ -202,7 +202,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
202 202
203 /* Obtain client and file */ 203 /* Obtain client and file */
204 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 204 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
205 return rpc_success; 205 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
206 206
207 /* Now try to remove the lock */ 207 /* Now try to remove the lock */
208 resp->status = nlmsvc_unlock(file, &argp->lock); 208 resp->status = nlmsvc_unlock(file, &argp->lock);
@@ -217,7 +217,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
217 * GRANTED: A server calls us to tell that a process' lock request 217 * GRANTED: A server calls us to tell that a process' lock request
218 * was granted 218 * was granted
219 */ 219 */
220static int 220static __be32
221nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, 221nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
222 struct nlm_res *resp) 222 struct nlm_res *resp)
223{ 223{
@@ -253,14 +253,16 @@ static const struct rpc_call_ops nlm4svc_callback_ops = {
253 * because we send the callback before the reply proper. I hope this 253 * because we send the callback before the reply proper. I hope this
254 * doesn't break any clients. 254 * doesn't break any clients.
255 */ 255 */
256static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, 256static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
257 int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) 257 __be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *))
258{ 258{
259 struct nlm_host *host; 259 struct nlm_host *host;
260 struct nlm_rqst *call; 260 struct nlm_rqst *call;
261 int stat; 261 __be32 stat;
262 262
263 host = nlmsvc_lookup_host(rqstp); 263 host = nlmsvc_lookup_host(rqstp,
264 argp->lock.caller,
265 argp->lock.len);
264 if (host == NULL) 266 if (host == NULL)
265 return rpc_system_err; 267 return rpc_system_err;
266 268
@@ -280,35 +282,35 @@ static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *a
280 return rpc_success; 282 return rpc_success;
281} 283}
282 284
283static int nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 285static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
284 void *resp) 286 void *resp)
285{ 287{
286 dprintk("lockd: TEST_MSG called\n"); 288 dprintk("lockd: TEST_MSG called\n");
287 return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test); 289 return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test);
288} 290}
289 291
290static int nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 292static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
291 void *resp) 293 void *resp)
292{ 294{
293 dprintk("lockd: LOCK_MSG called\n"); 295 dprintk("lockd: LOCK_MSG called\n");
294 return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock); 296 return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock);
295} 297}
296 298
297static int nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 299static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
298 void *resp) 300 void *resp)
299{ 301{
300 dprintk("lockd: CANCEL_MSG called\n"); 302 dprintk("lockd: CANCEL_MSG called\n");
301 return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel); 303 return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel);
302} 304}
303 305
304static int nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 306static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
305 void *resp) 307 void *resp)
306{ 308{
307 dprintk("lockd: UNLOCK_MSG called\n"); 309 dprintk("lockd: UNLOCK_MSG called\n");
308 return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock); 310 return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock);
309} 311}
310 312
311static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 313static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
312 void *resp) 314 void *resp)
313{ 315{
314 dprintk("lockd: GRANTED_MSG called\n"); 316 dprintk("lockd: GRANTED_MSG called\n");
@@ -318,7 +320,7 @@ static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *arg
318/* 320/*
319 * SHARE: create a DOS share or alter existing share. 321 * SHARE: create a DOS share or alter existing share.
320 */ 322 */
321static int 323static __be32
322nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, 324nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
323 struct nlm_res *resp) 325 struct nlm_res *resp)
324{ 326{
@@ -337,7 +339,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
337 339
338 /* Obtain client and file */ 340 /* Obtain client and file */
339 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 341 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
340 return rpc_success; 342 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
341 343
342 /* Now try to create the share */ 344 /* Now try to create the share */
343 resp->status = nlmsvc_share_file(host, file, argp); 345 resp->status = nlmsvc_share_file(host, file, argp);
@@ -351,7 +353,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
351/* 353/*
352 * UNSHARE: Release a DOS share. 354 * UNSHARE: Release a DOS share.
353 */ 355 */
354static int 356static __be32
355nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, 357nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
356 struct nlm_res *resp) 358 struct nlm_res *resp)
357{ 359{
@@ -370,7 +372,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
370 372
371 /* Obtain client and file */ 373 /* Obtain client and file */
372 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 374 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
373 return rpc_success; 375 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
374 376
375 /* Now try to lock the file */ 377 /* Now try to lock the file */
376 resp->status = nlmsvc_unshare_file(host, file, argp); 378 resp->status = nlmsvc_unshare_file(host, file, argp);
@@ -384,7 +386,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
384/* 386/*
385 * NM_LOCK: Create an unmonitored lock 387 * NM_LOCK: Create an unmonitored lock
386 */ 388 */
387static int 389static __be32
388nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, 390nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
389 struct nlm_res *resp) 391 struct nlm_res *resp)
390{ 392{
@@ -397,7 +399,7 @@ nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
397/* 399/*
398 * FREE_ALL: Release all locks and shares held by client 400 * FREE_ALL: Release all locks and shares held by client
399 */ 401 */
400static int 402static __be32
401nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, 403nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
402 void *resp) 404 void *resp)
403{ 405{
@@ -415,15 +417,11 @@ nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
415/* 417/*
416 * SM_NOTIFY: private callback from statd (not part of official NLM proto) 418 * SM_NOTIFY: private callback from statd (not part of official NLM proto)
417 */ 419 */
418static int 420static __be32
419nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, 421nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
420 void *resp) 422 void *resp)
421{ 423{
422 struct sockaddr_in saddr = rqstp->rq_addr; 424 struct sockaddr_in saddr = rqstp->rq_addr;
423 int vers = argp->vers;
424 int prot = argp->proto >> 1;
425
426 struct nlm_host *host;
427 425
428 dprintk("lockd: SM_NOTIFY called\n"); 426 dprintk("lockd: SM_NOTIFY called\n");
429 if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) 427 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,
438 /* Obtain the host pointer for this NFS server and try to 436 /* Obtain the host pointer for this NFS server and try to
439 * reclaim all locks we hold on this server. 437 * reclaim all locks we hold on this server.
440 */ 438 */
439 memset(&saddr, 0, sizeof(saddr));
441 saddr.sin_addr.s_addr = argp->addr; 440 saddr.sin_addr.s_addr = argp->addr;
441 nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);
442 442
443 if ((argp->proto & 1)==0) {
444 if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
445 nlmclnt_recovery(host, argp->state);
446 nlm_release_host(host);
447 }
448 } else {
449 /* If we run on an NFS server, delete all locks held by the client */
450
451 if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) {
452 nlmsvc_free_host_resources(host);
453 nlm_release_host(host);
454 }
455 }
456 return rpc_success; 443 return rpc_success;
457} 444}
458 445
459/* 446/*
460 * client sent a GRANTED_RES, let's remove the associated block 447 * client sent a GRANTED_RES, let's remove the associated block
461 */ 448 */
462static int 449static __be32
463nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, 450nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
464 void *resp) 451 void *resp)
465{ 452{
@@ -468,7 +455,7 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
468 455
469 dprintk("lockd: GRANTED_RES called\n"); 456 dprintk("lockd: GRANTED_RES called\n");
470 457
471 nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status); 458 nlmsvc_grant_reply(&argp->cookie, argp->status);
472 return rpc_success; 459 return rpc_success;
473} 460}
474 461
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 93c00ee7189d..7e219b938552 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -40,7 +40,7 @@
40 40
41static void nlmsvc_release_block(struct nlm_block *block); 41static void nlmsvc_release_block(struct nlm_block *block);
42static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); 42static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
43static int nlmsvc_remove_block(struct nlm_block *block); 43static void nlmsvc_remove_block(struct nlm_block *block);
44 44
45static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); 45static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock);
46static void nlmsvc_freegrantargs(struct nlm_rqst *call); 46static void nlmsvc_freegrantargs(struct nlm_rqst *call);
@@ -49,7 +49,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops;
49/* 49/*
50 * The list of blocked locks to retry 50 * The list of blocked locks to retry
51 */ 51 */
52static struct nlm_block * nlm_blocked; 52static LIST_HEAD(nlm_blocked);
53 53
54/* 54/*
55 * Insert a blocked lock into the global list 55 * Insert a blocked lock into the global list
@@ -57,48 +57,44 @@ static struct nlm_block * nlm_blocked;
57static void 57static void
58nlmsvc_insert_block(struct nlm_block *block, unsigned long when) 58nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
59{ 59{
60 struct nlm_block **bp, *b; 60 struct nlm_block *b;
61 struct list_head *pos;
61 62
62 dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when); 63 dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when);
63 kref_get(&block->b_count); 64 if (list_empty(&block->b_list)) {
64 if (block->b_queued) 65 kref_get(&block->b_count);
65 nlmsvc_remove_block(block); 66 } else {
66 bp = &nlm_blocked; 67 list_del_init(&block->b_list);
68 }
69
70 pos = &nlm_blocked;
67 if (when != NLM_NEVER) { 71 if (when != NLM_NEVER) {
68 if ((when += jiffies) == NLM_NEVER) 72 if ((when += jiffies) == NLM_NEVER)
69 when ++; 73 when ++;
70 while ((b = *bp) && time_before_eq(b->b_when,when) && b->b_when != NLM_NEVER) 74 list_for_each(pos, &nlm_blocked) {
71 bp = &b->b_next; 75 b = list_entry(pos, struct nlm_block, b_list);
72 } else 76 if (time_after(b->b_when,when) || b->b_when == NLM_NEVER)
73 while ((b = *bp) != 0) 77 break;
74 bp = &b->b_next; 78 }
79 /* On normal exit from the loop, pos == &nlm_blocked,
80 * so we will be adding to the end of the list - good
81 */
82 }
75 83
76 block->b_queued = 1; 84 list_add_tail(&block->b_list, pos);
77 block->b_when = when; 85 block->b_when = when;
78 block->b_next = b;
79 *bp = block;
80} 86}
81 87
82/* 88/*
83 * Remove a block from the global list 89 * Remove a block from the global list
84 */ 90 */
85static int 91static inline void
86nlmsvc_remove_block(struct nlm_block *block) 92nlmsvc_remove_block(struct nlm_block *block)
87{ 93{
88 struct nlm_block **bp, *b; 94 if (!list_empty(&block->b_list)) {
89 95 list_del_init(&block->b_list);
90 if (!block->b_queued) 96 nlmsvc_release_block(block);
91 return 1;
92 for (bp = &nlm_blocked; (b = *bp) != 0; bp = &b->b_next) {
93 if (b == block) {
94 *bp = block->b_next;
95 block->b_queued = 0;
96 nlmsvc_release_block(block);
97 return 1;
98 }
99 } 97 }
100
101 return 0;
102} 98}
103 99
104/* 100/*
@@ -107,14 +103,14 @@ nlmsvc_remove_block(struct nlm_block *block)
107static struct nlm_block * 103static struct nlm_block *
108nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock) 104nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
109{ 105{
110 struct nlm_block **head, *block; 106 struct nlm_block *block;
111 struct file_lock *fl; 107 struct file_lock *fl;
112 108
113 dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n", 109 dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n",
114 file, lock->fl.fl_pid, 110 file, lock->fl.fl_pid,
115 (long long)lock->fl.fl_start, 111 (long long)lock->fl.fl_start,
116 (long long)lock->fl.fl_end, lock->fl.fl_type); 112 (long long)lock->fl.fl_end, lock->fl.fl_type);
117 for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { 113 list_for_each_entry(block, &nlm_blocked, b_list) {
118 fl = &block->b_call->a_args.lock.fl; 114 fl = &block->b_call->a_args.lock.fl;
119 dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", 115 dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
120 block->b_file, fl->fl_pid, 116 block->b_file, fl->fl_pid,
@@ -143,20 +139,20 @@ static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
143 * Find a block with a given NLM cookie. 139 * Find a block with a given NLM cookie.
144 */ 140 */
145static inline struct nlm_block * 141static inline struct nlm_block *
146nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) 142nlmsvc_find_block(struct nlm_cookie *cookie)
147{ 143{
148 struct nlm_block *block; 144 struct nlm_block *block;
149 145
150 for (block = nlm_blocked; block; block = block->b_next) { 146 list_for_each_entry(block, &nlm_blocked, b_list) {
151 dprintk("cookie: head of blocked queue %p, block %p\n", 147 if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie))
152 nlm_blocked, block); 148 goto found;
153 if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie)
154 && nlm_cmp_addr(sin, &block->b_host->h_addr))
155 break;
156 } 149 }
157 150
158 if (block != NULL) 151 return NULL;
159 kref_get(&block->b_count); 152
153found:
154 dprintk("nlmsvc_find_block(%s): block=%p\n", nlmdbg_cookie2a(cookie), block);
155 kref_get(&block->b_count);
160 return block; 156 return block;
161} 157}
162 158
@@ -169,6 +165,11 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin)
169 * request, but (as I found out later) that's because some implementations 165 * request, but (as I found out later) that's because some implementations
170 * do just this. Never mind the standards comittees, they support our 166 * do just this. Never mind the standards comittees, they support our
171 * logging industries. 167 * logging industries.
168 *
169 * 10 years later: I hope we can safely ignore these old and broken
170 * clients by now. Let's fix this so we can uniquely identify an incoming
171 * GRANTED_RES message by cookie, without having to rely on the client's IP
172 * address. --okir
172 */ 173 */
173static inline struct nlm_block * 174static inline struct nlm_block *
174nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, 175nlmsvc_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,
179 struct nlm_rqst *call = NULL; 180 struct nlm_rqst *call = NULL;
180 181
181 /* Create host handle for callback */ 182 /* Create host handle for callback */
182 host = nlmsvc_lookup_host(rqstp); 183 host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len);
183 if (host == NULL) 184 if (host == NULL)
184 return NULL; 185 return NULL;
185 186
@@ -192,6 +193,8 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
192 if (block == NULL) 193 if (block == NULL)
193 goto failed; 194 goto failed;
194 kref_init(&block->b_count); 195 kref_init(&block->b_count);
196 INIT_LIST_HEAD(&block->b_list);
197 INIT_LIST_HEAD(&block->b_flist);
195 198
196 if (!nlmsvc_setgrantargs(call, lock)) 199 if (!nlmsvc_setgrantargs(call, lock))
197 goto failed_free; 200 goto failed_free;
@@ -199,7 +202,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
199 /* Set notifier function for VFS, and init args */ 202 /* Set notifier function for VFS, and init args */
200 call->a_args.lock.fl.fl_flags |= FL_SLEEP; 203 call->a_args.lock.fl.fl_flags |= FL_SLEEP;
201 call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; 204 call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations;
202 call->a_args.cookie = *cookie; /* see above */ 205 nlmclnt_next_cookie(&call->a_args.cookie);
203 206
204 dprintk("lockd: created block %p...\n", block); 207 dprintk("lockd: created block %p...\n", block);
205 208
@@ -210,8 +213,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
210 file->f_count++; 213 file->f_count++;
211 214
212 /* Add to file's list of blocks */ 215 /* Add to file's list of blocks */
213 block->b_fnext = file->f_blocks; 216 list_add(&block->b_flist, &file->f_blocks);
214 file->f_blocks = block;
215 217
216 /* Set up RPC arguments for callback */ 218 /* Set up RPC arguments for callback */
217 block->b_call = call; 219 block->b_call = call;
@@ -248,19 +250,13 @@ static void nlmsvc_free_block(struct kref *kref)
248{ 250{
249 struct nlm_block *block = container_of(kref, struct nlm_block, b_count); 251 struct nlm_block *block = container_of(kref, struct nlm_block, b_count);
250 struct nlm_file *file = block->b_file; 252 struct nlm_file *file = block->b_file;
251 struct nlm_block **bp;
252 253
253 dprintk("lockd: freeing block %p...\n", block); 254 dprintk("lockd: freeing block %p...\n", block);
254 255
255 down(&file->f_sema);
256 /* Remove block from file's list of blocks */ 256 /* Remove block from file's list of blocks */
257 for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { 257 mutex_lock(&file->f_mutex);
258 if (*bp == block) { 258 list_del_init(&block->b_flist);
259 *bp = block->b_fnext; 259 mutex_unlock(&file->f_mutex);
260 break;
261 }
262 }
263 up(&file->f_sema);
264 260
265 nlmsvc_freegrantargs(block->b_call); 261 nlmsvc_freegrantargs(block->b_call);
266 nlm_release_call(block->b_call); 262 nlm_release_call(block->b_call);
@@ -274,47 +270,32 @@ static void nlmsvc_release_block(struct nlm_block *block)
274 kref_put(&block->b_count, nlmsvc_free_block); 270 kref_put(&block->b_count, nlmsvc_free_block);
275} 271}
276 272
277static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file) 273/*
278{ 274 * Loop over all blocks and delete blocks held by
279 struct nlm_block *block; 275 * a matching host.
280 276 */
281 down(&file->f_sema); 277void nlmsvc_traverse_blocks(struct nlm_host *host,
282 for (block = file->f_blocks; block != NULL; block = block->b_fnext) 278 struct nlm_file *file,
283 block->b_host->h_inuse = 1; 279 nlm_host_match_fn_t match)
284 up(&file->f_sema);
285}
286
287static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file)
288{ 280{
289 struct nlm_block *block; 281 struct nlm_block *block, *next;
290 282
291restart: 283restart:
292 down(&file->f_sema); 284 mutex_lock(&file->f_mutex);
293 for (block = file->f_blocks; block != NULL; block = block->b_fnext) { 285 list_for_each_entry_safe(block, next, &file->f_blocks, b_flist) {
294 if (host != NULL && host != block->b_host) 286 if (!match(block->b_host, host))
295 continue; 287 continue;
296 if (!block->b_queued) 288 /* Do not destroy blocks that are not on
289 * the global retry list - why? */
290 if (list_empty(&block->b_list))
297 continue; 291 continue;
298 kref_get(&block->b_count); 292 kref_get(&block->b_count);
299 up(&file->f_sema); 293 mutex_unlock(&file->f_mutex);
300 nlmsvc_unlink_block(block); 294 nlmsvc_unlink_block(block);
301 nlmsvc_release_block(block); 295 nlmsvc_release_block(block);
302 goto restart; 296 goto restart;
303 } 297 }
304 up(&file->f_sema); 298 mutex_unlock(&file->f_mutex);
305}
306
307/*
308 * Loop over all blocks and perform the action specified.
309 * (NLM_ACT_CHECK handled by nlmsvc_inspect_file).
310 */
311void
312nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action)
313{
314 if (action == NLM_ACT_MARK)
315 nlmsvc_act_mark(host, file);
316 else
317 nlmsvc_act_unlock(host, file);
318} 299}
319 300
320/* 301/*
@@ -353,13 +334,13 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call)
353 * Attempt to establish a lock, and if it can't be granted, block it 334 * Attempt to establish a lock, and if it can't be granted, block it
354 * if required. 335 * if required.
355 */ 336 */
356u32 337__be32
357nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, 338nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
358 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) 339 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
359{ 340{
360 struct nlm_block *block, *newblock = NULL; 341 struct nlm_block *block, *newblock = NULL;
361 int error; 342 int error;
362 u32 ret; 343 __be32 ret;
363 344
364 dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", 345 dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
365 file->f_file->f_dentry->d_inode->i_sb->s_id, 346 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,
373 lock->fl.fl_flags &= ~FL_SLEEP; 354 lock->fl.fl_flags &= ~FL_SLEEP;
374again: 355again:
375 /* Lock file against concurrent access */ 356 /* Lock file against concurrent access */
376 down(&file->f_sema); 357 mutex_lock(&file->f_mutex);
377 /* Get existing block (in case client is busy-waiting) */ 358 /* Get existing block (in case client is busy-waiting) */
378 block = nlmsvc_lookup_block(file, lock); 359 block = nlmsvc_lookup_block(file, lock);
379 if (block == NULL) { 360 if (block == NULL) {
@@ -411,10 +392,10 @@ again:
411 392
412 /* If we don't have a block, create and initialize it. Then 393 /* If we don't have a block, create and initialize it. Then
413 * retry because we may have slept in kmalloc. */ 394 * retry because we may have slept in kmalloc. */
414 /* We have to release f_sema as nlmsvc_create_block may try to 395 /* We have to release f_mutex as nlmsvc_create_block may try to
415 * to claim it while doing host garbage collection */ 396 * to claim it while doing host garbage collection */
416 if (newblock == NULL) { 397 if (newblock == NULL) {
417 up(&file->f_sema); 398 mutex_unlock(&file->f_mutex);
418 dprintk("lockd: blocking on this lock (allocating).\n"); 399 dprintk("lockd: blocking on this lock (allocating).\n");
419 if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie))) 400 if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie)))
420 return nlm_lck_denied_nolocks; 401 return nlm_lck_denied_nolocks;
@@ -424,7 +405,7 @@ again:
424 /* Append to list of blocked */ 405 /* Append to list of blocked */
425 nlmsvc_insert_block(newblock, NLM_NEVER); 406 nlmsvc_insert_block(newblock, NLM_NEVER);
426out: 407out:
427 up(&file->f_sema); 408 mutex_unlock(&file->f_mutex);
428 nlmsvc_release_block(newblock); 409 nlmsvc_release_block(newblock);
429 nlmsvc_release_block(block); 410 nlmsvc_release_block(block);
430 dprintk("lockd: nlmsvc_lock returned %u\n", ret); 411 dprintk("lockd: nlmsvc_lock returned %u\n", ret);
@@ -434,7 +415,7 @@ out:
434/* 415/*
435 * Test for presence of a conflicting lock. 416 * Test for presence of a conflicting lock.
436 */ 417 */
437u32 418__be32
438nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, 419nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
439 struct nlm_lock *conflock) 420 struct nlm_lock *conflock)
440{ 421{
@@ -451,6 +432,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
451 (long long)conflock->fl.fl_start, 432 (long long)conflock->fl.fl_start,
452 (long long)conflock->fl.fl_end); 433 (long long)conflock->fl.fl_end);
453 conflock->caller = "somehost"; /* FIXME */ 434 conflock->caller = "somehost"; /* FIXME */
435 conflock->len = strlen(conflock->caller);
454 conflock->oh.len = 0; /* don't return OH info */ 436 conflock->oh.len = 0; /* don't return OH info */
455 conflock->svid = conflock->fl.fl_pid; 437 conflock->svid = conflock->fl.fl_pid;
456 return nlm_lck_denied; 438 return nlm_lck_denied;
@@ -466,7 +448,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
466 * afterwards. In this case the block will still be there, and hence 448 * afterwards. In this case the block will still be there, and hence
467 * must be removed. 449 * must be removed.
468 */ 450 */
469u32 451__be32
470nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) 452nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
471{ 453{
472 int error; 454 int error;
@@ -494,7 +476,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
494 * be in progress. 476 * be in progress.
495 * The calling procedure must check whether the file can be closed. 477 * The calling procedure must check whether the file can be closed.
496 */ 478 */
497u32 479__be32
498nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) 480nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
499{ 481{
500 struct nlm_block *block; 482 struct nlm_block *block;
@@ -507,9 +489,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
507 (long long)lock->fl.fl_start, 489 (long long)lock->fl.fl_start,
508 (long long)lock->fl.fl_end); 490 (long long)lock->fl.fl_end);
509 491
510 down(&file->f_sema); 492 mutex_lock(&file->f_mutex);
511 block = nlmsvc_lookup_block(file, lock); 493 block = nlmsvc_lookup_block(file, lock);
512 up(&file->f_sema); 494 mutex_unlock(&file->f_mutex);
513 if (block != NULL) { 495 if (block != NULL) {
514 status = nlmsvc_unlink_block(block); 496 status = nlmsvc_unlink_block(block);
515 nlmsvc_release_block(block); 497 nlmsvc_release_block(block);
@@ -527,10 +509,10 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
527static void 509static void
528nlmsvc_notify_blocked(struct file_lock *fl) 510nlmsvc_notify_blocked(struct file_lock *fl)
529{ 511{
530 struct nlm_block **bp, *block; 512 struct nlm_block *block;
531 513
532 dprintk("lockd: VFS unblock notification for block %p\n", fl); 514 dprintk("lockd: VFS unblock notification for block %p\n", fl);
533 for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) { 515 list_for_each_entry(block, &nlm_blocked, b_list) {
534 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { 516 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
535 nlmsvc_insert_block(block, 0); 517 nlmsvc_insert_block(block, 0);
536 svc_wake_up(block->b_daemon); 518 svc_wake_up(block->b_daemon);
@@ -663,17 +645,14 @@ static const struct rpc_call_ops nlmsvc_grant_ops = {
663 * block. 645 * block.
664 */ 646 */
665void 647void
666nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status) 648nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
667{ 649{
668 struct nlm_block *block; 650 struct nlm_block *block;
669 struct nlm_file *file;
670 651
671 dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", 652 dprintk("grant_reply: looking for cookie %x, s=%d \n",
672 *(unsigned int *)(cookie->data), 653 *(unsigned int *)(cookie->data), status);
673 ntohl(rqstp->rq_addr.sin_addr.s_addr), status); 654 if (!(block = nlmsvc_find_block(cookie)))
674 if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr)))
675 return; 655 return;
676 file = block->b_file;
677 656
678 if (block) { 657 if (block) {
679 if (status == NLM_LCK_DENIED_GRACE_PERIOD) { 658 if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
@@ -696,16 +675,19 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status
696unsigned long 675unsigned long
697nlmsvc_retry_blocked(void) 676nlmsvc_retry_blocked(void)
698{ 677{
699 struct nlm_block *block; 678 unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
679 struct nlm_block *block;
680
681 while (!list_empty(&nlm_blocked)) {
682 block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
700 683
701 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
702 nlm_blocked,
703 nlm_blocked? nlm_blocked->b_when : 0);
704 while ((block = nlm_blocked) != 0) {
705 if (block->b_when == NLM_NEVER) 684 if (block->b_when == NLM_NEVER)
706 break; 685 break;
707 if (time_after(block->b_when,jiffies)) 686 if (time_after(block->b_when,jiffies)) {
687 timeout = block->b_when - jiffies;
708 break; 688 break;
689 }
690
709 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", 691 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
710 block, block->b_when); 692 block, block->b_when);
711 kref_get(&block->b_count); 693 kref_get(&block->b_count);
@@ -713,8 +695,5 @@ nlmsvc_retry_blocked(void)
713 nlmsvc_release_block(block); 695 nlmsvc_release_block(block);
714 } 696 }
715 697
716 if ((block = nlm_blocked) && block->b_when != NLM_NEVER) 698 return timeout;
717 return (block->b_when - jiffies);
718
719 return MAX_SCHEDULE_TIMEOUT;
720} 699}
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index dbb66a3b5cd9..32e99a6e8dca 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -22,8 +22,8 @@
22#define NLMDBG_FACILITY NLMDBG_CLIENT 22#define NLMDBG_FACILITY NLMDBG_CLIENT
23 23
24#ifdef CONFIG_LOCKD_V4 24#ifdef CONFIG_LOCKD_V4
25static u32 25static __be32
26cast_to_nlm(u32 status, u32 vers) 26cast_to_nlm(__be32 status, u32 vers)
27{ 27{
28 /* Note: status is assumed to be in network byte order !!! */ 28 /* Note: status is assumed to be in network byte order !!! */
29 if (vers != 4){ 29 if (vers != 4){
@@ -52,22 +52,22 @@ cast_to_nlm(u32 status, u32 vers)
52/* 52/*
53 * Obtain client and file from arguments 53 * Obtain client and file from arguments
54 */ 54 */
55static u32 55static __be32
56nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, 56nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
57 struct nlm_host **hostp, struct nlm_file **filp) 57 struct nlm_host **hostp, struct nlm_file **filp)
58{ 58{
59 struct nlm_host *host = NULL; 59 struct nlm_host *host = NULL;
60 struct nlm_file *file = NULL; 60 struct nlm_file *file = NULL;
61 struct nlm_lock *lock = &argp->lock; 61 struct nlm_lock *lock = &argp->lock;
62 u32 error; 62 __be32 error = 0;
63 63
64 /* nfsd callbacks must have been installed for this procedure */ 64 /* nfsd callbacks must have been installed for this procedure */
65 if (!nlmsvc_ops) 65 if (!nlmsvc_ops)
66 return nlm_lck_denied_nolocks; 66 return nlm_lck_denied_nolocks;
67 67
68 /* Obtain host handle */ 68 /* Obtain host handle */
69 if (!(host = nlmsvc_lookup_host(rqstp)) 69 if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
70 || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0)) 70 || (argp->monitor && nsm_monitor(host) < 0))
71 goto no_locks; 71 goto no_locks;
72 *hostp = host; 72 *hostp = host;
73 73
@@ -88,13 +88,15 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
88no_locks: 88no_locks:
89 if (host) 89 if (host)
90 nlm_release_host(host); 90 nlm_release_host(host);
91 if (error)
92 return error;
91 return nlm_lck_denied_nolocks; 93 return nlm_lck_denied_nolocks;
92} 94}
93 95
94/* 96/*
95 * NULL: Test for presence of service 97 * NULL: Test for presence of service
96 */ 98 */
97static int 99static __be32
98nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) 100nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
99{ 101{
100 dprintk("lockd: NULL called\n"); 102 dprintk("lockd: NULL called\n");
@@ -104,7 +106,7 @@ nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
104/* 106/*
105 * TEST: Check for conflicting lock 107 * TEST: Check for conflicting lock
106 */ 108 */
107static int 109static __be32
108nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, 110nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
109 struct nlm_res *resp) 111 struct nlm_res *resp)
110{ 112{
@@ -122,7 +124,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
122 124
123 /* Obtain client and file */ 125 /* Obtain client and file */
124 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 126 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
125 return rpc_success; 127 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
126 128
127 /* Now check for conflicting locks */ 129 /* Now check for conflicting locks */
128 resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock)); 130 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,
134 return rpc_success; 136 return rpc_success;
135} 137}
136 138
137static int 139static __be32
138nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, 140nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
139 struct nlm_res *resp) 141 struct nlm_res *resp)
140{ 142{
@@ -153,7 +155,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
153 155
154 /* Obtain client and file */ 156 /* Obtain client and file */
155 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 157 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
156 return rpc_success; 158 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
157 159
158#if 0 160#if 0
159 /* If supplied state doesn't match current state, we assume it's 161 /* 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,
177 return rpc_success; 179 return rpc_success;
178} 180}
179 181
180static int 182static __be32
181nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, 183nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
182 struct nlm_res *resp) 184 struct nlm_res *resp)
183{ 185{
@@ -196,7 +198,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
196 198
197 /* Obtain client and file */ 199 /* Obtain client and file */
198 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 200 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
199 return rpc_success; 201 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
200 202
201 /* Try to cancel request. */ 203 /* Try to cancel request. */
202 resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock)); 204 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,
210/* 212/*
211 * UNLOCK: release a lock 213 * UNLOCK: release a lock
212 */ 214 */
213static int 215static __be32
214nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, 216nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
215 struct nlm_res *resp) 217 struct nlm_res *resp)
216{ 218{
@@ -229,7 +231,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
229 231
230 /* Obtain client and file */ 232 /* Obtain client and file */
231 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 233 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
232 return rpc_success; 234 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
233 235
234 /* Now try to remove the lock */ 236 /* Now try to remove the lock */
235 resp->status = cast_status(nlmsvc_unlock(file, &argp->lock)); 237 resp->status = cast_status(nlmsvc_unlock(file, &argp->lock));
@@ -244,7 +246,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
244 * GRANTED: A server calls us to tell that a process' lock request 246 * GRANTED: A server calls us to tell that a process' lock request
245 * was granted 247 * was granted
246 */ 248 */
247static int 249static __be32
248nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, 250nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
249 struct nlm_res *resp) 251 struct nlm_res *resp)
250{ 252{
@@ -280,14 +282,16 @@ static const struct rpc_call_ops nlmsvc_callback_ops = {
280 * because we send the callback before the reply proper. I hope this 282 * because we send the callback before the reply proper. I hope this
281 * doesn't break any clients. 283 * doesn't break any clients.
282 */ 284 */
283static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, 285static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
284 int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) 286 __be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *))
285{ 287{
286 struct nlm_host *host; 288 struct nlm_host *host;
287 struct nlm_rqst *call; 289 struct nlm_rqst *call;
288 int stat; 290 __be32 stat;
289 291
290 host = nlmsvc_lookup_host(rqstp); 292 host = nlmsvc_lookup_host(rqstp,
293 argp->lock.caller,
294 argp->lock.len);
291 if (host == NULL) 295 if (host == NULL)
292 return rpc_system_err; 296 return rpc_system_err;
293 297
@@ -307,28 +311,28 @@ static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *ar
307 return rpc_success; 311 return rpc_success;
308} 312}
309 313
310static int nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 314static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
311 void *resp) 315 void *resp)
312{ 316{
313 dprintk("lockd: TEST_MSG called\n"); 317 dprintk("lockd: TEST_MSG called\n");
314 return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test); 318 return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test);
315} 319}
316 320
317static int nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 321static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
318 void *resp) 322 void *resp)
319{ 323{
320 dprintk("lockd: LOCK_MSG called\n"); 324 dprintk("lockd: LOCK_MSG called\n");
321 return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock); 325 return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock);
322} 326}
323 327
324static int nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 328static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
325 void *resp) 329 void *resp)
326{ 330{
327 dprintk("lockd: CANCEL_MSG called\n"); 331 dprintk("lockd: CANCEL_MSG called\n");
328 return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel); 332 return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel);
329} 333}
330 334
331static int 335static __be32
332nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 336nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
333 void *resp) 337 void *resp)
334{ 338{
@@ -336,7 +340,7 @@ nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
336 return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock); 340 return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock);
337} 341}
338 342
339static int 343static __be32
340nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 344nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
341 void *resp) 345 void *resp)
342{ 346{
@@ -347,7 +351,7 @@ nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
347/* 351/*
348 * SHARE: create a DOS share or alter existing share. 352 * SHARE: create a DOS share or alter existing share.
349 */ 353 */
350static int 354static __be32
351nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, 355nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
352 struct nlm_res *resp) 356 struct nlm_res *resp)
353{ 357{
@@ -366,7 +370,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
366 370
367 /* Obtain client and file */ 371 /* Obtain client and file */
368 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 372 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
369 return rpc_success; 373 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
370 374
371 /* Now try to create the share */ 375 /* Now try to create the share */
372 resp->status = cast_status(nlmsvc_share_file(host, file, argp)); 376 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,
380/* 384/*
381 * UNSHARE: Release a DOS share. 385 * UNSHARE: Release a DOS share.
382 */ 386 */
383static int 387static __be32
384nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, 388nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
385 struct nlm_res *resp) 389 struct nlm_res *resp)
386{ 390{
@@ -399,7 +403,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
399 403
400 /* Obtain client and file */ 404 /* Obtain client and file */
401 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 405 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
402 return rpc_success; 406 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
403 407
404 /* Now try to unshare the file */ 408 /* Now try to unshare the file */
405 resp->status = cast_status(nlmsvc_unshare_file(host, file, argp)); 409 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,
413/* 417/*
414 * NM_LOCK: Create an unmonitored lock 418 * NM_LOCK: Create an unmonitored lock
415 */ 419 */
416static int 420static __be32
417nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, 421nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
418 struct nlm_res *resp) 422 struct nlm_res *resp)
419{ 423{
@@ -426,7 +430,7 @@ nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
426/* 430/*
427 * FREE_ALL: Release all locks and shares held by client 431 * FREE_ALL: Release all locks and shares held by client
428 */ 432 */
429static int 433static __be32
430nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, 434nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
431 void *resp) 435 void *resp)
432{ 436{
@@ -444,14 +448,11 @@ nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
444/* 448/*
445 * SM_NOTIFY: private callback from statd (not part of official NLM proto) 449 * SM_NOTIFY: private callback from statd (not part of official NLM proto)
446 */ 450 */
447static int 451static __be32
448nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, 452nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
449 void *resp) 453 void *resp)
450{ 454{
451 struct sockaddr_in saddr = rqstp->rq_addr; 455 struct sockaddr_in saddr = rqstp->rq_addr;
452 int vers = argp->vers;
453 int prot = argp->proto >> 1;
454 struct nlm_host *host;
455 456
456 dprintk("lockd: SM_NOTIFY called\n"); 457 dprintk("lockd: SM_NOTIFY called\n");
457 if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) 458 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,
466 /* Obtain the host pointer for this NFS server and try to 467 /* Obtain the host pointer for this NFS server and try to
467 * reclaim all locks we hold on this server. 468 * reclaim all locks we hold on this server.
468 */ 469 */
470 memset(&saddr, 0, sizeof(saddr));
469 saddr.sin_addr.s_addr = argp->addr; 471 saddr.sin_addr.s_addr = argp->addr;
470 if ((argp->proto & 1)==0) { 472 nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);
471 if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
472 nlmclnt_recovery(host, argp->state);
473 nlm_release_host(host);
474 }
475 } else {
476 /* If we run on an NFS server, delete all locks held by the client */
477 if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) {
478 nlmsvc_free_host_resources(host);
479 nlm_release_host(host);
480 }
481 }
482 473
483 return rpc_success; 474 return rpc_success;
484} 475}
@@ -486,7 +477,7 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
486/* 477/*
487 * client sent a GRANTED_RES, let's remove the associated block 478 * client sent a GRANTED_RES, let's remove the associated block
488 */ 479 */
489static int 480static __be32
490nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, 481nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
491 void *resp) 482 void *resp)
492{ 483{
@@ -495,7 +486,7 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
495 486
496 dprintk("lockd: GRANTED_RES called\n"); 487 dprintk("lockd: GRANTED_RES called\n");
497 488
498 nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status); 489 nlmsvc_grant_reply(&argp->cookie, argp->status);
499 return rpc_success; 490 return rpc_success;
500} 491}
501 492
diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
index 27288c83da96..6220dc2a3f2c 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)
23 && !memcmp(share->s_owner.data, oh->data, oh->len); 23 && !memcmp(share->s_owner.data, oh->data, oh->len);
24} 24}
25 25
26u32 26__be32
27nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file, 27nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file,
28 struct nlm_args *argp) 28 struct nlm_args *argp)
29{ 29{
@@ -64,7 +64,7 @@ update:
64/* 64/*
65 * Delete a share. 65 * Delete a share.
66 */ 66 */
67u32 67__be32
68nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file, 68nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
69 struct nlm_args *argp) 69 struct nlm_args *argp)
70{ 70{
@@ -85,24 +85,20 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
85} 85}
86 86
87/* 87/*
88 * Traverse all shares for a given file (and host). 88 * Traverse all shares for a given file, and delete
89 * NLM_ACT_CHECK is handled by nlmsvc_inspect_file. 89 * those owned by the given (type of) host
90 */ 90 */
91void 91void nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file,
92nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, int action) 92 nlm_host_match_fn_t match)
93{ 93{
94 struct nlm_share *share, **shpp; 94 struct nlm_share *share, **shpp;
95 95
96 shpp = &file->f_shares; 96 shpp = &file->f_shares;
97 while ((share = *shpp) != NULL) { 97 while ((share = *shpp) != NULL) {
98 if (action == NLM_ACT_MARK) 98 if (match(share->s_host, host)) {
99 share->s_host->h_inuse = 1; 99 *shpp = share->s_next;
100 else if (action == NLM_ACT_UNLOCK) { 100 kfree(share);
101 if (host == NULL || host == share->s_host) { 101 continue;
102 *shpp = share->s_next;
103 kfree(share);
104 continue;
105 }
106 } 102 }
107 shpp = &share->s_next; 103 shpp = &share->s_next;
108 } 104 }
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index a92dd98f8401..e83024e16042 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -25,9 +25,9 @@
25/* 25/*
26 * Global file hash table 26 * Global file hash table
27 */ 27 */
28#define FILE_HASH_BITS 5 28#define FILE_HASH_BITS 7
29#define FILE_NRHASH (1<<FILE_HASH_BITS) 29#define FILE_NRHASH (1<<FILE_HASH_BITS)
30static struct nlm_file * nlm_files[FILE_NRHASH]; 30static struct hlist_head nlm_files[FILE_NRHASH];
31static DEFINE_MUTEX(nlm_file_mutex); 31static DEFINE_MUTEX(nlm_file_mutex);
32 32
33#ifdef NFSD_DEBUG 33#ifdef NFSD_DEBUG
@@ -78,13 +78,14 @@ static inline unsigned int file_hash(struct nfs_fh *f)
78 * This is not quite right, but for now, we assume the client performs 78 * This is not quite right, but for now, we assume the client performs
79 * the proper R/W checking. 79 * the proper R/W checking.
80 */ 80 */
81u32 81__be32
82nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, 82nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
83 struct nfs_fh *f) 83 struct nfs_fh *f)
84{ 84{
85 struct hlist_node *pos;
85 struct nlm_file *file; 86 struct nlm_file *file;
86 unsigned int hash; 87 unsigned int hash;
87 u32 nfserr; 88 __be32 nfserr;
88 89
89 nlm_debug_print_fh("nlm_file_lookup", f); 90 nlm_debug_print_fh("nlm_file_lookup", f);
90 91
@@ -93,7 +94,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
93 /* Lock file table */ 94 /* Lock file table */
94 mutex_lock(&nlm_file_mutex); 95 mutex_lock(&nlm_file_mutex);
95 96
96 for (file = nlm_files[hash]; file; file = file->f_next) 97 hlist_for_each_entry(file, pos, &nlm_files[hash], f_list)
97 if (!nfs_compare_fh(&file->f_handle, f)) 98 if (!nfs_compare_fh(&file->f_handle, f))
98 goto found; 99 goto found;
99 100
@@ -105,8 +106,9 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
105 goto out_unlock; 106 goto out_unlock;
106 107
107 memcpy(&file->f_handle, f, sizeof(struct nfs_fh)); 108 memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
108 file->f_hash = hash; 109 mutex_init(&file->f_mutex);
109 init_MUTEX(&file->f_sema); 110 INIT_HLIST_NODE(&file->f_list);
111 INIT_LIST_HEAD(&file->f_blocks);
110 112
111 /* Open the file. Note that this must not sleep for too long, else 113 /* Open the file. Note that this must not sleep for too long, else
112 * we would lock up lockd:-) So no NFS re-exports, folks. 114 * 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,
115 * the file. 117 * the file.
116 */ 118 */
117 if ((nfserr = nlmsvc_ops->fopen(rqstp, f, &file->f_file)) != 0) { 119 if ((nfserr = nlmsvc_ops->fopen(rqstp, f, &file->f_file)) != 0) {
118 dprintk("lockd: open failed (nfserr %d)\n", ntohl(nfserr)); 120 dprintk("lockd: open failed (error %d)\n", nfserr);
119 goto out_free; 121 goto out_free;
120 } 122 }
121 123
122 file->f_next = nlm_files[hash]; 124 hlist_add_head(&file->f_list, &nlm_files[hash]);
123 nlm_files[hash] = file;
124 125
125found: 126found:
126 dprintk("lockd: found file %p (count %d)\n", file, file->f_count); 127 dprintk("lockd: found file %p (count %d)\n", file, file->f_count);
@@ -134,12 +135,6 @@ out_unlock:
134 135
135out_free: 136out_free:
136 kfree(file); 137 kfree(file);
137#ifdef CONFIG_LOCKD_V4
138 if (nfserr == 1)
139 nfserr = nlm4_stale_fh;
140 else
141#endif
142 nfserr = nlm_lck_denied;
143 goto out_unlock; 138 goto out_unlock;
144} 139}
145 140
@@ -149,22 +144,14 @@ out_free:
149static inline void 144static inline void
150nlm_delete_file(struct nlm_file *file) 145nlm_delete_file(struct nlm_file *file)
151{ 146{
152 struct nlm_file **fp, *f;
153
154 nlm_debug_print_file("closing file", file); 147 nlm_debug_print_file("closing file", file);
155 148 if (!hlist_unhashed(&file->f_list)) {
156 fp = nlm_files + file->f_hash; 149 hlist_del(&file->f_list);
157 while ((f = *fp) != NULL) { 150 nlmsvc_ops->fclose(file->f_file);
158 if (f == file) { 151 kfree(file);
159 *fp = file->f_next; 152 } else {
160 nlmsvc_ops->fclose(file->f_file); 153 printk(KERN_WARNING "lockd: attempt to release unknown file!\n");
161 kfree(file);
162 return;
163 }
164 fp = &f->f_next;
165 } 154 }
166
167 printk(KERN_WARNING "lockd: attempt to release unknown file!\n");
168} 155}
169 156
170/* 157/*
@@ -172,7 +159,8 @@ nlm_delete_file(struct nlm_file *file)
172 * action. 159 * action.
173 */ 160 */
174static int 161static int
175nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file, int action) 162nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
163 nlm_host_match_fn_t match)
176{ 164{
177 struct inode *inode = nlmsvc_file_inode(file); 165 struct inode *inode = nlmsvc_file_inode(file);
178 struct file_lock *fl; 166 struct file_lock *fl;
@@ -186,17 +174,11 @@ again:
186 174
187 /* update current lock count */ 175 /* update current lock count */
188 file->f_locks++; 176 file->f_locks++;
177
189 lockhost = (struct nlm_host *) fl->fl_owner; 178 lockhost = (struct nlm_host *) fl->fl_owner;
190 if (action == NLM_ACT_MARK) 179 if (match(lockhost, host)) {
191 lockhost->h_inuse = 1;
192 else if (action == NLM_ACT_CHECK)
193 return 1;
194 else if (action == NLM_ACT_UNLOCK) {
195 struct file_lock lock = *fl; 180 struct file_lock lock = *fl;
196 181
197 if (host && lockhost != host)
198 continue;
199
200 lock.fl_type = F_UNLCK; 182 lock.fl_type = F_UNLCK;
201 lock.fl_start = 0; 183 lock.fl_start = 0;
202 lock.fl_end = OFFSET_MAX; 184 lock.fl_end = OFFSET_MAX;
@@ -213,53 +195,66 @@ again:
213} 195}
214 196
215/* 197/*
216 * Operate on a single file 198 * Inspect a single file
199 */
200static inline int
201nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, nlm_host_match_fn_t match)
202{
203 nlmsvc_traverse_blocks(host, file, match);
204 nlmsvc_traverse_shares(host, file, match);
205 return nlm_traverse_locks(host, file, match);
206}
207
208/*
209 * Quick check whether there are still any locks, blocks or
210 * shares on a given file.
217 */ 211 */
218static inline int 212static inline int
219nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, int action) 213nlm_file_inuse(struct nlm_file *file)
220{ 214{
221 if (action == NLM_ACT_CHECK) { 215 struct inode *inode = nlmsvc_file_inode(file);
222 /* Fast path for mark and sweep garbage collection */ 216 struct file_lock *fl;
223 if (file->f_count || file->f_blocks || file->f_shares) 217
218 if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares)
219 return 1;
220
221 for (fl = inode->i_flock; fl; fl = fl->fl_next) {
222 if (fl->fl_lmops == &nlmsvc_lock_operations)
224 return 1; 223 return 1;
225 } else {
226 nlmsvc_traverse_blocks(host, file, action);
227 nlmsvc_traverse_shares(host, file, action);
228 } 224 }
229 return nlm_traverse_locks(host, file, action); 225 file->f_locks = 0;
226 return 0;
230} 227}
231 228
232/* 229/*
233 * Loop over all files in the file table. 230 * Loop over all files in the file table.
234 */ 231 */
235static int 232static int
236nlm_traverse_files(struct nlm_host *host, int action) 233nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
237{ 234{
238 struct nlm_file *file, **fp; 235 struct hlist_node *pos, *next;
236 struct nlm_file *file;
239 int i, ret = 0; 237 int i, ret = 0;
240 238
241 mutex_lock(&nlm_file_mutex); 239 mutex_lock(&nlm_file_mutex);
242 for (i = 0; i < FILE_NRHASH; i++) { 240 for (i = 0; i < FILE_NRHASH; i++) {
243 fp = nlm_files + i; 241 hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) {
244 while ((file = *fp) != NULL) {
245 file->f_count++; 242 file->f_count++;
246 mutex_unlock(&nlm_file_mutex); 243 mutex_unlock(&nlm_file_mutex);
247 244
248 /* Traverse locks, blocks and shares of this file 245 /* Traverse locks, blocks and shares of this file
249 * and update file->f_locks count */ 246 * and update file->f_locks count */
250 if (nlm_inspect_file(host, file, action)) 247 if (nlm_inspect_file(host, file, match))
251 ret = 1; 248 ret = 1;
252 249
253 mutex_lock(&nlm_file_mutex); 250 mutex_lock(&nlm_file_mutex);
254 file->f_count--; 251 file->f_count--;
255 /* No more references to this file. Let go of it. */ 252 /* No more references to this file. Let go of it. */
256 if (!file->f_blocks && !file->f_locks 253 if (list_empty(&file->f_blocks) && !file->f_locks
257 && !file->f_shares && !file->f_count) { 254 && !file->f_shares && !file->f_count) {
258 *fp = file->f_next; 255 hlist_del(&file->f_list);
259 nlmsvc_ops->fclose(file->f_file); 256 nlmsvc_ops->fclose(file->f_file);
260 kfree(file); 257 kfree(file);
261 } else {
262 fp = &file->f_next;
263 } 258 }
264 } 259 }
265 } 260 }
@@ -286,23 +281,63 @@ nlm_release_file(struct nlm_file *file)
286 mutex_lock(&nlm_file_mutex); 281 mutex_lock(&nlm_file_mutex);
287 282
288 /* If there are no more locks etc, delete the file */ 283 /* If there are no more locks etc, delete the file */
289 if(--file->f_count == 0) { 284 if (--file->f_count == 0 && !nlm_file_inuse(file))
290 if(!nlm_inspect_file(NULL, file, NLM_ACT_CHECK)) 285 nlm_delete_file(file);
291 nlm_delete_file(file);
292 }
293 286
294 mutex_unlock(&nlm_file_mutex); 287 mutex_unlock(&nlm_file_mutex);
295} 288}
296 289
297/* 290/*
291 * Helpers function for resource traversal
292 *
293 * nlmsvc_mark_host:
294 * used by the garbage collector; simply sets h_inuse.
295 * Always returns 0.
296 *
297 * nlmsvc_same_host:
298 * returns 1 iff the two hosts match. Used to release
299 * all resources bound to a specific host.
300 *
301 * nlmsvc_is_client:
302 * returns 1 iff the host is a client.
303 * Used by nlmsvc_invalidate_all
304 */
305static int
306nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy)
307{
308 host->h_inuse = 1;
309 return 0;
310}
311
312static int
313nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other)
314{
315 return host == other;
316}
317
318static int
319nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy)
320{
321 if (host->h_server) {
322 /* we are destroying locks even though the client
323 * hasn't asked us too, so don't unmonitor the
324 * client
325 */
326 if (host->h_nsmhandle)
327 host->h_nsmhandle->sm_sticky = 1;
328 return 1;
329 } else
330 return 0;
331}
332
333/*
298 * Mark all hosts that still hold resources 334 * Mark all hosts that still hold resources
299 */ 335 */
300void 336void
301nlmsvc_mark_resources(void) 337nlmsvc_mark_resources(void)
302{ 338{
303 dprintk("lockd: nlmsvc_mark_resources\n"); 339 dprintk("lockd: nlmsvc_mark_resources\n");
304 340 nlm_traverse_files(NULL, nlmsvc_mark_host);
305 nlm_traverse_files(NULL, NLM_ACT_MARK);
306} 341}
307 342
308/* 343/*
@@ -313,23 +348,25 @@ nlmsvc_free_host_resources(struct nlm_host *host)
313{ 348{
314 dprintk("lockd: nlmsvc_free_host_resources\n"); 349 dprintk("lockd: nlmsvc_free_host_resources\n");
315 350
316 if (nlm_traverse_files(host, NLM_ACT_UNLOCK)) 351 if (nlm_traverse_files(host, nlmsvc_same_host)) {
317 printk(KERN_WARNING 352 printk(KERN_WARNING
318 "lockd: couldn't remove all locks held by %s", 353 "lockd: couldn't remove all locks held by %s\n",
319 host->h_name); 354 host->h_name);
355 BUG();
356 }
320} 357}
321 358
322/* 359/*
323 * delete all hosts structs for clients 360 * Remove all locks held for clients
324 */ 361 */
325void 362void
326nlmsvc_invalidate_all(void) 363nlmsvc_invalidate_all(void)
327{ 364{
328 struct nlm_host *host; 365 /* Release all locks held by NFS clients.
329 while ((host = nlm_find_client()) != NULL) { 366 * Previously, the code would call
330 nlmsvc_free_host_resources(host); 367 * nlmsvc_free_host_resources for each client in
331 host->h_expires = 0; 368 * turn, which is about as inefficient as it gets.
332 host->h_killed = 1; 369 * Now we just do it once in nlm_traverse_files.
333 nlm_release_host(host); 370 */
334 } 371 nlm_traverse_files(NULL, nlmsvc_is_client);
335} 372}
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 61c46facf257..b7c949256e5a 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -43,7 +43,7 @@ loff_t_to_s32(loff_t offset)
43/* 43/*
44 * XDR functions for basic NLM types 44 * XDR functions for basic NLM types
45 */ 45 */
46static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) 46static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c)
47{ 47{
48 unsigned int len; 48 unsigned int len;
49 49
@@ -69,8 +69,8 @@ static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c)
69 return p; 69 return p;
70} 70}
71 71
72static inline u32 * 72static inline __be32 *
73nlm_encode_cookie(u32 *p, struct nlm_cookie *c) 73nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)
74{ 74{
75 *p++ = htonl(c->len); 75 *p++ = htonl(c->len);
76 memcpy(p, c->data, c->len); 76 memcpy(p, c->data, c->len);
@@ -78,8 +78,8 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c)
78 return p; 78 return p;
79} 79}
80 80
81static u32 * 81static __be32 *
82nlm_decode_fh(u32 *p, struct nfs_fh *f) 82nlm_decode_fh(__be32 *p, struct nfs_fh *f)
83{ 83{
84 unsigned int len; 84 unsigned int len;
85 85
@@ -95,8 +95,8 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f)
95 return p + XDR_QUADLEN(NFS2_FHSIZE); 95 return p + XDR_QUADLEN(NFS2_FHSIZE);
96} 96}
97 97
98static inline u32 * 98static inline __be32 *
99nlm_encode_fh(u32 *p, struct nfs_fh *f) 99nlm_encode_fh(__be32 *p, struct nfs_fh *f)
100{ 100{
101 *p++ = htonl(NFS2_FHSIZE); 101 *p++ = htonl(NFS2_FHSIZE);
102 memcpy(p, f->data, NFS2_FHSIZE); 102 memcpy(p, f->data, NFS2_FHSIZE);
@@ -106,20 +106,20 @@ nlm_encode_fh(u32 *p, struct nfs_fh *f)
106/* 106/*
107 * Encode and decode owner handle 107 * Encode and decode owner handle
108 */ 108 */
109static inline u32 * 109static inline __be32 *
110nlm_decode_oh(u32 *p, struct xdr_netobj *oh) 110nlm_decode_oh(__be32 *p, struct xdr_netobj *oh)
111{ 111{
112 return xdr_decode_netobj(p, oh); 112 return xdr_decode_netobj(p, oh);
113} 113}
114 114
115static inline u32 * 115static inline __be32 *
116nlm_encode_oh(u32 *p, struct xdr_netobj *oh) 116nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)
117{ 117{
118 return xdr_encode_netobj(p, oh); 118 return xdr_encode_netobj(p, oh);
119} 119}
120 120
121static u32 * 121static __be32 *
122nlm_decode_lock(u32 *p, struct nlm_lock *lock) 122nlm_decode_lock(__be32 *p, struct nlm_lock *lock)
123{ 123{
124 struct file_lock *fl = &lock->fl; 124 struct file_lock *fl = &lock->fl;
125 s32 start, len, end; 125 s32 start, len, end;
@@ -153,8 +153,8 @@ nlm_decode_lock(u32 *p, struct nlm_lock *lock)
153/* 153/*
154 * Encode a lock as part of an NLM call 154 * Encode a lock as part of an NLM call
155 */ 155 */
156static u32 * 156static __be32 *
157nlm_encode_lock(u32 *p, struct nlm_lock *lock) 157nlm_encode_lock(__be32 *p, struct nlm_lock *lock)
158{ 158{
159 struct file_lock *fl = &lock->fl; 159 struct file_lock *fl = &lock->fl;
160 __s32 start, len; 160 __s32 start, len;
@@ -184,8 +184,8 @@ nlm_encode_lock(u32 *p, struct nlm_lock *lock)
184/* 184/*
185 * Encode result of a TEST/TEST_MSG call 185 * Encode result of a TEST/TEST_MSG call
186 */ 186 */
187static u32 * 187static __be32 *
188nlm_encode_testres(u32 *p, struct nlm_res *resp) 188nlm_encode_testres(__be32 *p, struct nlm_res *resp)
189{ 189{
190 s32 start, len; 190 s32 start, len;
191 191
@@ -221,7 +221,7 @@ nlm_encode_testres(u32 *p, struct nlm_res *resp)
221 * First, the server side XDR functions 221 * First, the server side XDR functions
222 */ 222 */
223int 223int
224nlmsvc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 224nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
225{ 225{
226 u32 exclusive; 226 u32 exclusive;
227 227
@@ -238,7 +238,7 @@ nlmsvc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
238} 238}
239 239
240int 240int
241nlmsvc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 241nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
242{ 242{
243 if (!(p = nlm_encode_testres(p, resp))) 243 if (!(p = nlm_encode_testres(p, resp)))
244 return 0; 244 return 0;
@@ -246,7 +246,7 @@ nlmsvc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
246} 246}
247 247
248int 248int
249nlmsvc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 249nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
250{ 250{
251 u32 exclusive; 251 u32 exclusive;
252 252
@@ -266,7 +266,7 @@ nlmsvc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
266} 266}
267 267
268int 268int
269nlmsvc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 269nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
270{ 270{
271 u32 exclusive; 271 u32 exclusive;
272 272
@@ -282,7 +282,7 @@ nlmsvc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
282} 282}
283 283
284int 284int
285nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 285nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
286{ 286{
287 if (!(p = nlm_decode_cookie(p, &argp->cookie)) 287 if (!(p = nlm_decode_cookie(p, &argp->cookie))
288 || !(p = nlm_decode_lock(p, &argp->lock))) 288 || !(p = nlm_decode_lock(p, &argp->lock)))
@@ -292,7 +292,7 @@ nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
292} 292}
293 293
294int 294int
295nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 295nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
296{ 296{
297 struct nlm_lock *lock = &argp->lock; 297 struct nlm_lock *lock = &argp->lock;
298 298
@@ -313,7 +313,7 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
313} 313}
314 314
315int 315int
316nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 316nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
317{ 317{
318 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 318 if (!(p = nlm_encode_cookie(p, &resp->cookie)))
319 return 0; 319 return 0;
@@ -323,7 +323,7 @@ nlmsvc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
323} 323}
324 324
325int 325int
326nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 326nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
327{ 327{
328 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 328 if (!(p = nlm_encode_cookie(p, &resp->cookie)))
329 return 0; 329 return 0;
@@ -332,7 +332,7 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
332} 332}
333 333
334int 334int
335nlmsvc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) 335nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp)
336{ 336{
337 struct nlm_lock *lock = &argp->lock; 337 struct nlm_lock *lock = &argp->lock;
338 338
@@ -344,7 +344,7 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp)
344} 344}
345 345
346int 346int
347nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) 347nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
348{ 348{
349 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 349 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
350 return 0; 350 return 0;
@@ -357,7 +357,7 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
357} 357}
358 358
359int 359int
360nlmsvc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 360nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
361{ 361{
362 if (!(p = nlm_decode_cookie(p, &resp->cookie))) 362 if (!(p = nlm_decode_cookie(p, &resp->cookie)))
363 return 0; 363 return 0;
@@ -366,13 +366,13 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
366} 366}
367 367
368int 368int
369nlmsvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) 369nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
370{ 370{
371 return xdr_argsize_check(rqstp, p); 371 return xdr_argsize_check(rqstp, p);
372} 372}
373 373
374int 374int
375nlmsvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) 375nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
376{ 376{
377 return xdr_ressize_check(rqstp, p); 377 return xdr_ressize_check(rqstp, p);
378} 378}
@@ -389,7 +389,7 @@ nlmclt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr)
389#endif 389#endif
390 390
391static int 391static int
392nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 392nlmclt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
393{ 393{
394 struct nlm_lock *lock = &argp->lock; 394 struct nlm_lock *lock = &argp->lock;
395 395
@@ -403,7 +403,7 @@ nlmclt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
403} 403}
404 404
405static int 405static int
406nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 406nlmclt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
407{ 407{
408 if (!(p = nlm_decode_cookie(p, &resp->cookie))) 408 if (!(p = nlm_decode_cookie(p, &resp->cookie)))
409 return -EIO; 409 return -EIO;
@@ -438,7 +438,7 @@ nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
438 438
439 439
440static int 440static int
441nlmclt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 441nlmclt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
442{ 442{
443 struct nlm_lock *lock = &argp->lock; 443 struct nlm_lock *lock = &argp->lock;
444 444
@@ -455,7 +455,7 @@ nlmclt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
455} 455}
456 456
457static int 457static int
458nlmclt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 458nlmclt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
459{ 459{
460 struct nlm_lock *lock = &argp->lock; 460 struct nlm_lock *lock = &argp->lock;
461 461
@@ -470,7 +470,7 @@ nlmclt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
470} 470}
471 471
472static int 472static int
473nlmclt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 473nlmclt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
474{ 474{
475 struct nlm_lock *lock = &argp->lock; 475 struct nlm_lock *lock = &argp->lock;
476 476
@@ -483,7 +483,7 @@ nlmclt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
483} 483}
484 484
485static int 485static int
486nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 486nlmclt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
487{ 487{
488 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 488 if (!(p = nlm_encode_cookie(p, &resp->cookie)))
489 return -EIO; 489 return -EIO;
@@ -493,7 +493,7 @@ nlmclt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
493} 493}
494 494
495static int 495static int
496nlmclt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 496nlmclt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
497{ 497{
498 if (!(p = nlm_encode_testres(p, resp))) 498 if (!(p = nlm_encode_testres(p, resp)))
499 return -EIO; 499 return -EIO;
@@ -502,7 +502,7 @@ nlmclt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
502} 502}
503 503
504static int 504static int
505nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 505nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
506{ 506{
507 if (!(p = nlm_decode_cookie(p, &resp->cookie))) 507 if (!(p = nlm_decode_cookie(p, &resp->cookie)))
508 return -EIO; 508 return -EIO;
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 36eb175ec335..f4c0b2b9f75a 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -44,8 +44,8 @@ loff_t_to_s64(loff_t offset)
44/* 44/*
45 * XDR functions for basic NLM types 45 * XDR functions for basic NLM types
46 */ 46 */
47static u32 * 47static __be32 *
48nlm4_decode_cookie(u32 *p, struct nlm_cookie *c) 48nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c)
49{ 49{
50 unsigned int len; 50 unsigned int len;
51 51
@@ -71,8 +71,8 @@ nlm4_decode_cookie(u32 *p, struct nlm_cookie *c)
71 return p; 71 return p;
72} 72}
73 73
74static u32 * 74static __be32 *
75nlm4_encode_cookie(u32 *p, struct nlm_cookie *c) 75nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
76{ 76{
77 *p++ = htonl(c->len); 77 *p++ = htonl(c->len);
78 memcpy(p, c->data, c->len); 78 memcpy(p, c->data, c->len);
@@ -80,8 +80,8 @@ nlm4_encode_cookie(u32 *p, struct nlm_cookie *c)
80 return p; 80 return p;
81} 81}
82 82
83static u32 * 83static __be32 *
84nlm4_decode_fh(u32 *p, struct nfs_fh *f) 84nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
85{ 85{
86 memset(f->data, 0, sizeof(f->data)); 86 memset(f->data, 0, sizeof(f->data));
87 f->size = ntohl(*p++); 87 f->size = ntohl(*p++);
@@ -95,8 +95,8 @@ nlm4_decode_fh(u32 *p, struct nfs_fh *f)
95 return p + XDR_QUADLEN(f->size); 95 return p + XDR_QUADLEN(f->size);
96} 96}
97 97
98static u32 * 98static __be32 *
99nlm4_encode_fh(u32 *p, struct nfs_fh *f) 99nlm4_encode_fh(__be32 *p, struct nfs_fh *f)
100{ 100{
101 *p++ = htonl(f->size); 101 *p++ = htonl(f->size);
102 if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */ 102 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)
107/* 107/*
108 * Encode and decode owner handle 108 * Encode and decode owner handle
109 */ 109 */
110static u32 * 110static __be32 *
111nlm4_decode_oh(u32 *p, struct xdr_netobj *oh) 111nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)
112{ 112{
113 return xdr_decode_netobj(p, oh); 113 return xdr_decode_netobj(p, oh);
114} 114}
115 115
116static u32 * 116static __be32 *
117nlm4_encode_oh(u32 *p, struct xdr_netobj *oh) 117nlm4_encode_oh(__be32 *p, struct xdr_netobj *oh)
118{ 118{
119 return xdr_encode_netobj(p, oh); 119 return xdr_encode_netobj(p, oh);
120} 120}
121 121
122static u32 * 122static __be32 *
123nlm4_decode_lock(u32 *p, struct nlm_lock *lock) 123nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
124{ 124{
125 struct file_lock *fl = &lock->fl; 125 struct file_lock *fl = &lock->fl;
126 __s64 len, start, end; 126 __s64 len, start, end;
@@ -153,8 +153,8 @@ nlm4_decode_lock(u32 *p, struct nlm_lock *lock)
153/* 153/*
154 * Encode a lock as part of an NLM call 154 * Encode a lock as part of an NLM call
155 */ 155 */
156static u32 * 156static __be32 *
157nlm4_encode_lock(u32 *p, struct nlm_lock *lock) 157nlm4_encode_lock(__be32 *p, struct nlm_lock *lock)
158{ 158{
159 struct file_lock *fl = &lock->fl; 159 struct file_lock *fl = &lock->fl;
160 __s64 start, len; 160 __s64 start, len;
@@ -185,8 +185,8 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock)
185/* 185/*
186 * Encode result of a TEST/TEST_MSG call 186 * Encode result of a TEST/TEST_MSG call
187 */ 187 */
188static u32 * 188static __be32 *
189nlm4_encode_testres(u32 *p, struct nlm_res *resp) 189nlm4_encode_testres(__be32 *p, struct nlm_res *resp)
190{ 190{
191 s64 start, len; 191 s64 start, len;
192 192
@@ -227,7 +227,7 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp)
227 * First, the server side XDR functions 227 * First, the server side XDR functions
228 */ 228 */
229int 229int
230nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 230nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
231{ 231{
232 u32 exclusive; 232 u32 exclusive;
233 233
@@ -244,7 +244,7 @@ nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
244} 244}
245 245
246int 246int
247nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 247nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
248{ 248{
249 if (!(p = nlm4_encode_testres(p, resp))) 249 if (!(p = nlm4_encode_testres(p, resp)))
250 return 0; 250 return 0;
@@ -252,7 +252,7 @@ nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
252} 252}
253 253
254int 254int
255nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 255nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
256{ 256{
257 u32 exclusive; 257 u32 exclusive;
258 258
@@ -272,7 +272,7 @@ nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
272} 272}
273 273
274int 274int
275nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 275nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
276{ 276{
277 u32 exclusive; 277 u32 exclusive;
278 278
@@ -288,7 +288,7 @@ nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
288} 288}
289 289
290int 290int
291nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 291nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
292{ 292{
293 if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 293 if (!(p = nlm4_decode_cookie(p, &argp->cookie))
294 || !(p = nlm4_decode_lock(p, &argp->lock))) 294 || !(p = nlm4_decode_lock(p, &argp->lock)))
@@ -298,7 +298,7 @@ nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
298} 298}
299 299
300int 300int
301nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) 301nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
302{ 302{
303 struct nlm_lock *lock = &argp->lock; 303 struct nlm_lock *lock = &argp->lock;
304 304
@@ -319,7 +319,7 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
319} 319}
320 320
321int 321int
322nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 322nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
323{ 323{
324 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 324 if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
325 return 0; 325 return 0;
@@ -329,7 +329,7 @@ nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
329} 329}
330 330
331int 331int
332nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 332nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
333{ 333{
334 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 334 if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
335 return 0; 335 return 0;
@@ -338,7 +338,7 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
338} 338}
339 339
340int 340int
341nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp) 341nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp)
342{ 342{
343 struct nlm_lock *lock = &argp->lock; 343 struct nlm_lock *lock = &argp->lock;
344 344
@@ -350,7 +350,7 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp)
350} 350}
351 351
352int 352int
353nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) 353nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
354{ 354{
355 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 355 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
356 return 0; 356 return 0;
@@ -363,7 +363,7 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
363} 363}
364 364
365int 365int
366nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp) 366nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
367{ 367{
368 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 368 if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
369 return 0; 369 return 0;
@@ -372,13 +372,13 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
372} 372}
373 373
374int 374int
375nlm4svc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) 375nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
376{ 376{
377 return xdr_argsize_check(rqstp, p); 377 return xdr_argsize_check(rqstp, p);
378} 378}
379 379
380int 380int
381nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy) 381nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
382{ 382{
383 return xdr_ressize_check(rqstp, p); 383 return xdr_ressize_check(rqstp, p);
384} 384}
@@ -388,14 +388,14 @@ nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
388 */ 388 */
389#ifdef NLMCLNT_SUPPORT_SHARES 389#ifdef NLMCLNT_SUPPORT_SHARES
390static int 390static int
391nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr) 391nlm4clt_decode_void(struct rpc_rqst *req, __be32 *p, void *ptr)
392{ 392{
393 return 0; 393 return 0;
394} 394}
395#endif 395#endif
396 396
397static int 397static int
398nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 398nlm4clt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
399{ 399{
400 struct nlm_lock *lock = &argp->lock; 400 struct nlm_lock *lock = &argp->lock;
401 401
@@ -409,7 +409,7 @@ nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
409} 409}
410 410
411static int 411static int
412nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 412nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
413{ 413{
414 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 414 if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
415 return -EIO; 415 return -EIO;
@@ -444,7 +444,7 @@ nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
444 444
445 445
446static int 446static int
447nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 447nlm4clt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
448{ 448{
449 struct nlm_lock *lock = &argp->lock; 449 struct nlm_lock *lock = &argp->lock;
450 450
@@ -461,7 +461,7 @@ nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
461} 461}
462 462
463static int 463static int
464nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 464nlm4clt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
465{ 465{
466 struct nlm_lock *lock = &argp->lock; 466 struct nlm_lock *lock = &argp->lock;
467 467
@@ -476,7 +476,7 @@ nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
476} 476}
477 477
478static int 478static int
479nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp) 479nlm4clt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp)
480{ 480{
481 struct nlm_lock *lock = &argp->lock; 481 struct nlm_lock *lock = &argp->lock;
482 482
@@ -489,7 +489,7 @@ nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
489} 489}
490 490
491static int 491static int
492nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 492nlm4clt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
493{ 493{
494 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 494 if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
495 return -EIO; 495 return -EIO;
@@ -499,7 +499,7 @@ nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
499} 499}
500 500
501static int 501static int
502nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 502nlm4clt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
503{ 503{
504 if (!(p = nlm4_encode_testres(p, resp))) 504 if (!(p = nlm4_encode_testres(p, resp)))
505 return -EIO; 505 return -EIO;
@@ -508,7 +508,7 @@ nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
508} 508}
509 509
510static int 510static int
511nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) 511nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
512{ 512{
513 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 513 if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
514 return -EIO; 514 return -EIO;