+\f
+static bool vlog_async_inited = false;
+
+static worker_request_func vlog_async_write_request_cb;
+
+static void
+vlog_write_file(struct ds *s)
+{
+ if (worker_is_running()) {
+ static bool in_worker_request = false;
+ if (!in_worker_request) {
+ in_worker_request = true;
+
+ worker_request(s->string, s->length,
+ &log_fd, vlog_async_inited ? 0 : 1,
+ vlog_async_write_request_cb, NULL, NULL);
+ vlog_async_inited = true;
+
+ in_worker_request = false;
+ return;
+ } else {
+ /* We've been entered recursively. This can happen if
+ * worker_request(), or a function that it calls, tries to log
+ * something. We can't call worker_request() recursively, so fall
+ * back to writing the log file directly. */
+ COVERAGE_INC(vlog_recursive);
+ }
+ }
+ ignore(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) {
+ ignore(write(log_fd, request->data, request->size));
+ }
+}