diff options
author | David Teigland <teigland@redhat.com> | 2011-10-20 14:26:28 -0400 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2012-01-04 09:55:57 -0500 |
commit | 757a42719635495779462514458bbfbf12a37dac (patch) | |
tree | be6ea155fc54c397cb57eb193b81824b37989e56 /fs/dlm/member.c | |
parent | f95a34c66554235b70a681fcd9feebc195f7ec0e (diff) |
dlm: add node slots and generation
Slot numbers are assigned to nodes when they join the lockspace.
The slot number chosen is the minimum unused value starting at 1.
Once a node is assigned a slot, that slot number will not change
while the node remains a lockspace member. If the node leaves
and rejoins it can be assigned a new slot number.
A new generation number is also added to a lockspace. It is
set and incremented during each recovery along with the slot
collection/assignment.
The slot numbers will be passed to gfs2 which will use them as
journal id's.
Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/member.c')
-rw-r--r-- | fs/dlm/member.c | 284 |
1 files changed, 283 insertions, 1 deletions
diff --git a/fs/dlm/member.c b/fs/dlm/member.c index 5ebd1df69675..eebc52aae82e 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c | |||
@@ -19,6 +19,280 @@ | |||
19 | #include "config.h" | 19 | #include "config.h" |
20 | #include "lowcomms.h" | 20 | #include "lowcomms.h" |
21 | 21 | ||
22 | int dlm_slots_version(struct dlm_header *h) | ||
23 | { | ||
24 | if ((h->h_version & 0x0000FFFF) < DLM_HEADER_SLOTS) | ||
25 | return 0; | ||
26 | return 1; | ||
27 | } | ||
28 | |||
29 | void dlm_slot_save(struct dlm_ls *ls, struct dlm_rcom *rc, | ||
30 | struct dlm_member *memb) | ||
31 | { | ||
32 | struct rcom_config *rf = (struct rcom_config *)rc->rc_buf; | ||
33 | |||
34 | if (!dlm_slots_version(&rc->rc_header)) | ||
35 | return; | ||
36 | |||
37 | memb->slot = le16_to_cpu(rf->rf_our_slot); | ||
38 | memb->generation = le32_to_cpu(rf->rf_generation); | ||
39 | } | ||
40 | |||
41 | void dlm_slots_copy_out(struct dlm_ls *ls, struct dlm_rcom *rc) | ||
42 | { | ||
43 | struct dlm_slot *slot; | ||
44 | struct rcom_slot *ro; | ||
45 | int i; | ||
46 | |||
47 | ro = (struct rcom_slot *)(rc->rc_buf + sizeof(struct rcom_config)); | ||
48 | |||
49 | /* ls_slots array is sparse, but not rcom_slots */ | ||
50 | |||
51 | for (i = 0; i < ls->ls_slots_size; i++) { | ||
52 | slot = &ls->ls_slots[i]; | ||
53 | if (!slot->nodeid) | ||
54 | continue; | ||
55 | ro->ro_nodeid = cpu_to_le32(slot->nodeid); | ||
56 | ro->ro_slot = cpu_to_le16(slot->slot); | ||
57 | ro++; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | #define SLOT_DEBUG_LINE 128 | ||
62 | |||
63 | static void log_debug_slots(struct dlm_ls *ls, uint32_t gen, int num_slots, | ||
64 | struct rcom_slot *ro0, struct dlm_slot *array, | ||
65 | int array_size) | ||
66 | { | ||
67 | char line[SLOT_DEBUG_LINE]; | ||
68 | int len = SLOT_DEBUG_LINE - 1; | ||
69 | int pos = 0; | ||
70 | int ret, i; | ||
71 | |||
72 | if (!dlm_config.ci_log_debug) | ||
73 | return; | ||
74 | |||
75 | memset(line, 0, sizeof(line)); | ||
76 | |||
77 | if (array) { | ||
78 | for (i = 0; i < array_size; i++) { | ||
79 | if (!array[i].nodeid) | ||
80 | continue; | ||
81 | |||
82 | ret = snprintf(line + pos, len - pos, " %d:%d", | ||
83 | array[i].slot, array[i].nodeid); | ||
84 | if (ret >= len - pos) | ||
85 | break; | ||
86 | pos += ret; | ||
87 | } | ||
88 | } else if (ro0) { | ||
89 | for (i = 0; i < num_slots; i++) { | ||
90 | ret = snprintf(line + pos, len - pos, " %d:%d", | ||
91 | ro0[i].ro_slot, ro0[i].ro_nodeid); | ||
92 | if (ret >= len - pos) | ||
93 | break; | ||
94 | pos += ret; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | log_debug(ls, "generation %u slots %d%s", gen, num_slots, line); | ||
99 | } | ||
100 | |||
101 | int dlm_slots_copy_in(struct dlm_ls *ls) | ||
102 | { | ||
103 | struct dlm_member *memb; | ||
104 | struct dlm_rcom *rc = ls->ls_recover_buf; | ||
105 | struct rcom_config *rf = (struct rcom_config *)rc->rc_buf; | ||
106 | struct rcom_slot *ro0, *ro; | ||
107 | int our_nodeid = dlm_our_nodeid(); | ||
108 | int i, num_slots; | ||
109 | uint32_t gen; | ||
110 | |||
111 | if (!dlm_slots_version(&rc->rc_header)) | ||
112 | return -1; | ||
113 | |||
114 | gen = le32_to_cpu(rf->rf_generation); | ||
115 | if (gen <= ls->ls_generation) { | ||
116 | log_error(ls, "dlm_slots_copy_in gen %u old %u", | ||
117 | gen, ls->ls_generation); | ||
118 | } | ||
119 | ls->ls_generation = gen; | ||
120 | |||
121 | num_slots = le16_to_cpu(rf->rf_num_slots); | ||
122 | if (!num_slots) | ||
123 | return -1; | ||
124 | |||
125 | ro0 = (struct rcom_slot *)(rc->rc_buf + sizeof(struct rcom_config)); | ||
126 | |||
127 | for (i = 0, ro = ro0; i < num_slots; i++, ro++) { | ||
128 | ro->ro_nodeid = le32_to_cpu(ro->ro_nodeid); | ||
129 | ro->ro_slot = le16_to_cpu(ro->ro_slot); | ||
130 | } | ||
131 | |||
132 | log_debug_slots(ls, gen, num_slots, ro0, NULL, 0); | ||
133 | |||
134 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
135 | for (i = 0, ro = ro0; i < num_slots; i++, ro++) { | ||
136 | if (ro->ro_nodeid != memb->nodeid) | ||
137 | continue; | ||
138 | memb->slot = ro->ro_slot; | ||
139 | memb->slot_prev = memb->slot; | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | if (memb->nodeid == our_nodeid) { | ||
144 | if (ls->ls_slot && ls->ls_slot != memb->slot) { | ||
145 | log_error(ls, "dlm_slots_copy_in our slot " | ||
146 | "changed %d %d", ls->ls_slot, | ||
147 | memb->slot); | ||
148 | return -1; | ||
149 | } | ||
150 | |||
151 | if (!ls->ls_slot) | ||
152 | ls->ls_slot = memb->slot; | ||
153 | } | ||
154 | |||
155 | if (!memb->slot) { | ||
156 | log_error(ls, "dlm_slots_copy_in nodeid %d no slot", | ||
157 | memb->nodeid); | ||
158 | return -1; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | /* for any nodes that do not support slots, we will not have set memb->slot | ||
166 | in wait_status_all(), so memb->slot will remain -1, and we will not | ||
167 | assign slots or set ls_num_slots here */ | ||
168 | |||
169 | int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size, | ||
170 | struct dlm_slot **slots_out, uint32_t *gen_out) | ||
171 | { | ||
172 | struct dlm_member *memb; | ||
173 | struct dlm_slot *array; | ||
174 | int our_nodeid = dlm_our_nodeid(); | ||
175 | int array_size, max_slots, i; | ||
176 | int need = 0; | ||
177 | int max = 0; | ||
178 | int num = 0; | ||
179 | uint32_t gen = 0; | ||
180 | |||
181 | /* our own memb struct will have slot -1 gen 0 */ | ||
182 | |||
183 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
184 | if (memb->nodeid == our_nodeid) { | ||
185 | memb->slot = ls->ls_slot; | ||
186 | memb->generation = ls->ls_generation; | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
192 | if (memb->generation > gen) | ||
193 | gen = memb->generation; | ||
194 | |||
195 | /* node doesn't support slots */ | ||
196 | |||
197 | if (memb->slot == -1) | ||
198 | return -1; | ||
199 | |||
200 | /* node needs a slot assigned */ | ||
201 | |||
202 | if (!memb->slot) | ||
203 | need++; | ||
204 | |||
205 | /* node has a slot assigned */ | ||
206 | |||
207 | num++; | ||
208 | |||
209 | if (!max || max < memb->slot) | ||
210 | max = memb->slot; | ||
211 | |||
212 | /* sanity check, once slot is assigned it shouldn't change */ | ||
213 | |||
214 | if (memb->slot_prev && memb->slot && memb->slot_prev != memb->slot) { | ||
215 | log_error(ls, "nodeid %d slot changed %d %d", | ||
216 | memb->nodeid, memb->slot_prev, memb->slot); | ||
217 | return -1; | ||
218 | } | ||
219 | memb->slot_prev = memb->slot; | ||
220 | } | ||
221 | |||
222 | array_size = max + need; | ||
223 | |||
224 | array = kzalloc(array_size * sizeof(struct dlm_slot), GFP_NOFS); | ||
225 | if (!array) | ||
226 | return -ENOMEM; | ||
227 | |||
228 | num = 0; | ||
229 | |||
230 | /* fill in slots (offsets) that are used */ | ||
231 | |||
232 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
233 | if (!memb->slot) | ||
234 | continue; | ||
235 | |||
236 | if (memb->slot > array_size) { | ||
237 | log_error(ls, "invalid slot number %d", memb->slot); | ||
238 | kfree(array); | ||
239 | return -1; | ||
240 | } | ||
241 | |||
242 | array[memb->slot - 1].nodeid = memb->nodeid; | ||
243 | array[memb->slot - 1].slot = memb->slot; | ||
244 | num++; | ||
245 | } | ||
246 | |||
247 | /* assign new slots from unused offsets */ | ||
248 | |||
249 | list_for_each_entry(memb, &ls->ls_nodes, list) { | ||
250 | if (memb->slot) | ||
251 | continue; | ||
252 | |||
253 | for (i = 0; i < array_size; i++) { | ||
254 | if (array[i].nodeid) | ||
255 | continue; | ||
256 | |||
257 | memb->slot = i + 1; | ||
258 | memb->slot_prev = memb->slot; | ||
259 | array[i].nodeid = memb->nodeid; | ||
260 | array[i].slot = memb->slot; | ||
261 | num++; | ||
262 | |||
263 | if (!ls->ls_slot && memb->nodeid == our_nodeid) | ||
264 | ls->ls_slot = memb->slot; | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | if (!memb->slot) { | ||
269 | log_error(ls, "no free slot found"); | ||
270 | kfree(array); | ||
271 | return -1; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | gen++; | ||
276 | |||
277 | log_debug_slots(ls, gen, num, NULL, array, array_size); | ||
278 | |||
279 | max_slots = (dlm_config.ci_buffer_size - sizeof(struct dlm_rcom) - | ||
280 | sizeof(struct rcom_config)) / sizeof(struct rcom_slot); | ||
281 | |||
282 | if (num > max_slots) { | ||
283 | log_error(ls, "num_slots %d exceeds max_slots %d", | ||
284 | num, max_slots); | ||
285 | kfree(array); | ||
286 | return -1; | ||
287 | } | ||
288 | |||
289 | *gen_out = gen; | ||
290 | *slots_out = array; | ||
291 | *slots_size = array_size; | ||
292 | *num_slots = num; | ||
293 | return 0; | ||
294 | } | ||
295 | |||
22 | static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) | 296 | static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) |
23 | { | 297 | { |
24 | struct dlm_member *memb = NULL; | 298 | struct dlm_member *memb = NULL; |
@@ -176,7 +450,7 @@ static int ping_members(struct dlm_ls *ls) | |||
176 | error = dlm_recovery_stopped(ls); | 450 | error = dlm_recovery_stopped(ls); |
177 | if (error) | 451 | if (error) |
178 | break; | 452 | break; |
179 | error = dlm_rcom_status(ls, memb->nodeid); | 453 | error = dlm_rcom_status(ls, memb->nodeid, 0); |
180 | if (error) | 454 | if (error) |
181 | break; | 455 | break; |
182 | } | 456 | } |
@@ -322,7 +596,15 @@ int dlm_ls_stop(struct dlm_ls *ls) | |||
322 | */ | 596 | */ |
323 | 597 | ||
324 | dlm_recoverd_suspend(ls); | 598 | dlm_recoverd_suspend(ls); |
599 | |||
600 | spin_lock(&ls->ls_recover_lock); | ||
601 | kfree(ls->ls_slots); | ||
602 | ls->ls_slots = NULL; | ||
603 | ls->ls_num_slots = 0; | ||
604 | ls->ls_slots_size = 0; | ||
325 | ls->ls_recover_status = 0; | 605 | ls->ls_recover_status = 0; |
606 | spin_unlock(&ls->ls_recover_lock); | ||
607 | |||
326 | dlm_recoverd_resume(ls); | 608 | dlm_recoverd_resume(ls); |
327 | 609 | ||
328 | if (!ls->ls_recover_begin) | 610 | if (!ls->ls_recover_begin) |