1 /* 2 * linux/fs/lockd/host.c 3 * 4 * Management for NLM peer hosts. The nlm_host struct is shared 5 * between client and server implementation. The only reason to 6 * do so is to reduce code bloat. 7 * 8 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 9 */ 10 11 #include <linux/types.h> 12 #include <linux/slab.h> 13 #include <linux/in.h> 14 #include <linux/in6.h> 15 #include <linux/sunrpc/clnt.h> 16 #include <linux/sunrpc/svc.h> 17 #include <linux/lockd/lockd.h> 18 #include <linux/lockd/sm_inter.h> 19 #include <linux/mutex.h> 20 21 #include <net/ipv6.h> 22 23 #define NLMDBG_FACILITY NLMDBG_HOSTCACHE 24 #define NLM_HOST_NRHASH 32 25 #define NLM_HOST_REBIND (60 * HZ) 26 #define NLM_HOST_EXPIRE (300 * HZ) 27 #define NLM_HOST_COLLECT (120 * HZ) 28 29 static struct hlist_head nlm_hosts[NLM_HOST_NRHASH]; 30 static unsigned long next_gc; 31 static int nrhosts; 32 static DEFINE_MUTEX(nlm_host_mutex); 33 34 static void nlm_gc_hosts(void); 35 static struct nsm_handle *nsm_find(const struct sockaddr *sap, 36 const size_t salen, 37 const char *hostname, 38 const size_t hostname_len, 39 const int create); 40 41 struct nlm_lookup_host_info { 42 const int server; /* search for server|client */ 43 const struct sockaddr *sap; /* address to search for */ 44 const size_t salen; /* it's length */ 45 const unsigned short protocol; /* transport to search for*/ 46 const u32 version; /* NLM version to search for */ 47 const char *hostname; /* remote's hostname */ 48 const size_t hostname_len; /* it's length */ 49 const struct sockaddr *src_sap; /* our address (optional) */ 50 const size_t src_len; /* it's length */ 51 }; 52 53 /* 54 * Hash function must work well on big- and little-endian platforms 55 */ 56 static unsigned int __nlm_hash32(const __be32 n) 57 { 58 unsigned int hash = (__force u32)n ^ ((__force u32)n >> 16); 59 return hash ^ (hash >> 8); 60 } 61 62 static unsigned int __nlm_hash_addr4(const struct sockaddr *sap) 63 { 64 const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 65 return __nlm_hash32(sin->sin_addr.s_addr); 66 } 67 68 static unsigned int __nlm_hash_addr6(const struct sockaddr *sap) 69 { 70 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 71 const struct in6_addr addr = sin6->sin6_addr; 72 return __nlm_hash32(addr.s6_addr32[0]) ^ 73 __nlm_hash32(addr.s6_addr32[1]) ^ 74 __nlm_hash32(addr.s6_addr32[2]) ^ 75 __nlm_hash32(addr.s6_addr32[3]); 76 } 77 78 static unsigned int nlm_hash_address(const struct sockaddr *sap) 79 { 80 unsigned int hash; 81 82 switch (sap->sa_family) { 83 case AF_INET: 84 hash = __nlm_hash_addr4(sap); 85 break; 86 case AF_INET6: 87 hash = __nlm_hash_addr6(sap); 88 break; 89 default: 90 hash = 0; 91 } 92 return hash & (NLM_HOST_NRHASH - 1); 93 } 94 95 static void nlm_clear_port(struct sockaddr *sap) 96 { 97 switch (sap->sa_family) { 98 case AF_INET: 99 ((struct sockaddr_in *)sap)->sin_port = 0; 100 break; 101 case AF_INET6: 102 ((struct sockaddr_in6 *)sap)->sin6_port = 0; 103 break; 104 } 105 } 106 107 static void nlm_display_address(const struct sockaddr *sap, 108 char *buf, const size_t len) 109 { 110 const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 111 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 112 113 switch (sap->sa_family) { 114 case AF_UNSPEC: 115 snprintf(buf, len, "unspecified"); 116 break; 117 case AF_INET: 118 snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); 119 break; 120 case AF_INET6: 121 if (ipv6_addr_v4mapped(&sin6->sin6_addr)) 122 snprintf(buf, len, NIPQUAD_FMT, 123 NIPQUAD(sin6->sin6_addr.s6_addr32[3])); 124 else 125 snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr)); 126 break; 127 default: 128 snprintf(buf, len, "unsupported address family"); 129 break; 130 } 131 } 132 133 /* 134 * Common host lookup routine for server & client 135 */ 136 static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) 137 { 138 struct hlist_head *chain; 139 struct hlist_node *pos; 140 struct nlm_host *host; 141 struct nsm_handle *nsm = NULL; 142 143 mutex_lock(&nlm_host_mutex); 144 145 if (time_after_eq(jiffies, next_gc)) 146 nlm_gc_hosts(); 147 148 /* We may keep several nlm_host objects for a peer, because each 149 * nlm_host is identified by 150 * (address, protocol, version, server/client) 151 * We could probably simplify this a little by putting all those 152 * different NLM rpc_clients into one single nlm_host object. 153 * This would allow us to have one nlm_host per address. 154 */ 155 chain = &nlm_hosts[nlm_hash_address(ni->sap)]; 156 hlist_for_each_entry(host, pos, chain, h_hash) { 157 if (!nlm_cmp_addr(nlm_addr(host), ni->sap)) 158 continue; 159 160 /* See if we have an NSM handle for this client */ 161 if (!nsm) 162 nsm = host->h_nsmhandle; 163 164 if (host->h_proto != ni->protocol) 165 continue; 166 if (host->h_version != ni->version) 167 continue; 168 if (host->h_server != ni->server) 169 continue; 170 if (ni->server && 171 !nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap)) 172 continue; 173 174 /* Move to head of hash chain. */ 175 hlist_del(&host->h_hash); 176 hlist_add_head(&host->h_hash, chain); 177 178 nlm_get_host(host); 179 dprintk("lockd: nlm_lookup_host found host %s (%s)\n", 180 host->h_name, host->h_addrbuf); 181 goto out; 182 } 183 184 /* 185 * The host wasn't in our hash table. If we don't 186 * have an NSM handle for it yet, create one. 187 */ 188 if (nsm) 189 atomic_inc(&nsm->sm_count); 190 else { 191 host = NULL; 192 nsm = nsm_find(ni->sap, ni->salen, 193 ni->hostname, ni->hostname_len, 1); 194 if (!nsm) { 195 dprintk("lockd: nlm_lookup_host failed; " 196 "no nsm handle\n"); 197 goto out; 198 } 199 } 200 201 host = kzalloc(sizeof(*host), GFP_KERNEL); 202 if (!host) { 203 nsm_release(nsm); 204 dprintk("lockd: nlm_lookup_host failed; no memory\n"); 205 goto out; 206 } 207 host->h_name = nsm->sm_name; 208 memcpy(nlm_addr(host), ni->sap, ni->salen); 209 host->h_addrlen = ni->salen; 210 nlm_clear_port(nlm_addr(host)); 211 memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len); 212 host->h_version = ni->version; 213 host->h_proto = ni->protocol; 214 host->h_rpcclnt = NULL; 215 mutex_init(&host->h_mutex); 216 host->h_nextrebind = jiffies + NLM_HOST_REBIND; 217 host->h_expires = jiffies + NLM_HOST_EXPIRE; 218 atomic_set(&host->h_count, 1); 219 init_waitqueue_head(&host->h_gracewait); 220 init_rwsem(&host->h_rwsem); 221 host->h_state = 0; /* pseudo NSM state */ 222 host->h_nsmstate = 0; /* real NSM state */ 223 host->h_nsmhandle = nsm; 224 host->h_server = ni->server; 225 hlist_add_head(&host->h_hash, chain); 226 INIT_LIST_HEAD(&host->h_lockowners); 227 spin_lock_init(&host->h_lock); 228 INIT_LIST_HEAD(&host->h_granted); 229 INIT_LIST_HEAD(&host->h_reclaim); 230 231 nrhosts++; 232 233 nlm_display_address((struct sockaddr *)&host->h_addr, 234 host->h_addrbuf, sizeof(host->h_addrbuf)); 235 nlm_display_address((struct sockaddr *)&host->h_srcaddr, 236 host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf)); 237 238 dprintk("lockd: nlm_lookup_host created host %s\n", 239 host->h_name); 240 241 out: 242 mutex_unlock(&nlm_host_mutex); 243 return host; 244 } 245 246 /* 247 * Destroy a host 248 */ 249 static void 250 nlm_destroy_host(struct nlm_host *host) 251 { 252 struct rpc_clnt *clnt; 253 254 BUG_ON(!list_empty(&host->h_lockowners)); 255 BUG_ON(atomic_read(&host->h_count)); 256 257 /* 258 * Release NSM handle and unmonitor host. 259 */ 260 nsm_unmonitor(host); 261 262 clnt = host->h_rpcclnt; 263 if (clnt != NULL) 264 rpc_shutdown_client(clnt); 265 kfree(host); 266 } 267 268 /** 269 * nlmclnt_lookup_host - Find an NLM host handle matching a remote server 270 * @sap: network address of server 271 * @salen: length of server address 272 * @protocol: transport protocol to use 273 * @version: NLM protocol version 274 * @hostname: '\0'-terminated hostname of server 275 * 276 * Returns an nlm_host structure that matches the passed-in 277 * [server address, transport protocol, NLM version, server hostname]. 278 * If one doesn't already exist in the host cache, a new handle is 279 * created and returned. 280 */ 281 struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, 282 const size_t salen, 283 const unsigned short protocol, 284 const u32 version, const char *hostname) 285 { 286 const struct sockaddr source = { 287 .sa_family = AF_UNSPEC, 288 }; 289 struct nlm_lookup_host_info ni = { 290 .server = 0, 291 .sap = sap, 292 .salen = salen, 293 .protocol = protocol, 294 .version = version, 295 .hostname = hostname, 296 .hostname_len = strlen(hostname), 297 .src_sap = &source, 298 .src_len = sizeof(source), 299 }; 300 301 dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, 302 (hostname ? hostname : "<none>"), version, 303 (protocol == IPPROTO_UDP ? "udp" : "tcp")); 304 305 return nlm_lookup_host(&ni); 306 } 307 308 /** 309 * nlmsvc_lookup_host - Find an NLM host handle matching a remote client 310 * @rqstp: incoming NLM request 311 * @hostname: name of client host 312 * @hostname_len: length of client hostname 313 * 314 * Returns an nlm_host structure that matches the [client address, 315 * transport protocol, NLM version, client hostname] of the passed-in 316 * NLM request. If one doesn't already exist in the host cache, a 317 * new handle is created and returned. 318 * 319 * Before possibly creating a new nlm_host, construct a sockaddr 320 * for a specific source address in case the local system has 321 * multiple network addresses. The family of the address in 322 * rq_daddr is guaranteed to be the same as the family of the 323 * address in rq_addr, so it's safe to use the same family for 324 * the source address. 325 */ 326 struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, 327 const char *hostname, 328 const size_t hostname_len) 329 { 330 struct sockaddr_in sin = { 331 .sin_family = AF_INET, 332 }; 333 struct sockaddr_in6 sin6 = { 334 .sin6_family = AF_INET6, 335 }; 336 struct nlm_lookup_host_info ni = { 337 .server = 1, 338 .sap = svc_addr(rqstp), 339 .salen = rqstp->rq_addrlen, 340 .protocol = rqstp->rq_prot, 341 .version = rqstp->rq_vers, 342 .hostname = hostname, 343 .hostname_len = hostname_len, 344 .src_len = rqstp->rq_addrlen, 345 }; 346 347 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, 348 (int)hostname_len, hostname, rqstp->rq_vers, 349 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); 350 351 switch (ni.sap->sa_family) { 352 case AF_INET: 353 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr; 354 ni.src_sap = (struct sockaddr *)&sin; 355 break; 356 case AF_INET6: 357 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6); 358 ni.src_sap = (struct sockaddr *)&sin6; 359 break; 360 default: 361 return NULL; 362 } 363 364 return nlm_lookup_host(&ni); 365 } 366 367 /* 368 * Create the NLM RPC client for an NLM peer 369 */ 370 struct rpc_clnt * 371 nlm_bind_host(struct nlm_host *host) 372 { 373 struct rpc_clnt *clnt; 374 375 dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", 376 host->h_name, host->h_addrbuf, host->h_srcaddrbuf); 377 378 /* Lock host handle */ 379 mutex_lock(&host->h_mutex); 380 381 /* If we've already created an RPC client, check whether 382 * RPC rebind is required 383 */ 384 if ((clnt = host->h_rpcclnt) != NULL) { 385 if (time_after_eq(jiffies, host->h_nextrebind)) { 386 rpc_force_rebind(clnt); 387 host->h_nextrebind = jiffies + NLM_HOST_REBIND; 388 dprintk("lockd: next rebind in %lu jiffies\n", 389 host->h_nextrebind - jiffies); 390 } 391 } else { 392 unsigned long increment = nlmsvc_timeout; 393 struct rpc_timeout timeparms = { 394 .to_initval = increment, 395 .to_increment = increment, 396 .to_maxval = increment * 6UL, 397 .to_retries = 5U, 398 }; 399 struct rpc_create_args args = { 400 .protocol = host->h_proto, 401 .address = nlm_addr(host), 402 .addrsize = host->h_addrlen, 403 .saddress = nlm_srcaddr(host), 404 .timeout = &timeparms, 405 .servername = host->h_name, 406 .program = &nlm_program, 407 .version = host->h_version, 408 .authflavor = RPC_AUTH_UNIX, 409 .flags = (RPC_CLNT_CREATE_NOPING | 410 RPC_CLNT_CREATE_AUTOBIND), 411 }; 412 413 /* 414 * lockd retries server side blocks automatically so we want 415 * those to be soft RPC calls. Client side calls need to be 416 * hard RPC tasks. 417 */ 418 if (!host->h_server) 419 args.flags |= RPC_CLNT_CREATE_HARDRTRY; 420 421 clnt = rpc_create(&args); 422 if (!IS_ERR(clnt)) 423 host->h_rpcclnt = clnt; 424 else { 425 printk("lockd: couldn't create RPC handle for %s\n", host->h_name); 426 clnt = NULL; 427 } 428 } 429 430 mutex_unlock(&host->h_mutex); 431 return clnt; 432 } 433 434 /* 435 * Force a portmap lookup of the remote lockd port 436 */ 437 void 438 nlm_rebind_host(struct nlm_host *host) 439 { 440 dprintk("lockd: rebind host %s\n", host->h_name); 441 if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) { 442 rpc_force_rebind(host->h_rpcclnt); 443 host->h_nextrebind = jiffies + NLM_HOST_REBIND; 444 } 445 } 446 447 /* 448 * Increment NLM host count 449 */ 450 struct nlm_host * nlm_get_host(struct nlm_host *host) 451 { 452 if (host) { 453 dprintk("lockd: get host %s\n", host->h_name); 454 atomic_inc(&host->h_count); 455 host->h_expires = jiffies + NLM_HOST_EXPIRE; 456 } 457 return host; 458 } 459 460 /* 461 * Release NLM host after use 462 */ 463 void nlm_release_host(struct nlm_host *host) 464 { 465 if (host != NULL) { 466 dprintk("lockd: release host %s\n", host->h_name); 467 BUG_ON(atomic_read(&host->h_count) < 0); 468 if (atomic_dec_and_test(&host->h_count)) { 469 BUG_ON(!list_empty(&host->h_lockowners)); 470 BUG_ON(!list_empty(&host->h_granted)); 471 BUG_ON(!list_empty(&host->h_reclaim)); 472 } 473 } 474 } 475 476 /* 477 * We were notified that the host indicated by address &sin 478 * has rebooted. 479 * Release all resources held by that peer. 480 */ 481 void nlm_host_rebooted(const struct sockaddr_in *sin, 482 const char *hostname, 483 unsigned int hostname_len, 484 u32 new_state) 485 { 486 struct hlist_head *chain; 487 struct hlist_node *pos; 488 struct nsm_handle *nsm; 489 struct nlm_host *host; 490 491 nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin), 492 hostname, hostname_len, 0); 493 if (nsm == NULL) { 494 dprintk("lockd: never saw rebooted peer '%.*s' before\n", 495 hostname_len, hostname); 496 return; 497 } 498 499 dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n", 500 hostname_len, hostname, nsm->sm_addrbuf); 501 502 /* When reclaiming locks on this peer, make sure that 503 * we set up a new notification */ 504 nsm->sm_monitored = 0; 505 506 /* Mark all hosts tied to this NSM state as having rebooted. 507 * We run the loop repeatedly, because we drop the host table 508 * lock for this. 509 * To avoid processing a host several times, we match the nsmstate. 510 */ 511 again: mutex_lock(&nlm_host_mutex); 512 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 513 hlist_for_each_entry(host, pos, chain, h_hash) { 514 if (host->h_nsmhandle == nsm 515 && host->h_nsmstate != new_state) { 516 host->h_nsmstate = new_state; 517 host->h_state++; 518 519 nlm_get_host(host); 520 mutex_unlock(&nlm_host_mutex); 521 522 if (host->h_server) { 523 /* We're server for this guy, just ditch 524 * all the locks he held. */ 525 nlmsvc_free_host_resources(host); 526 } else { 527 /* He's the server, initiate lock recovery. */ 528 nlmclnt_recovery(host); 529 } 530 531 nlm_release_host(host); 532 goto again; 533 } 534 } 535 } 536 537 mutex_unlock(&nlm_host_mutex); 538 } 539 540 /* 541 * Shut down the hosts module. 542 * Note that this routine is called only at server shutdown time. 543 */ 544 void 545 nlm_shutdown_hosts(void) 546 { 547 struct hlist_head *chain; 548 struct hlist_node *pos; 549 struct nlm_host *host; 550 551 dprintk("lockd: shutting down host module\n"); 552 mutex_lock(&nlm_host_mutex); 553 554 /* First, make all hosts eligible for gc */ 555 dprintk("lockd: nuking all hosts...\n"); 556 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 557 hlist_for_each_entry(host, pos, chain, h_hash) { 558 host->h_expires = jiffies - 1; 559 if (host->h_rpcclnt) { 560 rpc_shutdown_client(host->h_rpcclnt); 561 host->h_rpcclnt = NULL; 562 } 563 } 564 } 565 566 /* Then, perform a garbage collection pass */ 567 nlm_gc_hosts(); 568 mutex_unlock(&nlm_host_mutex); 569 570 /* complain if any hosts are left */ 571 if (nrhosts) { 572 printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); 573 dprintk("lockd: %d hosts left:\n", nrhosts); 574 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 575 hlist_for_each_entry(host, pos, chain, h_hash) { 576 dprintk(" %s (cnt %d use %d exp %ld)\n", 577 host->h_name, atomic_read(&host->h_count), 578 host->h_inuse, host->h_expires); 579 } 580 } 581 } 582 } 583 584 /* 585 * Garbage collect any unused NLM hosts. 586 * This GC combines reference counting for async operations with 587 * mark & sweep for resources held by remote clients. 588 */ 589 static void 590 nlm_gc_hosts(void) 591 { 592 struct hlist_head *chain; 593 struct hlist_node *pos, *next; 594 struct nlm_host *host; 595 596 dprintk("lockd: host garbage collection\n"); 597 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 598 hlist_for_each_entry(host, pos, chain, h_hash) 599 host->h_inuse = 0; 600 } 601 602 /* Mark all hosts that hold locks, blocks or shares */ 603 nlmsvc_mark_resources(); 604 605 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 606 hlist_for_each_entry_safe(host, pos, next, chain, h_hash) { 607 if (atomic_read(&host->h_count) || host->h_inuse 608 || time_before(jiffies, host->h_expires)) { 609 dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n", 610 host->h_name, atomic_read(&host->h_count), 611 host->h_inuse, host->h_expires); 612 continue; 613 } 614 dprintk("lockd: delete host %s\n", host->h_name); 615 hlist_del_init(&host->h_hash); 616 617 nlm_destroy_host(host); 618 nrhosts--; 619 } 620 } 621 622 next_gc = jiffies + NLM_HOST_COLLECT; 623 } 624 625 626 /* 627 * Manage NSM handles 628 */ 629 static LIST_HEAD(nsm_handles); 630 static DEFINE_SPINLOCK(nsm_lock); 631 632 static struct nsm_handle *nsm_find(const struct sockaddr *sap, 633 const size_t salen, 634 const char *hostname, 635 const size_t hostname_len, 636 const int create) 637 { 638 struct nsm_handle *nsm = NULL; 639 struct nsm_handle *pos; 640 641 if (!sap) 642 return NULL; 643 644 if (hostname && memchr(hostname, '/', hostname_len) != NULL) { 645 if (printk_ratelimit()) { 646 printk(KERN_WARNING "Invalid hostname \"%.*s\" " 647 "in NFS lock request\n", 648 (int)hostname_len, hostname); 649 } 650 return NULL; 651 } 652 653 retry: 654 spin_lock(&nsm_lock); 655 list_for_each_entry(pos, &nsm_handles, sm_link) { 656 657 if (hostname && nsm_use_hostnames) { 658 if (strlen(pos->sm_name) != hostname_len 659 || memcmp(pos->sm_name, hostname, hostname_len)) 660 continue; 661 } else if (!nlm_cmp_addr(nsm_addr(pos), sap)) 662 continue; 663 atomic_inc(&pos->sm_count); 664 kfree(nsm); 665 nsm = pos; 666 goto found; 667 } 668 if (nsm) { 669 list_add(&nsm->sm_link, &nsm_handles); 670 goto found; 671 } 672 spin_unlock(&nsm_lock); 673 674 if (!create) 675 return NULL; 676 677 nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL); 678 if (nsm == NULL) 679 return NULL; 680 681 memcpy(nsm_addr(nsm), sap, salen); 682 nsm->sm_addrlen = salen; 683 nsm->sm_name = (char *) (nsm + 1); 684 memcpy(nsm->sm_name, hostname, hostname_len); 685 nsm->sm_name[hostname_len] = '\0'; 686 nlm_display_address((struct sockaddr *)&nsm->sm_addr, 687 nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf)); 688 atomic_set(&nsm->sm_count, 1); 689 goto retry; 690 691 found: 692 spin_unlock(&nsm_lock); 693 return nsm; 694 } 695 696 /* 697 * Release an NSM handle 698 */ 699 void 700 nsm_release(struct nsm_handle *nsm) 701 { 702 if (!nsm) 703 return; 704 if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { 705 list_del(&nsm->sm_link); 706 spin_unlock(&nsm_lock); 707 kfree(nsm); 708 } 709 } 710