summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-11-04 23:39:36 +0300
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-11-04 23:39:36 +0300
commit6bfc93ef98f00b38f1913a7fdeae46ae8dbd7c52 (patch)
tree2eb5f2fa26376b3d6ae5eebd65e93d4eec9555bd
parent888e694c167975709f17526dbbed2d98f84e8f85 (diff)
downloadlinux-6bfc93ef98f00b38f1913a7fdeae46ae8dbd7c52.tar.xz
NFSv4: Teach NFSv4 to cache locks when we hold a delegation
Now that we have a method of dealing with delegation recalls, actually enable the caching of posix and BSD locks. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4proc.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e6a9322a321f..21482b2518f6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2918,6 +2918,10 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
struct nfs4_lock_state *lsp;
int status;
+ /* Is this a delegated lock? */
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+ return do_vfs_lock(request->fl_file, request);
+
status = nfs4_set_lock_state(state, request);
if (status != 0)
return status;
@@ -3032,6 +3036,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
struct nfs4_exception exception = { };
int err;
+ /* Cache the lock if possible... */
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+ return 0;
do {
err = _nfs4_do_setlk(state, F_SETLK, request, 1);
if (err != -NFS4ERR_DELAY)
@@ -3047,6 +3054,9 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
struct nfs4_exception exception = { };
int err;
+ err = nfs4_set_lock_state(state, request);
+ if (err != 0)
+ return err;
do {
err = _nfs4_do_setlk(state, F_SETLK, request, 0);
if (err != -NFS4ERR_DELAY)
@@ -3062,15 +3072,25 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
int status;
down_read(&clp->cl_sem);
- status = nfs4_set_lock_state(state, request);
- if (status == 0)
- status = _nfs4_do_setlk(state, cmd, request, 0);
- if (status == 0) {
- /* Note: we always want to sleep here! */
- request->fl_flags |= FL_SLEEP;
- if (do_vfs_lock(request->fl_file, request) < 0)
- printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
+ /* Is this a delegated open? */
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+ /* Yes: cache locks! */
+ status = do_vfs_lock(request->fl_file, request);
+ /* ...but avoid races with delegation recall... */
+ if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags))
+ goto out;
}
+ status = nfs4_set_lock_state(state, request);
+ if (status != 0)
+ goto out;
+ status = _nfs4_do_setlk(state, cmd, request, 0);
+ if (status != 0)
+ goto out;
+ /* Note: we always want to sleep here! */
+ request->fl_flags |= FL_SLEEP;
+ if (do_vfs_lock(request->fl_file, request) < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
+out:
up_read(&clp->cl_sem);
return status;
}