[ovs-dev] [worker 10/12] vlog: Use worker process to write to log file.

Ben Pfaff blp at nicira.com
Wed May 23 00:19:13 UTC 2012


Writes to regular files under Unix-like kernels, including Linux, typically
block until the write is complete, regardless of O_NONBLOCK.  When the I/O
subsystem is busy, this can cause indefinite delays.  We have actually
observed "write" calls sleep for 5 seconds or more for this reason.

Delegating to a subprocess through the worker mechanism should solve the
problem.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 lib/vlog.c |   52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 51 insertions(+), 1 deletions(-)

diff --git a/lib/vlog.c b/lib/vlog.c
index f7030b9..0a8dab1 100644
--- a/lib/vlog.c
+++ b/lib/vlog.c
@@ -30,11 +30,13 @@
 #include <unistd.h>
 #include "dirs.h"
 #include "dynamic-string.h"
+#include "ofpbuf.h"
 #include "sat-math.h"
 #include "svec.h"
 #include "timeval.h"
 #include "unixctl.h"
 #include "util.h"
+#include "worker.h"
 
 VLOG_DEFINE_THIS_MODULE(vlog);
 
@@ -94,6 +96,8 @@ static void format_log_message(const struct vlog_module *, enum vlog_level,
                                enum vlog_facility, unsigned int msg_num,
                                const char *message, va_list, struct ds *)
     PRINTF_FORMAT(5, 0);
+static void vlog_write_file(struct ds *);
+static void vlog_update_async_log_fd(void);
 
 /* Searches the 'n_names' in 'names'.  Returns the index of a match for
  * 'target', or 'n_names' if no name matches. */
@@ -298,6 +302,9 @@ vlog_set_log_file(const char *file_name)
     /* Open new log file and update min_levels[] to reflect whether we actually
      * have a log_file. */
     log_fd = open(log_file_name, O_WRONLY | O_CREAT | O_APPEND, 0666);
+    if (log_fd >= 0) {
+        vlog_update_async_log_fd();
+    }
     for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
         update_min_level(*mp);
     }
@@ -719,7 +726,7 @@ vlog_valist(const struct vlog_module *module, enum vlog_level level,
             format_log_message(module, level, VLF_FILE, msg_num,
                                message, args, &s);
             ds_put_char(&s, '\n');
-            write(log_fd, s.string, s.length);
+            vlog_write_file(&s);
         }
 
         ds_destroy(&s);
@@ -877,3 +884,46 @@ vlog_usage(void)
            "                          (default: %s/%s.log)\n",
            ovs_logdir(), program_name);
 }
+
+static bool vlog_async_inited;
+
+static worker_request_func vlog_async_write_request_cb;
+
+static void
+vlog_write_file(struct ds *s)
+{
+    if (worker_is_running()) {
+        worker_request(s->string, s->length,
+                       &log_fd, vlog_async_inited ? 0 : 1,
+                       vlog_async_write_request_cb, NULL, NULL);
+        vlog_async_inited = true;
+    } else {
+        write(log_fd, s->string, s->length);
+    }
+}
+
+static void
+vlog_update_async_log_fd(void)
+{
+    if (worker_is_running()) {
+        worker_request(NULL, 0, &log_fd, 1, vlog_async_write_request_cb,
+                       NULL, NULL);
+        vlog_async_inited = true;
+    }
+}
+
+static void
+vlog_async_write_request_cb(struct ofpbuf *request,
+                            const int *fd, size_t n_fds)
+{
+    if (n_fds > 0) {
+        if (log_fd >= 0) {
+            close(log_fd);
+        }
+        log_fd = *fd;
+    }
+
+    if (request->size > 0) {
+        write(log_fd, request->data, request->size);
+    }
+}
-- 
1.7.2.5




More information about the dev mailing list