summaryrefslogtreecommitdiff
path: root/fs/nfs/delegation.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2020-01-27 12:44:41 -0500
committerTrond Myklebust <trond.myklebust@hammerspace.com>2020-03-16 08:34:28 -0400
commit57f188e047731e50cb6af94d473c3c70d3bce7f9 (patch)
tree81b4d1bfff5b0727f3cad56298d9cdc21dd63c71 /fs/nfs/delegation.c
parent59e356a967c403b6b8dcb0035edbe0c45a84ac85 (diff)
downloadlinux-rpi-57f188e047731e50cb6af94d473c3c70d3bce7f9.tar.gz
linux-rpi-57f188e047731e50cb6af94d473c3c70d3bce7f9.tar.bz2
linux-rpi-57f188e047731e50cb6af94d473c3c70d3bce7f9.zip
NFSv4: nfs_update_inplace_delegation() should update delegation cred
If the cred assigned to the delegation that we're updating differs from the one we're updating too, then we need to update that field too. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r--fs/nfs/delegation.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 1865322de142..509b7235b132 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -378,6 +378,18 @@ nfs_inode_detach_delegation(struct inode *inode)
}
static void
+nfs_update_delegation_cred(struct nfs_delegation *delegation,
+ const struct cred *cred)
+{
+ const struct cred *old;
+
+ if (cred_fscmp(delegation->cred, cred) != 0) {
+ old = xchg(&delegation->cred, get_cred(cred));
+ put_cred(old);
+ }
+}
+
+static void
nfs_update_inplace_delegation(struct nfs_delegation *delegation,
const struct nfs_delegation *update)
{
@@ -385,8 +397,14 @@ nfs_update_inplace_delegation(struct nfs_delegation *delegation,
delegation->stateid.seqid = update->stateid.seqid;
smp_wmb();
delegation->type = update->type;
- if (test_and_clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
+ delegation->pagemod_limit = update->pagemod_limit;
+ if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
+ delegation->change_attr = update->change_attr;
+ nfs_update_delegation_cred(delegation, update->cred);
+ /* smp_mb__before_atomic() is implicit due to xchg() */
+ clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
atomic_long_inc(&nfs_active_delegations);
+ }
}
}