0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/types.h>
0013 #include <linux/slab.h>
0014 #include <linux/in.h>
0015 #include <linux/in6.h>
0016 #include <linux/sunrpc/clnt.h>
0017 #include <linux/sunrpc/addr.h>
0018 #include <linux/sunrpc/svc.h>
0019 #include <linux/lockd/lockd.h>
0020 #include <linux/mutex.h>
0021
0022 #include <linux/sunrpc/svc_xprt.h>
0023
0024 #include <net/ipv6.h>
0025
0026 #include "netns.h"
0027
0028 #define NLMDBG_FACILITY NLMDBG_HOSTCACHE
0029 #define NLM_HOST_NRHASH 32
0030 #define NLM_HOST_REBIND (60 * HZ)
0031 #define NLM_HOST_EXPIRE (300 * HZ)
0032 #define NLM_HOST_COLLECT (120 * HZ)
0033
0034 static struct hlist_head nlm_server_hosts[NLM_HOST_NRHASH];
0035 static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH];
0036
0037 #define for_each_host(host, chain, table) \
0038 for ((chain) = (table); \
0039 (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
0040 hlist_for_each_entry((host), (chain), h_hash)
0041
0042 #define for_each_host_safe(host, next, chain, table) \
0043 for ((chain) = (table); \
0044 (chain) < (table) + NLM_HOST_NRHASH; ++(chain)) \
0045 hlist_for_each_entry_safe((host), (next), \
0046 (chain), h_hash)
0047
0048 static unsigned long nrhosts;
0049 static DEFINE_MUTEX(nlm_host_mutex);
0050
0051 static void nlm_gc_hosts(struct net *net);
0052
0053 struct nlm_lookup_host_info {
0054 const int server;
0055 const struct sockaddr *sap;
0056 const size_t salen;
0057 const unsigned short protocol;
0058 const u32 version;
0059 const char *hostname;
0060 const size_t hostname_len;
0061 const int noresvport;
0062 struct net *net;
0063 const struct cred *cred;
0064 };
0065
0066
0067
0068
0069 static unsigned int __nlm_hash32(const __be32 n)
0070 {
0071 unsigned int hash = (__force u32)n ^ ((__force u32)n >> 16);
0072 return hash ^ (hash >> 8);
0073 }
0074
0075 static unsigned int __nlm_hash_addr4(const struct sockaddr *sap)
0076 {
0077 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
0078 return __nlm_hash32(sin->sin_addr.s_addr);
0079 }
0080
0081 static unsigned int __nlm_hash_addr6(const struct sockaddr *sap)
0082 {
0083 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
0084 const struct in6_addr addr = sin6->sin6_addr;
0085 return __nlm_hash32(addr.s6_addr32[0]) ^
0086 __nlm_hash32(addr.s6_addr32[1]) ^
0087 __nlm_hash32(addr.s6_addr32[2]) ^
0088 __nlm_hash32(addr.s6_addr32[3]);
0089 }
0090
0091 static unsigned int nlm_hash_address(const struct sockaddr *sap)
0092 {
0093 unsigned int hash;
0094
0095 switch (sap->sa_family) {
0096 case AF_INET:
0097 hash = __nlm_hash_addr4(sap);
0098 break;
0099 case AF_INET6:
0100 hash = __nlm_hash_addr6(sap);
0101 break;
0102 default:
0103 hash = 0;
0104 }
0105 return hash & (NLM_HOST_NRHASH - 1);
0106 }
0107
0108
0109
0110
0111 static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
0112 struct nsm_handle *nsm)
0113 {
0114 struct nlm_host *host = NULL;
0115 unsigned long now = jiffies;
0116
0117 if (nsm != NULL)
0118 refcount_inc(&nsm->sm_count);
0119 else {
0120 host = NULL;
0121 nsm = nsm_get_handle(ni->net, ni->sap, ni->salen,
0122 ni->hostname, ni->hostname_len);
0123 if (unlikely(nsm == NULL)) {
0124 dprintk("lockd: %s failed; no nsm handle\n",
0125 __func__);
0126 goto out;
0127 }
0128 }
0129
0130 host = kmalloc(sizeof(*host), GFP_KERNEL);
0131 if (unlikely(host == NULL)) {
0132 dprintk("lockd: %s failed; no memory\n", __func__);
0133 nsm_release(nsm);
0134 goto out;
0135 }
0136
0137 memcpy(nlm_addr(host), ni->sap, ni->salen);
0138 host->h_addrlen = ni->salen;
0139 rpc_set_port(nlm_addr(host), 0);
0140 host->h_srcaddrlen = 0;
0141
0142 host->h_rpcclnt = NULL;
0143 host->h_name = nsm->sm_name;
0144 host->h_version = ni->version;
0145 host->h_proto = ni->protocol;
0146 host->h_reclaiming = 0;
0147 host->h_server = ni->server;
0148 host->h_noresvport = ni->noresvport;
0149 host->h_inuse = 0;
0150 init_waitqueue_head(&host->h_gracewait);
0151 init_rwsem(&host->h_rwsem);
0152 host->h_state = 0;
0153 host->h_nsmstate = 0;
0154 host->h_pidcount = 0;
0155 refcount_set(&host->h_count, 1);
0156 mutex_init(&host->h_mutex);
0157 host->h_nextrebind = now + NLM_HOST_REBIND;
0158 host->h_expires = now + NLM_HOST_EXPIRE;
0159 INIT_LIST_HEAD(&host->h_lockowners);
0160 spin_lock_init(&host->h_lock);
0161 INIT_LIST_HEAD(&host->h_granted);
0162 INIT_LIST_HEAD(&host->h_reclaim);
0163 host->h_nsmhandle = nsm;
0164 host->h_addrbuf = nsm->sm_addrbuf;
0165 host->net = ni->net;
0166 host->h_cred = get_cred(ni->cred);
0167 strlcpy(host->nodename, utsname()->nodename, sizeof(host->nodename));
0168
0169 out:
0170 return host;
0171 }
0172
0173
0174
0175
0176
0177
0178 static void nlm_destroy_host_locked(struct nlm_host *host)
0179 {
0180 struct rpc_clnt *clnt;
0181 struct lockd_net *ln = net_generic(host->net, lockd_net_id);
0182
0183 dprintk("lockd: destroy host %s\n", host->h_name);
0184
0185 hlist_del_init(&host->h_hash);
0186
0187 nsm_unmonitor(host);
0188 nsm_release(host->h_nsmhandle);
0189
0190 clnt = host->h_rpcclnt;
0191 if (clnt != NULL)
0192 rpc_shutdown_client(clnt);
0193 put_cred(host->h_cred);
0194 kfree(host);
0195
0196 ln->nrhosts--;
0197 nrhosts--;
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
0217 const size_t salen,
0218 const unsigned short protocol,
0219 const u32 version,
0220 const char *hostname,
0221 int noresvport,
0222 struct net *net,
0223 const struct cred *cred)
0224 {
0225 struct nlm_lookup_host_info ni = {
0226 .server = 0,
0227 .sap = sap,
0228 .salen = salen,
0229 .protocol = protocol,
0230 .version = version,
0231 .hostname = hostname,
0232 .hostname_len = strlen(hostname),
0233 .noresvport = noresvport,
0234 .net = net,
0235 .cred = cred,
0236 };
0237 struct hlist_head *chain;
0238 struct nlm_host *host;
0239 struct nsm_handle *nsm = NULL;
0240 struct lockd_net *ln = net_generic(net, lockd_net_id);
0241
0242 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
0243 (hostname ? hostname : "<none>"), version,
0244 (protocol == IPPROTO_UDP ? "udp" : "tcp"));
0245
0246 mutex_lock(&nlm_host_mutex);
0247
0248 chain = &nlm_client_hosts[nlm_hash_address(sap)];
0249 hlist_for_each_entry(host, chain, h_hash) {
0250 if (host->net != net)
0251 continue;
0252 if (!rpc_cmp_addr(nlm_addr(host), sap))
0253 continue;
0254
0255
0256 if (nsm == NULL)
0257 nsm = host->h_nsmhandle;
0258
0259 if (host->h_proto != protocol)
0260 continue;
0261 if (host->h_version != version)
0262 continue;
0263
0264 nlm_get_host(host);
0265 dprintk("lockd: %s found host %s (%s)\n", __func__,
0266 host->h_name, host->h_addrbuf);
0267 goto out;
0268 }
0269
0270 host = nlm_alloc_host(&ni, nsm);
0271 if (unlikely(host == NULL))
0272 goto out;
0273
0274 hlist_add_head(&host->h_hash, chain);
0275 ln->nrhosts++;
0276 nrhosts++;
0277
0278 dprintk("lockd: %s created host %s (%s)\n", __func__,
0279 host->h_name, host->h_addrbuf);
0280
0281 out:
0282 mutex_unlock(&nlm_host_mutex);
0283 return host;
0284 }
0285
0286
0287
0288
0289
0290
0291 void nlmclnt_release_host(struct nlm_host *host)
0292 {
0293 if (host == NULL)
0294 return;
0295
0296 dprintk("lockd: release client host %s\n", host->h_name);
0297
0298 WARN_ON_ONCE(host->h_server);
0299
0300 if (refcount_dec_and_mutex_lock(&host->h_count, &nlm_host_mutex)) {
0301 WARN_ON_ONCE(!list_empty(&host->h_lockowners));
0302 WARN_ON_ONCE(!list_empty(&host->h_granted));
0303 WARN_ON_ONCE(!list_empty(&host->h_reclaim));
0304
0305 nlm_destroy_host_locked(host);
0306 mutex_unlock(&nlm_host_mutex);
0307 }
0308 }
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
0329 const char *hostname,
0330 const size_t hostname_len)
0331 {
0332 struct hlist_head *chain;
0333 struct nlm_host *host = NULL;
0334 struct nsm_handle *nsm = NULL;
0335 struct sockaddr *src_sap = svc_daddr(rqstp);
0336 size_t src_len = rqstp->rq_daddrlen;
0337 struct net *net = SVC_NET(rqstp);
0338 struct nlm_lookup_host_info ni = {
0339 .server = 1,
0340 .sap = svc_addr(rqstp),
0341 .salen = rqstp->rq_addrlen,
0342 .protocol = rqstp->rq_prot,
0343 .version = rqstp->rq_vers,
0344 .hostname = hostname,
0345 .hostname_len = hostname_len,
0346 .net = net,
0347 };
0348 struct lockd_net *ln = net_generic(net, lockd_net_id);
0349
0350 dprintk("lockd: %s(host='%.*s', vers=%u, proto=%s)\n", __func__,
0351 (int)hostname_len, hostname, rqstp->rq_vers,
0352 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));
0353
0354 mutex_lock(&nlm_host_mutex);
0355
0356 if (time_after_eq(jiffies, ln->next_gc))
0357 nlm_gc_hosts(net);
0358
0359 chain = &nlm_server_hosts[nlm_hash_address(ni.sap)];
0360 hlist_for_each_entry(host, chain, h_hash) {
0361 if (host->net != net)
0362 continue;
0363 if (!rpc_cmp_addr(nlm_addr(host), ni.sap))
0364 continue;
0365
0366
0367 if (nsm == NULL)
0368 nsm = host->h_nsmhandle;
0369
0370 if (host->h_proto != ni.protocol)
0371 continue;
0372 if (host->h_version != ni.version)
0373 continue;
0374 if (!rpc_cmp_addr(nlm_srcaddr(host), src_sap))
0375 continue;
0376
0377
0378 hlist_del(&host->h_hash);
0379 hlist_add_head(&host->h_hash, chain);
0380
0381 nlm_get_host(host);
0382 dprintk("lockd: %s found host %s (%s)\n",
0383 __func__, host->h_name, host->h_addrbuf);
0384 goto out;
0385 }
0386
0387 host = nlm_alloc_host(&ni, nsm);
0388 if (unlikely(host == NULL))
0389 goto out;
0390
0391 memcpy(nlm_srcaddr(host), src_sap, src_len);
0392 host->h_srcaddrlen = src_len;
0393 hlist_add_head(&host->h_hash, chain);
0394 ln->nrhosts++;
0395 nrhosts++;
0396
0397 refcount_inc(&host->h_count);
0398
0399 dprintk("lockd: %s created host %s (%s)\n",
0400 __func__, host->h_name, host->h_addrbuf);
0401
0402 out:
0403 mutex_unlock(&nlm_host_mutex);
0404 return host;
0405 }
0406
0407
0408
0409
0410
0411
0412
0413 void nlmsvc_release_host(struct nlm_host *host)
0414 {
0415 if (host == NULL)
0416 return;
0417
0418 dprintk("lockd: release server host %s\n", host->h_name);
0419
0420 WARN_ON_ONCE(!host->h_server);
0421 refcount_dec(&host->h_count);
0422 }
0423
0424
0425
0426
0427 struct rpc_clnt *
0428 nlm_bind_host(struct nlm_host *host)
0429 {
0430 struct rpc_clnt *clnt;
0431
0432 dprintk("lockd: nlm_bind_host %s (%s)\n",
0433 host->h_name, host->h_addrbuf);
0434
0435
0436 mutex_lock(&host->h_mutex);
0437
0438
0439
0440
0441 if ((clnt = host->h_rpcclnt) != NULL) {
0442 nlm_rebind_host(host);
0443 } else {
0444 unsigned long increment = nlmsvc_timeout;
0445 struct rpc_timeout timeparms = {
0446 .to_initval = increment,
0447 .to_increment = increment,
0448 .to_maxval = increment * 6UL,
0449 .to_retries = 5U,
0450 };
0451 struct rpc_create_args args = {
0452 .net = host->net,
0453 .protocol = host->h_proto,
0454 .address = nlm_addr(host),
0455 .addrsize = host->h_addrlen,
0456 .timeout = &timeparms,
0457 .servername = host->h_name,
0458 .program = &nlm_program,
0459 .version = host->h_version,
0460 .authflavor = RPC_AUTH_UNIX,
0461 .flags = (RPC_CLNT_CREATE_NOPING |
0462 RPC_CLNT_CREATE_AUTOBIND |
0463 RPC_CLNT_CREATE_REUSEPORT),
0464 .cred = host->h_cred,
0465 };
0466
0467
0468
0469
0470
0471
0472 if (!host->h_server)
0473 args.flags |= RPC_CLNT_CREATE_HARDRTRY;
0474 if (host->h_noresvport)
0475 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
0476 if (host->h_srcaddrlen)
0477 args.saddress = nlm_srcaddr(host);
0478
0479 clnt = rpc_create(&args);
0480 if (!IS_ERR(clnt))
0481 host->h_rpcclnt = clnt;
0482 else {
0483 printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
0484 clnt = NULL;
0485 }
0486 }
0487
0488 mutex_unlock(&host->h_mutex);
0489 return clnt;
0490 }
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500 void
0501 nlm_rebind_host(struct nlm_host *host)
0502 {
0503 if (host->h_proto != IPPROTO_UDP)
0504 return;
0505
0506 if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) {
0507 rpc_force_rebind(host->h_rpcclnt);
0508 host->h_nextrebind = jiffies + NLM_HOST_REBIND;
0509 }
0510 }
0511
0512
0513
0514
0515 struct nlm_host * nlm_get_host(struct nlm_host *host)
0516 {
0517 if (host) {
0518 dprintk("lockd: get host %s\n", host->h_name);
0519 refcount_inc(&host->h_count);
0520 host->h_expires = jiffies + NLM_HOST_EXPIRE;
0521 }
0522 return host;
0523 }
0524
0525 static struct nlm_host *next_host_state(struct hlist_head *cache,
0526 struct nsm_handle *nsm,
0527 const struct nlm_reboot *info)
0528 {
0529 struct nlm_host *host;
0530 struct hlist_head *chain;
0531
0532 mutex_lock(&nlm_host_mutex);
0533 for_each_host(host, chain, cache) {
0534 if (host->h_nsmhandle == nsm
0535 && host->h_nsmstate != info->state) {
0536 host->h_nsmstate = info->state;
0537 host->h_state++;
0538
0539 nlm_get_host(host);
0540 mutex_unlock(&nlm_host_mutex);
0541 return host;
0542 }
0543 }
0544
0545 mutex_unlock(&nlm_host_mutex);
0546 return NULL;
0547 }
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557 void nlm_host_rebooted(const struct net *net, const struct nlm_reboot *info)
0558 {
0559 struct nsm_handle *nsm;
0560 struct nlm_host *host;
0561
0562 nsm = nsm_reboot_lookup(net, info);
0563 if (unlikely(nsm == NULL))
0564 return;
0565
0566
0567
0568
0569
0570
0571 while ((host = next_host_state(nlm_server_hosts, nsm, info)) != NULL) {
0572 nlmsvc_free_host_resources(host);
0573 nlmsvc_release_host(host);
0574 }
0575 while ((host = next_host_state(nlm_client_hosts, nsm, info)) != NULL) {
0576 nlmclnt_recovery(host);
0577 nlmclnt_release_host(host);
0578 }
0579
0580 nsm_release(nsm);
0581 }
0582
0583 static void nlm_complain_hosts(struct net *net)
0584 {
0585 struct hlist_head *chain;
0586 struct nlm_host *host;
0587
0588 if (net) {
0589 struct lockd_net *ln = net_generic(net, lockd_net_id);
0590
0591 if (ln->nrhosts == 0)
0592 return;
0593 pr_warn("lockd: couldn't shutdown host module for net %x!\n",
0594 net->ns.inum);
0595 dprintk("lockd: %lu hosts left in net %x:\n", ln->nrhosts,
0596 net->ns.inum);
0597 } else {
0598 if (nrhosts == 0)
0599 return;
0600 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
0601 dprintk("lockd: %lu hosts left:\n", nrhosts);
0602 }
0603
0604 for_each_host(host, chain, nlm_server_hosts) {
0605 if (net && host->net != net)
0606 continue;
0607 dprintk(" %s (cnt %d use %d exp %ld net %x)\n",
0608 host->h_name, refcount_read(&host->h_count),
0609 host->h_inuse, host->h_expires, host->net->ns.inum);
0610 }
0611 }
0612
0613 void
0614 nlm_shutdown_hosts_net(struct net *net)
0615 {
0616 struct hlist_head *chain;
0617 struct nlm_host *host;
0618
0619 mutex_lock(&nlm_host_mutex);
0620
0621
0622 dprintk("lockd: nuking all hosts in net %x...\n",
0623 net ? net->ns.inum : 0);
0624 for_each_host(host, chain, nlm_server_hosts) {
0625 if (net && host->net != net)
0626 continue;
0627 host->h_expires = jiffies - 1;
0628 if (host->h_rpcclnt) {
0629 rpc_shutdown_client(host->h_rpcclnt);
0630 host->h_rpcclnt = NULL;
0631 }
0632 }
0633
0634
0635 nlm_gc_hosts(net);
0636 nlm_complain_hosts(net);
0637 mutex_unlock(&nlm_host_mutex);
0638 }
0639
0640
0641
0642
0643
0644 void
0645 nlm_shutdown_hosts(void)
0646 {
0647 dprintk("lockd: shutting down host module\n");
0648 nlm_shutdown_hosts_net(NULL);
0649 }
0650
0651
0652
0653
0654
0655
0656 static void
0657 nlm_gc_hosts(struct net *net)
0658 {
0659 struct hlist_head *chain;
0660 struct hlist_node *next;
0661 struct nlm_host *host;
0662
0663 dprintk("lockd: host garbage collection for net %x\n",
0664 net ? net->ns.inum : 0);
0665 for_each_host(host, chain, nlm_server_hosts) {
0666 if (net && host->net != net)
0667 continue;
0668 host->h_inuse = 0;
0669 }
0670
0671
0672 nlmsvc_mark_resources(net);
0673
0674 for_each_host_safe(host, next, chain, nlm_server_hosts) {
0675 if (net && host->net != net)
0676 continue;
0677 if (host->h_inuse || time_before(jiffies, host->h_expires)) {
0678 dprintk("nlm_gc_hosts skipping %s "
0679 "(cnt %d use %d exp %ld net %x)\n",
0680 host->h_name, refcount_read(&host->h_count),
0681 host->h_inuse, host->h_expires,
0682 host->net->ns.inum);
0683 continue;
0684 }
0685 if (refcount_dec_if_one(&host->h_count))
0686 nlm_destroy_host_locked(host);
0687 }
0688
0689 if (net) {
0690 struct lockd_net *ln = net_generic(net, lockd_net_id);
0691
0692 ln->next_gc = jiffies + NLM_HOST_COLLECT;
0693 }
0694 }