mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-28 04:17:47 +00:00
NFSv4: Deal with atomic upgrades of an existing delegation
Ensure that we deal correctly with the case where the server sends us a newer instance of the same delegation. If the stateids match, but the sequence numbers differ, then treat the new delegation as if it were an atomic upgrade. Signed-off-by: Trond Myklebust <Trond.Myklebust@primarydata.com>
This commit is contained in:
parent
89f0ff386c
commit
cf6726e2ee
@ -301,6 +301,17 @@ nfs_inode_detach_delegation(struct inode *inode)
|
||||
return nfs_detach_delegation(nfsi, delegation, server);
|
||||
}
|
||||
|
||||
static void
|
||||
nfs_update_inplace_delegation(struct nfs_delegation *delegation,
|
||||
const struct nfs_delegation *update)
|
||||
{
|
||||
if (nfs4_stateid_is_newer(&update->stateid, &delegation->stateid)) {
|
||||
delegation->stateid.seqid = update->stateid.seqid;
|
||||
smp_wmb();
|
||||
delegation->type = update->type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_inode_set_delegation - set up a delegation on an inode
|
||||
* @inode: inode to which delegation applies
|
||||
@ -334,9 +345,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
|
||||
old_delegation = rcu_dereference_protected(nfsi->delegation,
|
||||
lockdep_is_held(&clp->cl_lock));
|
||||
if (old_delegation != NULL) {
|
||||
if (nfs4_stateid_match(&delegation->stateid,
|
||||
&old_delegation->stateid) &&
|
||||
delegation->type == old_delegation->type) {
|
||||
/* Is this an update of the existing delegation? */
|
||||
if (nfs4_stateid_match_other(&old_delegation->stateid,
|
||||
&delegation->stateid)) {
|
||||
nfs_update_inplace_delegation(old_delegation,
|
||||
delegation);
|
||||
nfsi->delegation_state = old_delegation->type;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user