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 | |
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>
-rw-r--r-- | fs/lockd/clntproc.c | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 35 |
2 files changed, 31 insertions, 12 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 24c691f5480e..89ba0df14c22 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -496,6 +496,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) | |||
496 | struct nlm_host *host = req->a_host; | 496 | struct nlm_host *host = req->a_host; |
497 | struct nlm_res *resp = &req->a_res; | 497 | struct nlm_res *resp = &req->a_res; |
498 | struct nlm_wait *block = NULL; | 498 | struct nlm_wait *block = NULL; |
499 | unsigned char fl_flags = fl->fl_flags; | ||
499 | int status = -ENOLCK; | 500 | int status = -ENOLCK; |
500 | 501 | ||
501 | if (!host->h_monitored && nsm_monitor(host) < 0) { | 502 | if (!host->h_monitored && nsm_monitor(host) < 0) { |
@@ -503,6 +504,10 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) | |||
503 | host->h_name); | 504 | host->h_name); |
504 | goto out; | 505 | goto out; |
505 | } | 506 | } |
507 | fl->fl_flags |= FL_ACCESS; | ||
508 | status = do_vfs_lock(fl); | ||
509 | if (status < 0) | ||
510 | goto out; | ||
506 | 511 | ||
507 | block = nlmclnt_prepare_block(host, fl); | 512 | block = nlmclnt_prepare_block(host, fl); |
508 | again: | 513 | again: |
@@ -537,8 +542,8 @@ again: | |||
537 | up_read(&host->h_rwsem); | 542 | up_read(&host->h_rwsem); |
538 | goto again; | 543 | goto again; |
539 | } | 544 | } |
540 | fl->fl_flags |= FL_SLEEP; | ||
541 | /* Ensure the resulting lock will get added to granted list */ | 545 | /* Ensure the resulting lock will get added to granted list */ |
546 | fl->fl_flags = fl_flags | FL_SLEEP; | ||
542 | if (do_vfs_lock(fl) < 0) | 547 | if (do_vfs_lock(fl) < 0) |
543 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); | 548 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); |
544 | up_read(&host->h_rwsem); | 549 | up_read(&host->h_rwsem); |
@@ -551,6 +556,7 @@ out_unblock: | |||
551 | nlmclnt_cancel(host, req->a_args.block, fl); | 556 | nlmclnt_cancel(host, req->a_args.block, fl); |
552 | out: | 557 | out: |
553 | nlm_release_call(req); | 558 | nlm_release_call(req); |
559 | fl->fl_flags = fl_flags; | ||
554 | return status; | 560 | return status; |
555 | } | 561 | } |
556 | 562 | ||
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 | ||