11 #include <linux/types.h>
12 #include <linux/slab.h>
14 #include <linux/in6.h>
26 #define NLMDBG_FACILITY NLMDBG_HOSTCACHE
27 #define NLM_HOST_NRHASH 32
28 #define NLM_HOST_REBIND (60 * HZ)
29 #define NLM_HOST_EXPIRE (300 * HZ)
30 #define NLM_HOST_COLLECT (120 * HZ)
35 #define for_each_host(host, pos, chain, table) \
36 for ((chain) = (table); \
37 (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
38 hlist_for_each_entry((host), (pos), (chain), h_hash)
40 #define for_each_host_safe(host, pos, next, chain, table) \
41 for ((chain) = (table); \
42 (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
43 hlist_for_each_entry_safe((host), (pos), (next), \
46 static unsigned long nrhosts;
49 static void nlm_gc_hosts(
struct net *
net);
66 static unsigned int __nlm_hash32(
const __be32 n)
69 return hash ^ (hash >> 8);
72 static unsigned int __nlm_hash_addr4(
const struct sockaddr *sap)
75 return __nlm_hash32(sin->
sin_addr.s_addr);
78 static unsigned int __nlm_hash_addr6(
const struct sockaddr *sap)
82 return __nlm_hash32(addr.s6_addr32[0]) ^
83 __nlm_hash32(addr.s6_addr32[1]) ^
84 __nlm_hash32(addr.s6_addr32[2]) ^
85 __nlm_hash32(addr.s6_addr32[3]);
88 static unsigned int nlm_hash_address(
const struct sockaddr *sap)
94 hash = __nlm_hash_addr4(sap);
97 hash = __nlm_hash_addr6(sap);
109 struct nsm_handle *nsm)
121 dprintk(
"lockd: %s failed; no nsm handle\n",
129 dprintk(
"lockd: %s failed; no memory\n", __func__);
135 host->h_addrlen = ni->
salen;
136 rpc_set_port(nlm_addr(host), 0);
137 host->h_srcaddrlen = 0;
139 host->h_rpcclnt =
NULL;
140 host->h_name = nsm->sm_name;
143 host->h_reclaiming = 0;
144 host->h_server = ni->
server;
150 host->h_nsmstate = 0;
151 host->h_pidcount = 0;
156 INIT_LIST_HEAD(&host->h_lockowners);
158 INIT_LIST_HEAD(&host->h_granted);
159 INIT_LIST_HEAD(&host->h_reclaim);
160 host->h_nsmhandle = nsm;
161 host->h_addrbuf = nsm->sm_addrbuf;
173 static void nlm_destroy_host_locked(
struct nlm_host *host)
178 dprintk(
"lockd: destroy host %s\n", host->h_name);
180 BUG_ON(!list_empty(&host->h_lockowners));
183 hlist_del_init(&host->h_hash);
188 clnt = host->h_rpcclnt;
215 const char *hostname,
226 .hostname_len =
strlen(hostname),
232 struct nlm_host *host;
233 struct nsm_handle *nsm =
NULL;
236 dprintk(
"lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
237 (hostname ? hostname :
"<none>"), version,
242 chain = &nlm_client_hosts[nlm_hash_address(sap)];
244 if (host->net != net)
246 if (!rpc_cmp_addr(nlm_addr(host), sap))
251 nsm = host->h_nsmhandle;
253 if (host->h_proto != protocol)
255 if (host->h_version != version)
259 dprintk(
"lockd: %s found host %s (%s)\n", __func__,
260 host->h_name, host->h_addrbuf);
264 host = nlm_alloc_host(&ni, nsm);
268 hlist_add_head(&host->h_hash, chain);
272 dprintk(
"lockd: %s created host %s (%s)\n", __func__,
273 host->h_name, host->h_addrbuf);
290 dprintk(
"lockd: release client host %s\n", host->h_name);
296 BUG_ON(!list_empty(&host->h_lockowners));
297 BUG_ON(!list_empty(&host->h_granted));
298 BUG_ON(!list_empty(&host->h_reclaim));
301 nlm_destroy_host_locked(host);
325 const char *hostname,
330 struct nlm_host *host =
NULL;
331 struct nsm_handle *nsm =
NULL;
332 struct sockaddr *src_sap = svc_daddr(rqstp);
337 .sap = svc_addr(rqstp),
347 dprintk(
"lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
348 (
int)hostname_len, hostname, rqstp->
rq_vers,
356 chain = &nlm_server_hosts[nlm_hash_address(ni.
sap)];
358 if (host->net != net)
360 if (!rpc_cmp_addr(nlm_addr(host), ni.
sap))
365 nsm = host->h_nsmhandle;
369 if (host->h_version != ni.
version)
371 if (!rpc_cmp_addr(nlm_srcaddr(host), src_sap))
375 hlist_del(&host->h_hash);
376 hlist_add_head(&host->h_hash, chain);
379 dprintk(
"lockd: %s found host %s (%s)\n",
380 __func__, host->h_name, host->h_addrbuf);
384 host = nlm_alloc_host(&ni, nsm);
388 memcpy(nlm_srcaddr(host), src_sap, src_len);
389 host->h_srcaddrlen = src_len;
390 hlist_add_head(&host->h_hash, chain);
394 dprintk(
"lockd: %s created host %s (%s)\n",
395 __func__, host->h_name, host->h_addrbuf);
413 dprintk(
"lockd: release server host %s\n", host->h_name);
428 dprintk(
"lockd: nlm_bind_host %s (%s)\n",
429 host->h_name, host->h_addrbuf);
437 if ((clnt = host->h_rpcclnt) !=
NULL) {
441 dprintk(
"lockd: next rebind in %lu jiffies\n",
446 struct rpc_timeout timeparms = {
447 .to_initval = increment,
448 .to_increment = increment,
449 .to_maxval = increment * 6
UL,
452 struct rpc_create_args args = {
454 .protocol = host->h_proto,
455 .address = nlm_addr(host),
456 .addrsize = host->h_addrlen,
457 .timeout = &timeparms,
458 .servername = host->h_name,
460 .version = host->h_version,
461 .authflavor = RPC_AUTH_UNIX,
462 .flags = (RPC_CLNT_CREATE_NOPING |
463 RPC_CLNT_CREATE_AUTOBIND),
472 args.flags |= RPC_CLNT_CREATE_HARDRTRY;
473 if (host->h_noresvport)
474 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
475 if (host->h_srcaddrlen)
476 args.saddress = nlm_srcaddr(host);
480 host->h_rpcclnt = clnt;
482 printk(
"lockd: couldn't create RPC handle for %s\n", host->h_name);
497 dprintk(
"lockd: rebind host %s\n", host->h_name);
510 dprintk(
"lockd: get host %s\n", host->h_name);
518 struct nsm_handle *nsm,
521 struct nlm_host *host;
527 if (host->h_nsmhandle == nsm
528 && host->h_nsmstate != info->
state) {
529 host->h_nsmstate = info->
state;
551 struct nsm_handle *nsm;
552 struct nlm_host *host;
563 while ((host = next_host_state(nlm_server_hosts, nsm, info)) !=
NULL) {
567 while ((host = next_host_state(nlm_client_hosts, nsm, info)) !=
NULL) {
575 static void nlm_complain_hosts(
struct net *
net)
579 struct nlm_host *host;
596 if (net && host->net != net)
598 dprintk(
" %s (cnt %d use %d exp %ld net %p)\n",
600 host->h_inuse, host->h_expires, host->net);
609 struct nlm_host *host;
614 dprintk(
"lockd: nuking all hosts in net %p...\n", net);
616 if (net && host->net != net)
619 if (host->h_rpcclnt) {
621 host->h_rpcclnt =
NULL;
629 nlm_complain_hosts(net);
639 dprintk(
"lockd: shutting down host module\n");
649 nlm_gc_hosts(
struct net *net)
653 struct nlm_host *host;
655 dprintk(
"lockd: host garbage collection for net %p\n", net);
657 if (net && host->net != net)
666 if (net && host->net != net)
670 dprintk(
"nlm_gc_hosts skipping %s "
671 "(cnt %d use %d exp %ld net %p)\n",
673 host->h_inuse, host->h_expires, host->net);
676 nlm_destroy_host_locked(host);