]> git.proxmox.com Git - corosync-pve.git/blob - patches/0006-CPG-callback-merging.patch
buildsys: fix source tarball generation directory level one-off
[corosync-pve.git] / patches / 0006-CPG-callback-merging.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
3 Date: Wed, 22 May 2019 12:27:19 +0200
4 Subject: [PATCH] CPG callback merging
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 cherry-picked from upstream PR 468.
10
11 this series aims to minimize callback calls in case of cluster cold
12 starts or re-joining after network partitions, which cause a huge spike
13 in network load on bigger clusters running pmxcfs.
14
15 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
16 ---
17 ...more-comments-to-notify_lib_joinlist.patch | 193 +++++++++++++++++
18 ...illing-of-member_list-to-subfunction.patch | 130 ++++++++++++
19 ...ify_lib_joinlist-drop-conn-parameter.patch | 112 ++++++++++
20 ...-confchg-event-per-group-on-joinlist.patch | 199 ++++++++++++++++++
21 debian/patches/series | 4 +
22 5 files changed, 638 insertions(+)
23 create mode 100644 debian/patches/cpg-Add-more-comments-to-notify_lib_joinlist.patch
24 create mode 100644 debian/patches/cpg-Move-filling-of-member_list-to-subfunction.patch
25 create mode 100644 debian/patches/cpg-notify_lib_joinlist-drop-conn-parameter.patch
26 create mode 100644 debian/patches/cpg-send-single-confchg-event-per-group-on-joinlist.patch
27
28 diff --git a/debian/patches/cpg-Add-more-comments-to-notify_lib_joinlist.patch b/debian/patches/cpg-Add-more-comments-to-notify_lib_joinlist.patch
29 new file mode 100644
30 index 00000000..e32102fa
31 --- /dev/null
32 +++ b/debian/patches/cpg-Add-more-comments-to-notify_lib_joinlist.patch
33 @@ -0,0 +1,193 @@
34 +From: Jan Friesse <jfriesse@redhat.com>
35 +Date: Wed, 15 May 2019 17:39:13 +0200
36 +Subject: cpg: Add more comments to notify_lib_joinlist
37 +
38 +And make handling of left_list more generic. Also free skiplist
39 +allocated by joinlist_inform_clients function. Last (but not least)
40 +remove czechlish founded (should have been pp of "find").
41 +
42 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
43 +(cherry picked from commit 10702c7e6c0cf8164ad8f05acb4e334461555973)
44 +---
45 + exec/cpg.c | 91 +++++++++++++++++++++++++++++++++++++++++---------------------
46 + 1 file changed, 60 insertions(+), 31 deletions(-)
47 +
48 +diff --git a/exec/cpg.c b/exec/cpg.c
49 +index e04ba57..2ecdc6b 100644
50 +--- a/exec/cpg.c
51 ++++ b/exec/cpg.c
52 +@@ -663,31 +663,37 @@ static int notify_lib_joinlist(
53 + int size;
54 + char *buf;
55 + struct qb_list_head *iter;
56 +- int count;
57 ++ int member_list_entries;
58 + struct res_lib_cpg_confchg_callback *res;
59 + mar_cpg_address_t *retgi;
60 ++ int i;
61 +
62 +- count = 0;
63 ++ /*
64 ++ * Find size of member_list (use process_info_list but remove items in left_list)
65 ++ */
66 ++ member_list_entries = 0;
67 +
68 + qb_list_for_each(iter, &process_info_list_head) {
69 + struct process_info *pi = qb_list_entry (iter, struct process_info, list);
70 ++
71 + if (mar_name_compare (&pi->group, group_name) == 0) {
72 +- int i;
73 +- int founded = 0;
74 ++ int in_left_list = 0;
75 +
76 + for (i = 0; i < left_list_entries; i++) {
77 + if (left_list[i].nodeid == pi->nodeid && left_list[i].pid == pi->pid) {
78 +- founded++;
79 ++ in_left_list = 1;
80 ++ break ;
81 + }
82 + }
83 +
84 +- if (!founded)
85 +- count++;
86 ++ if (!in_left_list) {
87 ++ member_list_entries++;
88 ++ }
89 + }
90 + }
91 +
92 + size = sizeof(struct res_lib_cpg_confchg_callback) +
93 +- sizeof(mar_cpg_address_t) * (count + left_list_entries + joined_list_entries);
94 ++ sizeof(mar_cpg_address_t) * (member_list_entries + left_list_entries + joined_list_entries);
95 + buf = alloca(size);
96 + if (!buf)
97 + return CS_ERR_LIBRARY;
98 +@@ -695,27 +701,30 @@ static int notify_lib_joinlist(
99 + res = (struct res_lib_cpg_confchg_callback *)buf;
100 + res->joined_list_entries = joined_list_entries;
101 + res->left_list_entries = left_list_entries;
102 +- res->member_list_entries = count;
103 ++ res->member_list_entries = member_list_entries;
104 + retgi = res->member_list;
105 + res->header.size = size;
106 + res->header.id = id;
107 + res->header.error = CS_OK;
108 + memcpy(&res->group_name, group_name, sizeof(mar_cpg_name_t));
109 +
110 ++ /*
111 ++ * Fill res->memberlist. Use process_info_list but remove items in left_list.
112 ++ */
113 + qb_list_for_each(iter, &process_info_list_head) {
114 +- struct process_info *pi=qb_list_entry (iter, struct process_info, list);
115 ++ struct process_info *pi = qb_list_entry (iter, struct process_info, list);
116 +
117 + if (mar_name_compare (&pi->group, group_name) == 0) {
118 +- int i;
119 +- int founded = 0;
120 ++ int in_left_list = 0;
121 +
122 +- for (i = 0;i < left_list_entries; i++) {
123 ++ for (i = 0; i < left_list_entries; i++) {
124 + if (left_list[i].nodeid == pi->nodeid && left_list[i].pid == pi->pid) {
125 +- founded++;
126 ++ in_left_list = 1;
127 ++ break ;
128 + }
129 + }
130 +
131 +- if (!founded) {
132 ++ if (!in_left_list) {
133 + retgi->nodeid = pi->nodeid;
134 + retgi->pid = pi->pid;
135 + retgi->reason = CPG_REASON_UNDEFINED;
136 +@@ -724,23 +733,30 @@ static int notify_lib_joinlist(
137 + }
138 + }
139 +
140 ++ /*
141 ++ * Fill res->left_list
142 ++ */
143 + if (left_list_entries) {
144 + memcpy (retgi, left_list, left_list_entries * sizeof(mar_cpg_address_t));
145 + retgi += left_list_entries;
146 + }
147 +
148 + if (joined_list_entries) {
149 +- int i;
150 +-
151 ++ /*
152 ++ * Fill res->joined_list
153 ++ */
154 + memcpy (retgi, joined_list, joined_list_entries * sizeof(mar_cpg_address_t));
155 + retgi += joined_list_entries;
156 +
157 +- for (i=0; i < joined_list_entries; i++) {
158 ++ /*
159 ++ * Update cpd_state for all local joined processes in group
160 ++ */
161 ++ for (i = 0; i < joined_list_entries; i++) {
162 + if (joined_list[i].nodeid == api->totem_nodeid_get()) {
163 +- qb_list_for_each(iter, &cpg_pd_list_head) {
164 ++ qb_list_for_each(iter, &cpg_pd_list_head) {
165 + struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
166 +- if (mar_name_compare (&cpd->group_name, group_name) == 0 &&
167 +- joined_list[i].pid == cpd->pid) {
168 ++ if (joined_list[i].pid == cpd->pid &&
169 ++ mar_name_compare (&cpd->group_name, group_name) == 0) {
170 + cpd->cpd_state = CPD_STATE_JOIN_COMPLETED;
171 + }
172 + }
173 +@@ -748,6 +764,9 @@ static int notify_lib_joinlist(
174 + }
175 + }
176 +
177 ++ /*
178 ++ * Send notification to all ipc clients joined in group_name
179 ++ */
180 + qb_list_for_each(iter, &cpg_pd_list_head) {
181 + struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
182 + if (mar_name_compare (&cpd->group_name, group_name) == 0) {
183 +@@ -760,16 +779,25 @@ static int notify_lib_joinlist(
184 + }
185 + }
186 +
187 +- if (left_list_entries &&
188 +- left_list[0].nodeid == api->totem_nodeid_get() &&
189 +- left_list[0].reason == CONFCHG_CPG_REASON_LEAVE) {
190 +- qb_list_for_each(iter, &cpg_pd_list_head) {
191 +- struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
192 +- if (mar_name_compare (&cpd->group_name, group_name) == 0 &&
193 +- left_list[0].pid == cpd->pid) {
194 +- cpd->pid = 0;
195 +- memset (&cpd->group_name, 0, sizeof(cpd->group_name));
196 +- cpd->cpd_state = CPD_STATE_UNJOINED;
197 ++ if (left_list_entries) {
198 ++ /*
199 ++ * Zero internal cpd state for all local processes leaving group
200 ++ * (this loop is not strictly needed because left_list always either
201 ++ * contains exactly one process running on local node or more items
202 ++ * but none of them is running on local node)
203 ++ */
204 ++ for (i = 0; i < joined_list_entries; i++) {
205 ++ if (left_list[i].nodeid == api->totem_nodeid_get() &&
206 ++ left_list[i].reason == CONFCHG_CPG_REASON_LEAVE) {
207 ++ qb_list_for_each(iter, &cpg_pd_list_head) {
208 ++ struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
209 ++ if (left_list[i].pid == cpd->pid &&
210 ++ mar_name_compare (&cpd->group_name, group_name) == 0) {
211 ++ cpd->pid = 0;
212 ++ memset (&cpd->group_name, 0, sizeof(cpd->group_name));
213 ++ cpd->cpd_state = CPD_STATE_UNJOINED;
214 ++ }
215 ++ }
216 + }
217 + }
218 + }
219 +@@ -966,6 +994,7 @@ static void joinlist_inform_clients (void)
220 + free(jld);
221 + }
222 + qb_map_iter_free(miter);
223 ++ qb_map_destroy(group_notify_map);
224 +
225 + joinlist_remove_zombie_pi_entries ();
226 + }
227 diff --git a/debian/patches/cpg-Move-filling-of-member_list-to-subfunction.patch b/debian/patches/cpg-Move-filling-of-member_list-to-subfunction.patch
228 new file mode 100644
229 index 00000000..9ec65353
230 --- /dev/null
231 +++ b/debian/patches/cpg-Move-filling-of-member_list-to-subfunction.patch
232 @@ -0,0 +1,130 @@
233 +From: Jan Friesse <jfriesse@redhat.com>
234 +Date: Thu, 16 May 2019 14:08:25 +0200
235 +Subject: cpg: Move filling of member_list to subfunction
236 +
237 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
238 +(cherry picked from commit 0c1de94461368b4a924b516b77691e6ec471dcb0)
239 +---
240 + exec/cpg.c | 86 ++++++++++++++++++++++++++++++++++++--------------------------
241 + 1 file changed, 50 insertions(+), 36 deletions(-)
242 +
243 +diff --git a/exec/cpg.c b/exec/cpg.c
244 +index 2ecdc6b..98a16a6 100644
245 +--- a/exec/cpg.c
246 ++++ b/exec/cpg.c
247 +@@ -652,26 +652,27 @@ static int notify_lib_totem_membership (
248 + return CS_OK;
249 + }
250 +
251 +-static int notify_lib_joinlist(
252 ++/*
253 ++ * Helper function for notify_lib_joinlist which prepares member_list using
254 ++ * process_info_list with removed left_list items.
255 ++ * member_list_entries - When not NULL it contains number of member_list entries
256 ++ * member_list - When not NULL it is used as pointer to start of preallocated
257 ++ * array of members. Pointer is adjusted to the end of array on
258 ++ * exit.
259 ++ */
260 ++static void notify_lib_joinlist_fill_member_list(
261 + const mar_cpg_name_t *group_name,
262 +- int joined_list_entries,
263 +- mar_cpg_address_t *joined_list,
264 + int left_list_entries,
265 +- mar_cpg_address_t *left_list,
266 +- int id)
267 ++ const mar_cpg_address_t *left_list,
268 ++ int *member_list_entries,
269 ++ mar_cpg_address_t **member_list)
270 + {
271 +- int size;
272 +- char *buf;
273 + struct qb_list_head *iter;
274 +- int member_list_entries;
275 +- struct res_lib_cpg_confchg_callback *res;
276 +- mar_cpg_address_t *retgi;
277 + int i;
278 +
279 +- /*
280 +- * Find size of member_list (use process_info_list but remove items in left_list)
281 +- */
282 +- member_list_entries = 0;
283 ++ if (member_list_entries != NULL) {
284 ++ *member_list_entries = 0;
285 ++ }
286 +
287 + qb_list_for_each(iter, &process_info_list_head) {
288 + struct process_info *pi = qb_list_entry (iter, struct process_info, list);
289 +@@ -687,10 +688,42 @@ static int notify_lib_joinlist(
290 + }
291 +
292 + if (!in_left_list) {
293 +- member_list_entries++;
294 ++ if (member_list_entries != NULL) {
295 ++ (*member_list_entries)++;
296 ++ }
297 ++
298 ++ if (member_list != NULL) {
299 ++ (*member_list)->nodeid = pi->nodeid;
300 ++ (*member_list)->pid = pi->pid;
301 ++ (*member_list)->reason = CPG_REASON_UNDEFINED;
302 ++ (*member_list)++;
303 ++ }
304 + }
305 + }
306 + }
307 ++}
308 ++
309 ++static int notify_lib_joinlist(
310 ++ const mar_cpg_name_t *group_name,
311 ++ int joined_list_entries,
312 ++ mar_cpg_address_t *joined_list,
313 ++ int left_list_entries,
314 ++ mar_cpg_address_t *left_list,
315 ++ int id)
316 ++{
317 ++ int size;
318 ++ char *buf;
319 ++ struct qb_list_head *iter;
320 ++ int member_list_entries;
321 ++ struct res_lib_cpg_confchg_callback *res;
322 ++ mar_cpg_address_t *retgi;
323 ++ int i;
324 ++
325 ++ /*
326 ++ * Find size of member_list (use process_info_list but remove items in left_list)
327 ++ */
328 ++ notify_lib_joinlist_fill_member_list(group_name, left_list_entries, left_list,
329 ++ &member_list_entries, NULL);
330 +
331 + size = sizeof(struct res_lib_cpg_confchg_callback) +
332 + sizeof(mar_cpg_address_t) * (member_list_entries + left_list_entries + joined_list_entries);
333 +@@ -711,27 +744,8 @@ static int notify_lib_joinlist(
334 + /*
335 + * Fill res->memberlist. Use process_info_list but remove items in left_list.
336 + */
337 +- qb_list_for_each(iter, &process_info_list_head) {
338 +- struct process_info *pi = qb_list_entry (iter, struct process_info, list);
339 +-
340 +- if (mar_name_compare (&pi->group, group_name) == 0) {
341 +- int in_left_list = 0;
342 +-
343 +- for (i = 0; i < left_list_entries; i++) {
344 +- if (left_list[i].nodeid == pi->nodeid && left_list[i].pid == pi->pid) {
345 +- in_left_list = 1;
346 +- break ;
347 +- }
348 +- }
349 +-
350 +- if (!in_left_list) {
351 +- retgi->nodeid = pi->nodeid;
352 +- retgi->pid = pi->pid;
353 +- retgi->reason = CPG_REASON_UNDEFINED;
354 +- retgi++;
355 +- }
356 +- }
357 +- }
358 ++ notify_lib_joinlist_fill_member_list(group_name, left_list_entries, left_list,
359 ++ NULL, &retgi);
360 +
361 + /*
362 + * Fill res->left_list
363 diff --git a/debian/patches/cpg-notify_lib_joinlist-drop-conn-parameter.patch b/debian/patches/cpg-notify_lib_joinlist-drop-conn-parameter.patch
364 new file mode 100644
365 index 00000000..e1742bf9
366 --- /dev/null
367 +++ b/debian/patches/cpg-notify_lib_joinlist-drop-conn-parameter.patch
368 @@ -0,0 +1,112 @@
369 +From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
370 +Date: Wed, 15 May 2019 13:45:13 +0200
371 +Subject: cpg: notify_lib_joinlist: drop conn parameter
372 +
373 +since it is always set to NULL.
374 +
375 +(cherry picked from commit d5e9723695b2ae63162b238300013d785e875ea7)
376 +---
377 + exec/cpg.c | 54 ++++++++++++++++++++++++------------------------------
378 + 1 file changed, 24 insertions(+), 30 deletions(-)
379 +
380 +diff --git a/exec/cpg.c b/exec/cpg.c
381 +index e39ca34..b752cc1 100644
382 +--- a/exec/cpg.c
383 ++++ b/exec/cpg.c
384 +@@ -647,7 +647,6 @@ static int notify_lib_totem_membership (
385 +
386 + static int notify_lib_joinlist(
387 + const mar_cpg_name_t *group_name,
388 +- void *conn,
389 + int joined_list_entries,
390 + mar_cpg_address_t *joined_list,
391 + int left_list_entries,
392 +@@ -728,40 +727,35 @@ static int notify_lib_joinlist(
393 + retgi += joined_list_entries;
394 + }
395 +
396 +- if (conn) {
397 +- api->ipc_dispatch_send (conn, buf, size);
398 +- } else {
399 + qb_list_for_each(iter, &cpg_pd_list_head) {
400 +- struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
401 +- if (mar_name_compare (&cpd->group_name, group_name) == 0) {
402 +- assert (joined_list_entries <= 1);
403 +- if (joined_list_entries) {
404 +- if (joined_list[0].pid == cpd->pid &&
405 +- joined_list[0].nodeid == api->totem_nodeid_get()) {
406 +- cpd->cpd_state = CPD_STATE_JOIN_COMPLETED;
407 +- }
408 ++ struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
409 ++ if (mar_name_compare (&cpd->group_name, group_name) == 0) {
410 ++ assert (joined_list_entries <= 1);
411 ++ if (joined_list_entries) {
412 ++ if (joined_list[0].pid == cpd->pid &&
413 ++ joined_list[0].nodeid == api->totem_nodeid_get()) {
414 ++ cpd->cpd_state = CPD_STATE_JOIN_COMPLETED;
415 + }
416 +- if (cpd->cpd_state == CPD_STATE_JOIN_COMPLETED ||
417 +- cpd->cpd_state == CPD_STATE_LEAVE_STARTED) {
418 ++ }
419 ++ if (cpd->cpd_state == CPD_STATE_JOIN_COMPLETED ||
420 ++ cpd->cpd_state == CPD_STATE_LEAVE_STARTED) {
421 +
422 +- api->ipc_dispatch_send (cpd->conn, buf, size);
423 +- cpd->transition_counter++;
424 +- }
425 +- if (left_list_entries) {
426 +- if (left_list[0].pid == cpd->pid &&
427 +- left_list[0].nodeid == api->totem_nodeid_get() &&
428 +- left_list[0].reason == CONFCHG_CPG_REASON_LEAVE) {
429 +-
430 +- cpd->pid = 0;
431 +- memset (&cpd->group_name, 0, sizeof(cpd->group_name));
432 +- cpd->cpd_state = CPD_STATE_UNJOINED;
433 +- }
434 ++ api->ipc_dispatch_send (cpd->conn, buf, size);
435 ++ cpd->transition_counter++;
436 ++ }
437 ++ if (left_list_entries) {
438 ++ if (left_list[0].pid == cpd->pid &&
439 ++ left_list[0].nodeid == api->totem_nodeid_get() &&
440 ++ left_list[0].reason == CONFCHG_CPG_REASON_LEAVE) {
441 ++
442 ++ cpd->pid = 0;
443 ++ memset (&cpd->group_name, 0, sizeof(cpd->group_name));
444 ++ cpd->cpd_state = CPD_STATE_UNJOINED;
445 + }
446 + }
447 + }
448 + }
449 +
450 +-
451 + /*
452 + * Traverse thru cpds and send totem membership for cpd, where it is not send yet
453 + */
454 +@@ -858,7 +852,7 @@ static void downlist_inform_clients (void)
455 + }
456 +
457 + /* send confchg event */
458 +- notify_lib_joinlist(&group, NULL,
459 ++ notify_lib_joinlist(&group,
460 + 0, NULL,
461 + pcd->left_list_entries,
462 + pcd->left_list,
463 +@@ -1157,7 +1151,7 @@ static void do_proc_join(
464 + notify_info.nodeid = nodeid;
465 + notify_info.reason = reason;
466 +
467 +- notify_lib_joinlist(&pi->group, NULL,
468 ++ notify_lib_joinlist(&pi->group,
469 + 1, &notify_info,
470 + 0, NULL,
471 + MESSAGE_RES_CPG_CONFCHG_CALLBACK);
472 +@@ -1177,7 +1171,7 @@ static void do_proc_leave(
473 + notify_info.nodeid = nodeid;
474 + notify_info.reason = reason;
475 +
476 +- notify_lib_joinlist(name, NULL,
477 ++ notify_lib_joinlist(name,
478 + 0, NULL,
479 + 1, &notify_info,
480 + MESSAGE_RES_CPG_CONFCHG_CALLBACK);
481 diff --git a/debian/patches/cpg-send-single-confchg-event-per-group-on-joinlist.patch b/debian/patches/cpg-send-single-confchg-event-per-group-on-joinlist.patch
482 new file mode 100644
483 index 00000000..013baaa0
484 --- /dev/null
485 +++ b/debian/patches/cpg-send-single-confchg-event-per-group-on-joinlist.patch
486 @@ -0,0 +1,199 @@
487 +From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
488 +Date: Wed, 8 May 2019 16:31:15 +0200
489 +Subject: cpg: send single confchg event per group on joinlist
490 +MIME-Version: 1.0
491 +Content-Type: text/plain; charset="utf-8"
492 +Content-Transfer-Encoding: 8bit
493 +
494 +using a similar approach to
495 +
496 +43bead364514e8ae2ba00bcf07c460e31d0b1765 "Send one confchg event per CPG group to CPG client"
497 +
498 +which did the same for leave events on a network partition.
499 +
500 +Fixes: #351
501 +
502 +Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
503 +(cherry picked from commit 9c60289b831ef0b138142c3fc39c9a9da8a2ada2)
504 +---
505 + exec/cpg.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++----------------
506 + 1 file changed, 73 insertions(+), 24 deletions(-)
507 +
508 +diff --git a/exec/cpg.c b/exec/cpg.c
509 +index b752cc1..e04ba57 100644
510 +--- a/exec/cpg.c
511 ++++ b/exec/cpg.c
512 +@@ -194,6 +194,12 @@ struct join_list_entry {
513 + mar_cpg_name_t group_name;
514 + };
515 +
516 ++struct join_list_confchg_data {
517 ++ mar_cpg_name_t cpg_group;
518 ++ mar_cpg_address_t join_list[CPG_MEMBERS_MAX];
519 ++ int join_list_entries;
520 ++};
521 ++
522 + /*
523 + * Service Interfaces required by service_message_handler struct
524 + */
525 +@@ -312,7 +318,8 @@ static void do_proc_join(
526 + const mar_cpg_name_t *name,
527 + uint32_t pid,
528 + unsigned int nodeid,
529 +- int reason);
530 ++ int reason,
531 ++ qb_map_t *group_notify_map);
532 +
533 + static void do_proc_leave(
534 + const mar_cpg_name_t *name,
535 +@@ -723,35 +730,46 @@ static int notify_lib_joinlist(
536 + }
537 +
538 + if (joined_list_entries) {
539 ++ int i;
540 ++
541 + memcpy (retgi, joined_list, joined_list_entries * sizeof(mar_cpg_address_t));
542 + retgi += joined_list_entries;
543 ++
544 ++ for (i=0; i < joined_list_entries; i++) {
545 ++ if (joined_list[i].nodeid == api->totem_nodeid_get()) {
546 ++ qb_list_for_each(iter, &cpg_pd_list_head) {
547 ++ struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
548 ++ if (mar_name_compare (&cpd->group_name, group_name) == 0 &&
549 ++ joined_list[i].pid == cpd->pid) {
550 ++ cpd->cpd_state = CPD_STATE_JOIN_COMPLETED;
551 ++ }
552 ++ }
553 ++ }
554 ++ }
555 + }
556 +
557 + qb_list_for_each(iter, &cpg_pd_list_head) {
558 + struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
559 + if (mar_name_compare (&cpd->group_name, group_name) == 0) {
560 +- assert (joined_list_entries <= 1);
561 +- if (joined_list_entries) {
562 +- if (joined_list[0].pid == cpd->pid &&
563 +- joined_list[0].nodeid == api->totem_nodeid_get()) {
564 +- cpd->cpd_state = CPD_STATE_JOIN_COMPLETED;
565 +- }
566 +- }
567 + if (cpd->cpd_state == CPD_STATE_JOIN_COMPLETED ||
568 + cpd->cpd_state == CPD_STATE_LEAVE_STARTED) {
569 +
570 + api->ipc_dispatch_send (cpd->conn, buf, size);
571 + cpd->transition_counter++;
572 + }
573 +- if (left_list_entries) {
574 +- if (left_list[0].pid == cpd->pid &&
575 +- left_list[0].nodeid == api->totem_nodeid_get() &&
576 +- left_list[0].reason == CONFCHG_CPG_REASON_LEAVE) {
577 +-
578 +- cpd->pid = 0;
579 +- memset (&cpd->group_name, 0, sizeof(cpd->group_name));
580 +- cpd->cpd_state = CPD_STATE_UNJOINED;
581 +- }
582 ++ }
583 ++ }
584 ++
585 ++ if (left_list_entries &&
586 ++ left_list[0].nodeid == api->totem_nodeid_get() &&
587 ++ left_list[0].reason == CONFCHG_CPG_REASON_LEAVE) {
588 ++ qb_list_for_each(iter, &cpg_pd_list_head) {
589 ++ struct cpg_pd *cpd = qb_list_entry (iter, struct cpg_pd, list);
590 ++ if (mar_name_compare (&cpd->group_name, group_name) == 0 &&
591 ++ left_list[0].pid == cpd->pid) {
592 ++ cpd->pid = 0;
593 ++ memset (&cpd->group_name, 0, sizeof(cpd->group_name));
594 ++ cpd->cpd_state = CPD_STATE_UNJOINED;
595 + }
596 + }
597 + }
598 +@@ -915,6 +933,11 @@ static void joinlist_inform_clients (void)
599 + struct joinlist_msg *stored_msg;
600 + struct qb_list_head *iter;
601 + unsigned int i;
602 ++ qb_map_t *group_notify_map;
603 ++ qb_map_iter_t *miter;
604 ++ struct join_list_confchg_data *jld;
605 ++
606 ++ group_notify_map = qb_skiplist_create();
607 +
608 + i = 0;
609 + qb_list_for_each(iter, &joinlist_messages_head) {
610 +@@ -931,9 +954,19 @@ static void joinlist_inform_clients (void)
611 + }
612 +
613 + do_proc_join (&stored_msg->group_name, stored_msg->pid, stored_msg->sender_nodeid,
614 +- CONFCHG_CPG_REASON_NODEUP);
615 ++ CONFCHG_CPG_REASON_NODEUP, group_notify_map);
616 + }
617 +
618 ++ miter = qb_map_iter_create(group_notify_map);
619 ++ while (qb_map_iter_next(miter, (void **)&jld)) {
620 ++ notify_lib_joinlist(&jld->cpg_group,
621 ++ jld->join_list_entries, jld->join_list,
622 ++ 0, NULL,
623 ++ MESSAGE_RES_CPG_CONFCHG_CALLBACK);
624 ++ free(jld);
625 ++ }
626 ++ qb_map_iter_free(miter);
627 ++
628 + joinlist_remove_zombie_pi_entries ();
629 + }
630 +
631 +@@ -1111,13 +1144,15 @@ static void do_proc_join(
632 + const mar_cpg_name_t *name,
633 + uint32_t pid,
634 + unsigned int nodeid,
635 +- int reason)
636 ++ int reason,
637 ++ qb_map_t *group_notify_map)
638 + {
639 + struct process_info *pi;
640 + struct process_info *pi_entry;
641 + mar_cpg_address_t notify_info;
642 + struct qb_list_head *list;
643 + struct qb_list_head *list_to_add = NULL;
644 ++ int size;
645 +
646 + if (process_info_find (name, pid, nodeid) != NULL) {
647 + return ;
648 +@@ -1151,10 +1186,24 @@ static void do_proc_join(
649 + notify_info.nodeid = nodeid;
650 + notify_info.reason = reason;
651 +
652 +- notify_lib_joinlist(&pi->group,
653 +- 1, &notify_info,
654 +- 0, NULL,
655 +- MESSAGE_RES_CPG_CONFCHG_CALLBACK);
656 ++ if (group_notify_map == NULL) {
657 ++ notify_lib_joinlist(&pi->group,
658 ++ 1, &notify_info,
659 ++ 0, NULL,
660 ++ MESSAGE_RES_CPG_CONFCHG_CALLBACK);
661 ++ } else {
662 ++ struct join_list_confchg_data *jld = qb_map_get(group_notify_map, pi->group.value);
663 ++ if (jld == NULL) {
664 ++ jld = (struct join_list_confchg_data *)calloc(1, sizeof(struct join_list_confchg_data));
665 ++ memcpy(&jld->cpg_group, &pi->group, sizeof(mar_cpg_name_t));
666 ++ qb_map_put(group_notify_map, jld->cpg_group.value, jld);
667 ++ }
668 ++ size = jld->join_list_entries;
669 ++ jld->join_list[size].nodeid = notify_info.nodeid;
670 ++ jld->join_list[size].pid = notify_info.pid;
671 ++ jld->join_list[size].reason = notify_info.reason;
672 ++ jld->join_list_entries++;
673 ++ }
674 + }
675 +
676 + static void do_proc_leave(
677 +@@ -1219,7 +1268,7 @@ static void message_handler_req_exec_cpg_procjoin (
678 +
679 + do_proc_join (&req_exec_cpg_procjoin->group_name,
680 + req_exec_cpg_procjoin->pid, nodeid,
681 +- CONFCHG_CPG_REASON_JOIN);
682 ++ CONFCHG_CPG_REASON_JOIN, NULL);
683 + }
684 +
685 + static void message_handler_req_exec_cpg_procleave (
686 diff --git a/debian/patches/series b/debian/patches/series
687 index 803038e4..fec11c03 100644
688 --- a/debian/patches/series
689 +++ b/debian/patches/series
690 @@ -52,3 +52,7 @@ vqsim-Check-length-of-copied-optarg.patch
691 Fix-various-typos-in-ChangeLog.patch
692 Enable-PrivateTmp-in-the-systemd-service-files.patch
693 pve__only-start-corosync.service-if-conf-exists.patch
694 +cpg-notify_lib_joinlist-drop-conn-parameter.patch
695 +cpg-send-single-confchg-event-per-group-on-joinlist.patch
696 +cpg-Add-more-comments-to-notify_lib_joinlist.patch
697 +cpg-Move-filling-of-member_list-to-subfunction.patch