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>
This commit is contained in:
parent
f07f18dd6f
commit
01c3b861cd
|
@ -496,6 +496,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
|
||||||
struct nlm_host *host = req->a_host;
|
struct nlm_host *host = req->a_host;
|
||||||
struct nlm_res *resp = &req->a_res;
|
struct nlm_res *resp = &req->a_res;
|
||||||
struct nlm_wait *block = NULL;
|
struct nlm_wait *block = NULL;
|
||||||
|
unsigned char fl_flags = fl->fl_flags;
|
||||||
int status = -ENOLCK;
|
int status = -ENOLCK;
|
||||||
|
|
||||||
if (!host->h_monitored && nsm_monitor(host) < 0) {
|
if (!host->h_monitored && nsm_monitor(host) < 0) {
|
||||||
|
@ -503,6 +504,10 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
|
||||||
host->h_name);
|
host->h_name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
fl->fl_flags |= FL_ACCESS;
|
||||||
|
status = do_vfs_lock(fl);
|
||||||
|
if (status < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
block = nlmclnt_prepare_block(host, fl);
|
block = nlmclnt_prepare_block(host, fl);
|
||||||
again:
|
again:
|
||||||
|
@ -537,8 +542,8 @@ again:
|
||||||
up_read(&host->h_rwsem);
|
up_read(&host->h_rwsem);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
fl->fl_flags |= FL_SLEEP;
|
|
||||||
/* Ensure the resulting lock will get added to granted list */
|
/* Ensure the resulting lock will get added to granted list */
|
||||||
|
fl->fl_flags = fl_flags | FL_SLEEP;
|
||||||
if (do_vfs_lock(fl) < 0)
|
if (do_vfs_lock(fl) < 0)
|
||||||
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
|
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
|
||||||
up_read(&host->h_rwsem);
|
up_read(&host->h_rwsem);
|
||||||
|
@ -551,6 +556,7 @@ out_unblock:
|
||||||
nlmclnt_cancel(host, req->a_args.block, fl);
|
nlmclnt_cancel(host, req->a_args.block, fl);
|
||||||
out:
|
out:
|
||||||
nlm_release_call(req);
|
nlm_release_call(req);
|
||||||
|
fl->fl_flags = fl_flags;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3489,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)
|
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
|
||||||
{
|
{
|
||||||
struct nfs4_client *clp = state->owner->so_client;
|
struct nfs4_client *clp = state->owner->so_client;
|
||||||
|
unsigned char fl_flags = request->fl_flags;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* Is this a delegated open? */
|
/* 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);
|
status = nfs4_set_lock_state(state, request);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
goto out;
|
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);
|
status = _nfs4_do_setlk(state, cmd, request, 0);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
goto out;
|
goto out_unlock;
|
||||||
/* Note: we always want to sleep here! */
|
/* 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)
|
if (do_vfs_lock(request->fl_file, request) < 0)
|
||||||
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
|
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
|
||||||
out:
|
out_unlock:
|
||||||
up_read(&clp->cl_sem);
|
up_read(&clp->cl_sem);
|
||||||
|
out:
|
||||||
|
request->fl_flags = fl_flags;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue