diff --git a/SOURCES/bz1678480-add-child_wait_time.patch b/SOURCES/bz1678480-add-child_wait_time.patch
new file mode 100644
index 0000000..11e4db7
--- /dev/null
+++ b/SOURCES/bz1678480-add-child_wait_time.patch
@@ -0,0 +1,158 @@
+From d3292ee776448de67241bf7efc8f9bb23f166752 Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Fri, 2 Feb 2018 10:12:06 +0000
+Subject: [PATCH 1/8] Add child_wait_time to allow longer shutdown time of
+ child processes
+
+With very large configurations it can be necessary to allow longer than
+the default 5 seconds for child processes to cleanup and terminate.
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ doc/keepalived.conf.SYNOPSIS    |  5 ++++-
+ doc/man/man5/keepalived.conf.5  |  3 +++
+ keepalived/core/global_parser.c | 19 +++++++++++++++++++
+ keepalived/core/main.c          | 12 +++++++-----
+ keepalived/include/main.h       |  3 +++
+ lib/parser.c                    |  2 ++
+ 6 files changed, 38 insertions(+), 6 deletions(-)
+
+diff --git a/doc/keepalived.conf.SYNOPSIS b/doc/keepalived.conf.SYNOPSIS
+index 90eb83d4..3d042b1c 100644
+--- a/doc/keepalived.conf.SYNOPSIS
++++ b/doc/keepalived.conf.SYNOPSIS
+@@ -176,7 +176,10 @@ use_pid_dir				   # Create pid files in /var/run/keepalived
+ 
+ linkbeat_use_polling			   # Use media link failure detection polling fashion
+ 
+-	1.2. Static addresses
++child_wait_time SECS                          # Time for main process to allow for child processes to exit on termination
++                                              #   in seconds (default 5). This can be needed for very large configurations.
++
++    1.2. Static addresses
+ 
+ 	The configuration block looks like :
+ 
+diff --git a/doc/man/man5/keepalived.conf.5 b/doc/man/man5/keepalived.conf.5
+index 1dabdec7..d0d04727 100644
+--- a/doc/man/man5/keepalived.conf.5
++++ b/doc/man/man5/keepalived.conf.5
+@@ -219,6 +219,9 @@ and
+ 
+  linkbeat_use_polling         # Poll to detect media link failure otherwise attempt to use ETHTOOL or MII interface
+ 
++ child_wait_time SECS         # Time for main process to allow for child processes to exit on termination
++                              #   in seconds (default 5). This can be needed for very large configurations.
++
+ .SH Static routes/addresses/rules
+ .PP
+ Keepalived can configure static addresses, routes, and rules. These addresses are
+diff --git a/keepalived/core/global_parser.c b/keepalived/core/global_parser.c
+index a59fbc0b..e8ed6333 100644
+--- a/keepalived/core/global_parser.c
++++ b/keepalived/core/global_parser.c
+@@ -719,6 +719,24 @@ script_security_handler(__attribute__((unused)) vector_t *strvec)
+ 	global_data->script_security = true;
+ }
+ 
++static void
++child_wait_handler(vector_t *strvec)
++{
++	char *endptr;
++	unsigned long secs;
++
++	if (!strvec)
++		return;
++
++	secs = strtoul(strvec_slot(strvec,1), &endptr, 10);
++	if (*endptr) {
++		log_message(LOG_INFO, "Invalid child_wait_time %s", FMT_STR_VSLOT(strvec, 1));
++		return;
++	}
++
++	child_wait_time = secs;
++}
++
+ void
+ init_global_keywords(bool global_active)
+ {
+@@ -730,6 +748,7 @@ init_global_keywords(bool global_active)
+ #endif
+ 	install_keyword_root("use_pid_dir", &use_pid_dir_handler, !global_active);
+ 	install_keyword_root("instance", &instance_handler, !global_active);
++	install_keyword_root("child_wait_time", &child_wait_handler, !global_active);
+ 	install_keyword_root("global_defs", NULL, global_active);
+ 	install_keyword("router_id", &routerid_handler);
+ 	install_keyword("notification_email_from", &emailfrom_handler);
+diff --git a/keepalived/core/main.c b/keepalived/core/main.c
+index 95bb76a9..51f83a07 100644
+--- a/keepalived/core/main.c
++++ b/keepalived/core/main.c
+@@ -93,6 +93,8 @@ bool namespace_with_ipsets;				/* Override for using namespaces and ipsets with
+ static char *override_namespace;			/* If namespace specified on command line */
+ #endif
+ 
++unsigned child_wait_time = CHILD_WAIT_SECS;		/* Time to wait for children to exit */
++
+ /* Log facility table */
+ static struct {
+ 	int facility;
+@@ -359,7 +361,7 @@ sigend(__attribute__((unused)) void *v, __attribute__((unused)) int sig)
+ 	int wait_count = 0;
+ 	sigset_t old_set, child_wait;
+ 	struct timespec timeout = {
+-		.tv_sec = CHILD_WAIT_SECS,
++		.tv_sec = child_wait_time,
+ 		.tv_nsec = 0
+ 	};
+ 	struct timeval start_time, now;
+@@ -416,17 +418,17 @@ sigend(__attribute__((unused)) void *v, __attribute__((unused)) int sig)
+ 			gettimeofday(&now, NULL);
+ 			if (now.tv_usec < start_time.tv_usec) {
+ 				timeout.tv_nsec = (start_time.tv_usec - now.tv_usec) * 1000;
+-				timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec);
++				timeout.tv_sec = child_wait_time - (now.tv_sec - start_time.tv_sec);
+ 			} else if (now.tv_usec == start_time.tv_usec) {
+ 				timeout.tv_nsec = 0;
+-				timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec);
++				timeout.tv_sec = child_wait_time - (now.tv_sec - start_time.tv_sec);
+ 			} else {
+ 				timeout.tv_nsec = (1000000L + start_time.tv_usec - now.tv_usec) * 1000;
+-				timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec + 1);
++				timeout.tv_sec = child_wait_time - (now.tv_sec - start_time.tv_sec + 1);
+ 			}
+ 
+ 			timeout.tv_nsec = (start_time.tv_usec - now.tv_usec) * 1000;
+-			timeout.tv_sec = CHILD_WAIT_SECS - (now.tv_sec - start_time.tv_sec);
++			timeout.tv_sec = child_wait_time - (now.tv_sec - start_time.tv_sec);
+ 			if (timeout.tv_nsec < 0) {
+ 				timeout.tv_nsec += 1000000000L;
+ 				timeout.tv_sec--;
+diff --git a/keepalived/include/main.h b/keepalived/include/main.h
+index eebde77e..b03a7efd 100644
+--- a/keepalived/include/main.h
++++ b/keepalived/include/main.h
+@@ -82,4 +82,7 @@ extern void free_parent_mallocs_exit(void);
+ extern char *make_syslog_ident(const char*);
+ 
+ extern int keepalived_main(int, char**); /* The "real" main function */
++
++extern unsigned child_wait_time;
++
+ #endif
+diff --git a/lib/parser.c b/lib/parser.c
+index a5c3465b..2e1beac8 100644
+--- a/lib/parser.c
++++ b/lib/parser.c
+@@ -120,6 +120,8 @@ install_sublevel_end(void)
+ void
+ install_keyword_root(const char *string, void (*handler) (vector_t *), bool active)
+ {
++	/* If the root keyword is inactive, the handler will still be called,
++	 * but with a NULL strvec */
+ 	keyword_alloc(keywords, string, handler, active);
+ }
+ 
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-fix-checker-coding-style.patch b/SOURCES/bz1678480-fix-checker-coding-style.patch
new file mode 100644
index 0000000..6b12508
--- /dev/null
+++ b/SOURCES/bz1678480-fix-checker-coding-style.patch
@@ -0,0 +1,350 @@
+From 99ad17d4906f478c51b58ab8f288edbca0bab906 Mon Sep 17 00:00:00 2001
+From: YAMAMOTO Masaya <pandax381@gmail.com>
+Date: Fri, 14 Jul 2017 14:34:28 +0900
+Subject: [PATCH 6/8] Fix to match coding style
+
+---
+ keepalived/check/check_api.c   | 22 ++++++++++------------
+ keepalived/check/check_dns.c   | 20 +++++++++-----------
+ keepalived/check/check_http.c  | 26 ++++++++++++--------------
+ keepalived/check/check_misc.c  | 18 ++++++++----------
+ keepalived/check/check_smtp.c  | 26 ++++++++++++--------------
+ keepalived/check/check_tcp.c   | 18 ++++++++----------
+ keepalived/include/check_api.h |  6 +++---
+ 7 files changed, 62 insertions(+), 74 deletions(-)
+
+diff --git a/keepalived/check/check_api.c b/keepalived/check/check_api.c
+index a722fc84..1d915414 100644
+--- a/keepalived/check/check_api.c
++++ b/keepalived/check/check_api.c
+@@ -81,7 +81,7 @@ dump_conn_opts(void *data)
+ void
+ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
+ 	      , int (*launch) (thread_t *)
+-	      , int (*compare) (void *, void *)
++	      , bool (*compare) (void *, void *)
+ 	      , void *data
+ 	      , conn_opts_t *co)
+ {
+@@ -120,28 +120,26 @@ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
+ 	}
+ }
+ 
+-int
++bool
+ compare_conn_opts(conn_opts_t *a, conn_opts_t *b)
+ {
+ 	if (a == b)
+-		return 0;
++		return true;
+ 
+ 	if (!a || !b)
+-		goto err;
++		return false;
+ 	if (!sockstorage_equal(&a->dst, &b->dst))
+-		goto err;
++		return false;
+ 	if (!sockstorage_equal(&a->bindto, &b->bindto))
+-		goto err;
+-	//if (a->connection_to != b->connection_to)
+-	//	goto err;
++		return false;
++	if (a->connection_to != b->connection_to)
++		return false;
+ #ifdef _WITH_SO_MARK_
+ 	if (a->fwmark != b->fwmark)
+-		goto err;
++		return false;
+ #endif
+ 
+-	return  0;
+-err:
+-	return -1;
++	return true;
+ }
+ 
+ static void
+diff --git a/keepalived/check/check_dns.c b/keepalived/check/check_dns.c
+index 84a5f56d..603742a4 100644
+--- a/keepalived/check/check_dns.c
++++ b/keepalived/check/check_dns.c
+@@ -388,24 +388,22 @@ dns_dump(void *data)
+ 	log_message(LOG_INFO, "   Name = %s", dns_check->name);
+ }
+ 
+-static int
+-dns_compare(void *a, void *b)
++static bool 
++dns_check_compare(void *a, void *b)
+ {
+ 	dns_check_t *old = CHECKER_DATA(a);
+ 	dns_check_t *new = CHECKER_DATA(b);
+ 
+-	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
+-		goto err;
++	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
++		return false;
+ 	if (old->retry != new->retry)
+-		goto err;
++		return false;
+ 	if (strcmp(old->type, new->type) != 0)
+-		goto err;
++		return false;
+ 	if (strcmp(old->name, new->name) != 0)
+-		goto err;
++		return false;
+ 
+-	return  0;
+-err:
+-	return -1;
++	return true;
+ }
+ 
+ static void
+@@ -417,7 +415,7 @@ dns_check_handler(__attribute__((unused)) vector_t * strvec)
+ 	dns_check->type = DNS_DEFAULT_TYPE;
+ 	dns_check->name = DNS_DEFAULT_NAME;
+ 	queue_checker(dns_free, dns_dump, dns_connect_thread,
+-		      dns_compare, dns_check, CHECKER_NEW_CO());
++		      dns_check_compare, dns_check, CHECKER_NEW_CO());
+ }
+ 
+ static void
+diff --git a/keepalived/check/check_http.c b/keepalived/check/check_http.c
+index c2089a3b..1ad395cf 100644
+--- a/keepalived/check/check_http.c
++++ b/keepalived/check/check_http.c
+@@ -123,36 +123,34 @@ alloc_http_get(char *proto)
+ 	return http_get_chk;
+ }
+ 
+-static int
+-compare_http_get_check(void *a, void *b)
++static bool
++http_get_check_compare(void *a, void *b)
+ {
+ 	http_checker_t *old = CHECKER_DATA(a);
+ 	http_checker_t *new = CHECKER_DATA(b);
+ 	size_t n;
+ 	url_t *u1, *u2;
+ 
+-	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
+-		goto err;
++	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
++		return false;
+ 	if (old->nb_get_retry != new->nb_get_retry)
+-		goto err;
++		return false;
+ 	if (old->delay_before_retry != new->delay_before_retry)
+-		goto err;
++		return false;
+ 	if (LIST_SIZE(old->url) != LIST_SIZE(new->url))
+-		goto err;
++		return false;
+ 	for (n = 0; n < LIST_SIZE(new->url); n++) {
+ 		u1 = (url_t *)list_element(old->url, n);
+ 		u2 = (url_t *)list_element(new->url, n);
+ 		if (strcmp(u1->path, u2->path) != 0)
+-			goto err;
++			return false;
+ 		if (strcmp(u1->digest, u2->digest) != 0)
+-			goto err;
++			return false;
+ 		if (u1->status_code != u2->status_code)
+-			goto err;
++			return false;
+ 	}
+ 
+-	return  0;
+-err:
+-	return -1;
++	return true;
+ }
+ 
+ static void
+@@ -164,7 +162,7 @@ http_get_handler(vector_t *strvec)
+ 	/* queue new checker */
+ 	http_get_chk = alloc_http_get(str);
+ 	queue_checker(free_http_get_check, dump_http_get_check,
+-		      http_connect_thread, compare_http_get_check,
++		      http_connect_thread, http_get_check_compare,
+ 		      http_get_chk, CHECKER_NEW_CO());
+ }
+ 
+diff --git a/keepalived/check/check_misc.c b/keepalived/check/check_misc.c
+index 311a1127..f1f66955 100644
+--- a/keepalived/check/check_misc.c
++++ b/keepalived/check/check_misc.c
+@@ -72,24 +72,22 @@ dump_misc_check(void *data)
+ 	log_message(LOG_INFO, "   insecure = %s", misck_checker->insecure ? "Yes" : "No");
+ }
+ 
+-static int
+-compare_misc_check(void *a, void *b)
++static bool
++misc_check_compare(void *a, void *b)
+ {
+ 	misc_checker_t *old = CHECKER_DATA(a);
+ 	misc_checker_t *new = CHECKER_DATA(b);
+ 
+ 	if (strcmp(old->path, new->path) != 0)
+-		goto err;
++		return false;
+ 	if (old->timeout != new->timeout)
+-		goto err;
++		return false;
+ 	if (old->dynamic != new->dynamic)
+-		goto err;
++		return false;
+ 	if (old->uid != new->uid || new->gid != new->gid)
+-		goto err;
++		return false;
+ 
+-	return  0;
+-err:
+-	return -1;
++	return true;
+ }
+ 
+ static void
+@@ -169,7 +167,7 @@ log_message(LOG_INFO, "Setting uid.gid");
+ 	}
+ 
+ 	/* queue new checker */
+-	queue_checker(free_misc_check, dump_misc_check, misc_check_thread, compare_misc_check, misck_checker, NULL);
++	queue_checker(free_misc_check, dump_misc_check, misc_check_thread, misc_check_compare, misck_checker, NULL);
+ 	misck_checker = NULL;
+ log_message(LOG_INFO, "Leaving misc_end_handler");
+ }
+diff --git a/keepalived/check/check_smtp.c b/keepalived/check/check_smtp.c
+index e19511cc..44d15e01 100644
+--- a/keepalived/check/check_smtp.c
++++ b/keepalived/check/check_smtp.c
+@@ -82,8 +82,8 @@ dump_smtp_check(void *data)
+ 	dump_list(smtp_checker->host);
+ }
+ 
+-static int
+-compare_smtp_check(void *a, void *b)
++static bool
++smtp_check_compare(void *a, void *b)
+ {
+ 	smtp_checker_t *old = CHECKER_DATA(a);
+ 	smtp_checker_t *new = CHECKER_DATA(b);
+@@ -91,26 +91,24 @@ compare_smtp_check(void *a, void *b)
+ 	smtp_host_t *h1, *h2;
+ 
+ 	if (strcmp(old->helo_name, new->helo_name) != 0)
+-		goto err;
++		return false;
+ 	if (old->retry != new->retry)
+-		goto err;
++		return false;
+ 	if (old->db_retry != new->db_retry)
+-		goto err;
+-	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
+-		goto err;
++		return false;
++	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
++		return false;
+ 	if (LIST_SIZE(old->host) != LIST_SIZE(new->host))
+-		goto err;
++		return false;
+ 	for (n = 0; n < LIST_SIZE(new->host); n++) {
+ 		h1 = (smtp_host_t *)list_element(old->host, n);
+ 		h2 = (smtp_host_t *)list_element(new->host, n);
+-		if (compare_conn_opts(h1, h2) != 0) {
+-			goto err;
++		if (!compare_conn_opts(h1, h2)) {
++			return false;
+ 		}
+ 	}
+ 
+-	return  0;
+-err:
+-	return -1;
++	return true;
+ }
+ 
+ /* Allocates a default host structure */
+@@ -167,7 +165,7 @@ smtp_check_handler(__attribute__((unused)) vector_t *strvec)
+ 	 *               void *data, conn_opts_t *)
+ 	 */
+ 	queue_checker(free_smtp_check, dump_smtp_check, smtp_connect_thread,
+-		      compare_smtp_check, smtp_checker, smtp_checker->default_co);
++		      smtp_check_compare, smtp_checker, smtp_checker->default_co);
+ 
+ 	/*
+ 	 * Last, allocate the list that will hold all the per host
+diff --git a/keepalived/check/check_tcp.c b/keepalived/check/check_tcp.c
+index 026a0e3c..1858f5fc 100644
+--- a/keepalived/check/check_tcp.c
++++ b/keepalived/check/check_tcp.c
+@@ -62,22 +62,20 @@ dump_tcp_check(void *data)
+ 	}
+ }
+ 
+-static int
+-compare_tcp_check(void *a, void *b)
++static bool
++tcp_check_compare(void *a, void *b)
+ {
+ 	tcp_check_t *old = CHECKER_DATA(a);
+ 	tcp_check_t *new = CHECKER_DATA(b);
+ 
+-	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
+-		goto err;
++	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
++		return false;
+ 	if (old->n_retry != new->n_retry)
+-		goto err;
++		return false;
+ 	if (old->delay_before_retry != new->delay_before_retry)
+-		goto err;
++		return false;
+ 
+-	return  0;
+-err:
+-	return -1;
++	return true;
+ }
+ 
+ static void
+@@ -91,7 +89,7 @@ tcp_check_handler(__attribute__((unused)) vector_t *strvec)
+ 
+ 	/* queue new checker */
+ 	queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread,
+-		      compare_tcp_check, tcp_check, CHECKER_NEW_CO());
++		      tcp_check_compare, tcp_check, CHECKER_NEW_CO());
+ }
+ 
+ static void
+diff --git a/keepalived/include/check_api.h b/keepalived/include/check_api.h
+index 4a10a36b..c7bc297d 100644
+--- a/keepalived/include/check_api.h
++++ b/keepalived/include/check_api.h
+@@ -36,7 +36,7 @@ typedef struct _checker {
+ 	void				(*free_func) (void *);
+ 	void				(*dump_func) (void *);
+ 	int				(*launch) (struct _thread *);
+-	int				(*compare) (void *, void *);
++	bool				(*compare) (void *, void *);
+ 	virtual_server_t		*vs;	/* pointer to the checker thread virtualserver */
+ 	real_server_t			*rs;	/* pointer to the checker thread realserver */
+ 	void				*data;
+@@ -71,10 +71,10 @@ extern void init_checkers_queue(void);
+ extern void dump_conn_opts(void *);
+ extern void queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
+ 			  , int (*launch) (thread_t *)
+-			  , int (*compare) (void *, void *)
++			  , bool (*compare) (void *, void *)
+ 			  , void *
+ 			  , conn_opts_t *);
+-extern int  compare_conn_opts(conn_opts_t *, conn_opts_t *);
++extern bool compare_conn_opts(conn_opts_t *, conn_opts_t *);
+ extern void dump_checkers_queue(void);
+ extern void free_checkers_queue(void);
+ extern void register_checkers_thread(void);
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-fix-wrong-migrate-checker-id.patch b/SOURCES/bz1678480-fix-wrong-migrate-checker-id.patch
new file mode 100644
index 0000000..eb171fe
--- /dev/null
+++ b/SOURCES/bz1678480-fix-wrong-migrate-checker-id.patch
@@ -0,0 +1,25 @@
+From cd8b3f6b79d8cd5e89a05825144277785933b687 Mon Sep 17 00:00:00 2001
+From: YAMAMOTO Masaya <pandax381@gmail.com>
+Date: Tue, 11 Jul 2017 15:47:12 +0900
+Subject: [PATCH 4/8] Fix worng migrate of checker-id
+
+---
+ keepalived/check/ipwrapper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index 49262e25..09d86f08 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -651,7 +651,7 @@ migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs)
+ 			if (old_c->compare == new_c->compare && new_c->compare(old_c, new_c) == 0) {
+ 				if (svr_checker_up(old_c->id, old_rs) == 0) {
+ 					id = (checker_id_t *) MALLOC(sizeof(checker_id_t));
+-					*id = old_c->id;
++					*id = new_c->id;
+ 					list_add(new_rs->failed_checkers, id);
+ 				}
+ 				break;
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-implment-checker-comparison.patch b/SOURCES/bz1678480-implment-checker-comparison.patch
new file mode 100644
index 0000000..b542750
--- /dev/null
+++ b/SOURCES/bz1678480-implment-checker-comparison.patch
@@ -0,0 +1,420 @@
+From fce93460597d27a86798c57ec410f63e4bd33be9 Mon Sep 17 00:00:00 2001
+From: YAMAMOTO Masaya <pandax381@gmail.com>
+Date: Fri, 7 Jul 2017 19:27:16 +0900
+Subject: [PATCH 3/8] Implement comparison of checkers
+
+---
+ keepalived/check/check_api.c    | 29 ++++++++++++++++++++++++-
+ keepalived/check/check_daemon.c |  7 +++++-
+ keepalived/check/check_dns.c    | 24 +++++++++++++++++++--
+ keepalived/check/check_http.c   | 35 +++++++++++++++++++++++++++++-
+ keepalived/check/check_misc.c   | 22 ++++++++++++++++++-
+ keepalived/check/check_smtp.c   | 33 +++++++++++++++++++++++++++-
+ keepalived/check/check_tcp.c    | 22 +++++++++++++++++--
+ keepalived/check/ipwrapper.c    | 38 +++++++++++++++++++++++++--------
+ keepalived/include/check_api.h  |  5 +++++
+ 9 files changed, 197 insertions(+), 18 deletions(-)
+
+diff --git a/keepalived/check/check_api.c b/keepalived/check/check_api.c
+index b7081fd0..a722fc84 100644
+--- a/keepalived/check/check_api.c
++++ b/keepalived/check/check_api.c
+@@ -42,8 +42,9 @@
+ #include "check_dns.h"
+ 
+ /* Global vars */
+-static checker_id_t ncheckers = 0;
++checker_id_t ncheckers = 0;
+ list checkers_queue;
++list old_checkers_queue;
+ 
+ /* free checker data */
+ static void
+@@ -80,6 +81,7 @@ dump_conn_opts(void *data)
+ void
+ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
+ 	      , int (*launch) (thread_t *)
++	      , int (*compare) (void *, void *)
+ 	      , void *data
+ 	      , conn_opts_t *co)
+ {
+@@ -96,6 +98,7 @@ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
+ 	checker->free_func = free_func;
+ 	checker->dump_func = dump_func;
+ 	checker->launch = launch;
++	checker->compare = compare;
+ 	checker->vs = vs;
+ 	checker->rs = rs;
+ 	checker->data = data;
+@@ -117,6 +120,30 @@ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
+ 	}
+ }
+ 
++int
++compare_conn_opts(conn_opts_t *a, conn_opts_t *b)
++{
++	if (a == b)
++		return 0;
++
++	if (!a || !b)
++		goto err;
++	if (!sockstorage_equal(&a->dst, &b->dst))
++		goto err;
++	if (!sockstorage_equal(&a->bindto, &b->bindto))
++		goto err;
++	//if (a->connection_to != b->connection_to)
++	//	goto err;
++#ifdef _WITH_SO_MARK_
++	if (a->fwmark != b->fwmark)
++		goto err;
++#endif
++
++	return  0;
++err:
++	return -1;
++}
++
+ static void
+ checker_set_dst_port(struct sockaddr_storage *dst, uint16_t port)
+ {
+diff --git a/keepalived/check/check_daemon.c b/keepalived/check/check_daemon.c
+index a3ff8cab..462360e6 100644
+--- a/keepalived/check/check_daemon.c
++++ b/keepalived/check/check_daemon.c
+@@ -233,7 +233,11 @@ reload_check_thread(__attribute__((unused)) thread_t * thread)
+ 	thread_cleanup_master(master);
+ 	free_global_data(global_data);
+ 
+-	free_checkers_queue();
++	/* Save previous checker data */
++	old_checkers_queue = checkers_queue;
++	checkers_queue = NULL;
++	ncheckers = 0;
++
+ 	free_ssl();
+ 	ipvs_stop();
+ 
+@@ -246,6 +250,7 @@ reload_check_thread(__attribute__((unused)) thread_t * thread)
+ 
+ 	/* free backup data */
+ 	free_check_data(old_check_data);
++	free_list(&old_checkers_queue);
+ 	UNSET_RELOAD;
+ 
+ 	return 0;
+diff --git a/keepalived/check/check_dns.c b/keepalived/check/check_dns.c
+index 96328027..84a5f56d 100644
+--- a/keepalived/check/check_dns.c
++++ b/keepalived/check/check_dns.c
+@@ -388,6 +388,26 @@ dns_dump(void *data)
+ 	log_message(LOG_INFO, "   Name = %s", dns_check->name);
+ }
+ 
++static int
++dns_compare(void *a, void *b)
++{
++	dns_check_t *old = CHECKER_DATA(a);
++	dns_check_t *new = CHECKER_DATA(b);
++
++	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
++		goto err;
++	if (old->retry != new->retry)
++		goto err;
++	if (strcmp(old->type, new->type) != 0)
++		goto err;
++	if (strcmp(old->name, new->name) != 0)
++		goto err;
++
++	return  0;
++err:
++	return -1;
++}
++
+ static void
+ dns_check_handler(__attribute__((unused)) vector_t * strvec)
+ {
+@@ -396,8 +416,8 @@ dns_check_handler(__attribute__((unused)) vector_t * strvec)
+ 	dns_check->attempts = 0;
+ 	dns_check->type = DNS_DEFAULT_TYPE;
+ 	dns_check->name = DNS_DEFAULT_NAME;
+-	queue_checker(dns_free, dns_dump, dns_connect_thread, dns_check,
+-		      CHECKER_NEW_CO());
++	queue_checker(dns_free, dns_dump, dns_connect_thread,
++		      dns_compare, dns_check, CHECKER_NEW_CO());
+ }
+ 
+ static void
+diff --git a/keepalived/check/check_http.c b/keepalived/check/check_http.c
+index 05e29b23..c2089a3b 100644
+--- a/keepalived/check/check_http.c
++++ b/keepalived/check/check_http.c
+@@ -123,6 +123,38 @@ alloc_http_get(char *proto)
+ 	return http_get_chk;
+ }
+ 
++static int
++compare_http_get_check(void *a, void *b)
++{
++	http_checker_t *old = CHECKER_DATA(a);
++	http_checker_t *new = CHECKER_DATA(b);
++	size_t n;
++	url_t *u1, *u2;
++
++	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
++		goto err;
++	if (old->nb_get_retry != new->nb_get_retry)
++		goto err;
++	if (old->delay_before_retry != new->delay_before_retry)
++		goto err;
++	if (LIST_SIZE(old->url) != LIST_SIZE(new->url))
++		goto err;
++	for (n = 0; n < LIST_SIZE(new->url); n++) {
++		u1 = (url_t *)list_element(old->url, n);
++		u2 = (url_t *)list_element(new->url, n);
++		if (strcmp(u1->path, u2->path) != 0)
++			goto err;
++		if (strcmp(u1->digest, u2->digest) != 0)
++			goto err;
++		if (u1->status_code != u2->status_code)
++			goto err;
++	}
++
++	return  0;
++err:
++	return -1;
++}
++
+ static void
+ http_get_handler(vector_t *strvec)
+ {
+@@ -132,7 +164,8 @@ http_get_handler(vector_t *strvec)
+ 	/* queue new checker */
+ 	http_get_chk = alloc_http_get(str);
+ 	queue_checker(free_http_get_check, dump_http_get_check,
+-		      http_connect_thread, http_get_chk, CHECKER_NEW_CO());
++		      http_connect_thread, compare_http_get_check,
++		      http_get_chk, CHECKER_NEW_CO());
+ }
+ 
+ static void
+diff --git a/keepalived/check/check_misc.c b/keepalived/check/check_misc.c
+index 10ac1e23..311a1127 100644
+--- a/keepalived/check/check_misc.c
++++ b/keepalived/check/check_misc.c
+@@ -72,6 +72,26 @@ dump_misc_check(void *data)
+ 	log_message(LOG_INFO, "   insecure = %s", misck_checker->insecure ? "Yes" : "No");
+ }
+ 
++static int
++compare_misc_check(void *a, void *b)
++{
++	misc_checker_t *old = CHECKER_DATA(a);
++	misc_checker_t *new = CHECKER_DATA(b);
++
++	if (strcmp(old->path, new->path) != 0)
++		goto err;
++	if (old->timeout != new->timeout)
++		goto err;
++	if (old->dynamic != new->dynamic)
++		goto err;
++	if (old->uid != new->uid || new->gid != new->gid)
++		goto err;
++
++	return  0;
++err:
++	return -1;
++}
++
+ static void
+ misc_check_handler(__attribute__((unused)) vector_t *strvec)
+ {
+@@ -149,7 +169,7 @@ log_message(LOG_INFO, "Setting uid.gid");
+ 	}
+ 
+ 	/* queue new checker */
+-	queue_checker(free_misc_check, dump_misc_check, misc_check_thread, misck_checker, NULL);
++	queue_checker(free_misc_check, dump_misc_check, misc_check_thread, compare_misc_check, misck_checker, NULL);
+ 	misck_checker = NULL;
+ log_message(LOG_INFO, "Leaving misc_end_handler");
+ }
+diff --git a/keepalived/check/check_smtp.c b/keepalived/check/check_smtp.c
+index 901b77f5..e19511cc 100644
+--- a/keepalived/check/check_smtp.c
++++ b/keepalived/check/check_smtp.c
+@@ -82,6 +82,37 @@ dump_smtp_check(void *data)
+ 	dump_list(smtp_checker->host);
+ }
+ 
++static int
++compare_smtp_check(void *a, void *b)
++{
++	smtp_checker_t *old = CHECKER_DATA(a);
++	smtp_checker_t *new = CHECKER_DATA(b);
++	size_t n;
++	smtp_host_t *h1, *h2;
++
++	if (strcmp(old->helo_name, new->helo_name) != 0)
++		goto err;
++	if (old->retry != new->retry)
++		goto err;
++	if (old->db_retry != new->db_retry)
++		goto err;
++	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
++		goto err;
++	if (LIST_SIZE(old->host) != LIST_SIZE(new->host))
++		goto err;
++	for (n = 0; n < LIST_SIZE(new->host); n++) {
++		h1 = (smtp_host_t *)list_element(old->host, n);
++		h2 = (smtp_host_t *)list_element(new->host, n);
++		if (compare_conn_opts(h1, h2) != 0) {
++			goto err;
++		}
++	}
++
++	return  0;
++err:
++	return -1;
++}
++
+ /* Allocates a default host structure */
+ static smtp_host_t *
+ smtp_alloc_host(void)
+@@ -136,7 +167,7 @@ smtp_check_handler(__attribute__((unused)) vector_t *strvec)
+ 	 *               void *data, conn_opts_t *)
+ 	 */
+ 	queue_checker(free_smtp_check, dump_smtp_check, smtp_connect_thread,
+-		      smtp_checker, smtp_checker->default_co);
++		      compare_smtp_check, smtp_checker, smtp_checker->default_co);
+ 
+ 	/*
+ 	 * Last, allocate the list that will hold all the per host
+diff --git a/keepalived/check/check_tcp.c b/keepalived/check/check_tcp.c
+index 078ba705..026a0e3c 100644
+--- a/keepalived/check/check_tcp.c
++++ b/keepalived/check/check_tcp.c
+@@ -62,6 +62,24 @@ dump_tcp_check(void *data)
+ 	}
+ }
+ 
++static int
++compare_tcp_check(void *a, void *b)
++{
++	tcp_check_t *old = CHECKER_DATA(a);
++	tcp_check_t *new = CHECKER_DATA(b);
++
++	if (compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)) != 0)
++		goto err;
++	if (old->n_retry != new->n_retry)
++		goto err;
++	if (old->delay_before_retry != new->delay_before_retry)
++		goto err;
++
++	return  0;
++err:
++	return -1;
++}
++
+ static void
+ tcp_check_handler(__attribute__((unused)) vector_t *strvec)
+ {
+@@ -72,8 +90,8 @@ tcp_check_handler(__attribute__((unused)) vector_t *strvec)
+ 	tcp_check->delay_before_retry = 1 * TIMER_HZ;
+ 
+ 	/* queue new checker */
+-	queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread
+-		      ,tcp_check, CHECKER_NEW_CO());
++	queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread,
++		      compare_tcp_check, tcp_check, CHECKER_NEW_CO());
+ }
+ 
+ static void
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index 6acf18ba..49262e25 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -626,20 +626,40 @@ rs_exist(real_server_t * old_rs, list l)
+ static void
+ migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs)
+ {
+-	element e;
+-	checker_t *checker;
++	list l;
++	element e, e1;
++	checker_t *old_c, *new_c;
+ 	checker_id_t *id;
+ 
+-	/* Notes: It's a provisional implementation */
+-	(void)old_rs;
++	l = alloc_list(NULL, NULL);
++	for (e = LIST_HEAD(old_checkers_queue); e; ELEMENT_NEXT(e)) {
++		old_c = ELEMENT_DATA(e);
++		if (old_c->rs == old_rs) {
++			list_add(l, old_c);
++		}
++	}
++
++	if (LIST_ISEMPTY(l))
++		goto end;
++
+ 	for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
+-		checker = ELEMENT_DATA(e);
+-		if (checker->rs == new_rs) {
+-			id = (checker_id_t *) MALLOC(sizeof(checker_id_t));
+-			*id = checker->id;
+-			list_add(new_rs->failed_checkers, id);
++		new_c = ELEMENT_DATA(e);
++		if (new_c->rs != new_rs || !new_c->compare)
++			continue;
++		for (e1 = LIST_HEAD(l); e1; ELEMENT_NEXT(e1)) {
++			old_c = ELEMENT_DATA(e1);
++			if (old_c->compare == new_c->compare && new_c->compare(old_c, new_c) == 0) {
++				if (svr_checker_up(old_c->id, old_rs) == 0) {
++					id = (checker_id_t *) MALLOC(sizeof(checker_id_t));
++					*id = old_c->id;
++					list_add(new_rs->failed_checkers, id);
++				}
++				break;
++			}
+ 		}
+ 	}
++end:
++	free_list(&l);
+ }
+ 
+ /* Clear the diff rs of the old vs */
+diff --git a/keepalived/include/check_api.h b/keepalived/include/check_api.h
+index 359c794a..4a10a36b 100644
+--- a/keepalived/include/check_api.h
++++ b/keepalived/include/check_api.h
+@@ -36,6 +36,7 @@ typedef struct _checker {
+ 	void				(*free_func) (void *);
+ 	void				(*dump_func) (void *);
+ 	int				(*launch) (struct _thread *);
++	int				(*compare) (void *, void *);
+ 	virtual_server_t		*vs;	/* pointer to the checker thread virtualserver */
+ 	real_server_t			*rs;	/* pointer to the checker thread realserver */
+ 	void				*data;
+@@ -46,7 +47,9 @@ typedef struct _checker {
+ } checker_t;
+ 
+ /* Checkers queue */
++extern checker_id_t ncheckers;
+ extern list checkers_queue;
++extern list old_checkers_queue;
+ 
+ /* utility macro */
+ #define CHECKER_ARG(X) ((X)->data)
+@@ -68,8 +71,10 @@ extern void init_checkers_queue(void);
+ extern void dump_conn_opts(void *);
+ extern void queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
+ 			  , int (*launch) (thread_t *)
++			  , int (*compare) (void *, void *)
+ 			  , void *
+ 			  , conn_opts_t *);
++extern int  compare_conn_opts(conn_opts_t *, conn_opts_t *);
+ extern void dump_checkers_queue(void);
+ extern void free_checkers_queue(void);
+ extern void register_checkers_thread(void);
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-include-check_api-in-ipwrapper.patch b/SOURCES/bz1678480-include-check_api-in-ipwrapper.patch
new file mode 100644
index 0000000..6d97ff0
--- /dev/null
+++ b/SOURCES/bz1678480-include-check_api-in-ipwrapper.patch
@@ -0,0 +1,24 @@
+From 44ad4db4a45c7f152c074dacab48e051b42fde53 Mon Sep 17 00:00:00 2001
+From: Ryan O'Hara <rohara@redhat.com>
+Date: Wed, 3 Apr 2019 07:28:56 -0500
+Subject: [PATCH] Include check_api in ipwrapper
+
+---
+ keepalived/check/ipwrapper.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index c9dce2b7..17f0157d 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -24,6 +24,7 @@
+ 
+ #include "ipwrapper.h"
+ #include "ipvswrapper.h"
++#include "check_api.h"
+ #include "logger.h"
+ #include "memory.h"
+ #include "utils.h"
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-migrate-failed-checkers-reload.patch b/SOURCES/bz1678480-migrate-failed-checkers-reload.patch
new file mode 100644
index 0000000..9b10fdd
--- /dev/null
+++ b/SOURCES/bz1678480-migrate-failed-checkers-reload.patch
@@ -0,0 +1,89 @@
+From 6c5646bec26fe86214a34a877b84da83f9d9cfb4 Mon Sep 17 00:00:00 2001
+From: YAMAMOTO Masaya <pandax381@gmail.com>
+Date: Tue, 4 Jul 2017 15:08:36 +0900
+Subject: [PATCH 2/8] Migrate failed checkers at reload (provisional
+ implementation)
+
+---
+ keepalived/check/ipwrapper.c | 36 +++++++++++++++++++++++++-----------
+ 1 file changed, 25 insertions(+), 11 deletions(-)
+
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index ecf12713..6acf18ba 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -623,9 +623,28 @@ rs_exist(real_server_t * old_rs, list l)
+ 	return NULL;
+ }
+ 
++static void
++migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs)
++{
++	element e;
++	checker_t *checker;
++	checker_id_t *id;
++
++	/* Notes: It's a provisional implementation */
++	(void)old_rs;
++	for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
++		checker = ELEMENT_DATA(e);
++		if (checker->rs == new_rs) {
++			id = (checker_id_t *) MALLOC(sizeof(checker_id_t));
++			*id = checker->id;
++			list_add(new_rs->failed_checkers, id);
++		}
++	}
++}
++
+ /* Clear the diff rs of the old vs */
+ static void
+-clear_diff_rs(virtual_server_t * old_vs, list new_rs_list)
++clear_diff_rs(virtual_server_t *old_vs, virtual_server_t *new_vs)
+ {
+ 	element e;
+ 	list l = old_vs->rs;
+@@ -639,7 +658,7 @@ clear_diff_rs(virtual_server_t * old_vs, list new_rs_list)
+ 	list rs_to_remove = alloc_list (NULL, NULL);
+ 	for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ 		rs = ELEMENT_DATA(e);
+-		new_rs = rs_exist(rs, new_rs_list);
++		new_rs = rs_exist(rs, new_vs->rs);
+ 		if (!new_rs) {
+ 			/* Reset inhibit flag to delete inhibit entries */
+ 			log_message(LOG_INFO, "service %s no longer exist"
+@@ -662,20 +681,15 @@ clear_diff_rs(virtual_server_t * old_vs, list new_rs_list)
+ 				free_list_elements(new_rs->failed_checkers);
+ 			} else {
+ 				/*
+-				 * if not alive, we must copy the failed checker list
++				 * if not alive, we must migrate the failed checker list
+ 				 * If we do not, the new RS is in a state where it’s reported
+ 				 * as down with no check failed. As a result, the server will never
+ 				 * be put up back when it’s alive again in check_tcp.c#83 because
+ 				 * of the check that put a rs up only if it was not previously up
+ 				 * based on the failed_checkers list
+ 				 */
+-				element hc_e;
+-				list hc_l = rs->failed_checkers;
+-				list new_hc_l = new_rs->failed_checkers;
+-				for (hc_e = LIST_HEAD(hc_l); hc_e; ELEMENT_NEXT(hc_e)) {
+-					list_add(new_hc_l, ELEMENT_DATA(hc_e));
+-					ELEMENT_DATA(hc_e) = NULL;
+-				}
++				if (!new_vs->alpha)
++					migrate_failed_checkers(rs, new_rs);
+ 			}
+ 		}
+ 	}
+@@ -748,7 +762,7 @@ clear_diff_services(void)
+ 			/* omega = false must not prevent the notifiers from being called,
+ 			   because the VS still exists in new configuration */
+ 			vs->omega = true;
+-			clear_diff_rs(vs, new_vs->rs);
++			clear_diff_rs(vs, new_vs);
+ 			clear_diff_s_srv(vs, new_vs->s_svr);
+ 		}
+ 	}
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-remove-unnecessary-parameter-compare.patch b/SOURCES/bz1678480-remove-unnecessary-parameter-compare.patch
new file mode 100644
index 0000000..5f3f18b
--- /dev/null
+++ b/SOURCES/bz1678480-remove-unnecessary-parameter-compare.patch
@@ -0,0 +1,91 @@
+From a6a44b6a8f8a6af9d1cef3efaae9331e24257572 Mon Sep 17 00:00:00 2001
+From: YAMAMOTO Masaya <pandax381@gmail.com>
+Date: Fri, 14 Jul 2017 14:47:00 +0900
+Subject: [PATCH 7/8] Remove unnecessary parameter compare
+
+---
+ keepalived/check/check_dns.c  | 2 --
+ keepalived/check/check_http.c | 4 ----
+ keepalived/check/check_misc.c | 6 ------
+ keepalived/check/check_smtp.c | 4 ----
+ keepalived/check/check_tcp.c  | 4 ----
+ 5 files changed, 20 deletions(-)
+
+diff --git a/keepalived/check/check_dns.c b/keepalived/check/check_dns.c
+index 603742a4..671062bf 100644
+--- a/keepalived/check/check_dns.c
++++ b/keepalived/check/check_dns.c
+@@ -396,8 +396,6 @@ dns_check_compare(void *a, void *b)
+ 
+ 	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
+ 		return false;
+-	if (old->retry != new->retry)
+-		return false;
+ 	if (strcmp(old->type, new->type) != 0)
+ 		return false;
+ 	if (strcmp(old->name, new->name) != 0)
+diff --git a/keepalived/check/check_http.c b/keepalived/check/check_http.c
+index 1ad395cf..2802d6f5 100644
+--- a/keepalived/check/check_http.c
++++ b/keepalived/check/check_http.c
+@@ -133,10 +133,6 @@ http_get_check_compare(void *a, void *b)
+ 
+ 	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
+ 		return false;
+-	if (old->nb_get_retry != new->nb_get_retry)
+-		return false;
+-	if (old->delay_before_retry != new->delay_before_retry)
+-		return false;
+ 	if (LIST_SIZE(old->url) != LIST_SIZE(new->url))
+ 		return false;
+ 	for (n = 0; n < LIST_SIZE(new->url); n++) {
+diff --git a/keepalived/check/check_misc.c b/keepalived/check/check_misc.c
+index f1f66955..0cc649b6 100644
+--- a/keepalived/check/check_misc.c
++++ b/keepalived/check/check_misc.c
+@@ -80,12 +80,6 @@ misc_check_compare(void *a, void *b)
+ 
+ 	if (strcmp(old->path, new->path) != 0)
+ 		return false;
+-	if (old->timeout != new->timeout)
+-		return false;
+-	if (old->dynamic != new->dynamic)
+-		return false;
+-	if (old->uid != new->uid || new->gid != new->gid)
+-		return false;
+ 
+ 	return true;
+ }
+diff --git a/keepalived/check/check_smtp.c b/keepalived/check/check_smtp.c
+index 44d15e01..c135258f 100644
+--- a/keepalived/check/check_smtp.c
++++ b/keepalived/check/check_smtp.c
+@@ -92,10 +92,6 @@ smtp_check_compare(void *a, void *b)
+ 
+ 	if (strcmp(old->helo_name, new->helo_name) != 0)
+ 		return false;
+-	if (old->retry != new->retry)
+-		return false;
+-	if (old->db_retry != new->db_retry)
+-		return false;
+ 	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
+ 		return false;
+ 	if (LIST_SIZE(old->host) != LIST_SIZE(new->host))
+diff --git a/keepalived/check/check_tcp.c b/keepalived/check/check_tcp.c
+index 1858f5fc..7afed022 100644
+--- a/keepalived/check/check_tcp.c
++++ b/keepalived/check/check_tcp.c
+@@ -70,10 +70,6 @@ tcp_check_compare(void *a, void *b)
+ 
+ 	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
+ 		return false;
+-	if (old->n_retry != new->n_retry)
+-		return false;
+-	if (old->delay_before_retry != new->delay_before_retry)
+-		return false;
+ 
+ 	return true;
+ }
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-resolve-compiler-warning.patch b/SOURCES/bz1678480-resolve-compiler-warning.patch
new file mode 100644
index 0000000..7d451eb
--- /dev/null
+++ b/SOURCES/bz1678480-resolve-compiler-warning.patch
@@ -0,0 +1,27 @@
+From 1dce490fdf829a0decb544a6147c4c5cc4cecf51 Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Fri, 14 Jul 2017 16:45:02 +0100
+Subject: [PATCH 8/8] Resolve compiler warning introduced by commit 8361b11
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ keepalived/check/check_tcp.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/keepalived/check/check_tcp.c b/keepalived/check/check_tcp.c
+index 7afed022..69615544 100644
+--- a/keepalived/check/check_tcp.c
++++ b/keepalived/check/check_tcp.c
+@@ -65,9 +65,6 @@ dump_tcp_check(void *data)
+ static bool
+ tcp_check_compare(void *a, void *b)
+ {
+-	tcp_check_t *old = CHECKER_DATA(a);
+-	tcp_check_t *new = CHECKER_DATA(b);
+-
+ 	if (!compare_conn_opts(CHECKER_CO(a), CHECKER_CO(b)))
+ 		return false;
+ 
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1678480-set-active-if-failed-checkers-empty.patch b/SOURCES/bz1678480-set-active-if-failed-checkers-empty.patch
new file mode 100644
index 0000000..3acd745
--- /dev/null
+++ b/SOURCES/bz1678480-set-active-if-failed-checkers-empty.patch
@@ -0,0 +1,26 @@
+From ebd51b5f4a26619a4dd0393a7e97e4ca1a122700 Mon Sep 17 00:00:00 2001
+From: YAMAMOTO Masaya <pandax381@gmail.com>
+Date: Tue, 11 Jul 2017 17:55:50 +0900
+Subject: [PATCH 5/8] Set active if new failed_checkers is empty
+
+---
+ keepalived/check/ipwrapper.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index 09d86f08..c9dce2b7 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -658,6 +658,9 @@ migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs)
+ 			}
+ 		}
+ 	}
++
++	if (LIST_ISEMPTY(new_rs->failed_checkers))
++		SET_ALIVE(new_rs);
+ end:
+ 	free_list(&l);
+ }
+-- 
+2.20.1
+
diff --git a/SOURCES/bz1715308-fix-checkers-comparison-on-reload.patch b/SOURCES/bz1715308-fix-checkers-comparison-on-reload.patch
new file mode 100644
index 0000000..30233b9
--- /dev/null
+++ b/SOURCES/bz1715308-fix-checkers-comparison-on-reload.patch
@@ -0,0 +1,46 @@
+From 8e42d6970457336bd92d327c628e38129f221f8a Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Mon, 17 Jul 2017 11:43:28 +0100
+Subject: [PATCH] Correct comparison for checker compare in
+ migrate_failed_checkers
+
+Commit 2ff6b3f changed the sense of the comparisons of checkers,
+but didn't make the corresponding change to checking the result.
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ keepalived/check/check_api.c | 4 ++--
+ keepalived/check/ipwrapper.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/keepalived/check/check_api.c b/keepalived/check/check_api.c
+index 1d915414..82b0f2df 100644
+--- a/keepalived/check/check_api.c
++++ b/keepalived/check/check_api.c
+@@ -266,8 +266,8 @@ register_checkers_thread(void)
+ 
+ 	for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
+ 		checker = ELEMENT_DATA(e);
+-		log_message(LOG_INFO, "%sctivating healthchecker for service %s"
+-				    , checker->enabled ? "A" : "Dea", FMT_VS(checker->vs));
++		log_message(LOG_INFO, "%sctivating healthchecker for service %s"
++				    , checker->enabled ? "A" : "Dea", FMT_VS(checker->vs));
+ 		if (checker->launch)
+ 		{
+ 			/* wait for a random timeout to begin checker thread.
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index 17f0157d..ad8c3154 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -649,7 +649,7 @@ migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs)
+ 			continue;
+ 		for (e1 = LIST_HEAD(l); e1; ELEMENT_NEXT(e1)) {
+ 			old_c = ELEMENT_DATA(e1);
+-			if (old_c->compare == new_c->compare && new_c->compare(old_c, new_c) == 0) {
++			if (old_c->compare == new_c->compare && new_c->compare(old_c, new_c)) {
+ 				if (svr_checker_up(old_c->id, old_rs) == 0) {
+ 					id = (checker_id_t *) MALLOC(sizeof(checker_id_t));
+ 					*id = new_c->id;
+-- 
+2.21.0
+
diff --git a/SOURCES/bz1715308-make-checker-variables-non-global.patch b/SOURCES/bz1715308-make-checker-variables-non-global.patch
new file mode 100644
index 0000000..b60e725
--- /dev/null
+++ b/SOURCES/bz1715308-make-checker-variables-non-global.patch
@@ -0,0 +1,173 @@
+From 6f18ff4f0a06015691b25cb91bf4c6dccec5cc89 Mon Sep 17 00:00:00 2001
+From: Quentin Armitage <quentin@armitage.org.uk>
+Date: Sun, 16 Jul 2017 10:00:20 +0100
+Subject: [PATCH] Make a couple of checker variables non global
+
+Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
+---
+ keepalived/check/check_api.c    |  4 ++--
+ keepalived/check/check_daemon.c | 11 ++++++-----
+ keepalived/check/ipwrapper.c    | 10 +++++-----
+ keepalived/include/check_api.h  |  2 --
+ keepalived/include/ipwrapper.h  |  2 +-
+ 5 files changed, 14 insertions(+), 15 deletions(-)
+
+diff --git a/keepalived/check/check_api.c b/keepalived/check/check_api.c
+index 82b0f2df..016850f0 100644
+--- a/keepalived/check/check_api.c
++++ b/keepalived/check/check_api.c
+@@ -42,9 +42,8 @@
+ #include "check_dns.h"
+ 
+ /* Global vars */
+-checker_id_t ncheckers = 0;
++static checker_id_t ncheckers;
+ list checkers_queue;
+-list old_checkers_queue;
+ 
+ /* free checker data */
+ static void
+@@ -243,6 +242,7 @@ void
+ init_checkers_queue(void)
+ {
+ 	checkers_queue = alloc_list(free_checker, dump_checker);
++	ncheckers = 0;
+ }
+ 
+ /* release the checkers_queue */
+diff --git a/keepalived/check/check_daemon.c b/keepalived/check/check_daemon.c
+index 462360e6..85f8bdbd 100644
+--- a/keepalived/check/check_daemon.c
++++ b/keepalived/check/check_daemon.c
+@@ -108,7 +108,7 @@ stop_check(int status)
+ 
+ /* Daemon init sequence */
+ static void
+-start_check(void)
++start_check(list old_checkers_queue)
+ {
+ 	/* Initialize sub-system */
+ 	if (ipvs_start() != IPVS_SUCCESS) {
+@@ -171,7 +171,7 @@ start_check(void)
+ 
+ 	/* Processing differential configuration parsing */
+ 	if (reload)
+-		clear_diff_services();
++		clear_diff_services(old_checkers_queue);
+ 
+ 	/* Initialize IPVS topology */
+ 	if (!init_services())
+@@ -219,6 +219,8 @@ check_signal_init(void)
+ static int
+ reload_check_thread(__attribute__((unused)) thread_t * thread)
+ {
++	list old_checkers_queue;
++
+ 	/* set the reloading flag */
+ 	SET_RELOAD;
+ 
+@@ -236,7 +238,6 @@ reload_check_thread(__attribute__((unused)) thread_t * thread)
+ 	/* Save previous checker data */
+ 	old_checkers_queue = checkers_queue;
+ 	checkers_queue = NULL;
+-	ncheckers = 0;
+ 
+ 	free_ssl();
+ 	ipvs_stop();
+@@ -246,7 +247,7 @@ reload_check_thread(__attribute__((unused)) thread_t * thread)
+ 	check_data = NULL;
+ 
+ 	/* Reload the conf */
+-	start_check();
++	start_check(old_checkers_queue);
+ 
+ 	/* free backup data */
+ 	free_check_data(old_check_data);
+@@ -355,7 +356,7 @@ start_check_child(void)
+ 	check_signal_init();
+ 
+ 	/* Start Healthcheck daemon */
+-	start_check();
++	start_check(NULL);
+ 
+ 	/* Launch the scheduling I/O multiplexer */
+ 	launch_scheduler();
+diff --git a/keepalived/check/ipwrapper.c b/keepalived/check/ipwrapper.c
+index ad8c3154..34bb59f8 100644
+--- a/keepalived/check/ipwrapper.c
++++ b/keepalived/check/ipwrapper.c
+@@ -625,7 +625,7 @@ rs_exist(real_server_t * old_rs, list l)
+ }
+ 
+ static void
+-migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs)
++migrate_failed_checkers(real_server_t *old_rs, real_server_t *new_rs, list old_checkers_queue)
+ {
+ 	list l;
+ 	element e, e1;
+@@ -668,7 +668,7 @@ end:
+ 
+ /* Clear the diff rs of the old vs */
+ static void
+-clear_diff_rs(virtual_server_t *old_vs, virtual_server_t *new_vs)
++clear_diff_rs(virtual_server_t *old_vs, virtual_server_t *new_vs, list old_checkers_queue)
+ {
+ 	element e;
+ 	list l = old_vs->rs;
+@@ -713,7 +713,7 @@ clear_diff_rs(virtual_server_t *old_vs, virtual_server_t *new_vs)
+ 				 * based on the failed_checkers list
+ 				 */
+ 				if (!new_vs->alpha)
+-					migrate_failed_checkers(rs, new_rs);
++					migrate_failed_checkers(rs, new_rs, old_checkers_queue);
+ 			}
+ 		}
+ 	}
+@@ -746,7 +746,7 @@ clear_diff_s_srv(virtual_server_t *old_vs, real_server_t *new_rs)
+ /* When reloading configuration, remove negative diff entries
+  * and copy status of existing entries to the new ones */
+ void
+-clear_diff_services(void)
++clear_diff_services(list old_checkers_queue)
+ {
+ 	element e;
+ 	list l = old_check_data->vs;
+@@ -786,7 +786,7 @@ clear_diff_services(void)
+ 			/* omega = false must not prevent the notifiers from being called,
+ 			   because the VS still exists in new configuration */
+ 			vs->omega = true;
+-			clear_diff_rs(vs, new_vs);
++			clear_diff_rs(vs, new_vs, old_checkers_queue);
+ 			clear_diff_s_srv(vs, new_vs->s_svr);
+ 		}
+ 	}
+diff --git a/keepalived/include/check_api.h b/keepalived/include/check_api.h
+index c7bc297d..c43eca14 100644
+--- a/keepalived/include/check_api.h
++++ b/keepalived/include/check_api.h
+@@ -47,9 +47,7 @@ typedef struct _checker {
+ } checker_t;
+ 
+ /* Checkers queue */
+-extern checker_id_t ncheckers;
+ extern list checkers_queue;
+-extern list old_checkers_queue;
+ 
+ /* utility macro */
+ #define CHECKER_ARG(X) ((X)->data)
+diff --git a/keepalived/include/ipwrapper.h b/keepalived/include/ipwrapper.h
+index 11cdbbc6..0a6c48ba 100644
+--- a/keepalived/include/ipwrapper.h
++++ b/keepalived/include/ipwrapper.h
+@@ -55,7 +55,7 @@ extern int svr_checker_up(checker_id_t, real_server_t *);
+ extern void update_svr_checker_state(bool, checker_id_t, virtual_server_t *, real_server_t *);
+ extern bool init_services(void);
+ extern void clear_services(void);
+-extern void clear_diff_services(void);
++extern void clear_diff_services(list);
+ extern void link_vsg_to_vs(void);
+ 
+ #endif
+-- 
+2.21.0
+
diff --git a/SPECS/keepalived.spec b/SPECS/keepalived.spec
index 83fd422..aa55882 100644
--- a/SPECS/keepalived.spec
+++ b/SPECS/keepalived.spec
@@ -9,7 +9,7 @@
 Name: keepalived
 Summary: Load balancer and high availability service
 Version: 1.3.5
-Release: 8%{?dist}
+Release: 8%{?dist}.5
 License: GPLv2+
 URL: http://www.keepalived.org/
 Group: System Environment/Daemons
@@ -25,6 +25,17 @@ Patch4: bz1508435-no-segfault-ip_vs-load.patch
 Patch5: bz1508435-remove-ipset-handling.patch
 Patch6: bz1477587-exclude-mismatch-vips.patch
 Patch7: bz1652694-fix-buffer-overflow-http-status.patch
+patch10: bz1678480-add-child_wait_time.patch
+patch11: bz1678480-migrate-failed-checkers-reload.patch
+patch12: bz1678480-implment-checker-comparison.patch
+patch13: bz1678480-fix-wrong-migrate-checker-id.patch
+patch14: bz1678480-set-active-if-failed-checkers-empty.patch
+patch15: bz1678480-fix-checker-coding-style.patch
+patch16: bz1678480-remove-unnecessary-parameter-compare.patch
+patch17: bz1678480-resolve-compiler-warning.patch
+patch18: bz1678480-include-check_api-in-ipwrapper.patch
+patch19: bz1715308-make-checker-variables-non-global.patch
+patch20: bz1715308-fix-checkers-comparison-on-reload.patch
 
 Requires: ipset-libs
 Requires(post): systemd
@@ -63,6 +74,17 @@ Keepalived also implements the Virtual Router Redundancy Protocol
 %patch5 -p1
 %patch6 -p1
 %patch7 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
 
 %build
 %configure \
@@ -119,7 +141,22 @@ Keepalived also implements the Virtual Router Redundancy Protocol
 %{_mandir}/man8/keepalived.8*
 
 %changelog
-* Thu Dec 31 2018 Ryan O'Hara <rohara@redhat.com> - 1.3.5-8
+* Mon Jun 03 2019 Ryan O'Hara <rohara@redhat.com> - 1.3.5-8.5
+- Rework previous checker comparison patch (#1716588)
+
+* Mon Jun 03 2019 Ryan O'Hara <rohara@redhat.com> - 1.3.5-8.4
+- Make checker variables non global (#1716588)
+
+* Mon Jun 03 2019 Ryan O'Hara <rohara@redhat.com> - 1.3.5-8.3
+- Fix comparison of checkers on reload (#1716588)
+
+* Wed Apr 03 2019 Ryan O'Hara <rohara@redhat.com> - 1.3.5-8.2
+- Fix build errors (#1678480)
+
+* Tue Apr 02 2019 Ryan O'Hara <rohara@redhat.com> - 1.3.5-8.1
+- Fix problems with health checks & real servers after reload/restart (#1695653)
+
+* Thu Dec 13 2018 Ryan O'Hara <rohara@redhat.com> - 1.3.5-8
 - Fixed patch that was incorrectly removed (#1652694)
 
 * Mon Dec 10 2018 Ryan O'Hara <rohara@redhat.com> - 1.3.5-7