|
@@ -3144,9 +3144,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
|
|
|
default:
|
|
|
BUG();
|
|
|
}
|
|
|
- if (res < 0)
|
|
|
- printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
|
|
|
- __FUNCTION__);
|
|
|
return res;
|
|
|
}
|
|
|
|
|
@@ -3258,8 +3255,6 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
}
|
|
|
|
|
|
- /* Unlock _before_ we do the RPC call */
|
|
|
- do_vfs_lock(fl->fl_file, fl);
|
|
|
return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
|
|
|
}
|
|
|
|
|
@@ -3270,30 +3265,28 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
|
|
|
struct rpc_task *task;
|
|
|
int status = 0;
|
|
|
|
|
|
- /* Is this a delegated lock? */
|
|
|
- if (test_bit(NFS_DELEGATED_STATE, &state->flags))
|
|
|
- goto out_unlock;
|
|
|
- /* Is this open_owner holding any locks on the server? */
|
|
|
- if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
|
|
|
- goto out_unlock;
|
|
|
-
|
|
|
status = nfs4_set_lock_state(state, request);
|
|
|
+ /* Unlock _before_ we do the RPC call */
|
|
|
+ request->fl_flags |= FL_EXISTS;
|
|
|
+ if (do_vfs_lock(request->fl_file, request) == -ENOENT)
|
|
|
+ goto out;
|
|
|
if (status != 0)
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
+ /* Is this a delegated lock? */
|
|
|
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags))
|
|
|
+ goto out;
|
|
|
lsp = request->fl_u.nfs4_fl.owner;
|
|
|
- status = -ENOMEM;
|
|
|
seqid = nfs_alloc_seqid(&lsp->ls_seqid);
|
|
|
+ status = -ENOMEM;
|
|
|
if (seqid == NULL)
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid);
|
|
|
status = PTR_ERR(task);
|
|
|
if (IS_ERR(task))
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
status = nfs4_wait_for_completion_rpc_task(task);
|
|
|
rpc_release_task(task);
|
|
|
- return status;
|
|
|
-out_unlock:
|
|
|
- do_vfs_lock(request->fl_file, request);
|
|
|
+out:
|
|
|
return status;
|
|
|
}
|
|
|
|
|
@@ -3461,10 +3454,10 @@ 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 {
|
|
|
+ /* Cache the lock if possible... */
|
|
|
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
|
|
|
+ return 0;
|
|
|
err = _nfs4_do_setlk(state, F_SETLK, request, 1);
|
|
|
if (err != -NFS4ERR_DELAY)
|
|
|
break;
|
|
@@ -3483,6 +3476,8 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
|
|
|
if (err != 0)
|
|
|
return err;
|
|
|
do {
|
|
|
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
|
|
|
+ return 0;
|
|
|
err = _nfs4_do_setlk(state, F_SETLK, request, 0);
|
|
|
if (err != -NFS4ERR_DELAY)
|
|
|
break;
|
|
@@ -3494,29 +3489,42 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
|
|
|
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
|
|
|
{
|
|
|
struct nfs4_client *clp = state->owner->so_client;
|
|
|
+ unsigned char fl_flags = request->fl_flags;
|
|
|
int status;
|
|
|
|
|
|
/* Is this a delegated open? */
|
|
|
- if (NFS_I(state->inode)->delegation_state != 0) {
|
|
|
- /* 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))
|
|
|
- return status;
|
|
|
- }
|
|
|
- down_read(&clp->cl_sem);
|
|
|
status = nfs4_set_lock_state(state, request);
|
|
|
if (status != 0)
|
|
|
goto out;
|
|
|
+ request->fl_flags |= FL_ACCESS;
|
|
|
+ status = do_vfs_lock(request->fl_file, request);
|
|
|
+ if (status < 0)
|
|
|
+ goto out;
|
|
|
+ down_read(&clp->cl_sem);
|
|
|
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
|
|
|
+ struct nfs_inode *nfsi = NFS_I(state->inode);
|
|
|
+ /* Yes: cache locks! */
|
|
|
+ down_read(&nfsi->rwsem);
|
|
|
+ /* ...but avoid races with delegation recall... */
|
|
|
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
|
|
|
+ request->fl_flags = fl_flags & ~FL_SLEEP;
|
|
|
+ status = do_vfs_lock(request->fl_file, request);
|
|
|
+ up_read(&nfsi->rwsem);
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+ up_read(&nfsi->rwsem);
|
|
|
+ }
|
|
|
status = _nfs4_do_setlk(state, cmd, request, 0);
|
|
|
if (status != 0)
|
|
|
- goto out;
|
|
|
+ goto out_unlock;
|
|
|
/* Note: we always want to sleep here! */
|
|
|
- request->fl_flags |= FL_SLEEP;
|
|
|
+ request->fl_flags = 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:
|
|
|
+out_unlock:
|
|
|
up_read(&clp->cl_sem);
|
|
|
+out:
|
|
|
+ request->fl_flags = fl_flags;
|
|
|
return status;
|
|
|
}
|
|
|
|