Skip to content

Commit

Permalink
lockd: NLM grace period shouldn't block NFSv4 opens
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
J. Bruce Fields committed Aug 13, 2015
1 parent 4bc6603 commit c87fb4a
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 9 deletions.
1 change: 1 addition & 0 deletions fs/lockd/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ static int lockd_init_net(struct net *net)

INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
INIT_LIST_HEAD(&ln->lockd_manager.list);
ln->lockd_manager.block_opens = false;
spin_lock_init(&ln->nsm_clnt_lock);
return 0;
}
Expand Down
23 changes: 21 additions & 2 deletions fs/nfs_common/grace.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,33 @@ EXPORT_SYMBOL_GPL(locks_end_grace);
* lock reclaims.
*/
int
locks_in_grace(struct net *net)
__state_in_grace(struct net *net, bool open)
{
struct list_head *grace_list = net_generic(net, grace_net_id);
struct lock_manager *lm;

return !list_empty(grace_list);
if (!open)
return !list_empty(grace_list);

list_for_each_entry(lm, grace_list, list) {
if (lm->block_opens)
return true;
}
return false;
}

int locks_in_grace(struct net *net)
{
return __state_in_grace(net, 0);
}
EXPORT_SYMBOL_GPL(locks_in_grace);

int opens_in_grace(struct net *net)
{
return __state_in_grace(net, 1);
}
EXPORT_SYMBOL_GPL(opens_in_grace);

static int __net_init
grace_init_net(struct net *net)
{
Expand Down
8 changes: 4 additions & 4 deletions fs/nfsd/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,10 +415,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
/* Openowner is now set, so sequence id will get bumped. Now we need
* these checks before we do any creates: */
status = nfserr_grace;
if (locks_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
if (opens_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
goto out;
status = nfserr_no_grace;
if (!locks_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
if (!opens_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
goto out;

switch (open->op_claim_type) {
Expand Down Expand Up @@ -827,7 +827,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{
__be32 status;

if (locks_in_grace(SVC_NET(rqstp)))
if (opens_in_grace(SVC_NET(rqstp)))
return nfserr_grace;
status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
remove->rm_name, remove->rm_namelen);
Expand All @@ -846,7 +846,7 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,

if (!cstate->save_fh.fh_dentry)
return status;
if (locks_in_grace(SVC_NET(rqstp)) &&
if (opens_in_grace(SVC_NET(rqstp)) &&
!(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
return nfserr_grace;
status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
Expand Down
8 changes: 5 additions & 3 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -4065,7 +4065,8 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
case NFS4_OPEN_CLAIM_FH:
/*
* Let's not give out any delegations till everyone's
* had the chance to reclaim theirs....
* had the chance to reclaim theirs, *and* until
* NLM locks have all been reclaimed:
*/
if (locks_in_grace(clp->net))
goto out_no_deleg;
Expand Down Expand Up @@ -4440,7 +4441,7 @@ check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid,
{
if (ONE_STATEID(stateid) && (flags & RD_STATE))
return nfs_ok;
else if (locks_in_grace(net)) {
else if (opens_in_grace(net)) {
/* Answer in remaining cases depends on existence of
* conflicting state; so we must wait out the grace period. */
return nfserr_grace;
Expand All @@ -4459,7 +4460,7 @@ check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid,
static inline int
grace_disallows_io(struct net *net, struct inode *inode)
{
return locks_in_grace(net) && mandatory_lock(inode);
return opens_in_grace(net) && mandatory_lock(inode);
}

/* Returns true iff a is later than b: */
Expand Down Expand Up @@ -6578,6 +6579,7 @@ nfs4_state_start_net(struct net *net)
return ret;
nn->boot_time = get_seconds();
nn->grace_ended = false;
nn->nfsd4_manager.block_opens = true;
locks_start_grace(net, &nn->nfsd4_manager);
nfsd4_client_tracking_init(net);
printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
Expand Down
6 changes: 6 additions & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -942,12 +942,18 @@ struct lock_manager_operations {

struct lock_manager {
struct list_head list;
/*
* NFSv4 and up also want opens blocked during the grace period;
* NLM doesn't care:
*/
bool block_opens;
};

struct net;
void locks_start_grace(struct net *, struct lock_manager *);
void locks_end_grace(struct lock_manager *);
int locks_in_grace(struct net *);
int opens_in_grace(struct net *);

/* that will die - we need it for nfs_lock_info */
#include <linux/nfs_fs_i.h>
Expand Down

0 comments on commit c87fb4a

Please sign in to comment.