diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-09-22 19:39:12 +0200 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2016-09-27 20:34:54 +0200 |
commit | b1a318de9bc4946ad4a20481ab3ce28c2e8cd72c (patch) | |
tree | e130b82c8bb97e7eec1adba8dc4f06aa6958d343 /fs/nfs/delegation.c | |
parent | NFSv4: Pass the stateid to the exception handler in nfs4_read/write_done_cb (diff) | |
download | linux-b1a318de9bc4946ad4a20481ab3ce28c2e8cd72c.tar.xz linux-b1a318de9bc4946ad4a20481ab3ce28c2e8cd72c.zip |
NFSv4: Fix a race in nfs_inode_reclaim_delegation()
If we race with a delegreturn before taking the spin lock, we
currently end up dropping the delegation stateid.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Tested-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r-- | fs/nfs/delegation.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 5de4cfb2ab07..094e0efe6a82 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -195,15 +195,13 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, rcu_read_unlock(); put_rpccred(oldcred); trace_nfs4_reclaim_delegation(inode, res->delegation_type); - } else { - /* We appear to have raced with a delegation return. */ - spin_unlock(&delegation->lock); - rcu_read_unlock(); - nfs_inode_set_delegation(inode, cred, res); + return; } - } else { - rcu_read_unlock(); + /* We appear to have raced with a delegation return. */ + spin_unlock(&delegation->lock); } + rcu_read_unlock(); + nfs_inode_set_delegation(inode, cred, res); } static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) |