aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/clntproc.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-09 09:40:27 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-09 09:40:27 -0400
commit28df955a2ad484d602314b30183ea8496a9aa34a (patch)
treec62632b2a0a49df114283f10764244c1b1b5f506 /fs/lockd/clntproc.c
parent5046791417dcac1ba126b77b8062af15a2f0b8e1 (diff)
NLM: Fix reclaim races
Currently it is possible for a task to remove its locks at the same time as the NLM recovery thread is trying to recover them. This quickly leads to an Oops. Protect the locks using an rw semaphore while they are being recovered. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/lockd/clntproc.c')
-rw-r--r--fs/lockd/clntproc.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index f96e38155b5c..4db62098d3f4 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -508,7 +508,10 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
508 } 508 }
509 509
510 block = nlmclnt_prepare_block(host, fl); 510 block = nlmclnt_prepare_block(host, fl);
511again:
511 for(;;) { 512 for(;;) {
513 /* Reboot protection */
514 fl->fl_u.nfs_fl.state = host->h_state;
512 status = nlmclnt_call(req, NLMPROC_LOCK); 515 status = nlmclnt_call(req, NLMPROC_LOCK);
513 if (status < 0) 516 if (status < 0)
514 goto out_unblock; 517 goto out_unblock;
@@ -531,10 +534,16 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
531 } 534 }
532 535
533 if (resp->status == NLM_LCK_GRANTED) { 536 if (resp->status == NLM_LCK_GRANTED) {
534 fl->fl_u.nfs_fl.state = host->h_state; 537 down_read(&host->h_rwsem);
538 /* Check whether or not the server has rebooted */
539 if (fl->fl_u.nfs_fl.state != host->h_state) {
540 up_read(&host->h_rwsem);
541 goto again;
542 }
535 fl->fl_flags |= FL_SLEEP; 543 fl->fl_flags |= FL_SLEEP;
536 /* Ensure the resulting lock will get added to granted list */ 544 /* Ensure the resulting lock will get added to granted list */
537 do_vfs_lock(fl); 545 do_vfs_lock(fl);
546 up_read(&host->h_rwsem);
538 } 547 }
539 status = nlm_stat_to_errno(resp->status); 548 status = nlm_stat_to_errno(resp->status);
540out_unblock: 549out_unblock:
@@ -596,6 +605,7 @@ nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl)
596static int 605static int
597nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) 606nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
598{ 607{
608 struct nlm_host *host = req->a_host;
599 struct nlm_res *resp = &req->a_res; 609 struct nlm_res *resp = &req->a_res;
600 int status; 610 int status;
601 611
@@ -604,7 +614,9 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
604 * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either 614 * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either
605 * case, we want to unlock. 615 * case, we want to unlock.
606 */ 616 */
617 down_read(&host->h_rwsem);
607 do_vfs_lock(fl); 618 do_vfs_lock(fl);
619 up_read(&host->h_rwsem);
608 620
609 if (req->a_flags & RPC_TASK_ASYNC) 621 if (req->a_flags & RPC_TASK_ASYNC)
610 return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); 622 return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);