diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-02-07 10:54:07 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-02-11 15:33:13 -0500 |
commit | 65b62a29f719e937b5be1df472287f4c61e53ac6 (patch) | |
tree | ea6b552a08883d92cfedb891044fa9697cbc5619 /fs/nfs/nfs4proc.c | |
parent | 37380e4264dbda9753e470a30d4322097aab7152 (diff) |
NFSv4: Ensure delegation recall and byte range lock removal don't conflict
Add a mutex to the struct nfs4_state_owner to ensure that delegation
recall doesn't conflict with byte range lock removal.
Note that we nest the new mutex _outside_ the state manager reclaim
protection (nfsi->rwsem) in order to avoid deadlocks.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f7e05ade5572..d51227371c67 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -4485,7 +4485,9 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
4485 | 4485 | ||
4486 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | 4486 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) |
4487 | { | 4487 | { |
4488 | struct nfs_inode *nfsi = NFS_I(state->inode); | 4488 | struct inode *inode = state->inode; |
4489 | struct nfs4_state_owner *sp = state->owner; | ||
4490 | struct nfs_inode *nfsi = NFS_I(inode); | ||
4489 | struct nfs_seqid *seqid; | 4491 | struct nfs_seqid *seqid; |
4490 | struct nfs4_lock_state *lsp; | 4492 | struct nfs4_lock_state *lsp; |
4491 | struct rpc_task *task; | 4493 | struct rpc_task *task; |
@@ -4495,12 +4497,17 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
4495 | status = nfs4_set_lock_state(state, request); | 4497 | status = nfs4_set_lock_state(state, request); |
4496 | /* Unlock _before_ we do the RPC call */ | 4498 | /* Unlock _before_ we do the RPC call */ |
4497 | request->fl_flags |= FL_EXISTS; | 4499 | request->fl_flags |= FL_EXISTS; |
4500 | /* Exclude nfs_delegation_claim_locks() */ | ||
4501 | mutex_lock(&sp->so_delegreturn_mutex); | ||
4502 | /* Exclude nfs4_reclaim_open_stateid() - note nesting! */ | ||
4498 | down_read(&nfsi->rwsem); | 4503 | down_read(&nfsi->rwsem); |
4499 | if (do_vfs_lock(request->fl_file, request) == -ENOENT) { | 4504 | if (do_vfs_lock(request->fl_file, request) == -ENOENT) { |
4500 | up_read(&nfsi->rwsem); | 4505 | up_read(&nfsi->rwsem); |
4506 | mutex_unlock(&sp->so_delegreturn_mutex); | ||
4501 | goto out; | 4507 | goto out; |
4502 | } | 4508 | } |
4503 | up_read(&nfsi->rwsem); | 4509 | up_read(&nfsi->rwsem); |
4510 | mutex_unlock(&sp->so_delegreturn_mutex); | ||
4504 | if (status != 0) | 4511 | if (status != 0) |
4505 | goto out; | 4512 | goto out; |
4506 | /* Is this a delegated lock? */ | 4513 | /* Is this a delegated lock? */ |