[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v13 3/7] remus: introduce remus device





On 06/27/2014 11:29 AM, Shriram Rajagopalan wrote:

On Jun 27, 2014 7:29 AM, "Yang Hongyang" <yanghy@xxxxxxxxxxxxxx
<mailto:yanghy@xxxxxxxxxxxxxx>> wrote:
 >
 > introduce remus device, an abstract layer of remus devices(nic, disk,
 > etc).It provides the following APIs for libxl:
 >   >libxl__remus_device_setup
 >     setup remus devices, like attach qdisc, enable disk buffering, etc
 >   >libxl__remus_device_teardown
 >     teardown devices
 >   >libxl__remus_device_postsuspend
 >   >libxl__remus_device_preresume
 >   >libxl__remus_device_commit
 >     above three are for checkpoint.
 > through remus device layer, the remus execution flow will be like
 > this:
 >   xl remus -> remus device setup
 >                 |-> remus checkpoint(postsuspend, preresume, commit)
 >                       ...
 >                        |-> remus device teardown, failover or abort
 > the remus device layer provides an interface
 >   libxl__remus_device_ops
 > which a remus device must implement. the whole remus structure:
 >                             |remus|
 >                                |
 >                         |remus device|
 >                                |
 >                 |nic| |drbd disks| |qemu disks| ...
 > a device(nic, drbd disks, qemu disks, etc) must implement
 > libxl__remus_device_ops to support remus.
 >
 > Signed-off-by: Yang Hongyang <yanghy@xxxxxxxxxxxxxx
<mailto:yanghy@xxxxxxxxxxxxxx>>
 > Signed-off-by: Wen Congyang <wency@xxxxxxxxxxxxxx 
<mailto:wency@xxxxxxxxxxxxxx>>
 > Signed-off-by: Lai Jiangshan <laijs@xxxxxxxxxxxxxx 
<mailto:laijs@xxxxxxxxxxxxxx>>
 > ---
 >  tools/libxl/Makefile             |   2 +
 >  tools/libxl/libxl.c              |  34 +++-
 >  tools/libxl/libxl_dom.c          | 132 +++++++++++++--
 >  tools/libxl/libxl_internal.h     | 182 +++++++++++++++++++++
 >  tools/libxl/libxl_remus_device.c | 340 
+++++++++++++++++++++++++++++++++++++++
 >  tools/libxl/libxl_types.idl      |   1 +
 >  6 files changed, 675 insertions(+), 16 deletions(-)
 >  create mode 100644 tools/libxl/libxl_remus_device.c
 >
 > diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
 > index fdffff3..cb2efdf 100644
 > --- a/tools/libxl/Makefile
 > +++ b/tools/libxl/Makefile
 > @@ -56,6 +56,8 @@ else
 >  LIBXL_OBJS-y += libxl_nonetbuffer.o
 >  endif
 >
 > +LIBXL_OBJS-y += libxl_remus_device.o
 > +
 >  LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o
 >  LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_arm.o
 >
 > diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
 > index 62e251a..f99477d 100644
 > --- a/tools/libxl/libxl.c
 > +++ b/tools/libxl/libxl.c
 > @@ -733,6 +733,31 @@ out:
 >  static void remus_failover_cb(libxl__egc *egc,
 >                                libxl__domain_suspend_state *dss, int rc);
 >
 > +static void libxl__remus_setup_failed(libxl__egc *egc,
 > +                                      libxl__remus_state *rs, int rc)
 > +{
 > +    STATE_AO_GC(rs->ao);
 > +    libxl__ao_complete(egc, ao, rc);
 > +}
 > +
 > +static void libxl__remus_setup_done(libxl__egc *egc,
 > +                                    libxl__remus_state *rs, int rc)
 > +{
 > +    libxl__domain_suspend_state *dss = CONTAINER_OF(rs, *dss, rs);
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    if (!rc) {
 > +        libxl__domain_suspend(egc, dss);
 > +        return;
 > +    }
 > +
 > +    LOG(ERROR, "Remus: failed to setup device for guest with domid %u",
 > +        dss->domid);
 > +    rs->saved_rc = rc;
 > +    rs->callback = libxl__remus_setup_failed;
 > +    libxl__remus_device_teardown(egc, rs);
 > +}
 > +
 >  /* TODO: Explicit Checkpoint acknowledgements via recv_fd. */
 >  int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
 >                               uint32_t domid, int send_fd, int recv_fd,
 > @@ -761,10 +786,15 @@ int libxl_domain_remus_start(libxl_ctx *ctx,
libxl_domain_remus_info *info,
 >
 >      assert(info);
 >
 > -    /* TBD: Remus setup - i.e. attach qdisc, enable disk buffering, etc */
 > +    /* Convenience aliases */
 > +    libxl__remus_state *const rs = &dss->rs;
 > +    rs->ao = ao;
 > +    rs->domid = domid;
 > +    rs->saved_rc = 0;
 > +    rs->callback = libxl__remus_setup_done;
 >
 >      /* Point of no return */
 > -    libxl__domain_suspend(egc, dss);
 > +    libxl__remus_device_setup(egc, rs);
 >      return AO_INPROGRESS;
 >
 >   out:
 > diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
 > index c11993d..dde8bf6 100644
 > --- a/tools/libxl/libxl_dom.c
 > +++ b/tools/libxl/libxl_dom.c
 > @@ -1426,6 +1426,17 @@ static void libxl__domain_suspend_callback(void *data)
 >      domain_suspend_callback_common(egc, dss);
 >  }
 >
 > +static void remus_device_postsuspend_cb(libxl__egc *egc,
 > +                                        libxl__remus_state *rs, int rc)
 > +{
 > +    int ok = 0;
 > +    libxl__domain_suspend_state *dss = CONTAINER_OF(rs, *dss, rs);
 > +
 > +    if (!rc)
 > +        ok = 1;
 > +    libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
 > +}
 > +
 >  static void domain_suspend_callback_common_done(libxl__egc *egc,
 >                                  libxl__domain_suspend_state *dss, int ok)
 >  {
 > @@ -1447,32 +1458,51 @@ static void libxl__remus_domain_suspend_callback(void
*data)
 >  static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
 >                                  libxl__domain_suspend_state *dss, int ok)
 >  {
 > -    /* REMUS TODO: Issue disk and network checkpoint reqs. */
 > +    if (!ok)
 > +        goto out;
 > +
 > +    libxl__remus_state *const rs = &dss->rs;
 > +    rs->callback = remus_device_postsuspend_cb;
 > +    libxl__remus_device_postsuspend(egc, rs);
 > +    return;
 > +
 > +out:
 >      libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
 >  }
 >
 > -static void libxl__remus_domain_resume_callback(void *data)
 > +static void remus_device_preresume_cb(libxl__egc *egc,
 > +                                      libxl__remus_state *rs, int rc)
 >  {
 >      int ok = 0;
 > +    libxl__domain_suspend_state *dss = CONTAINER_OF(rs, *dss, rs);
 > +    STATE_AO_GC(dss->ao);
 > +
 > +    if (!rc) {
 > +        /* Resumes the domain and the device model */
 > +        if (!libxl__domain_resume(gc, dss->domid, /* Fast Suspend */1))
 > +            ok = 1;
 > +    }
 > +    libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
 > +}
 > +
 > +static void libxl__remus_domain_resume_callback(void *data)
 > +{
 >      libxl__save_helper_state *shs = data;
 >      libxl__egc *egc = shs->egc;
 >      libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
 >      STATE_AO_GC(dss->ao);
 >
 > -    /* Resumes the domain and the device model */
 > -    if (libxl__domain_resume(gc, dss->domid, /* Fast Suspend */1))
 > -        goto out;
 > -
 > -    /* REMUS TODO: Deal with disk. Start a new network output buffer */
 > -    ok = 1;
 > -out:
 > -    libxl__xc_domain_saverestore_async_callback_done(egc, shs, ok);
 > +    libxl__remus_state *const rs = &dss->rs;
 > +    rs->callback = remus_device_preresume_cb;
 > +    libxl__remus_device_preresume(egc, rs);
 >  }
 >
 >  /*----- remus asynchronous checkpoint callback -----*/
 >
 >  static void remus_checkpoint_dm_saved(libxl__egc *egc,
 >                                        libxl__domain_suspend_state *dss, int 
rc);
 > +static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
 > +                                  const struct timeval *requested_abs);
 >
 >  static void libxl__remus_domain_checkpoint_callback(void *data)
 >  {
 > @@ -1489,13 +1519,67 @@ static void
libxl__remus_domain_checkpoint_callback(void *data)
 >      }
 >  }
 >
 > +static void remus_device_commit_cb(libxl__egc *egc,
 > +                                   libxl__remus_state *rs, int rc)
 > +{
 > +    libxl__domain_suspend_state *dss = CONTAINER_OF(rs, *dss, rs);
 > +
 > +    STATE_AO_GC(dss->ao);
 > +
 > +    if (rc) {
 > +        LOG(ERROR, "Failed to do device commit op."
 > +            " Terminating Remus..");
 > +        goto out;
 > +    } else {
 > +        /* Set checkpoint interval timeout */
 > +        rc = libxl__ev_time_register_rel(gc, &rs->timeout,
 > +                                         remus_next_checkpoint,
 > +                                         dss->interval);
 > +        if (rc) {
 > +            LOG(ERROR, "unable to register timeout for next epoch."
 > +                " Terminating Remus..");
 > +            goto out;
 > +        }
 > +    }
 > +    return;
 > +
 > +out:
 > +    libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
 > +}
 > +
 >  static void remus_checkpoint_dm_saved(libxl__egc *egc,
 >                                        libxl__domain_suspend_state *dss, int 
rc)
 >  {
 > -    /* REMUS TODO: Wait for disk and memory ack, release network buffer */
 > -    /* REMUS TODO: make this asynchronous */
 > -    assert(!rc); /* REMUS TODO handle this error properly */
 > -    usleep(dss->interval * 1000);
 > +    /* Convenience aliases */
 > +    libxl__remus_state *const rs = &dss->rs;
 > +
 > +    STATE_AO_GC(dss->ao);
 > +
 > +    if (rc) {
 > +        LOG(ERROR, "Failed to save device model. Terminating Remus..");
 > +        goto out;
 > +    }
 > +
 > +    rs->callback = remus_device_commit_cb;
 > +    libxl__remus_device_commit(egc, rs);
 > +
 > +    return;
 > +
 > +out:
 > +    libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
 > +}
 > +
 > +static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
 > +                                  const struct timeval *requested_abs)
 > +{
 > +    libxl__remus_state *rs = CONTAINER_OF(ev, *rs, timeout);
 > +
 > +    /* Convenience aliases */
 > +    libxl__domain_suspend_state *const dss = CONTAINER_OF(rs, *dss, rs);
 > +
 > +    STATE_AO_GC(dss->ao);
 > +
 > +    libxl__ev_time_deregister(gc, &rs->timeout);
 >      libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 1);
 >  }
 >
 > @@ -1720,6 +1804,13 @@ static void
save_device_model_datacopier_done(libxl__egc *egc,
 >      dss->save_dm_callback(egc, dss, our_rc);
 >  }
 >
 > +static void libxl__remus_teardown_done(libxl__egc *egc,
 > +                                       libxl__remus_state *rs, int rc)
 > +{
 > +    libxl__domain_suspend_state *dss = CONTAINER_OF(rs, *dss, rs);
 > +    dss->callback(egc, dss, rc);
 > +}
 > +
 >  static void domain_suspend_done(libxl__egc *egc,
 >                          libxl__domain_suspend_state *dss, int rc)
 >  {
 > @@ -1734,6 +1825,19 @@ static void domain_suspend_done(libxl__egc *egc,
 >          xc_suspend_evtchn_release(CTX->xch, CTX->xce, domid,
 >                             dss->guest_evtchn.port, 
&dss->guest_evtchn_lockfd);
 >
 > +    if (dss->remus) {
 > +        /*
 > +         * With Remus, if we reach this point, it means either
 > +         * backup died or some network error occurred preventing us
 > +         * from sending checkpoints. Teardown the network buffers and
 > +         * release netlink resources.  This is an async op.
 > +         */
 > +        dss->rs.saved_rc = rc;
 > +        dss->rs.callback = libxl__remus_teardown_done;
 > +        libxl__remus_device_teardown(egc, &dss->rs);
 > +        return;
 > +    }
 > +
 >      dss->callback(egc, dss, rc);
 >  }
 >
 > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
 > index 3fc90e2..5521a42 100644
 > --- a/tools/libxl/libxl_internal.h
 > +++ b/tools/libxl/libxl_internal.h
 > @@ -2470,6 +2470,187 @@ typedef struct libxl__save_helper_state {
 >                        * marshalling and xc callback functions */
 >  } libxl__save_helper_state;
 >
 > +/*----- remus device related state structure -----*/
 > +/* remus device is an abstract layer of remus devices(nic, disk,
 > + * etc).It provides the following APIs for libxl:
 > + *   >libxl__remus_device_setup
 > + *     setup remus devices, like attach qdisc, enable disk buffering, etc
 > + *   >libxl__remus_device_teardown
 > + *     teardown devices
 > + *   >libxl__remus_device_postsuspend
 > + *   >libxl__remus_device_preresume
 > + *   >libxl__remus_device_commit
 > + *     above three are for checkpoint.
 > + * through remus device layer, the remus execution flow will be like
 > + * this:
 > + * xl remus -> remus device setup
 > + *               |-> remus checkpoint(postsuspend, preresume, commit)
 > + *                     ...
 > + *                      |-> remus device teardown, failover or abort
 > + * the remus device layer provides an interface
 > + *   libxl__remus_device_ops
 > + * which a remus device must implement. the whole remus structure:
 > + *                           |remus|
 > + *                              |
 > + *                       |remus device|
 > + *                              |
 > + *               |nic| |drbd disks| |qemu disks| ...
 > + * a device(nic, drbd disks, qemu disks, etc) must implement
 > + * libxl__remus_device_ops to support remus.
 > + */
 > +
 > +typedef enum libxl__remus_device_kind {
 > +    LIBXL__REMUS_DEVICE_NIC,
 > +    LIBXL__REMUS_DEVICE_DISK,
 > +} libxl__remus_device_kind;
 > +
 > +typedef struct libxl__remus_state libxl__remus_state;
 > +typedef struct libxl__remus_device libxl__remus_device;
 > +typedef struct libxl__remus_device_state libxl__remus_device_state;
 > +typedef struct libxl__remus_device_ops libxl__remus_device_ops;
 > +
 > +struct libxl__remus_device_ops {
 > +    /*
 > +     * init() and destroy() APIs are produced by a device type and
 > +     * consumed by the main remus code, a device type must implement
 > +     * these two APIs.
 > +     */
 > +    /* init device ops private data, etc. must implement */
 > +    int (*init)(libxl__remus_device_ops *self,
 > +                libxl__remus_state *rs);
 > +    /* free device ops private data, etc. must implement */
 > +    void (*destroy)(libxl__remus_device_ops *self);
 > +    /*
 > +     * This is device ops's private data, for different device types,
 > +     * the data structs are different
 > +     */
 > +    void *data;
 > +
 > +    /*
 > +     * checkpoint callbacks, these are async ops, call dev->callback
 > +     * when done. These function pointers may be NULL, means the op is
 > +     * not implemented, and it will do nothing when checkpoint.
 > +     * The callers of these APIs must check the function pointer first.
 > +     * These callbacks can be implemented synchronously, call
 > +     * dev->callback at last directly.
 > +     */
 > +    void (*postsuspend)(libxl__remus_device *dev);
 > +    void (*preresume)(libxl__remus_device *dev);
 > +    void (*commit)(libxl__remus_device *dev);
 > +
 > +    /*
 > +     * This API determines whether the ops matchs the specific device. In 
the
 > +     * implementation, we first init all device ops, for example, NIC ops,
 > +     * DRBD ops ... Then we will find out the libxl devices, and match the
 > +     * device with the ops, if the device is a drbd disk, then it will be
 > +     * matched with DRBD ops, and the further ops(such as checkpoint ops 
etc.)
 > +     * of this device will using DRBD ops. This API is mainly for disks,
 > +     * because we must use an external script to determine whether a
 > +     * libxl_disk is a DRBD disk. a device type must implement this API.
 > +     * It's an async op and must be implemented asynchronously,
 > +     * call dev->callback when done.
 > +     */
 > +    void (*match)(libxl__remus_device_ops *self,
 > +                  libxl__remus_device *dev);
 > +
 > +    /*
 > +     * setup() and teardown() are refer to the actual remus device,
 > +     * a device type must implement these two APIs. They are async
 > +     * ops, and call dev->callback when done.
 > +     * These callbacks can be implemented synchronously, call
 > +     * dev->callback at last directly.
 > +     */
 > +    /* setup the remus device */
 > +    void (*setup)(libxl__remus_device *dev);
 > +
 > +    /* teardown the remus device */
 > +    void (*teardown)(libxl__remus_device *dev);
 > +};
 > +
 > +/*
 > + * This structure is for remus device layer, it records remus devices
 > + * that have been setuped.
 > + */
 > +struct libxl__remus_device_state {
 > +    libxl__ao *ao;
 > +    libxl__egc *egc;
 > +
 > +    /* devices that have been setuped */
 > +    libxl__remus_device **dev;
 > +
 > +    int num_nics;
 > +    int num_disks;
 > +
 > +    /* for counting devices that have been handled */
 > +    int num_devices;
 > +    /* for counting devices that matched and setuped */
 > +    int num_setuped;
 > +};
 > +
 > +typedef void libxl__remus_device_callback(libxl__egc *,
 > +                                          libxl__remus_device *,
 > +                                          int rc);
 > +/*
 > + * This structure is init and setup by remus device abstruct layer,
 > + * and pass to remus device ops
 > + */
 > +struct libxl__remus_device {
 > +    /* set by remus device abstruct layer */
 > +    int devid;
 > +    /* libxl__device_* which this remus device related to */
 > +    const void *backend_dev;
 > +    libxl__remus_device_kind kind;
 > +    /*
 > +     * This is for matching, we must go through all device ops until we
 > +     * find a matched op for the device. The ops_index record which ops
 > +     * we are matching.
 > +     */
 > +    int ops_index;
 > +    libxl__remus_device_ops *ops;
 > +    libxl__remus_device_callback *callback;
 > +    libxl__remus_device_state *rds;
 > +
 > +    /* used by remus device implementation */
 > +    /* *kind* of device's private data */
 > +    void *data;
 > +    /* for calling scripts, eg. setup|teardown|match scripts */
 > +    libxl__async_exec_state aes;
 > +    /*
 > +     * for async func calls, in the implenmentation of device ops, we
 > +     * may use fork to do async ops. this is owned by device-specific
 > +     * ops methods
 > +     */
 > +    libxl__ev_child child;
 > +};
 > +
 > +typedef void libxl__remus_callback(libxl__egc *,
 > +                                   libxl__remus_state *, int rc);
 > +
 > +struct libxl__remus_state {
 > +    /* must set by caller of libxl__remus_device_(setup|teardown) */
 > +    libxl__ao *ao;
 > +    uint32_t domid;
 > +    libxl__remus_callback *callback;
 > +
 > +    /* private */
 > +    int saved_rc;
 > +    /* context containing device related stuff */
 > +    libxl__remus_device_state dev_state;
 > +
 > +    libxl__ev_time timeout; /* used for checkpoint */
 > +};
 > +
 > +/* the following 5 APIs are async ops, call rs->callback when done */
 > +_hidden void libxl__remus_device_setup(libxl__egc *egc,
 > +                                       libxl__remus_state *rs);
 > +_hidden void libxl__remus_device_teardown(libxl__egc *egc,
 > +                                          libxl__remus_state *rs);
 > +_hidden void libxl__remus_device_postsuspend(libxl__egc *egc,
 > +                                             libxl__remus_state *rs);
 > +_hidden void libxl__remus_device_preresume(libxl__egc *egc,
 > +                                           libxl__remus_state *rs);
 > +_hidden void libxl__remus_device_commit(libxl__egc *egc,
 > +                                        libxl__remus_state *rs);
 >  _hidden int libxl__netbuffer_enabled(libxl__gc *gc);
 >
 >  /*----- Domain suspend (save) state structure -----*/
 > @@ -2500,6 +2681,7 @@ struct libxl__domain_suspend_state {
 >      int live;
 >      int debug;
 >      const libxl_domain_remus_info *remus;
 > +    libxl__remus_state rs;
 >      /* private */
 >      libxl__ev_evtchn guest_evtchn;
 >      int guest_evtchn_lockfd;
 > diff --git a/tools/libxl/libxl_remus_device.c 
b/tools/libxl/libxl_remus_device.c
 > new file mode 100644
 > index 0000000..07e298b
 > --- /dev/null
 > +++ b/tools/libxl/libxl_remus_device.c
 > @@ -0,0 +1,340 @@
 > +/*
 > + * Copyright (C) 2014
 > + * Author: Lai Jiangshan <laijs@xxxxxxxxxxxxxx 
<mailto:laijs@xxxxxxxxxxxxxx>>
 > + *         Yang Hongyang <yanghy@xxxxxxxxxxxxxx 
<mailto:yanghy@xxxxxxxxxxxxxx>>
 > + *
 > + * This program is free software; you can redistribute it and/or modify
 > + * it under the terms of the GNU Lesser General Public License as published
 > + * by the Free Software Foundation; version 2.1 only. with the special
 > + * exception on linking described in file LICENSE.
 > + *
 > + * This program is distributed in the hope that it will be useful,
 > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > + * GNU Lesser General Public License for more details.
 > + */
 > +
 > +#include "libxl_osdeps.h" /* must come before any other headers */
 > +
 > +#include "libxl_internal.h"
 > +
 > +static libxl__remus_device_ops *dev_ops[] = {
 > +};
 > +
 > +static void device_common_cb(libxl__egc *egc,
 > +                             libxl__remus_device *dev,
 > +                             int rc)
 > +{
 > +    /* Convenience aliases */
 > +    libxl__remus_device_state *const rds = dev->rds;
 > +    libxl__remus_state *const rs = CONTAINER_OF(rds, *rs, dev_state);
 > +
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    rds->num_devices++;
 > +
 > +    if (rc)
 > +        rs->saved_rc = ERROR_FAIL;
 > +
 > +    if (rds->num_devices == rds->num_setuped)
 > +        rs->callback(egc, rs, rs->saved_rc);
 > +}
 > +
 > +void libxl__remus_device_postsuspend(libxl__egc *egc, libxl__remus_state 
*rs)
 > +{
 > +    int i;
 > +    libxl__remus_device *dev;
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    /* Convenience aliases */
 > +    libxl__remus_device_state *const rds = &rs->dev_state;
 > +
 > +    rds->num_devices = 0;
 > +    rs->saved_rc = 0;
 > +
 > +    if(rds->num_setuped == 0)
 > +        goto out;
 > +
 > +    for (i = 0; i < rds->num_setuped; i++) {
 > +        dev = rds->dev[i];
 > +        dev->callback = device_common_cb;
 > +        if (dev->ops->postsuspend) {
 > +            dev->ops->postsuspend(dev);
 > +        } else {
 > +            rds->num_devices++;
 > +            if (rds->num_devices == rds->num_setuped)
 > +                rs->callback(egc, rs, rs->saved_rc);
 > +        }
 > +    }
 > +
 > +    return;
 > +
 > +out:
 > +    rs->callback(egc, rs, rs->saved_rc);
 > +}
 > +
 > +void libxl__remus_device_preresume(libxl__egc *egc, libxl__remus_state *rs)
 > +{
 > +    int i;
 > +    libxl__remus_device *dev;
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    /* Convenience aliases */
 > +    libxl__remus_device_state *const rds = &rs->dev_state;
 > +
 > +    rds->num_devices = 0;
 > +    rs->saved_rc = 0;
 > +
 > +    if(rds->num_setuped == 0)
 > +        goto out;
 > +
 > +    for (i = 0; i < rds->num_setuped; i++) {
 > +        dev = rds->dev[i];
 > +        dev->callback = device_common_cb;
 > +        if (dev->ops->preresume) {
 > +            dev->ops->preresume(dev);
 > +        } else {
 > +            rds->num_devices++;
 > +            if (rds->num_devices == rds->num_setuped)
 > +                rs->callback(egc, rs, rs->saved_rc);
 > +        }
 > +    }
 > +
 > +    return;
 > +
 > +out:
 > +    rs->callback(egc, rs, rs->saved_rc);
 > +}
 > +
 > +void libxl__remus_device_commit(libxl__egc *egc, libxl__remus_state *rs)
 > +{
 > +    int i;
 > +    libxl__remus_device *dev;
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    /*
 > +     * REMUS TODO: Wait for disk and explicit memory ack (through restore
 > +     * callback from remote) before releasing network buffer.
 > +     */
 > +    /* Convenience aliases */
 > +    libxl__remus_device_state *const rds = &rs->dev_state;
 > +
 > +    rds->num_devices = 0;
 > +    rs->saved_rc = 0;
 > +
 > +    if(rds->num_setuped == 0)
 > +        goto out;
 > +
 > +    for (i = 0; i < rds->num_setuped; i++) {
 > +        dev = rds->dev[i];
 > +        dev->callback = device_common_cb;
 > +        if (dev->ops->commit) {
 > +            dev->ops->commit(dev);
 > +        } else {
 > +            rds->num_devices++;
 > +            if (rds->num_devices == rds->num_setuped)
 > +                rs->callback(egc, rs, rs->saved_rc);
 > +        }
 > +    }
 > +
 > +    return;
 > +
 > +out:
 > +    rs->callback(egc, rs, rs->saved_rc);
 > +}
 > +
 > +static void device_setup_cb(libxl__egc *egc,
 > +                            libxl__remus_device *dev,
 > +                            int rc)
 > +{
 > +    /* Convenience aliases */
 > +    libxl__remus_device_state *const rds = dev->rds;
 > +    libxl__remus_state *const rs = CONTAINER_OF(rds, *rs, dev_state);
 > +
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    rds->num_devices++;
 > +    /*
 > +     * we add devices that have been setuped to the array no matter
 > +     * the setup process succeed or failed because we need to ensure
 > +     * the device been teardown while setup failed. If any of the
 > +     * device setup failed, we will quit remus, but before we exit,
 > +     * we will teardown the devices that have been added to **dev
 > +     */
 > +    rds->dev[rds->num_setuped++] = dev;
 > +    if (rc) {
 > +        /* setup failed */
 > +        rs->saved_rc = ERROR_FAIL;
 > +    }
 > +
 > +    if (rds->num_devices == (rds->num_nics + rds->num_disks))
 > +        rs->callback(egc, rs, rs->saved_rc);
 > +}
 > +
 > +static void device_match_cb(libxl__egc *egc,
 > +                            libxl__remus_device *dev,
 > +                            int rc)
 > +{
 > +    libxl__remus_device_state *const rds = dev->rds;
 > +    libxl__remus_state *rs = CONTAINER_OF(rds, *rs, dev_state);
 > +
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    if (rc) {
 > +        if (++dev->ops_index >= ARRAY_SIZE(dev_ops) ||
 > +            rc != ERROR_NOT_MATCH) {
 > +            /* the device can not be matched */
 > +            rds->num_devices++;
 > +            rs->saved_rc = ERROR_FAIL;
 > +            if (rds->num_devices == (rds->num_nics + rds->num_disks))
 > +                rs->callback(egc, rs, rs->saved_rc);
 > +            return;
 > +        }
 > +        /* the ops does not match, try next ops */
 > +        dev->ops = dev_ops[dev->ops_index];
 > +        dev->ops->match(dev->ops, dev);
 > +    } else {
 > +        /* the ops matched, setup the device */
 > +        dev->callback = device_setup_cb;
 > +        dev->ops->setup(dev);
 > +    }
 > +}
 > +
 > +static void device_teardown_cb(libxl__egc *egc,
 > +                               libxl__remus_device *dev,
 > +                               int rc)
 > +{
 > +    int i;
 > +    libxl__remus_device_ops *ops;
 > +    libxl__remus_device_state *const rds = dev->rds;
 > +    libxl__remus_state *rs = CONTAINER_OF(rds, *rs, dev_state);
 > +
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    /* ignore teardown errors to teardown as many devs as possible*/
 > +    rds->num_setuped--;
 > +
 > +    if (rds->num_setuped == 0) {
 > +        /* clean device ops */
 > +        for (i = 0; i < ARRAY_SIZE(dev_ops); i++) {
 > +            ops = dev_ops[i];
 > +            ops->destroy(ops);
 > +        }
 > +        rs->callback(egc, rs, rs->saved_rc);
 > +    }
 > +}
 > +
 > +static __attribute__((unused)) void libxl__remus_device_init(libxl__egc 
*egc,
 > +                                     libxl__remus_device_state *rds,
 > +                                     libxl__remus_device_kind kind,
 > +                                     void *libxl_dev)
 > +{
 > +    libxl__remus_device *dev = NULL;
 > +    libxl_device_nic *nic = NULL;
 > +    libxl_device_disk *disk = NULL;
 > +
 > +    STATE_AO_GC(rds->ao);
 > +    GCNEW(dev);
 > +    dev->ops_index = 0; /* we will match the ops later */
 > +    dev->backend_dev = libxl_dev;
 > +    dev->kind = kind;
 > +    dev->rds = rds;
 > +
 > +    switch (kind) {
 > +        case LIBXL__REMUS_DEVICE_NIC:
 > +            nic = libxl_dev;
 > +            dev->devid = nic->devid;
 > +            break;
 > +        case LIBXL__REMUS_DEVICE_DISK:
 > +            disk = libxl_dev;
 > +            /* there are no dev id for disk devices */
 > +            dev->devid = -1;
 > +            break;
 > +        default:
 > +            return;
 > +    }
 > +
 > +    libxl__async_exec_init(&dev->aes);
 > +    libxl__ev_child_init(&dev->child);
 > +
 > +    /* match the ops begin */
 > +    dev->callback = device_match_cb;
 > +    dev->ops = dev_ops[dev->ops_index];
 > +    dev->ops->match(dev->ops, dev);
 > +}
 > +
 > +void libxl__remus_device_setup(libxl__egc *egc, libxl__remus_state *rs)
 > +{
 > +    int i;
 > +    libxl__remus_device_ops *ops;
 > +
 > +    /* Convenience aliases */
 > +    libxl__remus_device_state *const rds = &rs->dev_state;
 > +
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    if (ARRAY_SIZE(dev_ops) == 0)
 > +        goto out;
 > +
 > +    for (i = 0; i < ARRAY_SIZE(dev_ops); i++) {
 > +        ops = dev_ops[i];
 > +        if (ops->init(ops, rs)) {
 > +            rs->saved_rc = ERROR_FAIL;
 > +            goto out;
 > +        }
 > +    }
 > +
 > +    rds->ao = rs->ao;
 > +    rds->egc = egc;
 > +    rds->num_devices = 0;
 > +    rds->num_nics = 0;
 > +    rds->num_disks = 0;
 > +
 > +    /* TBD: Remus setup - i.e. attach qdisc, enable disk buffering, etc */
 > +
 > +    if (rds->num_nics == 0 && rds->num_disks == 0)
 > +        goto out;
 > +
 > +    GCNEW_ARRAY(rds->dev, rds->num_nics + rds->num_disks);
 > +
 > +    /* TBD: CALL libxl__remus_device_init to init remus devices */
 > +
 > +    return;
 > +
 > +out:
 > +    rs->callback(egc, rs, rs->saved_rc);
 > +    return;
 > +}
 > +
 > +void libxl__remus_device_teardown(libxl__egc *egc, libxl__remus_state *rs)
 > +{
 > +    int i;
 > +    libxl__remus_device *dev;
 > +    libxl__remus_device_ops *ops;
 > +
 > +    STATE_AO_GC(rs->ao);
 > +
 > +    /* Convenience aliases */
 > +    libxl__remus_device_state *const rds = &rs->dev_state;
 > +
 > +    if (rds->num_setuped == 0) {
 > +        /* clean device ops */
 > +        for (i = 0; i < ARRAY_SIZE(dev_ops); i++) {
 > +            ops = dev_ops[i];
 > +            ops->destroy(ops);
 > +        }
 > +        goto out;
 > +    }
 > +
 > +    for (i = 0; i < rds->num_setuped; i++) {
 > +        dev = rds->dev[i];
 > +        dev->callback = device_teardown_cb;
 > +        dev->ops->teardown(dev);
 > +    }
 > +
 > +    return;
 > +
 > +out:
 > +    rs->callback(egc, rs, rs->saved_rc);
 > +    return;
 > +}
 > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
 > index 1018142..cc5d390 100644
 > --- a/tools/libxl/libxl_types.idl
 > +++ b/tools/libxl/libxl_types.idl
 > @@ -43,6 +43,7 @@ libxl_error = Enumeration("error", [
 >      (-12, "OSEVENT_REG_FAIL"),
 >      (-13, "BUFFERFULL"),
 >      (-14, "UNKNOWN_CHILD"),
 > +    (-15, "NOT_MATCH"),
 >      ], value_namespace = "")
 >
 >  libxl_domain_type = Enumeration("domain_type", [
 > --
 > 1.9.1
 >

As far as the Remus logic is concerned, I am fine with this patch. You can add
my acked-by if it matters here. I'll defer it to IanJ to make the final call on
the coding style, etc.


Thanks!

--
Thanks,
Yang.

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.