.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
---|
3 | 4 | * Copyright 2004-2011 Red Hat, Inc. |
---|
4 | | - * |
---|
5 | | - * This copyrighted material is made available to anyone wishing to use, |
---|
6 | | - * modify, copy, or redistribute it subject to the terms and conditions |
---|
7 | | - * of the GNU General Public License version 2. |
---|
8 | 5 | */ |
---|
9 | 6 | |
---|
10 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
19 | 16 | |
---|
20 | 17 | #include "incore.h" |
---|
21 | 18 | #include "glock.h" |
---|
| 19 | +#include "glops.h" |
---|
| 20 | +#include "recovery.h" |
---|
22 | 21 | #include "util.h" |
---|
23 | 22 | #include "sys.h" |
---|
24 | 23 | #include "trace_gfs2.h" |
---|
.. | .. |
---|
127 | 126 | |
---|
128 | 127 | switch (gl->gl_lksb.sb_status) { |
---|
129 | 128 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ |
---|
| 129 | + if (gl->gl_ops->go_free) |
---|
| 130 | + gl->gl_ops->go_free(gl); |
---|
130 | 131 | gfs2_glock_free(gl); |
---|
131 | 132 | return; |
---|
132 | 133 | case -DLM_ECANCEL: /* Cancel while getting lock */ |
---|
.. | .. |
---|
178 | 179 | gfs2_glock_cb(gl, LM_ST_SHARED); |
---|
179 | 180 | break; |
---|
180 | 181 | default: |
---|
181 | | - pr_err("unknown bast mode %d\n", mode); |
---|
| 182 | + fs_err(gl->gl_name.ln_sbd, "unknown bast mode %d\n", mode); |
---|
182 | 183 | BUG(); |
---|
183 | 184 | } |
---|
184 | 185 | } |
---|
185 | 186 | |
---|
186 | 187 | /* convert gfs lock-state to dlm lock-mode */ |
---|
187 | 188 | |
---|
188 | | -static int make_mode(const unsigned int lmstate) |
---|
| 189 | +static int make_mode(struct gfs2_sbd *sdp, const unsigned int lmstate) |
---|
189 | 190 | { |
---|
190 | 191 | switch (lmstate) { |
---|
191 | 192 | case LM_ST_UNLOCKED: |
---|
.. | .. |
---|
197 | 198 | case LM_ST_SHARED: |
---|
198 | 199 | return DLM_LOCK_PR; |
---|
199 | 200 | } |
---|
200 | | - pr_err("unknown LM state %d\n", lmstate); |
---|
| 201 | + fs_err(sdp, "unknown LM state %d\n", lmstate); |
---|
201 | 202 | BUG(); |
---|
202 | 203 | return -1; |
---|
203 | 204 | } |
---|
.. | .. |
---|
258 | 259 | u32 lkf; |
---|
259 | 260 | char strname[GDLM_STRNAME_BYTES] = ""; |
---|
260 | 261 | |
---|
261 | | - req = make_mode(req_state); |
---|
| 262 | + req = make_mode(gl->gl_name.ln_sbd, req_state); |
---|
262 | 263 | lkf = make_flags(gl, flags, req); |
---|
263 | 264 | gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); |
---|
264 | 265 | gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); |
---|
.. | .. |
---|
311 | 312 | error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, |
---|
312 | 313 | NULL, gl); |
---|
313 | 314 | if (error) { |
---|
314 | | - pr_err("gdlm_unlock %x,%llx err=%d\n", |
---|
| 315 | + fs_err(sdp, "gdlm_unlock %x,%llx err=%d\n", |
---|
315 | 316 | gl->gl_name.ln_type, |
---|
316 | 317 | (unsigned long long)gl->gl_name.ln_number, error); |
---|
317 | 318 | return; |
---|
.. | .. |
---|
327 | 328 | /* |
---|
328 | 329 | * dlm/gfs2 recovery coordination using dlm_recover callbacks |
---|
329 | 330 | * |
---|
| 331 | + * 0. gfs2 checks for another cluster node withdraw, needing journal replay |
---|
330 | 332 | * 1. dlm_controld sees lockspace members change |
---|
331 | 333 | * 2. dlm_controld blocks dlm-kernel locking activity |
---|
332 | 334 | * 3. dlm_controld within dlm-kernel notifies gfs2 (recover_prep) |
---|
.. | .. |
---|
575 | 577 | &ls->ls_control_lksb, "control_lock"); |
---|
576 | 578 | } |
---|
577 | 579 | |
---|
| 580 | +/** |
---|
| 581 | + * remote_withdraw - react to a node withdrawing from the file system |
---|
| 582 | + * @sdp: The superblock |
---|
| 583 | + */ |
---|
| 584 | +static void remote_withdraw(struct gfs2_sbd *sdp) |
---|
| 585 | +{ |
---|
| 586 | + struct gfs2_jdesc *jd; |
---|
| 587 | + int ret = 0, count = 0; |
---|
| 588 | + |
---|
| 589 | + list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { |
---|
| 590 | + if (jd->jd_jid == sdp->sd_lockstruct.ls_jid) |
---|
| 591 | + continue; |
---|
| 592 | + ret = gfs2_recover_journal(jd, true); |
---|
| 593 | + if (ret) |
---|
| 594 | + break; |
---|
| 595 | + count++; |
---|
| 596 | + } |
---|
| 597 | + |
---|
| 598 | + /* Now drop the additional reference we acquired */ |
---|
| 599 | + fs_err(sdp, "Journals checked: %d, ret = %d.\n", count, ret); |
---|
| 600 | +} |
---|
| 601 | + |
---|
578 | 602 | static void gfs2_control_func(struct work_struct *work) |
---|
579 | 603 | { |
---|
580 | 604 | struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_control_work.work); |
---|
.. | .. |
---|
584 | 608 | int write_lvb = 0; |
---|
585 | 609 | int recover_size; |
---|
586 | 610 | int i, error; |
---|
| 611 | + |
---|
| 612 | + /* First check for other nodes that may have done a withdraw. */ |
---|
| 613 | + if (test_bit(SDF_REMOTE_WITHDRAW, &sdp->sd_flags)) { |
---|
| 614 | + remote_withdraw(sdp); |
---|
| 615 | + clear_bit(SDF_REMOTE_WITHDRAW, &sdp->sd_flags); |
---|
| 616 | + return; |
---|
| 617 | + } |
---|
587 | 618 | |
---|
588 | 619 | spin_lock(&ls->ls_recover_spin); |
---|
589 | 620 | /* |
---|
.. | .. |
---|
1039 | 1070 | } |
---|
1040 | 1071 | |
---|
1041 | 1072 | old_size = ls->ls_recover_size; |
---|
1042 | | - |
---|
1043 | | - if (old_size >= max_jid + 1) |
---|
| 1073 | + new_size = old_size; |
---|
| 1074 | + while (new_size < max_jid + 1) |
---|
| 1075 | + new_size += RECOVER_SIZE_INC; |
---|
| 1076 | + if (new_size == old_size) |
---|
1044 | 1077 | return 0; |
---|
1045 | | - |
---|
1046 | | - new_size = old_size + RECOVER_SIZE_INC; |
---|
1047 | 1078 | |
---|
1048 | 1079 | submit = kcalloc(new_size, sizeof(uint32_t), GFP_NOFS); |
---|
1049 | 1080 | result = kcalloc(new_size, sizeof(uint32_t), GFP_NOFS); |
---|
.. | .. |
---|
1083 | 1114 | struct gfs2_sbd *sdp = arg; |
---|
1084 | 1115 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
---|
1085 | 1116 | |
---|
| 1117 | + if (gfs2_withdrawn(sdp)) { |
---|
| 1118 | + fs_err(sdp, "recover_prep ignored due to withdraw.\n"); |
---|
| 1119 | + return; |
---|
| 1120 | + } |
---|
1086 | 1121 | spin_lock(&ls->ls_recover_spin); |
---|
1087 | 1122 | ls->ls_recover_block = ls->ls_recover_start; |
---|
1088 | 1123 | set_bit(DFL_DLM_RECOVERY, &ls->ls_recover_flags); |
---|
.. | .. |
---|
1105 | 1140 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
---|
1106 | 1141 | int jid = slot->slot - 1; |
---|
1107 | 1142 | |
---|
| 1143 | + if (gfs2_withdrawn(sdp)) { |
---|
| 1144 | + fs_err(sdp, "recover_slot jid %d ignored due to withdraw.\n", |
---|
| 1145 | + jid); |
---|
| 1146 | + return; |
---|
| 1147 | + } |
---|
1108 | 1148 | spin_lock(&ls->ls_recover_spin); |
---|
1109 | 1149 | if (ls->ls_recover_size < jid + 1) { |
---|
1110 | 1150 | fs_err(sdp, "recover_slot jid %d gen %u short size %d\n", |
---|
.. | .. |
---|
1129 | 1169 | struct gfs2_sbd *sdp = arg; |
---|
1130 | 1170 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
---|
1131 | 1171 | |
---|
| 1172 | + if (gfs2_withdrawn(sdp)) { |
---|
| 1173 | + fs_err(sdp, "recover_done ignored due to withdraw.\n"); |
---|
| 1174 | + return; |
---|
| 1175 | + } |
---|
1132 | 1176 | /* ensure the ls jid arrays are large enough */ |
---|
1133 | 1177 | set_recover_size(sdp, slots, num_slots); |
---|
1134 | 1178 | |
---|
.. | .. |
---|
1156 | 1200 | { |
---|
1157 | 1201 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
---|
1158 | 1202 | |
---|
| 1203 | + if (gfs2_withdrawn(sdp)) { |
---|
| 1204 | + fs_err(sdp, "recovery_result jid %d ignored due to withdraw.\n", |
---|
| 1205 | + jid); |
---|
| 1206 | + return; |
---|
| 1207 | + } |
---|
1159 | 1208 | if (test_bit(DFL_NO_DLM_OPS, &ls->ls_recover_flags)) |
---|
1160 | 1209 | return; |
---|
1161 | 1210 | |
---|