diff options
-rw-r--r-- | fs/gfs2/glock.c | 35 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 1 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/lock.c | 3 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/thread.c | 10 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 2 | ||||
-rw-r--r-- | include/linux/lm_interface.h | 10 |
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) | |||
764 | static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | 764 | static 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 | ||
172 | struct gfs2_glock { | 173 | struct 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 |