aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2015-08-06 12:47:02 -0400
committerJ. Bruce Fields <bfields@redhat.com>2015-08-13 10:22:06 -0400
commitc87fb4a378f93f114b9906e180d83877cee4e7f4 (patch)
tree79af8260a9b9788247e37650fee5837799791723
parent4bc6603778e473938ae815123b786e724084790c (diff)
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>
-rw-r--r--fs/lockd/svc.c1
-rw-r--r--fs/nfs_common/grace.c23
-rw-r--r--fs/nfsd/nfs4proc.c8
-rw-r--r--fs/nfsd/nfs4state.c8
-rw-r--r--include/linux/fs.h6
5 files changed, 37 insertions, 9 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 530914b5c455..d678bcc3cbcb 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -591,6 +591,7 @@ static int lockd_init_net(struct net *net)
591 591
592 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender); 592 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
593 INIT_LIST_HEAD(&ln->lockd_manager.list); 593 INIT_LIST_HEAD(&ln->lockd_manager.list);
594 ln->lockd_manager.block_opens = false;
594 spin_lock_init(&ln->nsm_clnt_lock); 595 spin_lock_init(&ln->nsm_clnt_lock);
595 return 0; 596 return 0;
596} 597}
diff --git a/fs/nfs_common/grace.c b/fs/nfs_common/grace.c
index ae6e58ea4de5..fd8c9a5bcac4 100644
--- a/fs/nfs_common/grace.c
+++ b/fs/nfs_common/grace.c
@@ -63,14 +63,33 @@ EXPORT_SYMBOL_GPL(locks_end_grace);
63 * lock reclaims. 63 * lock reclaims.
64 */ 64 */
65int 65int
66locks_in_grace(struct net *net) 66__state_in_grace(struct net *net, bool open)
67{ 67{
68 struct list_head *grace_list = net_generic(net, grace_net_id); 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
81int locks_in_grace(struct net *net)
82{
83 return __state_in_grace(net, 0);
71} 84}
72EXPORT_SYMBOL_GPL(locks_in_grace); 85EXPORT_SYMBOL_GPL(locks_in_grace);
73 86
87int opens_in_grace(struct net *net)
88{
89 return __state_in_grace(net, 1);
90}
91EXPORT_SYMBOL_GPL(opens_in_grace);
92
74static int __net_init 93static int __net_init
75grace_init_net(struct net *net) 94grace_init_net(struct net *net)
76{ 95{
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e779d7db24b0..b9681ee0ed19 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -415,10 +415,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
415 /* Openowner is now set, so sequence id will get bumped. Now we need 415 /* Openowner is now set, so sequence id will get bumped. Now we need
416 * these checks before we do any creates: */ 416 * these checks before we do any creates: */
417 status = nfserr_grace; 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 goto out; 419 goto out;
420 status = nfserr_no_grace; 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 goto out; 422 goto out;
423 423
424 switch (open->op_claim_type) { 424 switch (open->op_claim_type) {
@@ -827,7 +827,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
827{ 827{
828 __be32 status; 828 __be32 status;
829 829
830 if (locks_in_grace(SVC_NET(rqstp))) 830 if (opens_in_grace(SVC_NET(rqstp)))
831 return nfserr_grace; 831 return nfserr_grace;
832 status = nfsd_unlink(rqstp, &cstate->current_fh, 0, 832 status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
833 remove->rm_name, remove->rm_namelen); 833 remove->rm_name, remove->rm_namelen);
@@ -846,7 +846,7 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
846 846
847 if (!cstate->save_fh.fh_dentry) 847 if (!cstate->save_fh.fh_dentry)
848 return status; 848 return status;
849 if (locks_in_grace(SVC_NET(rqstp)) && 849 if (opens_in_grace(SVC_NET(rqstp)) &&
850 !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK)) 850 !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
851 return nfserr_grace; 851 return nfserr_grace;
852 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, 852 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 43903abd6189..c0c47a878cc6 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4065,7 +4065,8 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
4065 case NFS4_OPEN_CLAIM_FH: 4065 case NFS4_OPEN_CLAIM_FH:
4066 /* 4066 /*
4067 * Let's not give out any delegations till everyone's 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 if (locks_in_grace(clp->net)) 4071 if (locks_in_grace(clp->net))
4071 goto out_no_deleg; 4072 goto out_no_deleg;
@@ -4440,7 +4441,7 @@ check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid,
4440{ 4441{
4441 if (ONE_STATEID(stateid) && (flags & RD_STATE)) 4442 if (ONE_STATEID(stateid) && (flags & RD_STATE))
4442 return nfs_ok; 4443 return nfs_ok;
4443 else if (locks_in_grace(net)) { 4444 else if (opens_in_grace(net)) {
4444 /* Answer in remaining cases depends on existence of 4445 /* Answer in remaining cases depends on existence of
4445 * conflicting state; so we must wait out the grace period. */ 4446 * conflicting state; so we must wait out the grace period. */
4446 return nfserr_grace; 4447 return nfserr_grace;
@@ -4459,7 +4460,7 @@ check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid,
4459static inline int 4460static inline int
4460grace_disallows_io(struct net *net, struct inode *inode) 4461grace_disallows_io(struct net *net, struct inode *inode)
4461{ 4462{
4462 return locks_in_grace(net) && mandatory_lock(inode); 4463 return opens_in_grace(net) && mandatory_lock(inode);
4463} 4464}
4464 4465
4465/* Returns true iff a is later than b: */ 4466/* Returns true iff a is later than b: */
@@ -6578,6 +6579,7 @@ nfs4_state_start_net(struct net *net)
6578 return ret; 6579 return ret;
6579 nn->boot_time = get_seconds(); 6580 nn->boot_time = get_seconds();
6580 nn->grace_ended = false; 6581 nn->grace_ended = false;
6582 nn->nfsd4_manager.block_opens = true;
6581 locks_start_grace(net, &nn->nfsd4_manager); 6583 locks_start_grace(net, &nn->nfsd4_manager);
6582 nfsd4_client_tracking_init(net); 6584 nfsd4_client_tracking_init(net);
6583 printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n", 6585 printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cc008c338f5a..9a9d314f7b27 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -942,12 +942,18 @@ struct lock_manager_operations {
942 942
943struct lock_manager { 943struct lock_manager {
944 struct list_head list; 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
947struct net; 952struct net;
948void locks_start_grace(struct net *, struct lock_manager *); 953void locks_start_grace(struct net *, struct lock_manager *);
949void locks_end_grace(struct lock_manager *); 954void locks_end_grace(struct lock_manager *);
950int locks_in_grace(struct net *); 955int locks_in_grace(struct net *);
956int opens_in_grace(struct net *);
951 957
952/* that will die - we need it for nfs_lock_info */ 958/* that will die - we need it for nfs_lock_info */
953#include <linux/nfs_fs_i.h> 959#include <linux/nfs_fs_i.h>