aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/clntlock.c4
-rw-r--r--fs/lockd/clntproc.c6
-rw-r--r--fs/lockd/host.c81
-rw-r--r--include/linux/lockd/lockd.h1
4 files changed, 78 insertions, 14 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 25509eb28fd7..8d4ea8351e3d 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(nlmclnt_init);
79 */ 79 */
80void nlmclnt_done(struct nlm_host *host) 80void nlmclnt_done(struct nlm_host *host)
81{ 81{
82 nlm_release_host(host); 82 nlmclnt_release_host(host);
83 lockd_down(); 83 lockd_down();
84} 84}
85EXPORT_SYMBOL_GPL(nlmclnt_done); 85EXPORT_SYMBOL_GPL(nlmclnt_done);
@@ -273,7 +273,7 @@ restart:
273 spin_unlock(&nlm_blocked_lock); 273 spin_unlock(&nlm_blocked_lock);
274 274
275 /* Release host handle after use */ 275 /* Release host handle after use */
276 nlm_release_host(host); 276 nlmclnt_release_host(host);
277 lockd_down(); 277 lockd_down();
278 return 0; 278 return 0;
279} 279}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index fbc6617f76c4..adb45ec9038c 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -58,7 +58,7 @@ static void nlm_put_lockowner(struct nlm_lockowner *lockowner)
58 return; 58 return;
59 list_del(&lockowner->list); 59 list_del(&lockowner->list);
60 spin_unlock(&lockowner->host->h_lock); 60 spin_unlock(&lockowner->host->h_lock);
61 nlm_release_host(lockowner->host); 61 nlmclnt_release_host(lockowner->host);
62 kfree(lockowner); 62 kfree(lockowner);
63} 63}
64 64
@@ -207,7 +207,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
207 printk("nlm_alloc_call: failed, waiting for memory\n"); 207 printk("nlm_alloc_call: failed, waiting for memory\n");
208 schedule_timeout_interruptible(5*HZ); 208 schedule_timeout_interruptible(5*HZ);
209 } 209 }
210 nlm_release_host(host); 210 nlmclnt_release_host(host);
211 return NULL; 211 return NULL;
212} 212}
213 213
@@ -215,7 +215,7 @@ void nlmclnt_release_call(struct nlm_rqst *call)
215{ 215{
216 if (!atomic_dec_and_test(&call->a_count)) 216 if (!atomic_dec_and_test(&call->a_count))
217 return; 217 return;
218 nlm_release_host(call->a_host); 218 nlmclnt_release_host(call->a_host);
219 nlmclnt_release_lockargs(call); 219 nlmclnt_release_lockargs(call);
220 kfree(call); 220 kfree(call);
221} 221}
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index e58e1426d161..c6942fb4bd0d 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -26,6 +26,7 @@
26#define NLM_HOST_COLLECT (120 * HZ) 26#define NLM_HOST_COLLECT (120 * HZ)
27 27
28static struct hlist_head nlm_hosts[NLM_HOST_NRHASH]; 28static struct hlist_head nlm_hosts[NLM_HOST_NRHASH];
29static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH];
29 30
30#define for_each_host(host, pos, chain, table) \ 31#define for_each_host(host, pos, chain, table) \
31 for ((chain) = (table); \ 32 for ((chain) = (table); \
@@ -288,12 +289,76 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
288 .hostname_len = strlen(hostname), 289 .hostname_len = strlen(hostname),
289 .noresvport = noresvport, 290 .noresvport = noresvport,
290 }; 291 };
292 struct hlist_head *chain;
293 struct hlist_node *pos;
294 struct nlm_host *host;
295 struct nsm_handle *nsm = NULL;
291 296
292 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, 297 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
293 (hostname ? hostname : "<none>"), version, 298 (hostname ? hostname : "<none>"), version,
294 (protocol == IPPROTO_UDP ? "udp" : "tcp")); 299 (protocol == IPPROTO_UDP ? "udp" : "tcp"));
295 300
296 return nlm_lookup_host(&ni); 301 mutex_lock(&nlm_host_mutex);
302
303 chain = &nlm_client_hosts[nlm_hash_address(sap)];
304 hlist_for_each_entry(host, pos, chain, h_hash) {
305 if (!rpc_cmp_addr(nlm_addr(host), sap))
306 continue;
307
308 /* Same address. Share an NSM handle if we already have one */
309 if (nsm == NULL)
310 nsm = host->h_nsmhandle;
311
312 if (host->h_proto != protocol)
313 continue;
314 if (host->h_version != version)
315 continue;
316
317 nlm_get_host(host);
318 dprintk("lockd: %s found host %s (%s)\n", __func__,
319 host->h_name, host->h_addrbuf);
320 goto out;
321 }
322
323 host = nlm_alloc_host(&ni, nsm);
324 if (unlikely(host == NULL))
325 goto out;
326
327 hlist_add_head(&host->h_hash, chain);
328 nrhosts++;
329
330 dprintk("lockd: %s created host %s (%s)\n", __func__,
331 host->h_name, host->h_addrbuf);
332
333out:
334 mutex_unlock(&nlm_host_mutex);
335 return host;
336}
337
338/**
339 * nlmclnt_release_host - release client nlm_host
340 * @host: nlm_host to release
341 *
342 */
343void nlmclnt_release_host(struct nlm_host *host)
344{
345 if (host == NULL)
346 return;
347
348 dprintk("lockd: release client host %s\n", host->h_name);
349
350 BUG_ON(atomic_read(&host->h_count) < 0);
351 BUG_ON(host->h_server);
352
353 if (atomic_dec_and_test(&host->h_count)) {
354 BUG_ON(!list_empty(&host->h_lockowners));
355 BUG_ON(!list_empty(&host->h_granted));
356 BUG_ON(!list_empty(&host->h_reclaim));
357
358 mutex_lock(&nlm_host_mutex);
359 nlm_destroy_host_locked(host);
360 mutex_unlock(&nlm_host_mutex);
361 }
297} 362}
298 363
299/** 364/**
@@ -515,16 +580,14 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
515 * To avoid processing a host several times, we match the nsmstate. 580 * To avoid processing a host several times, we match the nsmstate.
516 */ 581 */
517 while ((host = next_host_state(nlm_hosts, nsm, info)) != NULL) { 582 while ((host = next_host_state(nlm_hosts, nsm, info)) != NULL) {
518 if (host->h_server) { 583 nlmsvc_free_host_resources(host);
519 /* We're server for this guy, just ditch
520 * all the locks he held. */
521 nlmsvc_free_host_resources(host);
522 } else {
523 /* He's the server, initiate lock recovery. */
524 nlmclnt_recovery(host);
525 }
526 nlm_release_host(host); 584 nlm_release_host(host);
527 } 585 }
586 while ((host = next_host_state(nlm_client_hosts, nsm, info)) != NULL) {
587 nlmclnt_recovery(host);
588 nlmclnt_release_host(host);
589 }
590
528 nsm_release(nsm); 591 nsm_release(nsm);
529} 592}
530 593
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index a32ba62455af..6c2a0e2f298e 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -223,6 +223,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
223 const u32 version, 223 const u32 version,
224 const char *hostname, 224 const char *hostname,
225 int noresvport); 225 int noresvport);
226void nlmclnt_release_host(struct nlm_host *);
226struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, 227struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
227 const char *hostname, 228 const char *hostname,
228 const size_t hostname_len); 229 const size_t hostname_len);