c629ea
From d905fd132a536e9149c91816704500c659e154f0 Mon Sep 17 00:00:00 2001
c629ea
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
c629ea
Date: Tue, 26 Nov 2019 16:32:03 +0100
c629ea
Subject: [PATCH] Changed log lock from 'quick' to 'basic' because this is an
c629ea
 I/O lock.
c629ea
c629ea
We cannot use a 'quick' lock (i.e. lock spinning on the CPU) for the log
c629ea
lock because it can wait a lot on I/Os. Using a 'quick' lock leads to
c629ea
eating the CPU for no good reason.
c629ea
c629ea
Example of 'pidstat' output when using various locks for log_lock:
c629ea
c629ea
- 'quick' lock and slow log file system (tail -f on the log file on XFS on RHEL 8)
c629ea
c629ea
04:15:11 PM   UID      TGID       TID    %usr %system    %CPU CPU  Command
c629ea
04:15:21 PM   998     16431         -  100.00    4.20  100.00   2  unbound
c629ea
04:15:21 PM   998         -     16431   31.00    1.00   32.00   2  |__unbound
c629ea
04:15:21 PM   998         -     16432   31.30    0.80   32.10   0  |__unbound
c629ea
04:15:21 PM   998         -     16433   30.20    1.40   31.60   1  |__unbound
c629ea
04:15:21 PM   998         -     16434   30.70    1.00   31.70   3  |__unbound
c629ea
c629ea
- 'quick' lock and log file system being fast
c629ea
c629ea
04:15:40 PM   UID      TGID       TID    %usr %system   %CPU CPU  Command
c629ea
04:15:50 PM   998     16431         -   10.00    1.60  11.60   1  unbound
c629ea
04:15:50 PM   998         -     16431    2.50    0.50   3.00   1  |__unbound
c629ea
04:15:50 PM   998         -     16432    2.30    0.40   2.70   3  |__unbound
c629ea
04:15:50 PM   998         -     16433    2.70    0.30   3.00   0  |__unbound
c629ea
04:15:50 PM   998         -     16434    2.60    0.40   3.00   2  |__unbound
c629ea
c629ea
- 'basic' lock (this commit) and slow log file system (tail -f on the log file on XFS on RHEL 8)
c629ea
c629ea
04:29:48 PM   UID      TGID       TID    %usr %system   %CPU CPU  Command
c629ea
04:29:58 PM   998     11632         -    7.10   14.10  21.20   3  unbound
c629ea
04:29:58 PM   998         -     11632    1.70    3.20   4.90   3  |__unbound
c629ea
04:29:58 PM   998         -     11633    1.60    3.30   4.90   1  |__unbound
c629ea
04:29:58 PM   998         -     11634    2.00    4.10   6.10   1  |__unbound
c629ea
04:29:58 PM   998         -     11635    1.90    3.50   5.40   1  |__unbound
c629ea
c629ea
We can see in the above example, when 'basic' lock is used, that CPU
c629ea
isn't consumed when log file system is slow.
c629ea
c629ea
Another reproducer scenario: put the log file on a NFS share with 'sync'
c629ea
option.
c629ea
---
c629ea
 util/log.c | 30 +++++++++++++++---------------
c629ea
 1 file changed, 15 insertions(+), 15 deletions(-)
c629ea
c629ea
diff --git a/util/log.c b/util/log.c
c629ea
index c14b458..5b31854 100644
c629ea
--- a/util/log.c
c629ea
+++ b/util/log.c
c629ea
@@ -70,7 +70,7 @@ static int key_created = 0;
c629ea
 static ub_thread_key_type logkey;
c629ea
 #ifndef THREADS_DISABLED
c629ea
 /** pthread mutex to protect FILE* */
c629ea
-static lock_quick_type log_lock;
c629ea
+static lock_basic_type log_lock;
c629ea
 #endif
c629ea
 /** the identity of this executable/process */
c629ea
 static const char* ident="unbound";
c629ea
@@ -90,18 +90,18 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
c629ea
 	if(!key_created) {
c629ea
 		key_created = 1;
c629ea
 		ub_thread_key_create(&logkey, NULL);
c629ea
-		lock_quick_init(&log_lock);
c629ea
+		lock_basic_init(&log_lock);
c629ea
 	}
c629ea
-	lock_quick_lock(&log_lock);
c629ea
+	lock_basic_lock(&log_lock);
c629ea
 	if(logfile 
c629ea
 #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)
c629ea
 	|| logging_to_syslog
c629ea
 #endif
c629ea
 	) {
c629ea
-		lock_quick_unlock(&log_lock); /* verbose() needs the lock */
c629ea
+		lock_basic_unlock(&log_lock); /* verbose() needs the lock */
c629ea
 		verbose(VERB_QUERY, "switching log to %s", 
c629ea
 			use_syslog?"syslog":(filename&&filename[0]?filename:"stderr"));
c629ea
-		lock_quick_lock(&log_lock);
c629ea
+		lock_basic_lock(&log_lock);
c629ea
 	}
c629ea
 	if(logfile && logfile != stderr) {
c629ea
 		FILE* cl = logfile;
c629ea
@@ -119,7 +119,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
c629ea
 		 * chroot and no longer be able to access dev/log and so on */
c629ea
 		openlog(ident, LOG_NDELAY, LOG_DAEMON);
c629ea
 		logging_to_syslog = 1;
c629ea
-		lock_quick_unlock(&log_lock);
c629ea
+		lock_basic_unlock(&log_lock);
c629ea
 		return;
c629ea
 	}
c629ea
 #elif defined(UB_ON_WINDOWS)
c629ea
@@ -128,13 +128,13 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
c629ea
 	}
c629ea
 	if(use_syslog) {
c629ea
 		logging_to_syslog = 1;
c629ea
-		lock_quick_unlock(&log_lock);
c629ea
+		lock_basic_unlock(&log_lock);
c629ea
 		return;
c629ea
 	}
c629ea
 #endif /* HAVE_SYSLOG_H */
c629ea
 	if(!filename || !filename[0]) {
c629ea
 		logfile = stderr;
c629ea
-		lock_quick_unlock(&log_lock);
c629ea
+		lock_basic_unlock(&log_lock);
c629ea
 		return;
c629ea
 	}
c629ea
 	/* open the file for logging */
c629ea
@@ -143,7 +143,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
c629ea
 		filename += strlen(chrootdir);
c629ea
 	f = fopen(filename, "a");
c629ea
 	if(!f) {
c629ea
-		lock_quick_unlock(&log_lock);
c629ea
+		lock_basic_unlock(&log_lock);
c629ea
 		log_err("Could not open logfile %s: %s", filename, 
c629ea
 			strerror(errno));
c629ea
 		return;
c629ea
@@ -153,14 +153,14 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
c629ea
 	setvbuf(f, NULL, (int)_IOLBF, 0);
c629ea
 #endif
c629ea
 	logfile = f;
c629ea
-	lock_quick_unlock(&log_lock);
c629ea
+	lock_basic_unlock(&log_lock);
c629ea
 }
c629ea
 
c629ea
 void log_file(FILE *f)
c629ea
 {
c629ea
-	lock_quick_lock(&log_lock);
c629ea
+	lock_basic_lock(&log_lock);
c629ea
 	logfile = f;
c629ea
-	lock_quick_unlock(&log_lock);
c629ea
+	lock_basic_unlock(&log_lock);
c629ea
 }
c629ea
 
c629ea
 void log_thread_set(int* num)
c629ea
@@ -239,9 +239,9 @@ log_vmsg(int pri, const char* type,
c629ea
 		return;
c629ea
 	}
c629ea
 #endif /* HAVE_SYSLOG_H */
c629ea
-	lock_quick_lock(&log_lock);
c629ea
+	lock_basic_lock(&log_lock);
c629ea
 	if(!logfile) {
c629ea
-		lock_quick_unlock(&log_lock);
c629ea
+		lock_basic_unlock(&log_lock);
c629ea
 		return;
c629ea
 	}
c629ea
 	if(log_now)
c629ea
@@ -268,7 +268,7 @@ log_vmsg(int pri, const char* type,
c629ea
 	/* line buffering does not work on windows */
c629ea
 	fflush(logfile);
c629ea
 #endif
c629ea
-	lock_quick_unlock(&log_lock);
c629ea
+	lock_basic_unlock(&log_lock);
c629ea
 }
c629ea
 
c629ea
 /**
c629ea
-- 
c629ea
2.21.0
c629ea