diff options
-rw-r--r-- | fs/dlm/lock.c | 82 |
1 files changed, 80 insertions, 2 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index eac54d230fdc..d8d6e729f96b 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
@@ -224,6 +224,16 @@ static inline int is_demoted(struct dlm_lkb *lkb) | |||
224 | return (lkb->lkb_sbflags & DLM_SBF_DEMOTED); | 224 | return (lkb->lkb_sbflags & DLM_SBF_DEMOTED); |
225 | } | 225 | } |
226 | 226 | ||
227 | static inline int is_altmode(struct dlm_lkb *lkb) | ||
228 | { | ||
229 | return (lkb->lkb_sbflags & DLM_SBF_ALTMODE); | ||
230 | } | ||
231 | |||
232 | static inline int is_granted(struct dlm_lkb *lkb) | ||
233 | { | ||
234 | return (lkb->lkb_status == DLM_LKSTS_GRANTED); | ||
235 | } | ||
236 | |||
227 | static inline int is_remote(struct dlm_rsb *r) | 237 | static inline int is_remote(struct dlm_rsb *r) |
228 | { | 238 | { |
229 | DLM_ASSERT(r->res_nodeid >= 0, dlm_print_rsb(r);); | 239 | DLM_ASSERT(r->res_nodeid >= 0, dlm_print_rsb(r);); |
@@ -1191,6 +1201,50 @@ static void grant_lock_pending(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1191 | queue_cast(r, lkb, 0); | 1201 | queue_cast(r, lkb, 0); |
1192 | } | 1202 | } |
1193 | 1203 | ||
1204 | /* The special CONVDEADLK, ALTPR and ALTCW flags allow the master to | ||
1205 | change the granted/requested modes. We're munging things accordingly in | ||
1206 | the process copy. | ||
1207 | CONVDEADLK: our grmode may have been forced down to NL to resolve a | ||
1208 | conversion deadlock | ||
1209 | ALTPR/ALTCW: our rqmode may have been changed to PR or CW to become | ||
1210 | compatible with other granted locks */ | ||
1211 | |||
1212 | static void munge_demoted(struct dlm_lkb *lkb, struct dlm_message *ms) | ||
1213 | { | ||
1214 | if (ms->m_type != DLM_MSG_CONVERT_REPLY) { | ||
1215 | log_print("munge_demoted %x invalid reply type %d", | ||
1216 | lkb->lkb_id, ms->m_type); | ||
1217 | return; | ||
1218 | } | ||
1219 | |||
1220 | if (lkb->lkb_rqmode == DLM_LOCK_IV || lkb->lkb_grmode == DLM_LOCK_IV) { | ||
1221 | log_print("munge_demoted %x invalid modes gr %d rq %d", | ||
1222 | lkb->lkb_id, lkb->lkb_grmode, lkb->lkb_rqmode); | ||
1223 | return; | ||
1224 | } | ||
1225 | |||
1226 | lkb->lkb_grmode = DLM_LOCK_NL; | ||
1227 | } | ||
1228 | |||
1229 | static void munge_altmode(struct dlm_lkb *lkb, struct dlm_message *ms) | ||
1230 | { | ||
1231 | if (ms->m_type != DLM_MSG_REQUEST_REPLY && | ||
1232 | ms->m_type != DLM_MSG_GRANT) { | ||
1233 | log_print("munge_altmode %x invalid reply type %d", | ||
1234 | lkb->lkb_id, ms->m_type); | ||
1235 | return; | ||
1236 | } | ||
1237 | |||
1238 | if (lkb->lkb_exflags & DLM_LKF_ALTPR) | ||
1239 | lkb->lkb_rqmode = DLM_LOCK_PR; | ||
1240 | else if (lkb->lkb_exflags & DLM_LKF_ALTCW) | ||
1241 | lkb->lkb_rqmode = DLM_LOCK_CW; | ||
1242 | else { | ||
1243 | log_print("munge_altmode invalid exflags %x", lkb->lkb_exflags); | ||
1244 | dlm_print_lkb(lkb); | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1194 | static inline int first_in_list(struct dlm_lkb *lkb, struct list_head *head) | 1248 | static inline int first_in_list(struct dlm_lkb *lkb, struct list_head *head) |
1195 | { | 1249 | { |
1196 | struct dlm_lkb *first = list_entry(head->next, struct dlm_lkb, | 1250 | struct dlm_lkb *first = list_entry(head->next, struct dlm_lkb, |
@@ -1965,9 +2019,24 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1965 | goto out; | 2019 | goto out; |
1966 | } | 2020 | } |
1967 | 2021 | ||
1968 | if (can_be_queued(lkb)) { | 2022 | /* is_demoted() means the can_be_granted() above set the grmode |
1969 | if (is_demoted(lkb)) | 2023 | to NL, and left us on the granted queue. This auto-demotion |
2024 | (due to CONVDEADLK) might mean other locks, and/or this lock, are | ||
2025 | now grantable. We have to try to grant other converting locks | ||
2026 | before we try again to grant this one. */ | ||
2027 | |||
2028 | if (is_demoted(lkb)) { | ||
2029 | grant_pending_convert(r, DLM_LOCK_IV); | ||
2030 | if (_can_be_granted(r, lkb, 1)) { | ||
2031 | grant_lock(r, lkb); | ||
2032 | queue_cast(r, lkb, 0); | ||
1970 | grant_pending_locks(r); | 2033 | grant_pending_locks(r); |
2034 | goto out; | ||
2035 | } | ||
2036 | /* else fall through and move to convert queue */ | ||
2037 | } | ||
2038 | |||
2039 | if (can_be_queued(lkb)) { | ||
1971 | error = -EINPROGRESS; | 2040 | error = -EINPROGRESS; |
1972 | del_lkb(r, lkb); | 2041 | del_lkb(r, lkb); |
1973 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); | 2042 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); |
@@ -2908,6 +2977,8 @@ static void receive_grant(struct dlm_ls *ls, struct dlm_message *ms) | |||
2908 | lock_rsb(r); | 2977 | lock_rsb(r); |
2909 | 2978 | ||
2910 | receive_flags_reply(lkb, ms); | 2979 | receive_flags_reply(lkb, ms); |
2980 | if (is_altmode(lkb)) | ||
2981 | munge_altmode(lkb, ms); | ||
2911 | grant_lock_pc(r, lkb, ms); | 2982 | grant_lock_pc(r, lkb, ms); |
2912 | queue_cast(r, lkb, 0); | 2983 | queue_cast(r, lkb, 0); |
2913 | 2984 | ||
@@ -3038,6 +3109,8 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3038 | /* request was queued or granted on remote master */ | 3109 | /* request was queued or granted on remote master */ |
3039 | receive_flags_reply(lkb, ms); | 3110 | receive_flags_reply(lkb, ms); |
3040 | lkb->lkb_remid = ms->m_lkid; | 3111 | lkb->lkb_remid = ms->m_lkid; |
3112 | if (is_altmode(lkb)) | ||
3113 | munge_altmode(lkb, ms); | ||
3041 | if (result) | 3114 | if (result) |
3042 | add_lkb(r, lkb, DLM_LKSTS_WAITING); | 3115 | add_lkb(r, lkb, DLM_LKSTS_WAITING); |
3043 | else { | 3116 | else { |
@@ -3101,6 +3174,9 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
3101 | 3174 | ||
3102 | case -EINPROGRESS: | 3175 | case -EINPROGRESS: |
3103 | /* convert was queued on remote master */ | 3176 | /* convert was queued on remote master */ |
3177 | receive_flags_reply(lkb, ms); | ||
3178 | if (is_demoted(lkb)) | ||
3179 | munge_demoted(lkb, ms); | ||
3104 | del_lkb(r, lkb); | 3180 | del_lkb(r, lkb); |
3105 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); | 3181 | add_lkb(r, lkb, DLM_LKSTS_CONVERT); |
3106 | break; | 3182 | break; |
@@ -3108,6 +3184,8 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
3108 | case 0: | 3184 | case 0: |
3109 | /* convert was granted on remote master */ | 3185 | /* convert was granted on remote master */ |
3110 | receive_flags_reply(lkb, ms); | 3186 | receive_flags_reply(lkb, ms); |
3187 | if (is_demoted(lkb)) | ||
3188 | munge_demoted(lkb, ms); | ||
3111 | grant_lock_pc(r, lkb, ms); | 3189 | grant_lock_pc(r, lkb, ms); |
3112 | queue_cast(r, lkb, 0); | 3190 | queue_cast(r, lkb, 0); |
3113 | break; | 3191 | break; |