Blame SOURCES/0058-nft-cache-Retry-if-kernel-returns-EINTR.patch

ec5e2e
From 681cb811e4cb8c5f22fd0fae60a3533289657705 Mon Sep 17 00:00:00 2001
ec5e2e
From: Phil Sutter <psutter@redhat.com>
ec5e2e
Date: Wed, 4 Aug 2021 17:14:05 +0200
ec5e2e
Subject: [PATCH] nft: cache: Retry if kernel returns EINTR
ec5e2e
ec5e2e
In case of parallel ruleset updates, recvfrom() calls may return EINTR.
ec5e2e
Due to the fact that cache fetches may get triggered while iterating
ec5e2e
over cache elements, __nft_build_cache must not restart based on
ec5e2e
comparing before and after generation ID like upstream does. Instead,
ec5e2e
just retry the recvfrom() calls until they either succeed or return a
ec5e2e
different error than EINTR.
ec5e2e
---
ec5e2e
 iptables/nft-cache.c | 18 ++++++++++++++----
ec5e2e
 1 file changed, 14 insertions(+), 4 deletions(-)
ec5e2e
ec5e2e
diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c
ec5e2e
index 9623b463f0dd5..699dc66a95cd1 100644
ec5e2e
--- a/iptables/nft-cache.c
ec5e2e
+++ b/iptables/nft-cache.c
ec5e2e
@@ -98,9 +98,12 @@ static int fetch_table_cache(struct nft_handle *h)
ec5e2e
 	nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
ec5e2e
 					NLM_F_DUMP, h->seq);
ec5e2e
 
ec5e2e
+retry:
ec5e2e
 	ret = mnl_talk(h, nlh, nftnl_table_list_cb, list);
ec5e2e
-	if (ret < 0 && errno == EINTR)
ec5e2e
+	if (ret < 0 && errno == EINTR) {
ec5e2e
 		assert(nft_restart(h) >= 0);
ec5e2e
+		goto retry;
ec5e2e
+	}
ec5e2e
 
ec5e2e
 	h->cache->tables = list;
ec5e2e
 
ec5e2e
@@ -275,10 +278,11 @@ static int fetch_set_cache(struct nft_handle *h,
ec5e2e
 						NLM_F_DUMP, h->seq);
ec5e2e
 	}
ec5e2e
 
ec5e2e
+retry:
ec5e2e
 	ret = mnl_talk(h, nlh, nftnl_set_list_cb, &d);
ec5e2e
 	if (ret < 0 && errno == EINTR) {
ec5e2e
 		assert(nft_restart(h) >= 0);
ec5e2e
-		return ret;
ec5e2e
+		goto retry;
ec5e2e
 	}
ec5e2e
 
ec5e2e
 	if (t && set) {
ec5e2e
@@ -355,9 +359,12 @@ static int fetch_chain_cache(struct nft_handle *h,
ec5e2e
 						  h->seq);
ec5e2e
 	}
ec5e2e
 
ec5e2e
+retry:
ec5e2e
 	ret = mnl_talk(h, nlh, nftnl_chain_list_cb, &d);
ec5e2e
-	if (ret < 0 && errno == EINTR)
ec5e2e
+	if (ret < 0 && errno == EINTR) {
ec5e2e
 		assert(nft_restart(h) >= 0);
ec5e2e
+		goto retry;
ec5e2e
+	}
ec5e2e
 
ec5e2e
 	return ret;
ec5e2e
 }
ec5e2e
@@ -404,9 +411,12 @@ static int nft_rule_list_update(struct nftnl_chain *c, void *data)
ec5e2e
 					NLM_F_DUMP, h->seq);
ec5e2e
 	nftnl_rule_nlmsg_build_payload(nlh, rule);
ec5e2e
 
ec5e2e
+retry:
ec5e2e
 	ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c);
ec5e2e
-	if (ret < 0 && errno == EINTR)
ec5e2e
+	if (ret < 0 && errno == EINTR) {
ec5e2e
 		assert(nft_restart(h) >= 0);
ec5e2e
+		goto retry;
ec5e2e
+	}
ec5e2e
 
ec5e2e
 	nftnl_rule_free(rule);
ec5e2e
 
ec5e2e
-- 
ec5e2e
2.32.0
ec5e2e