OSDN Git Service

NFSv4: nfs_update_inplace_delegation() should update delegation cred
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 27 Jan 2020 17:44:41 +0000 (12:44 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 16 Mar 2020 12:34:28 +0000 (08:34 -0400)
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>
fs/nfs/delegation.c

index 1865322..509b723 100644 (file)
@@ -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);
+               }
        }
 }