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

lockd: NLM grace period shouldn't block NFSv4 opens

NLM locks don't conflict with NFSv4 share reservations, so we're not
going to learn anything new by watiting for them.

They do conflict with NFSv4 locks and with delegations.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>

+37 -9
+1
fs/lockd/svc.c
··· 591 591 592 592 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender); 593 593 INIT_LIST_HEAD(&ln->lockd_manager.list); 594 + ln->lockd_manager.block_opens = false; 594 595 spin_lock_init(&ln->nsm_clnt_lock); 595 596 return 0; 596 597 }
+21 -2
fs/nfs_common/grace.c
··· 63 63 * lock reclaims. 64 64 */ 65 65 int 66 - locks_in_grace(struct net *net) 66 + __state_in_grace(struct net *net, bool open) 67 67 { 68 68 struct list_head *grace_list = net_generic(net, grace_net_id); 69 + struct lock_manager *lm; 69 70 70 - return !list_empty(grace_list); 71 + if (!open) 72 + return !list_empty(grace_list); 73 + 74 + list_for_each_entry(lm, grace_list, list) { 75 + if (lm->block_opens) 76 + return true; 77 + } 78 + return false; 79 + } 80 + 81 + int locks_in_grace(struct net *net) 82 + { 83 + return __state_in_grace(net, 0); 71 84 } 72 85 EXPORT_SYMBOL_GPL(locks_in_grace); 86 + 87 + int opens_in_grace(struct net *net) 88 + { 89 + return __state_in_grace(net, 1); 90 + } 91 + EXPORT_SYMBOL_GPL(opens_in_grace); 73 92 74 93 static int __net_init 75 94 grace_init_net(struct net *net)
+4 -4
fs/nfsd/nfs4proc.c
··· 415 415 /* Openowner is now set, so sequence id will get bumped. Now we need 416 416 * these checks before we do any creates: */ 417 417 status = nfserr_grace; 418 - if (locks_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 418 + if (opens_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 419 419 goto out; 420 420 status = nfserr_no_grace; 421 - if (!locks_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) 421 + if (!opens_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) 422 422 goto out; 423 423 424 424 switch (open->op_claim_type) { ··· 827 827 { 828 828 __be32 status; 829 829 830 - if (locks_in_grace(SVC_NET(rqstp))) 830 + if (opens_in_grace(SVC_NET(rqstp))) 831 831 return nfserr_grace; 832 832 status = nfsd_unlink(rqstp, &cstate->current_fh, 0, 833 833 remove->rm_name, remove->rm_namelen); ··· 846 846 847 847 if (!cstate->save_fh.fh_dentry) 848 848 return status; 849 - if (locks_in_grace(SVC_NET(rqstp)) && 849 + if (opens_in_grace(SVC_NET(rqstp)) && 850 850 !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK)) 851 851 return nfserr_grace; 852 852 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
+5 -3
fs/nfsd/nfs4state.c
··· 4065 4065 case NFS4_OPEN_CLAIM_FH: 4066 4066 /* 4067 4067 * Let's not give out any delegations till everyone's 4068 - * had the chance to reclaim theirs.... 4068 + * had the chance to reclaim theirs, *and* until 4069 + * NLM locks have all been reclaimed: 4069 4070 */ 4070 4071 if (locks_in_grace(clp->net)) 4071 4072 goto out_no_deleg; ··· 4441 4440 { 4442 4441 if (ONE_STATEID(stateid) && (flags & RD_STATE)) 4443 4442 return nfs_ok; 4444 - else if (locks_in_grace(net)) { 4443 + else if (opens_in_grace(net)) { 4445 4444 /* Answer in remaining cases depends on existence of 4446 4445 * conflicting state; so we must wait out the grace period. */ 4447 4446 return nfserr_grace; ··· 4460 4459 static inline int 4461 4460 grace_disallows_io(struct net *net, struct inode *inode) 4462 4461 { 4463 - return locks_in_grace(net) && mandatory_lock(inode); 4462 + return opens_in_grace(net) && mandatory_lock(inode); 4464 4463 } 4465 4464 4466 4465 /* Returns true iff a is later than b: */ ··· 6579 6578 return ret; 6580 6579 nn->boot_time = get_seconds(); 6581 6580 nn->grace_ended = false; 6581 + nn->nfsd4_manager.block_opens = true; 6582 6582 locks_start_grace(net, &nn->nfsd4_manager); 6583 6583 nfsd4_client_tracking_init(net); 6584 6584 printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
+6
include/linux/fs.h
··· 942 942 943 943 struct lock_manager { 944 944 struct list_head list; 945 + /* 946 + * NFSv4 and up also want opens blocked during the grace period; 947 + * NLM doesn't care: 948 + */ 949 + bool block_opens; 945 950 }; 946 951 947 952 struct net; 948 953 void locks_start_grace(struct net *, struct lock_manager *); 949 954 void locks_end_grace(struct lock_manager *); 950 955 int locks_in_grace(struct net *); 956 + int opens_in_grace(struct net *); 951 957 952 958 /* that will die - we need it for nfs_lock_info */ 953 959 #include <linux/nfs_fs_i.h>