diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-01 18:57:06 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-19 16:53:30 -0400 |
commit | 4a9af59fee0701d9db99bc148d87b8852d6d6dd8 (patch) | |
tree | 5300720549fa750dc81b39a2ae5238840906a8ca /fs/lockd/clntproc.c | |
parent | 1e799b673c6b82b336ab13c48b5651d511ca3000 (diff) |
NLM/lockd: Ensure we don't corrupt fl->fl_flags in nlmclnt_unlock()
Also fix up nlmclnt_lock() so that it doesn't pass modified versions of
fl->fl_flags to nlmclnt_cancel() and other helpers.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/lockd/clntproc.c')
-rw-r--r-- | fs/lockd/clntproc.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index b6b74a60e1eb..4e1c0123b45d 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -493,6 +493,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) | |||
493 | } | 493 | } |
494 | fl->fl_flags |= FL_ACCESS; | 494 | fl->fl_flags |= FL_ACCESS; |
495 | status = do_vfs_lock(fl); | 495 | status = do_vfs_lock(fl); |
496 | fl->fl_flags = fl_flags; | ||
496 | if (status < 0) | 497 | if (status < 0) |
497 | goto out; | 498 | goto out; |
498 | 499 | ||
@@ -530,10 +531,11 @@ again: | |||
530 | goto again; | 531 | goto again; |
531 | } | 532 | } |
532 | /* Ensure the resulting lock will get added to granted list */ | 533 | /* Ensure the resulting lock will get added to granted list */ |
533 | fl->fl_flags = fl_flags | FL_SLEEP; | 534 | fl->fl_flags |= FL_SLEEP; |
534 | if (do_vfs_lock(fl) < 0) | 535 | if (do_vfs_lock(fl) < 0) |
535 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); | 536 | printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); |
536 | up_read(&host->h_rwsem); | 537 | up_read(&host->h_rwsem); |
538 | fl->fl_flags = fl_flags; | ||
537 | } | 539 | } |
538 | status = nlm_stat_to_errno(resp->status); | 540 | status = nlm_stat_to_errno(resp->status); |
539 | out_unblock: | 541 | out_unblock: |
@@ -543,7 +545,6 @@ out_unblock: | |||
543 | nlmclnt_cancel(host, req->a_args.block, fl); | 545 | nlmclnt_cancel(host, req->a_args.block, fl); |
544 | out: | 546 | out: |
545 | nlm_release_call(req); | 547 | nlm_release_call(req); |
546 | fl->fl_flags = fl_flags; | ||
547 | return status; | 548 | return status; |
548 | } | 549 | } |
549 | 550 | ||
@@ -598,7 +599,8 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) | |||
598 | { | 599 | { |
599 | struct nlm_host *host = req->a_host; | 600 | struct nlm_host *host = req->a_host; |
600 | struct nlm_res *resp = &req->a_res; | 601 | struct nlm_res *resp = &req->a_res; |
601 | int status = 0; | 602 | int status; |
603 | unsigned char fl_flags = fl->fl_flags; | ||
602 | 604 | ||
603 | /* | 605 | /* |
604 | * Note: the server is supposed to either grant us the unlock | 606 | * Note: the server is supposed to either grant us the unlock |
@@ -607,11 +609,13 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) | |||
607 | */ | 609 | */ |
608 | fl->fl_flags |= FL_EXISTS; | 610 | fl->fl_flags |= FL_EXISTS; |
609 | down_read(&host->h_rwsem); | 611 | down_read(&host->h_rwsem); |
610 | if (do_vfs_lock(fl) == -ENOENT) { | 612 | status = do_vfs_lock(fl); |
611 | up_read(&host->h_rwsem); | 613 | up_read(&host->h_rwsem); |
614 | fl->fl_flags = fl_flags; | ||
615 | if (status == -ENOENT) { | ||
616 | status = 0; | ||
612 | goto out; | 617 | goto out; |
613 | } | 618 | } |
614 | up_read(&host->h_rwsem); | ||
615 | 619 | ||
616 | if (req->a_flags & RPC_TASK_ASYNC) | 620 | if (req->a_flags & RPC_TASK_ASYNC) |
617 | return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); | 621 | return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); |