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; |
