aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2008-03-14 14:52:52 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2008-03-31 05:41:44 -0400
commit58e9fee13e579df44922172dbe3c9e3ba3edf7a3 (patch)
tree7b134f28032a3cd498b2d9a18c02ea085c0725e2
parentf5a8cd020173c455705fc0095b7d299da6f8f87b (diff)
[GFS2] Invalidate cache at correct point
GFS2 wasn't invalidating its cache before it called into the lock manager with a request that could potentially drop a lock. This was leaving a window where the lock could be actually be held by another node, but the file's page cache would still appear valid, causing coherency problems. This patch moves the cache invalidation to before the lock manager call when dropping a lock. It also adds the option to the lock_dlm lock manager to not use conversion mode deadlock avoidance, which, on a conversion from shared to exclusive, could internally drop the lock, and then reacquire in. GFS2 now asks lock_dlm to not do this. Instead, GFS2 manually drops the lock and reacquires it. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/glock.c35
-rw-r--r--fs/gfs2/incore.h1
-rw-r--r--fs/gfs2/locking/dlm/lock.c3
-rw-r--r--fs/gfs2/locking/dlm/thread.c10
-rw-r--r--fs/gfs2/ops_fstype.c2
-rw-r--r--include/linux/lm_interface.h10
6 files changed, 44 insertions, 17 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 63981e2fb835..d636b3e80f5d 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -764,7 +764,7 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
764static void drop_bh(struct gfs2_glock *gl, unsigned int ret) 764static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
765{ 765{
766 struct gfs2_sbd *sdp = gl->gl_sbd; 766 struct gfs2_sbd *sdp = gl->gl_sbd;
767 const struct gfs2_glock_operations *glops = gl->gl_ops; 767 struct gfs2_holder *gh = gl->gl_req_gh;
768 768
769 gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); 769 gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
770 gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); 770 gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
@@ -772,8 +772,14 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
772 772
773 state_change(gl, LM_ST_UNLOCKED); 773 state_change(gl, LM_ST_UNLOCKED);
774 774
775 if (glops->go_inval) 775 if (test_and_clear_bit(GLF_CONV_DEADLK, &gl->gl_flags)) {
776 glops->go_inval(gl, DIO_METADATA); 776 spin_lock(&gl->gl_spin);
777 gh->gh_error = 0;
778 spin_unlock(&gl->gl_spin);
779 gfs2_glock_xmote_th(gl, gl->gl_req_gh);
780 gfs2_glock_put(gl);
781 return;
782 }
777 783
778 spin_lock(&gl->gl_spin); 784 spin_lock(&gl->gl_spin);
779 gfs2_demote_wake(gl); 785 gfs2_demote_wake(gl);
@@ -794,7 +800,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
794 struct gfs2_sbd *sdp = gl->gl_sbd; 800 struct gfs2_sbd *sdp = gl->gl_sbd;
795 const struct gfs2_glock_operations *glops = gl->gl_ops; 801 const struct gfs2_glock_operations *glops = gl->gl_ops;
796 struct gfs2_holder *gh = gl->gl_req_gh; 802 struct gfs2_holder *gh = gl->gl_req_gh;
797 int prev_state = gl->gl_state;
798 int op_done = 1; 803 int op_done = 1;
799 804
800 if (!gh && (ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) { 805 if (!gh && (ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) {
@@ -808,16 +813,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
808 813
809 state_change(gl, ret & LM_OUT_ST_MASK); 814 state_change(gl, ret & LM_OUT_ST_MASK);
810 815
811 if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) {
812 if (glops->go_inval)
813 glops->go_inval(gl, DIO_METADATA);
814 } else if (gl->gl_state == LM_ST_DEFERRED) {
815 /* We might not want to do this here.
816 Look at moving to the inode glops. */
817 if (glops->go_inval)
818 glops->go_inval(gl, 0);
819 }
820
821 /* Deal with each possible exit condition */ 816 /* Deal with each possible exit condition */
822 817
823 if (!gh) { 818 if (!gh) {
@@ -837,6 +832,14 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
837 } 832 }
838 } else { 833 } else {
839 spin_lock(&gl->gl_spin); 834 spin_lock(&gl->gl_spin);
835 if (ret & LM_OUT_CONV_DEADLK) {
836 gh->gh_error = 0;
837 set_bit(GLF_CONV_DEADLK, &gl->gl_flags);
838 spin_unlock(&gl->gl_spin);
839 gfs2_glock_drop_th(gl);
840 gfs2_glock_put(gl);
841 return;
842 }
840 list_del_init(&gh->gh_list); 843 list_del_init(&gh->gh_list);
841 gh->gh_error = -EIO; 844 gh->gh_error = -EIO;
842 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 845 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
@@ -910,6 +913,8 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
910 913
911 if (glops->go_xmote_th) 914 if (glops->go_xmote_th)
912 glops->go_xmote_th(gl); 915 glops->go_xmote_th(gl);
916 if (state == LM_ST_DEFERRED && glops->go_inval)
917 glops->go_inval(gl, DIO_METADATA);
913 918
914 gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); 919 gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
915 gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); 920 gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
@@ -952,6 +957,8 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
952 957
953 if (glops->go_xmote_th) 958 if (glops->go_xmote_th)
954 glops->go_xmote_th(gl); 959 glops->go_xmote_th(gl);
960 if (glops->go_inval)
961 glops->go_inval(gl, DIO_METADATA);
955 962
956 gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); 963 gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
957 gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); 964 gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 4ba2ea63119d..9c2c0b90b22a 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -167,6 +167,7 @@ enum {
167 GLF_DEMOTE_IN_PROGRESS = 6, 167 GLF_DEMOTE_IN_PROGRESS = 6,
168 GLF_LFLUSH = 7, 168 GLF_LFLUSH = 7,
169 GLF_WAITERS2 = 8, 169 GLF_WAITERS2 = 8,
170 GLF_CONV_DEADLK = 9,
170}; 171};
171 172
172struct gfs2_glock { 173struct gfs2_glock {
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
index 542a797ac89a..53a6ab3c0919 100644
--- a/fs/gfs2/locking/dlm/lock.c
+++ b/fs/gfs2/locking/dlm/lock.c
@@ -137,7 +137,8 @@ static inline unsigned int make_flags(struct gdlm_lock *lp,
137 137
138 /* Conversion deadlock avoidance by DLM */ 138 /* Conversion deadlock avoidance by DLM */
139 139
140 if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) && 140 if (!(lp->ls->fsflags & LM_MFLAG_CONV_NODROP) &&
141 !test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
141 !(lkf & DLM_LKF_NOQUEUE) && 142 !(lkf & DLM_LKF_NOQUEUE) &&
142 cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req) 143 cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
143 lkf |= DLM_LKF_CONVDEADLK; 144 lkf |= DLM_LKF_CONVDEADLK;
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
index 521694fc19d6..e53db6fd28ab 100644
--- a/fs/gfs2/locking/dlm/thread.c
+++ b/fs/gfs2/locking/dlm/thread.c
@@ -135,7 +135,15 @@ static void process_complete(struct gdlm_lock *lp)
135 lp->lksb.sb_status, lp->lockname.ln_type, 135 lp->lksb.sb_status, lp->lockname.ln_type,
136 (unsigned long long)lp->lockname.ln_number, 136 (unsigned long long)lp->lockname.ln_number,
137 lp->flags); 137 lp->flags);
138 return; 138 if (lp->lksb.sb_status == -EDEADLOCK &&
139 lp->ls->fsflags & LM_MFLAG_CONV_NODROP) {
140 lp->req = lp->cur;
141 acb.lc_ret |= LM_OUT_CONV_DEADLK;
142 if (lp->cur == DLM_LOCK_IV)
143 lp->lksb.sb_lkid = 0;
144 goto out;
145 } else
146 return;
139 } 147 }
140 148
141 /* 149 /*
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 5b518f73497a..ef9c6c4f80f6 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -723,7 +723,7 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
723{ 723{
724 char *proto = sdp->sd_proto_name; 724 char *proto = sdp->sd_proto_name;
725 char *table = sdp->sd_table_name; 725 char *table = sdp->sd_table_name;
726 int flags = 0; 726 int flags = LM_MFLAG_CONV_NODROP;
727 int error; 727 int error;
728 728
729 if (sdp->sd_args.ar_spectator) 729 if (sdp->sd_args.ar_spectator)
diff --git a/include/linux/lm_interface.h b/include/linux/lm_interface.h
index 1418fdc9ac02..f274997bc283 100644
--- a/include/linux/lm_interface.h
+++ b/include/linux/lm_interface.h
@@ -21,9 +21,15 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
21 * modify the filesystem. The lock module shouldn't assign a journal to the FS 21 * modify the filesystem. The lock module shouldn't assign a journal to the FS
22 * mount. It shouldn't send recovery callbacks to the FS mount. If the node 22 * mount. It shouldn't send recovery callbacks to the FS mount. If the node
23 * dies or withdraws, all locks can be wiped immediately. 23 * dies or withdraws, all locks can be wiped immediately.
24 *
25 * LM_MFLAG_CONV_NODROP
26 * Do not allow the dlm to internally resolve conversion deadlocks by demoting
27 * the lock to unlocked and then reacquiring it in the requested mode. Instead,
28 * it should cancel the request and return LM_OUT_CONV_DEADLK.
24 */ 29 */
25 30
26#define LM_MFLAG_SPECTATOR 0x00000001 31#define LM_MFLAG_SPECTATOR 0x00000001
32#define LM_MFLAG_CONV_NODROP 0x00000002
27 33
28/* 34/*
29 * lm_lockstruct flags 35 * lm_lockstruct flags
@@ -110,6 +116,9 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
110 * 116 *
111 * LM_OUT_ASYNC 117 * LM_OUT_ASYNC
112 * The result of the request will be returned in an LM_CB_ASYNC callback. 118 * The result of the request will be returned in an LM_CB_ASYNC callback.
119 *
120 * LM_OUT_CONV_DEADLK
121 * The lock request was canceled do to a conversion deadlock.
113 */ 122 */
114 123
115#define LM_OUT_ST_MASK 0x00000003 124#define LM_OUT_ST_MASK 0x00000003
@@ -117,6 +126,7 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
117#define LM_OUT_CANCELED 0x00000008 126#define LM_OUT_CANCELED 0x00000008
118#define LM_OUT_ASYNC 0x00000080 127#define LM_OUT_ASYNC 0x00000080
119#define LM_OUT_ERROR 0x00000100 128#define LM_OUT_ERROR 0x00000100
129#define LM_OUT_CONV_DEADLK 0x00000200
120 130
121/* 131/*
122 * lm_callback_t types 132 * lm_callback_t types