Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfsd-4.15-1' of git://linux-nfs.org/~bfields/linux

Pull nfsd fixes from Bruce Fields:
"I screwed up my merge window pull request; I only sent half of what I
meant to.

There were no new features, just bugfixes of various importance and
some very minor cleanup, so I think it's all still appropriate for
-rc2.

Highlights:

- Fixes from Trond for some races in the NFSv4 state code.

- Fix from Naofumi Honda for a typo in the blocked lock notificiation
code

- Fixes from Vasily Averin for some problems starting and stopping
lockd especially in network namespaces"

* tag 'nfsd-4.15-1' of git://linux-nfs.org/~bfields/linux: (23 commits)
lockd: fix "list_add double add" caused by legacy signal interface
nlm_shutdown_hosts_net() cleanup
race of nfsd inetaddr notifiers vs nn->nfsd_serv change
race of lockd inetaddr notifiers vs nlmsvc_rqst change
SUNRPC: make cache_detail structures const
NFSD: make cache_detail structures const
sunrpc: make the function arg as const
nfsd: check for use of the closed special stateid
nfsd: fix panic in posix_unblock_lock called from nfs4_laundromat
lockd: lost rollback of set_grace_period() in lockd_down_net()
lockd: added cleanup checks in exit_net hook
grace: replace BUG_ON by WARN_ONCE in exit_net hook
nfsd: fix locking validator warning on nfs4_ol_stateid->st_mutex class
lockd: remove net pointer from messages
nfsd: remove net pointer from debug messages
nfsd: Fix races with check_stateid_generation()
nfsd: Ensure we check stateid validity in the seqid operation checks
nfsd: Fix race in lock stateid creation
nfsd4: move find_lock_stateid
nfsd: Ensure we don't recognise lock stateids after freeing them
...

+276 -138
+14 -10
fs/lockd/host.c
··· 578 578 579 579 if (ln->nrhosts == 0) 580 580 return; 581 - printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net); 582 - dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net); 581 + pr_warn("lockd: couldn't shutdown host module for net %x!\n", 582 + net->ns.inum); 583 + dprintk("lockd: %lu hosts left in net %x:\n", ln->nrhosts, 584 + net->ns.inum); 583 585 } else { 584 586 if (nrhosts == 0) 585 587 return; ··· 592 590 for_each_host(host, chain, nlm_server_hosts) { 593 591 if (net && host->net != net) 594 592 continue; 595 - dprintk(" %s (cnt %d use %d exp %ld net %p)\n", 593 + dprintk(" %s (cnt %d use %d exp %ld net %x)\n", 596 594 host->h_name, atomic_read(&host->h_count), 597 - host->h_inuse, host->h_expires, host->net); 595 + host->h_inuse, host->h_expires, host->net->ns.inum); 598 596 } 599 597 } 600 598 ··· 607 605 mutex_lock(&nlm_host_mutex); 608 606 609 607 /* First, make all hosts eligible for gc */ 610 - dprintk("lockd: nuking all hosts in net %p...\n", net); 608 + dprintk("lockd: nuking all hosts in net %x...\n", 609 + net ? net->ns.inum : 0); 611 610 for_each_host(host, chain, nlm_server_hosts) { 612 611 if (net && host->net != net) 613 612 continue; ··· 621 618 622 619 /* Then, perform a garbage collection pass */ 623 620 nlm_gc_hosts(net); 624 - mutex_unlock(&nlm_host_mutex); 625 - 626 621 nlm_complain_hosts(net); 622 + mutex_unlock(&nlm_host_mutex); 627 623 } 628 624 629 625 /* ··· 648 646 struct hlist_node *next; 649 647 struct nlm_host *host; 650 648 651 - dprintk("lockd: host garbage collection for net %p\n", net); 649 + dprintk("lockd: host garbage collection for net %x\n", 650 + net ? net->ns.inum : 0); 652 651 for_each_host(host, chain, nlm_server_hosts) { 653 652 if (net && host->net != net) 654 653 continue; ··· 665 662 if (atomic_read(&host->h_count) || host->h_inuse 666 663 || time_before(jiffies, host->h_expires)) { 667 664 dprintk("nlm_gc_hosts skipping %s " 668 - "(cnt %d use %d exp %ld net %p)\n", 665 + "(cnt %d use %d exp %ld net %x)\n", 669 666 host->h_name, atomic_read(&host->h_count), 670 - host->h_inuse, host->h_expires, host->net); 667 + host->h_inuse, host->h_expires, 668 + host->net->ns.inum); 671 669 continue; 672 670 } 673 671 nlm_destroy_host_locked(host);
+2 -1
fs/lockd/mon.c
··· 110 110 clnt = nsm_create(host->net, host->nodename); 111 111 if (IS_ERR(clnt)) { 112 112 dprintk("lockd: failed to create NSM upcall transport, " 113 - "status=%ld, net=%p\n", PTR_ERR(clnt), host->net); 113 + "status=%ld, net=%x\n", PTR_ERR(clnt), 114 + host->net->ns.inum); 114 115 return PTR_ERR(clnt); 115 116 } 116 117
+32 -6
fs/lockd/svc.c
··· 57 57 static struct svc_rqst *nlmsvc_rqst; 58 58 unsigned long nlmsvc_timeout; 59 59 60 + atomic_t nlm_ntf_refcnt = ATOMIC_INIT(0); 61 + DECLARE_WAIT_QUEUE_HEAD(nlm_ntf_wq); 62 + 60 63 unsigned int lockd_net_id; 61 64 62 65 /* ··· 262 259 if (error < 0) 263 260 goto err_bind; 264 261 set_grace_period(net); 265 - dprintk("lockd_up_net: per-net data created; net=%p\n", net); 262 + dprintk("%s: per-net data created; net=%x\n", __func__, net->ns.inum); 266 263 return 0; 267 264 268 265 err_bind: ··· 277 274 if (ln->nlmsvc_users) { 278 275 if (--ln->nlmsvc_users == 0) { 279 276 nlm_shutdown_hosts_net(net); 277 + cancel_delayed_work_sync(&ln->grace_period_end); 278 + locks_end_grace(&ln->lockd_manager); 280 279 svc_shutdown_net(serv, net); 281 - dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net); 280 + dprintk("%s: per-net data destroyed; net=%x\n", 281 + __func__, net->ns.inum); 282 282 } 283 283 } else { 284 - printk(KERN_ERR "lockd_down_net: no users! task=%p, net=%p\n", 285 - nlmsvc_task, net); 284 + pr_err("%s: no users! task=%p, net=%x\n", 285 + __func__, nlmsvc_task, net->ns.inum); 286 286 BUG(); 287 287 } 288 288 } ··· 296 290 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; 297 291 struct sockaddr_in sin; 298 292 299 - if (event != NETDEV_DOWN) 293 + if ((event != NETDEV_DOWN) || 294 + !atomic_inc_not_zero(&nlm_ntf_refcnt)) 300 295 goto out; 301 296 302 297 if (nlmsvc_rqst) { ··· 308 301 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server, 309 302 (struct sockaddr *)&sin); 310 303 } 304 + atomic_dec(&nlm_ntf_refcnt); 305 + wake_up(&nlm_ntf_wq); 311 306 312 307 out: 313 308 return NOTIFY_DONE; ··· 326 317 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; 327 318 struct sockaddr_in6 sin6; 328 319 329 - if (event != NETDEV_DOWN) 320 + if ((event != NETDEV_DOWN) || 321 + !atomic_inc_not_zero(&nlm_ntf_refcnt)) 330 322 goto out; 331 323 332 324 if (nlmsvc_rqst) { ··· 339 329 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server, 340 330 (struct sockaddr *)&sin6); 341 331 } 332 + atomic_dec(&nlm_ntf_refcnt); 333 + wake_up(&nlm_ntf_wq); 342 334 343 335 out: 344 336 return NOTIFY_DONE; ··· 357 345 #if IS_ENABLED(CONFIG_IPV6) 358 346 unregister_inet6addr_notifier(&lockd_inet6addr_notifier); 359 347 #endif 348 + wait_event(nlm_ntf_wq, atomic_read(&nlm_ntf_refcnt) == 0); 360 349 } 361 350 362 351 static void lockd_svc_exit_thread(void) 363 352 { 353 + atomic_dec(&nlm_ntf_refcnt); 364 354 lockd_unregister_notifiers(); 365 355 svc_exit_thread(nlmsvc_rqst); 366 356 } ··· 387 373 goto out_rqst; 388 374 } 389 375 376 + atomic_inc(&nlm_ntf_refcnt); 390 377 svc_sock_update_bufs(serv); 391 378 serv->sv_maxconn = nlm_max_connections; 392 379 ··· 691 676 692 677 static void lockd_exit_net(struct net *net) 693 678 { 679 + struct lockd_net *ln = net_generic(net, lockd_net_id); 680 + 681 + WARN_ONCE(!list_empty(&ln->lockd_manager.list), 682 + "net %x %s: lockd_manager.list is not empty\n", 683 + net->ns.inum, __func__); 684 + WARN_ONCE(!list_empty(&ln->nsm_handles), 685 + "net %x %s: nsm_handles list is not empty\n", 686 + net->ns.inum, __func__); 687 + WARN_ONCE(delayed_work_pending(&ln->grace_period_end), 688 + "net %x %s: grace_period_end was not cancelled\n", 689 + net->ns.inum, __func__); 694 690 } 695 691 696 692 static struct pernet_operations lockd_net_ops = {
+1 -1
fs/lockd/svcsubs.c
··· 370 370 { 371 371 struct nlm_host hint; 372 372 373 - dprintk("lockd: nlmsvc_mark_resources for net %p\n", net); 373 + dprintk("lockd: %s for net %x\n", __func__, net ? net->ns.inum : 0); 374 374 hint.net = net; 375 375 nlm_traverse_files(&hint, nlmsvc_mark_host, NULL); 376 376 }
+8 -2
fs/nfs_common/grace.c
··· 30 30 struct list_head *grace_list = net_generic(net, grace_net_id); 31 31 32 32 spin_lock(&grace_lock); 33 - list_add(&lm->list, grace_list); 33 + if (list_empty(&lm->list)) 34 + list_add(&lm->list, grace_list); 35 + else 36 + WARN(1, "double list_add attempt detected in net %x %s\n", 37 + net->ns.inum, (net == &init_net) ? "(init_net)" : ""); 34 38 spin_unlock(&grace_lock); 35 39 } 36 40 EXPORT_SYMBOL_GPL(locks_start_grace); ··· 108 104 { 109 105 struct list_head *grace_list = net_generic(net, grace_net_id); 110 106 111 - BUG_ON(!list_empty(grace_list)); 107 + WARN_ONCE(!list_empty(grace_list), 108 + "net %x %s: grace_list is not empty\n", 109 + net->ns.inum, __func__); 112 110 } 113 111 114 112 static struct pernet_operations grace_net_ops = {
+5 -5
fs/nfsd/export.c
··· 232 232 return NULL; 233 233 } 234 234 235 - static struct cache_detail svc_expkey_cache_template = { 235 + static const struct cache_detail svc_expkey_cache_template = { 236 236 .owner = THIS_MODULE, 237 237 .hash_size = EXPKEY_HASHMAX, 238 238 .name = "nfsd.fh", ··· 748 748 return NULL; 749 749 } 750 750 751 - static struct cache_detail svc_export_cache_template = { 751 + static const struct cache_detail svc_export_cache_template = { 752 752 .owner = THIS_MODULE, 753 753 .hash_size = EXPORT_HASHMAX, 754 754 .name = "nfsd.export", ··· 1230 1230 int rv; 1231 1231 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1232 1232 1233 - dprintk("nfsd: initializing export module (net: %p).\n", net); 1233 + dprintk("nfsd: initializing export module (net: %x).\n", net->ns.inum); 1234 1234 1235 1235 nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net); 1236 1236 if (IS_ERR(nn->svc_export_cache)) ··· 1278 1278 { 1279 1279 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1280 1280 1281 - dprintk("nfsd: shutting down export module (net: %p).\n", net); 1281 + dprintk("nfsd: shutting down export module (net: %x).\n", net->ns.inum); 1282 1282 1283 1283 cache_unregister_net(nn->svc_expkey_cache, net); 1284 1284 cache_unregister_net(nn->svc_export_cache, net); ··· 1286 1286 cache_destroy_net(nn->svc_export_cache, net); 1287 1287 svcauth_unix_purge(net); 1288 1288 1289 - dprintk("nfsd: export shutdown complete (net: %p).\n", net); 1289 + dprintk("nfsd: export shutdown complete (net: %x).\n", net->ns.inum); 1290 1290 }
+3
fs/nfsd/netns.h
··· 119 119 u32 clverifier_counter; 120 120 121 121 struct svc_serv *nfsd_serv; 122 + 123 + wait_queue_head_t ntf_wq; 124 + atomic_t ntf_refcnt; 122 125 }; 123 126 124 127 /* Simple check to find out if a given net was properly initialized */
+2 -2
fs/nfsd/nfs4idmap.c
··· 178 178 static struct ent *idtoname_update(struct cache_detail *, struct ent *, 179 179 struct ent *); 180 180 181 - static struct cache_detail idtoname_cache_template = { 181 + static const struct cache_detail idtoname_cache_template = { 182 182 .owner = THIS_MODULE, 183 183 .hash_size = ENT_HASHMAX, 184 184 .name = "nfs4.idtoname", ··· 341 341 struct ent *); 342 342 static int nametoid_parse(struct cache_detail *, char *, int); 343 343 344 - static struct cache_detail nametoid_cache_template = { 344 + static const struct cache_detail nametoid_cache_template = { 345 345 .owner = THIS_MODULE, 346 346 .hash_size = ENT_HASHMAX, 347 347 .name = "nfs4.nametoid",
+189 -102
fs/nfsd/nfs4state.c
··· 63 63 static const stateid_t currentstateid = { 64 64 .si_generation = 1, 65 65 }; 66 + static const stateid_t close_stateid = { 67 + .si_generation = 0xffffffffU, 68 + }; 66 69 67 70 static u64 current_sessionid = 1; 68 71 69 72 #define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t))) 70 73 #define ONE_STATEID(stateid) (!memcmp((stateid), &one_stateid, sizeof(stateid_t))) 71 74 #define CURRENT_STATEID(stateid) (!memcmp((stateid), &currentstateid, sizeof(stateid_t))) 75 + #define CLOSE_STATEID(stateid) (!memcmp((stateid), &close_stateid, sizeof(stateid_t))) 72 76 73 77 /* forward declarations */ 74 78 static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner); ··· 86 82 * eventually cover more: 87 83 */ 88 84 static DEFINE_SPINLOCK(state_lock); 85 + 86 + enum nfsd4_st_mutex_lock_subclass { 87 + OPEN_STATEID_MUTEX = 0, 88 + LOCK_STATEID_MUTEX = 1, 89 + }; 89 90 90 91 /* 91 92 * A waitqueue for all in-progress 4.0 CLOSE operations that are waiting for ··· 3571 3562 /* ignore lock owners */ 3572 3563 if (local->st_stateowner->so_is_open_owner == 0) 3573 3564 continue; 3574 - if (local->st_stateowner == &oo->oo_owner) { 3565 + if (local->st_stateowner != &oo->oo_owner) 3566 + continue; 3567 + if (local->st_stid.sc_type == NFS4_OPEN_STID) { 3575 3568 ret = local; 3576 3569 refcount_inc(&ret->st_stid.sc_count); 3577 3570 break; 3578 3571 } 3579 3572 } 3580 3573 return ret; 3574 + } 3575 + 3576 + static __be32 3577 + nfsd4_verify_open_stid(struct nfs4_stid *s) 3578 + { 3579 + __be32 ret = nfs_ok; 3580 + 3581 + switch (s->sc_type) { 3582 + default: 3583 + break; 3584 + case NFS4_CLOSED_STID: 3585 + case NFS4_CLOSED_DELEG_STID: 3586 + ret = nfserr_bad_stateid; 3587 + break; 3588 + case NFS4_REVOKED_DELEG_STID: 3589 + ret = nfserr_deleg_revoked; 3590 + } 3591 + return ret; 3592 + } 3593 + 3594 + /* Lock the stateid st_mutex, and deal with races with CLOSE */ 3595 + static __be32 3596 + nfsd4_lock_ol_stateid(struct nfs4_ol_stateid *stp) 3597 + { 3598 + __be32 ret; 3599 + 3600 + mutex_lock_nested(&stp->st_mutex, LOCK_STATEID_MUTEX); 3601 + ret = nfsd4_verify_open_stid(&stp->st_stid); 3602 + if (ret != nfs_ok) 3603 + mutex_unlock(&stp->st_mutex); 3604 + return ret; 3605 + } 3606 + 3607 + static struct nfs4_ol_stateid * 3608 + nfsd4_find_and_lock_existing_open(struct nfs4_file *fp, struct nfsd4_open *open) 3609 + { 3610 + struct nfs4_ol_stateid *stp; 3611 + for (;;) { 3612 + spin_lock(&fp->fi_lock); 3613 + stp = nfsd4_find_existing_open(fp, open); 3614 + spin_unlock(&fp->fi_lock); 3615 + if (!stp || nfsd4_lock_ol_stateid(stp) == nfs_ok) 3616 + break; 3617 + nfs4_put_stid(&stp->st_stid); 3618 + } 3619 + return stp; 3581 3620 } 3582 3621 3583 3622 static struct nfs4_openowner * ··· 3670 3613 stp = open->op_stp; 3671 3614 /* We are moving these outside of the spinlocks to avoid the warnings */ 3672 3615 mutex_init(&stp->st_mutex); 3673 - mutex_lock(&stp->st_mutex); 3616 + mutex_lock_nested(&stp->st_mutex, OPEN_STATEID_MUTEX); 3674 3617 3618 + retry: 3675 3619 spin_lock(&oo->oo_owner.so_client->cl_lock); 3676 3620 spin_lock(&fp->fi_lock); 3677 3621 ··· 3697 3639 spin_unlock(&fp->fi_lock); 3698 3640 spin_unlock(&oo->oo_owner.so_client->cl_lock); 3699 3641 if (retstp) { 3700 - mutex_lock(&retstp->st_mutex); 3642 + /* Handle races with CLOSE */ 3643 + if (nfsd4_lock_ol_stateid(retstp) != nfs_ok) { 3644 + nfs4_put_stid(&retstp->st_stid); 3645 + goto retry; 3646 + } 3701 3647 /* To keep mutex tracking happy */ 3702 3648 mutex_unlock(&stp->st_mutex); 3703 3649 stp = retstp; ··· 4511 4449 struct nfs4_ol_stateid *stp = NULL; 4512 4450 struct nfs4_delegation *dp = NULL; 4513 4451 __be32 status; 4452 + bool new_stp = false; 4514 4453 4515 4454 /* 4516 4455 * Lookup file; if found, lookup stateid and check open request, ··· 4523 4460 status = nfs4_check_deleg(cl, open, &dp); 4524 4461 if (status) 4525 4462 goto out; 4526 - spin_lock(&fp->fi_lock); 4527 - stp = nfsd4_find_existing_open(fp, open); 4528 - spin_unlock(&fp->fi_lock); 4463 + stp = nfsd4_find_and_lock_existing_open(fp, open); 4529 4464 } else { 4530 4465 open->op_file = NULL; 4531 4466 status = nfserr_bad_stateid; ··· 4531 4470 goto out; 4532 4471 } 4533 4472 4473 + if (!stp) { 4474 + stp = init_open_stateid(fp, open); 4475 + if (!open->op_stp) 4476 + new_stp = true; 4477 + } 4478 + 4534 4479 /* 4535 4480 * OPEN the file, or upgrade an existing OPEN. 4536 4481 * If truncate fails, the OPEN fails. 4482 + * 4483 + * stp is already locked. 4537 4484 */ 4538 - if (stp) { 4485 + if (!new_stp) { 4539 4486 /* Stateid was found, this is an OPEN upgrade */ 4540 - mutex_lock(&stp->st_mutex); 4541 4487 status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); 4542 4488 if (status) { 4543 4489 mutex_unlock(&stp->st_mutex); 4544 4490 goto out; 4545 4491 } 4546 4492 } else { 4547 - /* stp is returned locked. */ 4548 - stp = init_open_stateid(fp, open); 4549 - /* See if we lost the race to some other thread */ 4550 - if (stp->st_access_bmap != 0) { 4551 - status = nfs4_upgrade_open(rqstp, fp, current_fh, 4552 - stp, open); 4553 - if (status) { 4554 - mutex_unlock(&stp->st_mutex); 4555 - goto out; 4556 - } 4557 - goto upgrade_out; 4558 - } 4559 4493 status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); 4560 4494 if (status) { 4561 - mutex_unlock(&stp->st_mutex); 4495 + stp->st_stid.sc_type = NFS4_CLOSED_STID; 4562 4496 release_open_stateid(stp); 4497 + mutex_unlock(&stp->st_mutex); 4563 4498 goto out; 4564 4499 } 4565 4500 ··· 4564 4507 if (stp->st_clnt_odstate == open->op_odstate) 4565 4508 open->op_odstate = NULL; 4566 4509 } 4567 - upgrade_out: 4510 + 4568 4511 nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid); 4569 4512 mutex_unlock(&stp->st_mutex); 4570 4513 ··· 4791 4734 spin_unlock(&nn->blocked_locks_lock); 4792 4735 4793 4736 while (!list_empty(&reaplist)) { 4794 - nbl = list_first_entry(&nn->blocked_locks_lru, 4737 + nbl = list_first_entry(&reaplist, 4795 4738 struct nfsd4_blocked_lock, nbl_lru); 4796 4739 list_del_init(&nbl->nbl_lru); 4797 4740 posix_unblock_lock(&nbl->nbl_lock); ··· 4912 4855 return nfserr_old_stateid; 4913 4856 } 4914 4857 4858 + static __be32 nfsd4_stid_check_stateid_generation(stateid_t *in, struct nfs4_stid *s, bool has_session) 4859 + { 4860 + __be32 ret; 4861 + 4862 + spin_lock(&s->sc_lock); 4863 + ret = nfsd4_verify_open_stid(s); 4864 + if (ret == nfs_ok) 4865 + ret = check_stateid_generation(in, &s->sc_stateid, has_session); 4866 + spin_unlock(&s->sc_lock); 4867 + return ret; 4868 + } 4869 + 4915 4870 static __be32 nfsd4_check_openowner_confirmed(struct nfs4_ol_stateid *ols) 4916 4871 { 4917 4872 if (ols->st_stateowner->so_is_open_owner && ··· 4937 4868 struct nfs4_stid *s; 4938 4869 __be32 status = nfserr_bad_stateid; 4939 4870 4940 - if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 4871 + if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) || 4872 + CLOSE_STATEID(stateid)) 4941 4873 return status; 4942 4874 /* Client debugging aid. */ 4943 4875 if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) { ··· 4953 4883 s = find_stateid_locked(cl, stateid); 4954 4884 if (!s) 4955 4885 goto out_unlock; 4956 - status = check_stateid_generation(stateid, &s->sc_stateid, 1); 4886 + status = nfsd4_stid_check_stateid_generation(stateid, s, 1); 4957 4887 if (status) 4958 4888 goto out_unlock; 4959 4889 switch (s->sc_type) { ··· 4996 4926 else if (typemask & NFS4_DELEG_STID) 4997 4927 typemask |= NFS4_REVOKED_DELEG_STID; 4998 4928 4999 - if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 4929 + if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) || 4930 + CLOSE_STATEID(stateid)) 5000 4931 return nfserr_bad_stateid; 5001 4932 status = lookup_clientid(&stateid->si_opaque.so_clid, cstate, nn); 5002 4933 if (status == nfserr_stale_clientid) { ··· 5115 5044 &s, nn); 5116 5045 if (status) 5117 5046 return status; 5118 - status = check_stateid_generation(stateid, &s->sc_stateid, 5047 + status = nfsd4_stid_check_stateid_generation(stateid, s, 5119 5048 nfsd4_has_session(cstate)); 5120 5049 if (status) 5121 5050 goto out; ··· 5169 5098 struct nfs4_ol_stateid *stp = openlockstateid(s); 5170 5099 __be32 ret; 5171 5100 5172 - mutex_lock(&stp->st_mutex); 5101 + ret = nfsd4_lock_ol_stateid(stp); 5102 + if (ret) 5103 + goto out_put_stid; 5173 5104 5174 5105 ret = check_stateid_generation(stateid, &s->sc_stateid, 1); 5175 5106 if (ret) ··· 5182 5109 lockowner(stp->st_stateowner))) 5183 5110 goto out; 5184 5111 5112 + stp->st_stid.sc_type = NFS4_CLOSED_STID; 5185 5113 release_lock_stateid(stp); 5186 5114 ret = nfs_ok; 5187 5115 5188 5116 out: 5189 5117 mutex_unlock(&stp->st_mutex); 5118 + out_put_stid: 5190 5119 nfs4_put_stid(s); 5191 5120 return ret; 5192 5121 } ··· 5208 5133 s = find_stateid_locked(cl, stateid); 5209 5134 if (!s) 5210 5135 goto out_unlock; 5136 + spin_lock(&s->sc_lock); 5211 5137 switch (s->sc_type) { 5212 5138 case NFS4_DELEG_STID: 5213 5139 ret = nfserr_locks_held; ··· 5220 5144 ret = nfserr_locks_held; 5221 5145 break; 5222 5146 case NFS4_LOCK_STID: 5147 + spin_unlock(&s->sc_lock); 5223 5148 refcount_inc(&s->sc_count); 5224 5149 spin_unlock(&cl->cl_lock); 5225 5150 ret = nfsd4_free_lock_stateid(stateid, s); 5226 5151 goto out; 5227 5152 case NFS4_REVOKED_DELEG_STID: 5153 + spin_unlock(&s->sc_lock); 5228 5154 dp = delegstateid(s); 5229 5155 list_del_init(&dp->dl_recall_lru); 5230 5156 spin_unlock(&cl->cl_lock); ··· 5235 5157 goto out; 5236 5158 /* Default falls through and returns nfserr_bad_stateid */ 5237 5159 } 5160 + spin_unlock(&s->sc_lock); 5238 5161 out_unlock: 5239 5162 spin_unlock(&cl->cl_lock); 5240 5163 out: ··· 5258 5179 status = nfsd4_check_seqid(cstate, sop, seqid); 5259 5180 if (status) 5260 5181 return status; 5261 - if (stp->st_stid.sc_type == NFS4_CLOSED_STID 5262 - || stp->st_stid.sc_type == NFS4_REVOKED_DELEG_STID) 5263 - /* 5264 - * "Closed" stateid's exist *only* to return 5265 - * nfserr_replay_me from the previous step, and 5266 - * revoked delegations are kept only for free_stateid. 5267 - */ 5268 - return nfserr_bad_stateid; 5269 - mutex_lock(&stp->st_mutex); 5182 + status = nfsd4_lock_ol_stateid(stp); 5183 + if (status != nfs_ok) 5184 + return status; 5270 5185 status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); 5271 5186 if (status == nfs_ok) 5272 5187 status = nfs4_check_fh(current_fh, &stp->st_stid); ··· 5440 5367 bool unhashed; 5441 5368 LIST_HEAD(reaplist); 5442 5369 5443 - s->st_stid.sc_type = NFS4_CLOSED_STID; 5444 5370 spin_lock(&clp->cl_lock); 5445 5371 unhashed = unhash_open_stateid(s, &reaplist); 5446 5372 ··· 5479 5407 nfsd4_bump_seqid(cstate, status); 5480 5408 if (status) 5481 5409 goto out; 5410 + 5411 + stp->st_stid.sc_type = NFS4_CLOSED_STID; 5482 5412 nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); 5483 - mutex_unlock(&stp->st_mutex); 5484 5413 5485 5414 nfsd4_close_open_stateid(stp); 5415 + mutex_unlock(&stp->st_mutex); 5416 + 5417 + /* See RFC5661 sectionm 18.2.4 */ 5418 + if (stp->st_stid.sc_client->cl_minorversion) 5419 + memcpy(&close->cl_stateid, &close_stateid, 5420 + sizeof(close->cl_stateid)); 5486 5421 5487 5422 /* put reference from nfs4_preprocess_seqid_op */ 5488 5423 nfs4_put_stid(&stp->st_stid); ··· 5515 5436 if (status) 5516 5437 goto out; 5517 5438 dp = delegstateid(s); 5518 - status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); 5439 + status = nfsd4_stid_check_stateid_generation(stateid, &dp->dl_stid, nfsd4_has_session(cstate)); 5519 5440 if (status) 5520 5441 goto put_stateid; 5521 5442 ··· 5721 5642 return ret; 5722 5643 } 5723 5644 5724 - static void 5725 - init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, 5726 - struct nfs4_file *fp, struct inode *inode, 5727 - struct nfs4_ol_stateid *open_stp) 5728 - { 5729 - struct nfs4_client *clp = lo->lo_owner.so_client; 5730 - 5731 - lockdep_assert_held(&clp->cl_lock); 5732 - 5733 - refcount_inc(&stp->st_stid.sc_count); 5734 - stp->st_stid.sc_type = NFS4_LOCK_STID; 5735 - stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner); 5736 - get_nfs4_file(fp); 5737 - stp->st_stid.sc_file = fp; 5738 - stp->st_access_bmap = 0; 5739 - stp->st_deny_bmap = open_stp->st_deny_bmap; 5740 - stp->st_openstp = open_stp; 5741 - mutex_init(&stp->st_mutex); 5742 - list_add(&stp->st_locks, &open_stp->st_locks); 5743 - list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); 5744 - spin_lock(&fp->fi_lock); 5745 - list_add(&stp->st_perfile, &fp->fi_stateids); 5746 - spin_unlock(&fp->fi_lock); 5747 - } 5748 - 5749 5645 static struct nfs4_ol_stateid * 5750 5646 find_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp) 5751 5647 { ··· 5730 5676 lockdep_assert_held(&clp->cl_lock); 5731 5677 5732 5678 list_for_each_entry(lst, &lo->lo_owner.so_stateids, st_perstateowner) { 5679 + if (lst->st_stid.sc_type != NFS4_LOCK_STID) 5680 + continue; 5733 5681 if (lst->st_stid.sc_file == fp) { 5734 5682 refcount_inc(&lst->st_stid.sc_count); 5735 5683 return lst; 5736 5684 } 5737 5685 } 5738 5686 return NULL; 5687 + } 5688 + 5689 + static struct nfs4_ol_stateid * 5690 + init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, 5691 + struct nfs4_file *fp, struct inode *inode, 5692 + struct nfs4_ol_stateid *open_stp) 5693 + { 5694 + struct nfs4_client *clp = lo->lo_owner.so_client; 5695 + struct nfs4_ol_stateid *retstp; 5696 + 5697 + mutex_init(&stp->st_mutex); 5698 + mutex_lock_nested(&stp->st_mutex, OPEN_STATEID_MUTEX); 5699 + retry: 5700 + spin_lock(&clp->cl_lock); 5701 + spin_lock(&fp->fi_lock); 5702 + retstp = find_lock_stateid(lo, fp); 5703 + if (retstp) 5704 + goto out_unlock; 5705 + 5706 + refcount_inc(&stp->st_stid.sc_count); 5707 + stp->st_stid.sc_type = NFS4_LOCK_STID; 5708 + stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner); 5709 + get_nfs4_file(fp); 5710 + stp->st_stid.sc_file = fp; 5711 + stp->st_access_bmap = 0; 5712 + stp->st_deny_bmap = open_stp->st_deny_bmap; 5713 + stp->st_openstp = open_stp; 5714 + list_add(&stp->st_locks, &open_stp->st_locks); 5715 + list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); 5716 + list_add(&stp->st_perfile, &fp->fi_stateids); 5717 + out_unlock: 5718 + spin_unlock(&fp->fi_lock); 5719 + spin_unlock(&clp->cl_lock); 5720 + if (retstp) { 5721 + if (nfsd4_lock_ol_stateid(retstp) != nfs_ok) { 5722 + nfs4_put_stid(&retstp->st_stid); 5723 + goto retry; 5724 + } 5725 + /* To keep mutex tracking happy */ 5726 + mutex_unlock(&stp->st_mutex); 5727 + stp = retstp; 5728 + } 5729 + return stp; 5739 5730 } 5740 5731 5741 5732 static struct nfs4_ol_stateid * ··· 5793 5694 struct nfs4_openowner *oo = openowner(ost->st_stateowner); 5794 5695 struct nfs4_client *clp = oo->oo_owner.so_client; 5795 5696 5697 + *new = false; 5796 5698 spin_lock(&clp->cl_lock); 5797 5699 lst = find_lock_stateid(lo, fi); 5798 - if (lst == NULL) { 5799 - spin_unlock(&clp->cl_lock); 5800 - ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid); 5801 - if (ns == NULL) 5802 - return NULL; 5803 - 5804 - spin_lock(&clp->cl_lock); 5805 - lst = find_lock_stateid(lo, fi); 5806 - if (likely(!lst)) { 5807 - lst = openlockstateid(ns); 5808 - init_lock_stateid(lst, lo, fi, inode, ost); 5809 - ns = NULL; 5810 - *new = true; 5811 - } 5812 - } 5813 5700 spin_unlock(&clp->cl_lock); 5814 - if (ns) 5701 + if (lst != NULL) { 5702 + if (nfsd4_lock_ol_stateid(lst) == nfs_ok) 5703 + goto out; 5704 + nfs4_put_stid(&lst->st_stid); 5705 + } 5706 + ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid); 5707 + if (ns == NULL) 5708 + return NULL; 5709 + 5710 + lst = init_lock_stateid(openlockstateid(ns), lo, fi, inode, ost); 5711 + if (lst == openlockstateid(ns)) 5712 + *new = true; 5713 + else 5815 5714 nfs4_put_stid(ns); 5715 + out: 5816 5716 return lst; 5817 5717 } 5818 5718 ··· 5848 5750 struct nfs4_lockowner *lo; 5849 5751 struct nfs4_ol_stateid *lst; 5850 5752 unsigned int strhashval; 5851 - bool hashed; 5852 5753 5853 5754 lo = find_lockowner_str(cl, &lock->lk_new_owner); 5854 5755 if (!lo) { ··· 5863 5766 goto out; 5864 5767 } 5865 5768 5866 - retry: 5867 5769 lst = find_or_create_lock_stateid(lo, fi, inode, ost, new); 5868 5770 if (lst == NULL) { 5869 5771 status = nfserr_jukebox; 5870 5772 goto out; 5871 5773 } 5872 5774 5873 - mutex_lock(&lst->st_mutex); 5874 - 5875 - /* See if it's still hashed to avoid race with FREE_STATEID */ 5876 - spin_lock(&cl->cl_lock); 5877 - hashed = !list_empty(&lst->st_perfile); 5878 - spin_unlock(&cl->cl_lock); 5879 - 5880 - if (!hashed) { 5881 - mutex_unlock(&lst->st_mutex); 5882 - nfs4_put_stid(&lst->st_stid); 5883 - goto retry; 5884 - } 5885 5775 status = nfs_ok; 5886 5776 *plst = lst; 5887 5777 out: ··· 6074 5990 seqid_mutating_err(ntohl(status))) 6075 5991 lock_sop->lo_owner.so_seqid++; 6076 5992 6077 - mutex_unlock(&lock_stp->st_mutex); 6078 - 6079 5993 /* 6080 5994 * If this is a new, never-before-used stateid, and we are 6081 5995 * returning an error, then just go ahead and release it. 6082 5996 */ 6083 - if (status && new) 5997 + if (status && new) { 5998 + lock_stp->st_stid.sc_type = NFS4_CLOSED_STID; 6084 5999 release_lock_stateid(lock_stp); 6000 + } 6001 + 6002 + mutex_unlock(&lock_stp->st_mutex); 6085 6003 6086 6004 nfs4_put_stid(&lock_stp->st_stid); 6087 6005 } ··· 7103 7017 INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]); 7104 7018 nn->conf_name_tree = RB_ROOT; 7105 7019 nn->unconf_name_tree = RB_ROOT; 7020 + nn->boot_time = get_seconds(); 7021 + nn->grace_ended = false; 7022 + nn->nfsd4_manager.block_opens = true; 7023 + INIT_LIST_HEAD(&nn->nfsd4_manager.list); 7106 7024 INIT_LIST_HEAD(&nn->client_lru); 7107 7025 INIT_LIST_HEAD(&nn->close_lru); 7108 7026 INIT_LIST_HEAD(&nn->del_recall_lru); ··· 7164 7074 ret = nfs4_state_create_net(net); 7165 7075 if (ret) 7166 7076 return ret; 7167 - nn->boot_time = get_seconds(); 7168 - nn->grace_ended = false; 7169 - nn->nfsd4_manager.block_opens = true; 7170 7077 locks_start_grace(net, &nn->nfsd4_manager); 7171 7078 nfsd4_client_tracking_init(net); 7172 7079 printk(KERN_INFO "NFSD: starting %ld-second grace period (net %x)\n", ··· 7240 7153 spin_unlock(&nn->blocked_locks_lock); 7241 7154 7242 7155 while (!list_empty(&reaplist)) { 7243 - nbl = list_first_entry(&nn->blocked_locks_lru, 7156 + nbl = list_first_entry(&reaplist, 7244 7157 struct nfsd4_blocked_lock, nbl_lru); 7245 7158 list_del_init(&nbl->nbl_lru); 7246 7159 posix_unblock_lock(&nbl->nbl_lock);
+3
fs/nfsd/nfsctl.c
··· 1241 1241 nn->nfsd4_grace = 90; 1242 1242 nn->clverifier_counter = prandom_u32(); 1243 1243 nn->clientid_counter = prandom_u32(); 1244 + 1245 + atomic_set(&nn->ntf_refcnt, 0); 1246 + init_waitqueue_head(&nn->ntf_wq); 1244 1247 return 0; 1245 1248 1246 1249 out_idmap_error:
+11 -3
fs/nfsd/nfssvc.c
··· 335 335 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 336 336 struct sockaddr_in sin; 337 337 338 - if (event != NETDEV_DOWN) 338 + if ((event != NETDEV_DOWN) || 339 + !atomic_inc_not_zero(&nn->ntf_refcnt)) 339 340 goto out; 340 341 341 342 if (nn->nfsd_serv) { ··· 345 344 sin.sin_addr.s_addr = ifa->ifa_local; 346 345 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin); 347 346 } 347 + atomic_dec(&nn->ntf_refcnt); 348 + wake_up(&nn->ntf_wq); 348 349 349 350 out: 350 351 return NOTIFY_DONE; ··· 366 363 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 367 364 struct sockaddr_in6 sin6; 368 365 369 - if (event != NETDEV_DOWN) 366 + if ((event != NETDEV_DOWN) || 367 + !atomic_inc_not_zero(&nn->ntf_refcnt)) 370 368 goto out; 371 369 372 370 if (nn->nfsd_serv) { ··· 378 374 sin6.sin6_scope_id = ifa->idev->dev->ifindex; 379 375 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6); 380 376 } 381 - 377 + atomic_dec(&nn->ntf_refcnt); 378 + wake_up(&nn->ntf_wq); 382 379 out: 383 380 return NOTIFY_DONE; 384 381 } ··· 396 391 { 397 392 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 398 393 394 + atomic_dec(&nn->ntf_refcnt); 399 395 /* check if the notifier still has clients */ 400 396 if (atomic_dec_return(&nfsd_notifier_refcount) == 0) { 401 397 unregister_inetaddr_notifier(&nfsd_inetaddr_notifier); ··· 404 398 unregister_inet6addr_notifier(&nfsd_inet6addr_notifier); 405 399 #endif 406 400 } 401 + wait_event(nn->ntf_wq, atomic_read(&nn->ntf_refcnt) == 0); 407 402 408 403 /* 409 404 * write_ports can create the server without actually starting ··· 524 517 register_inet6addr_notifier(&nfsd_inet6addr_notifier); 525 518 #endif 526 519 } 520 + atomic_inc(&nn->ntf_refcnt); 527 521 ktime_get_real_ts64(&nn->nfssvc_boot); /* record boot time */ 528 522 return 0; 529 523 }
+1 -1
include/linux/sunrpc/cache.h
··· 213 213 extern int cache_register_net(struct cache_detail *cd, struct net *net); 214 214 extern void cache_unregister_net(struct cache_detail *cd, struct net *net); 215 215 216 - extern struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net); 216 + extern struct cache_detail *cache_create_net(const struct cache_detail *tmpl, struct net *net); 217 217 extern void cache_destroy_net(struct cache_detail *cd, struct net *net); 218 218 219 219 extern void sunrpc_init_cache_detail(struct cache_detail *cd);
+2 -2
net/sunrpc/auth_gss/svcauth_gss.c
··· 264 264 return status; 265 265 } 266 266 267 - static struct cache_detail rsi_cache_template = { 267 + static const struct cache_detail rsi_cache_template = { 268 268 .owner = THIS_MODULE, 269 269 .hash_size = RSI_HASHMAX, 270 270 .name = "auth.rpcsec.init", ··· 524 524 return status; 525 525 } 526 526 527 - static struct cache_detail rsc_cache_template = { 527 + static const struct cache_detail rsc_cache_template = { 528 528 .owner = THIS_MODULE, 529 529 .hash_size = RSC_HASHMAX, 530 530 .name = "auth.rpcsec.context",
+1 -1
net/sunrpc/cache.c
··· 1674 1674 } 1675 1675 EXPORT_SYMBOL_GPL(cache_unregister_net); 1676 1676 1677 - struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net) 1677 + struct cache_detail *cache_create_net(const struct cache_detail *tmpl, struct net *net) 1678 1678 { 1679 1679 struct cache_detail *cd; 1680 1680 int i;
+2 -2
net/sunrpc/svcauth_unix.c
··· 569 569 return 0; 570 570 } 571 571 572 - static struct cache_detail unix_gid_cache_template = { 572 + static const struct cache_detail unix_gid_cache_template = { 573 573 .owner = THIS_MODULE, 574 574 .hash_size = GID_HASHMAX, 575 575 .name = "auth.unix.gid", ··· 862 862 .set_client = svcauth_unix_set_client, 863 863 }; 864 864 865 - static struct cache_detail ip_map_cache_template = { 865 + static const struct cache_detail ip_map_cache_template = { 866 866 .owner = THIS_MODULE, 867 867 .hash_size = IP_HASHMAX, 868 868 .name = "auth.unix.ip",