diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-29 16:38:39 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:18 -0400 |
commit | 01c3b861cd77b28565a2d18c7caa3ce7f938e35c (patch) | |
tree | 1445669572dd5f0e97ec0690da88eefd8bbf5acb /fs/nfs | |
parent | f07f18dd6f29f11887b8d9cf7ecb736bf2f7dc62 (diff) |
NLM,NFSv4: Wait on local locks before we put RPC calls on the wire
Use FL_ACCESS flag to test and/or wait for local locks before we try
requesting a lock from the server
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8bdfe3ff7925..e6ee97f19d81 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3489,29 +3489,42 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
3489 | static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) | 3489 | static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) |
3490 | { | 3490 | { |
3491 | struct nfs4_client *clp = state->owner->so_client; | 3491 | struct nfs4_client *clp = state->owner->so_client; |
3492 | unsigned char fl_flags = request->fl_flags; | ||
3492 | int status; | 3493 | int status; |
3493 | 3494 | ||
3494 | /* Is this a delegated open? */ | 3495 | /* Is this a delegated open? */ |
3495 | if (NFS_I(state->inode)->delegation_state != 0) { | ||
3496 | /* Yes: cache locks! */ | ||
3497 | status = do_vfs_lock(request->fl_file, request); | ||
3498 | /* ...but avoid races with delegation recall... */ | ||
3499 | if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags)) | ||
3500 | return status; | ||
3501 | } | ||
3502 | down_read(&clp->cl_sem); | ||
3503 | status = nfs4_set_lock_state(state, request); | 3496 | status = nfs4_set_lock_state(state, request); |
3504 | if (status != 0) | 3497 | if (status != 0) |
3505 | goto out; | 3498 | goto out; |
3499 | request->fl_flags |= FL_ACCESS; | ||
3500 | status = do_vfs_lock(request->fl_file, request); | ||
3501 | if (status < 0) | ||
3502 | goto out; | ||
3503 | down_read(&clp->cl_sem); | ||
3504 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { | ||
3505 | struct nfs_inode *nfsi = NFS_I(state->inode); | ||
3506 | /* Yes: cache locks! */ | ||
3507 | down_read(&nfsi->rwsem); | ||
3508 | /* ...but avoid races with delegation recall... */ | ||
3509 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { | ||
3510 | request->fl_flags = fl_flags & ~FL_SLEEP; | ||
3511 | status = do_vfs_lock(request->fl_file, request); | ||
3512 | up_read(&nfsi->rwsem); | ||
3513 | goto out_unlock; | ||
3514 | } | ||
3515 | up_read(&nfsi->rwsem); | ||
3516 | } | ||
3506 | status = _nfs4_do_setlk(state, cmd, request, 0); | 3517 | status = _nfs4_do_setlk(state, cmd, request, 0); |
3507 | if (status != 0) | 3518 | if (status != 0) |
3508 | goto out; | 3519 | goto out_unlock; |
3509 | /* Note: we always want to sleep here! */ | 3520 | /* Note: we always want to sleep here! */ |
3510 | request->fl_flags |= FL_SLEEP; | 3521 | request->fl_flags = fl_flags | FL_SLEEP; |
3511 | if (do_vfs_lock(request->fl_file, request) < 0) | 3522 | if (do_vfs_lock(request->fl_file, request) < 0) |
3512 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); | 3523 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); |
3513 | out: | 3524 | out_unlock: |
3514 | up_read(&clp->cl_sem); | 3525 | up_read(&clp->cl_sem); |
3526 | out: | ||
3527 | request->fl_flags = fl_flags; | ||
3515 | return status; | 3528 | return status; |
3516 | } | 3529 | } |
3517 | 3530 | ||