aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/glock.c66
-rw-r--r--fs/gfs2/incore.h2
2 files changed, 44 insertions, 24 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index fb1960b7fdde..5341e03b873f 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -19,6 +19,7 @@
19#include <linux/gfs2_ondisk.h> 19#include <linux/gfs2_ondisk.h>
20#include <linux/list.h> 20#include <linux/list.h>
21#include <linux/lm_interface.h> 21#include <linux/lm_interface.h>
22#include <linux/wait.h>
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
24#include "gfs2.h" 25#include "gfs2.h"
@@ -395,7 +396,6 @@ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
395 gh->gh_flags = flags; 396 gh->gh_flags = flags;
396 gh->gh_error = 0; 397 gh->gh_error = 0;
397 gh->gh_iflags = 0; 398 gh->gh_iflags = 0;
398 init_completion(&gh->gh_wait);
399 399
400 if (gh->gh_state == LM_ST_EXCLUSIVE) 400 if (gh->gh_state == LM_ST_EXCLUSIVE)
401 gh->gh_flags |= GL_LOCAL_EXCL; 401 gh->gh_flags |= GL_LOCAL_EXCL;
@@ -479,6 +479,29 @@ static void gfs2_holder_put(struct gfs2_holder *gh)
479 kfree(gh); 479 kfree(gh);
480} 480}
481 481
482static void gfs2_holder_dispose_or_wake(struct gfs2_holder *gh)
483{
484 if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) {
485 gfs2_holder_put(gh);
486 return;
487 }
488 clear_bit(HIF_WAIT, &gh->gh_iflags);
489 smp_mb();
490 wake_up_bit(&gh->gh_iflags, HIF_WAIT);
491}
492
493static int holder_wait(void *word)
494{
495 schedule();
496 return 0;
497}
498
499static void wait_on_holder(struct gfs2_holder *gh)
500{
501 might_sleep();
502 wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE);
503}
504
482/** 505/**
483 * rq_mutex - process a mutex request in the queue 506 * rq_mutex - process a mutex request in the queue
484 * @gh: the glock holder 507 * @gh: the glock holder
@@ -493,7 +516,9 @@ static int rq_mutex(struct gfs2_holder *gh)
493 list_del_init(&gh->gh_list); 516 list_del_init(&gh->gh_list);
494 /* gh->gh_error never examined. */ 517 /* gh->gh_error never examined. */
495 set_bit(GLF_LOCK, &gl->gl_flags); 518 set_bit(GLF_LOCK, &gl->gl_flags);
496 complete(&gh->gh_wait); 519 clear_bit(HIF_WAIT, &gh->gh_flags);
520 smp_mb();
521 wake_up_bit(&gh->gh_iflags, HIF_WAIT);
497 522
498 return 1; 523 return 1;
499} 524}
@@ -549,7 +574,7 @@ static int rq_promote(struct gfs2_holder *gh)
549 gh->gh_error = 0; 574 gh->gh_error = 0;
550 set_bit(HIF_HOLDER, &gh->gh_iflags); 575 set_bit(HIF_HOLDER, &gh->gh_iflags);
551 576
552 complete(&gh->gh_wait); 577 gfs2_holder_dispose_or_wake(gh);
553 578
554 return 0; 579 return 0;
555} 580}
@@ -573,10 +598,7 @@ static int rq_demote(struct gfs2_holder *gh)
573 list_del_init(&gh->gh_list); 598 list_del_init(&gh->gh_list);
574 gh->gh_error = 0; 599 gh->gh_error = 0;
575 spin_unlock(&gl->gl_spin); 600 spin_unlock(&gl->gl_spin);
576 if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) 601 gfs2_holder_dispose_or_wake(gh);
577 gfs2_holder_put(gh);
578 else
579 complete(&gh->gh_wait);
580 spin_lock(&gl->gl_spin); 602 spin_lock(&gl->gl_spin);
581 } else { 603 } else {
582 gl->gl_req_gh = gh; 604 gl->gl_req_gh = gh;
@@ -684,6 +706,8 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl)
684 706
685 gfs2_holder_init(gl, 0, 0, &gh); 707 gfs2_holder_init(gl, 0, 0, &gh);
686 set_bit(HIF_MUTEX, &gh.gh_iflags); 708 set_bit(HIF_MUTEX, &gh.gh_iflags);
709 if (test_and_set_bit(HIF_WAIT, &gh.gh_iflags))
710 BUG();
687 711
688 spin_lock(&gl->gl_spin); 712 spin_lock(&gl->gl_spin);
689 if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { 713 if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
@@ -691,11 +715,13 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl)
691 } else { 715 } else {
692 gl->gl_owner = current; 716 gl->gl_owner = current;
693 gl->gl_ip = (unsigned long)__builtin_return_address(0); 717 gl->gl_ip = (unsigned long)__builtin_return_address(0);
694 complete(&gh.gh_wait); 718 clear_bit(HIF_WAIT, &gh.gh_iflags);
719 smp_mb();
720 wake_up_bit(&gh.gh_iflags, HIF_WAIT);
695 } 721 }
696 spin_unlock(&gl->gl_spin); 722 spin_unlock(&gl->gl_spin);
697 723
698 wait_for_completion(&gh.gh_wait); 724 wait_on_holder(&gh);
699 gfs2_holder_uninit(&gh); 725 gfs2_holder_uninit(&gh);
700} 726}
701 727
@@ -774,6 +800,7 @@ restart:
774 return; 800 return;
775 set_bit(HIF_DEMOTE, &new_gh->gh_iflags); 801 set_bit(HIF_DEMOTE, &new_gh->gh_iflags);
776 set_bit(HIF_DEALLOC, &new_gh->gh_iflags); 802 set_bit(HIF_DEALLOC, &new_gh->gh_iflags);
803 set_bit(HIF_WAIT, &new_gh->gh_iflags);
777 804
778 goto restart; 805 goto restart;
779 } 806 }
@@ -908,12 +935,8 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
908 935
909 gfs2_glock_put(gl); 936 gfs2_glock_put(gl);
910 937
911 if (gh) { 938 if (gh)
912 if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) 939 gfs2_holder_dispose_or_wake(gh);
913 gfs2_holder_put(gh);
914 else
915 complete(&gh->gh_wait);
916 }
917} 940}
918 941
919/** 942/**
@@ -999,12 +1022,8 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
999 1022
1000 gfs2_glock_put(gl); 1023 gfs2_glock_put(gl);
1001 1024
1002 if (gh) { 1025 if (gh)
1003 if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) 1026 gfs2_holder_dispose_or_wake(gh);
1004 gfs2_holder_put(gh);
1005 else
1006 complete(&gh->gh_wait);
1007 }
1008} 1027}
1009 1028
1010/** 1029/**
@@ -1105,8 +1124,7 @@ static int glock_wait_internal(struct gfs2_holder *gh)
1105 if (gh->gh_flags & LM_FLAG_PRIORITY) 1124 if (gh->gh_flags & LM_FLAG_PRIORITY)
1106 do_cancels(gh); 1125 do_cancels(gh);
1107 1126
1108 wait_for_completion(&gh->gh_wait); 1127 wait_on_holder(gh);
1109
1110 if (gh->gh_error) 1128 if (gh->gh_error)
1111 return gh->gh_error; 1129 return gh->gh_error;
1112 1130
@@ -1162,6 +1180,8 @@ static void add_to_queue(struct gfs2_holder *gh)
1162 struct gfs2_holder *existing; 1180 struct gfs2_holder *existing;
1163 1181
1164 BUG_ON(!gh->gh_owner); 1182 BUG_ON(!gh->gh_owner);
1183 if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags))
1184 BUG();
1165 1185
1166 existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner); 1186 existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner);
1167 if (existing) { 1187 if (existing) {
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 9114851ac53e..a24c4af09ce0 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -128,6 +128,7 @@ enum {
128 HIF_HOLDER = 6, 128 HIF_HOLDER = 6,
129 HIF_FIRST = 7, 129 HIF_FIRST = 7,
130 HIF_ABORTED = 9, 130 HIF_ABORTED = 9,
131 HIF_WAIT = 10,
131}; 132};
132 133
133struct gfs2_holder { 134struct gfs2_holder {
@@ -140,7 +141,6 @@ struct gfs2_holder {
140 141
141 int gh_error; 142 int gh_error;
142 unsigned long gh_iflags; 143 unsigned long gh_iflags;
143 struct completion gh_wait;
144 unsigned long gh_ip; 144 unsigned long gh_ip;
145}; 145};
146 146