Blame SOURCES/iptables-use_the_blocking_file_lock_request.patch

9c64ad
commit 72bb3dbf0ecdf3ec96aee80e5d152c8be4394da1
9c64ad
Author: Liping Zhang <zlpnobody@gmail.com>
9c64ad
Date:   Mon Feb 6 19:47:47 2017 +0800
9c64ad
9c64ad
    xshared: using the blocking file lock request when we wait indefinitely
9c64ad
    
9c64ad
    When using "-w" to avoid concurrent instances, we try to do flock() every
9c64ad
    one second until it success. But one second maybe too long in some
9c64ad
    situations, and it's hard to select a suitable interval time. So when
9c64ad
    using "iptables -w" to wait indefinitely, it's better to block until
9c64ad
    it become success.
9c64ad
    
9c64ad
    Now do some performance tests. First, flush all the iptables rules in
9c64ad
    filter table, and run "iptables -w -S" endlessly:
9c64ad
      # iptables -F
9c64ad
      # iptables -X
9c64ad
      # while : ; do
9c64ad
      iptables -w -S >&- &
9c64ad
      done
9c64ad
    
9c64ad
    Second, after adding and deleting the iptables rules 100 times, measure
9c64ad
    the time cost:
9c64ad
      # time for i in $(seq 100); do
9c64ad
      iptables -w -A INPUT
9c64ad
      iptables -w -D INPUT
9c64ad
      done
9c64ad
    
9c64ad
    Before this patch:
9c64ad
      real  1m15.962s
9c64ad
      user  0m0.224s
9c64ad
      sys   0m1.475s
9c64ad
    
9c64ad
    Apply this patch:
9c64ad
      real  0m1.830s
9c64ad
      user  0m0.168s
9c64ad
      sys   0m1.130s
9c64ad
    
9c64ad
    Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
9c64ad
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
9c64ad
9c64ad
diff --git a/iptables/xshared.c b/iptables/xshared.c
9c64ad
index 055acf2..f0a5ddd 100644
9c64ad
--- a/iptables/xshared.c
9c64ad
+++ b/iptables/xshared.c
9c64ad
@@ -1,4 +1,5 @@
9c64ad
 #include <getopt.h>
9c64ad
+#include <errno.h>
9c64ad
 #include <libgen.h>
9c64ad
 #include <netdb.h>
9c64ad
 #include <stdbool.h>
9c64ad
@@ -258,27 +259,29 @@ bool xtables_lock(int wait, struct timeval *wait_interval)
9c64ad
 	if (fd < 0)
9c64ad
 		return true;
9c64ad
 
9c64ad
+	if (wait == -1) {
9c64ad
+		if (flock(fd, LOCK_EX) == 0)
9c64ad
+			return true;
9c64ad
+
9c64ad
+		fprintf(stderr, "Can't lock %s: %s\n", XT_LOCK_NAME,
9c64ad
+			strerror(errno));
9c64ad
+		return false;
9c64ad
+	}
9c64ad
+
9c64ad
 	while (1) {
9c64ad
 		if (flock(fd, LOCK_EX | LOCK_NB) == 0)
9c64ad
 			return true;
9c64ad
-		else if (wait >= 0 && timercmp(&time_left, wait_interval, <))
9c64ad
+		else if (timercmp(&time_left, wait_interval, <))
9c64ad
 			return false;
9c64ad
 
9c64ad
 		if (++i % 10 == 0) {
9c64ad
-			if (wait != -1)
9c64ad
-				fprintf(stderr, "Another app is currently holding the xtables lock; "
9c64ad
-					"still %lds %ldus time ahead to have a chance to grab the lock...\n",
9c64ad
-					time_left.tv_sec, time_left.tv_usec);
9c64ad
-			else
9c64ad
-				fprintf(stderr, "Another app is currently holding the xtables lock; "
9c64ad
-						"waiting for it to exit...\n");
9c64ad
+			fprintf(stderr, "Another app is currently holding the xtables lock; "
9c64ad
+				"still %lds %ldus time ahead to have a chance to grab the lock...\n",
9c64ad
+				time_left.tv_sec, time_left.tv_usec);
9c64ad
 		}
9c64ad
 
9c64ad
 		wait_time = *wait_interval;
9c64ad
 		select(0, NULL, NULL, NULL, &wait_time);
9c64ad
-		if (wait == -1)
9c64ad
-			continue;
9c64ad
-
9c64ad
 		timersub(&time_left, wait_interval, &time_left);
9c64ad
 	}
9c64ad
 }