Thanks, I applied it to master.

On Fri, Aug 02, 2013 at 06:02:30PM -0700, Alex Wang wrote:
> Thanks Ben,
> 
> It looks good to me,
> 
> 
> On Fri, Aug 2, 2013 at 5:33 PM, Ben Pfaff <b...@nicira.com> wrote:
> 
> > Until now, the async append interface has required async_append_enable()
> > to be called while the process was still single-threaded, with the
> > rationale being that async_append_enable() could race with
> > async_append_write() on some existing async_append object.  This was a
> > difficult problem when the async append interface was introduced, because
> > at the time Open vSwitch did not have any infrastructure for inter-thread
> > synchronization.
> >
> > Now it is easy to solve, by introducing synchronization into the
> > async append module.  However, that's more or less wasted, because the
> > client is already required to serialize access to async append objects.
> > Moreover, vlog, the only existing client, needs to serialize access for
> > other reasons, so it wouldn't even be possible to just drop the client's
> > synchronization.
> >
> > This commit therefore takes another approach.  It drops the
> > async_append_enable() interface entirely.  Now any existing async_append
> > object is always enabled.  The responsibility for "enabling", then, now
> > rests in whether the client creates and uses an async_append object, and
> > so vlog now takes care of that by itself.  Also, since vlog now has to
> > deal with sometimes having an async_append and sometimes not having one,
> > we might as well allow creating an async_append to fail, thereby slightly
> > simplifying the "no async I/O" implementation from "write synchronously"
> > to "always fail creating an async_append".
> >
> > Reported-by: Shih-Hao Li <shi...@nicira.com>
> > Signed-off-by: Ben Pfaff <b...@nicira.com>
> > ---
> >  lib/async-append-aio.c                           |   15 -----------
> >  lib/{async-append-sync.c => async-append-null.c} |   29
> > +++++++-------------
> >  lib/async-append.h                               |   20 +++-----------
> >  lib/automake.mk                                  |    2 +-
> >  lib/vlog.c                                       |   31
> > +++++++++++++++++++---
> >  lib/vlog.h                                       |    1 +
> >  vswitchd/bridge.c                                |    2 +-
> >  7 files changed, 42 insertions(+), 58 deletions(-)
> >  rename lib/{async-append-sync.c => async-append-null.c} (63%)
> >
> > diff --git a/lib/async-append-aio.c b/lib/async-append-aio.c
> > index 48edc38..23430a4 100644
> > --- a/lib/async-append-aio.c
> > +++ b/lib/async-append-aio.c
> > @@ -50,16 +50,6 @@ struct async_append {
> >      struct byteq byteq;
> >  };
> >
> > -static bool async_append_enabled;
> > -
> > -void
> > -async_append_enable(void)
> > -{
> > -    assert_single_threaded();
> > -    forbid_forking("async i/o enabled");
> > -    async_append_enabled = true;
> > -}
> > -
> >  struct async_append *
> >  async_append_create(int fd)
> >  {
> > @@ -128,11 +118,6 @@ async_append_write(struct async_append *ap, const
> > void *data_, size_t size)
> >  {
> >      const uint8_t *data = data_;
> >
> > -    if (!async_append_enabled) {
> > -        ignore(write(ap->fd, data, size));
> > -        return;
> > -    }
> > -
> >      while (size > 0) {
> >          struct aiocb *aiocb;
> >          size_t chunk_size;
> > diff --git a/lib/async-append-sync.c b/lib/async-append-null.c
> > similarity index 63%
> > rename from lib/async-append-sync.c
> > rename to lib/async-append-null.c
> > index d40fdc8..3eef26e 100644
> > --- a/lib/async-append-sync.c
> > +++ b/lib/async-append-null.c
> > @@ -15,8 +15,8 @@
> >
> >  #include <config.h>
> >
> > -/* This implementation of the async-append.h interface uses ordinary
> > - * synchronous I/O, so it should be portable everywhere. */
> > +/* This is a null implementation of the asynchronous I/O interface for
> > systems
> > + * that don't have a form of asynchronous I/O. */
> >
> >  #include "async-append.h"
> >
> > @@ -25,38 +25,27 @@
> >
> >  #include "util.h"
> >
> > -struct async_append {
> > -    int fd;
> > -};
> > -
> > -void
> > -async_append_enable(void)
> > -{
> > -    /* Nothing to do. */
> > -}
> > -
> >  struct async_append *
> > -async_append_create(int fd)
> > +async_append_create(int fd OVS_UNUSED)
> >  {
> > -    struct async_append *ap = xmalloc(sizeof *ap);
> > -    ap->fd = fd;
> > -    return ap;
> > +    return NULL;
> >  }
> >
> >  void
> >  async_append_destroy(struct async_append *ap)
> >  {
> > -    free(ap);
> > +    ovs_assert(ap == NULL);
> >  }
> >
> >  void
> > -async_append_write(struct async_append *ap, const void *data, size_t size)
> > +async_append_write(struct async_append *ap OVS_UNUSED,
> > +                   const void *data OVS_UNUSED, size_t size OVS_UNUSED)
> >  {
> > -    ignore(write(ap->fd, data, size));
> > +    NOT_REACHED();
> >  }
> >
> >  void
> >  async_append_flush(struct async_append *ap OVS_UNUSED)
> >  {
> > -    /* Nothing to do. */
> > +    NOT_REACHED();
> >  }
> > diff --git a/lib/async-append.h b/lib/async-append.h
> > index fb0ce52..0f7a4ae 100644
> > --- a/lib/async-append.h
> > +++ b/lib/async-append.h
> > @@ -32,24 +32,10 @@
> >   * Only a single thread may use a given 'struct async_append' at one time.
> >   */
> >
> > -/* Enables using asynchronous I/O.  Some implementations may treat this
> > as a
> > - * no-op.
> > - *
> > - * Before this function is called, the POSIX aio implementation uses
> > ordinary
> > - * synchronous I/O because some POSIX aio libraries actually use threads
> > - * internally, which has enough cost and robustness implications that it's
> > - * better to use asynchronous I/O only when it has real expected benefits.
> > - *
> > - * Must be called while the process is still single-threaded.  May forbid
> > the
> > - * process from subsequently forking. */
> > -void async_append_enable(void);
> > -
> >  /* Creates and returns a new asynchronous appender for file descriptor
> > 'fd',
> > - * which the caller must have opened in append mode (O_APPEND).
> > - *
> > - * This function must always succeed.  If the system is for some reason
> > unable
> > - * to support asynchronous I/O on 'fd' then the library must fall back to
> > - * syncrhonous I/O. */
> > + * which the caller must have opened in append mode (O_APPEND).  If the
> > system
> > + * is for some reason unable to support asynchronous I/O on 'fd' this
> > function
> > + * may return NULL. */
> >  struct async_append *async_append_create(int fd);
> >
> >  /* Destroys 'ap', without closing its underlying file descriptor. */
> > diff --git a/lib/automake.mk b/lib/automake.mk
> > index f18df91..fdda006 100644
> > --- a/lib/automake.mk
> > +++ b/lib/automake.mk
> > @@ -263,7 +263,7 @@ endif
> >  if HAVE_POSIX_AIO
> >  lib_libopenvswitch_a_SOURCES += lib/async-append-aio.c
> >  else
> > -lib_libopenvswitch_a_SOURCES += lib/async-append-sync.c
> > +lib_libopenvswitch_a_SOURCES += lib/async-append-null.c
> >  endif
> >
> >  if ESX
> > diff --git a/lib/vlog.c b/lib/vlog.c
> > index 6f0a256..26d0e6c 100644
> > --- a/lib/vlog.c
> > +++ b/lib/vlog.c
> > @@ -110,6 +110,7 @@ static struct ovs_mutex log_file_mutex =
> > OVS_ADAPTIVE_MUTEX_INITIALIZER;
> >  static char *log_file_name OVS_GUARDED_BY(log_file_mutex);
> >  static int log_fd OVS_GUARDED_BY(log_file_mutex) = -1;
> >  static struct async_append *log_writer OVS_GUARDED_BY(log_file_mutex);
> > +static bool log_async OVS_GUARDED_BY(log_file_mutex);
> >
> >  static void format_log_message(const struct vlog_module *, enum
> > vlog_level,
> >                                 enum vlog_facility,
> > @@ -344,7 +345,9 @@ vlog_set_log_file(const char *file_name)
> >
> >      log_file_name = xstrdup(new_log_file_name);
> >      log_fd = new_log_fd;
> > -    log_writer = async_append_create(new_log_fd);
> > +    if (log_async) {
> > +        log_writer = async_append_create(new_log_fd);
> > +    }
> >
> >      for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
> >          update_min_level(*mp);
> > @@ -617,6 +620,22 @@ vlog_init(void)
> >      pthread_once(&once, vlog_init__);
> >  }
> >
> > +/* Enables VLF_FILE log output to be written asynchronously to disk.
> > + * Asynchronous file writes avoid blocking the process in the case of a
> > busy
> > + * disk, but on the other hand they are less robust: there is a chance
> > that the
> > + * write will not make it to the log file if the process crashes soon
> > after the
> > + * log call. */
> > +void
> > +vlog_enable_async(void)
> > +{
> > +    ovs_mutex_lock(&log_file_mutex);
> > +    log_async = true;
> > +    if (log_fd >= 0 && !log_writer) {
> > +        log_writer = async_append_create(log_fd);
> > +    }
> > +    ovs_mutex_unlock(&log_file_mutex);
> > +}
> > +
> >  /* Print the current logging level for each module. */
> >  char *
> >  vlog_get_levels(void)
> > @@ -836,9 +855,13 @@ vlog_valist(const struct vlog_module *module, enum
> > vlog_level level,
> >
> >              ovs_mutex_lock(&log_file_mutex);
> >              if (log_fd >= 0) {
> > -                async_append_write(log_writer, s.string, s.length);
> > -                if (level == VLL_EMER) {
> > -                    async_append_flush(log_writer);
> > +                if (log_writer) {
> > +                    async_append_write(log_writer, s.string, s.length);
> > +                    if (level == VLL_EMER) {
> > +                        async_append_flush(log_writer);
> > +                    }
> > +                } else {
> > +                    ignore(write(log_fd, s.string, s.length));
> >                  }
> >              }
> >              ovs_mutex_unlock(&log_file_mutex);
> > diff --git a/lib/vlog.h b/lib/vlog.h
> > index 901b3d3..87a9654 100644
> > --- a/lib/vlog.h
> > +++ b/lib/vlog.h
> > @@ -141,6 +141,7 @@ int vlog_reopen_log_file(void);
> >
> >  /* Initialization. */
> >  void vlog_init(void);
> > +void vlog_enable_async(void);
> >
> >  /* Functions for actual logging. */
> >  void vlog(const struct vlog_module *, enum vlog_level, const char
> > *format, ...)
> > diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> > index 9bbd559..abbda56 100644
> > --- a/vswitchd/bridge.c
> > +++ b/vswitchd/bridge.c
> > @@ -2447,7 +2447,7 @@ bridge_run(void)
> >               * process that forked us to exit successfully. */
> >              daemonize_complete();
> >
> > -            async_append_enable();
> > +            vlog_enable_async();
> >
> >              VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION);
> >          }
> > --
> > 1.7.10.4
> >
> > _______________________________________________
> > dev mailing list
> > dev@openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
> >
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to