Commit 374752a2 authored by Paul Durrant's avatar Paul Durrant Committed by Anthony PERARD
Browse files

xen / notify: introduce a new XenWatchList abstraction



Xenstore watch call-backs are already abstracted away from XenBus using
the XenWatch data structure but the associated NotifierList manipulation
and file handle registration is still open coded in various xen_bus_...()
functions.
This patch creates a new XenWatchList data structure to allow these
interactions to be abstracted away from XenBus as well. This is in
preparation for a subsequent patch which will introduce separate watch lists
for XenBus and XenDevice objects.

NOTE: This patch also introduces a new notifier_list_empty() helper function
      for the purposes of adding an assertion that a XenWatchList is not
      freed whilst its associated NotifierList is still occupied.

Signed-off-by: default avatarPaul Durrant <paul.durrant@citrix.com>
Reviewed-by: default avatarAnthony Perard <anthony.perard@citrix.com>
Message-Id: <20190913082159.31338-2-paul.durrant@citrix.com>
Signed-off-by: default avatarAnthony PERARD <anthony.perard@citrix.com>
parent df6180bb
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -19,9 +19,8 @@ xen_bus_unrealize(void) ""
xen_bus_enumerate(void) ""
xen_bus_type_enumerate(const char *type) "type: %s"
xen_bus_backend_create(const char *type, const char *path) "type: %s path: %s"
xen_bus_add_watch(const char *node, const char *key, char *token) "node: %s key: %s token: %s"
xen_bus_remove_watch(const char *node, const char *key, char *token) "node: %s key: %s token: %s"
xen_bus_watch(const char *token) "token: %s"
xen_bus_add_watch(const char *node, const char *key) "node: %s key: %s"
xen_bus_remove_watch(const char *node, const char *key) "node: %s key: %s"
xen_device_realize(const char *type, char *name) "type: %s name: %s"
xen_device_unrealize(const char *type, char *name) "type: %s name: %s"
xen_device_backend_state(const char *type, char *name, const char *state) "type: %s name: %s -> %s"
+76 −41
Original line number Diff line number Diff line
@@ -157,18 +157,60 @@ static void free_watch(XenWatch *watch)
    g_free(watch);
}

static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
struct XenWatchList {
    struct xs_handle *xsh;
    NotifierList notifiers;
};

static void watch_list_event(void *opaque)
{
    XenWatchList *watch_list = opaque;
    char **v;
    const char *token;

    v = xs_check_watch(watch_list->xsh);
    if (!v) {
        return;
    }

    token = v[XS_WATCH_TOKEN];

    notifier_list_notify(&watch_list->notifiers, (void *)token);

    free(v);
}

static XenWatchList *watch_list_create(struct xs_handle *xsh)
{
    XenWatchList *watch_list = g_new0(XenWatchList, 1);

    g_assert(xsh);

    watch_list->xsh = xsh;
    notifier_list_init(&watch_list->notifiers);
    qemu_set_fd_handler(xs_fileno(watch_list->xsh), watch_list_event, NULL,
                        watch_list);

    return watch_list;
}

static void watch_list_destroy(XenWatchList *watch_list)
{
    g_assert(notifier_list_empty(&watch_list->notifiers));
    qemu_set_fd_handler(xs_fileno(watch_list->xsh), NULL, NULL, NULL);
    g_free(watch_list);
}

static XenWatch *watch_list_add(XenWatchList *watch_list, const char *node,
                                const char *key, XenWatchHandler handler,
                                void *opaque, Error **errp)
{
    XenWatch *watch = new_watch(node, key, handler, opaque);
    Error *local_err = NULL;

    trace_xen_bus_add_watch(watch->node, watch->key, watch->token);
    notifier_list_add(&watch_list->notifiers, &watch->notifier);

    notifier_list_add(&xenbus->watch_notifiers, &watch->notifier);

    xs_node_watch(xenbus->xsh, node, key, watch->token, &local_err);
    xs_node_watch(watch_list->xsh, node, key, watch->token, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);

@@ -181,18 +223,34 @@ static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
    return watch;
}

static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
static void watch_list_remove(XenWatchList *watch_list, XenWatch *watch,
                              Error **errp)
{
    trace_xen_bus_remove_watch(watch->node, watch->key, watch->token);

    xs_node_unwatch(xenbus->xsh, watch->node, watch->key, watch->token,
    xs_node_unwatch(watch_list->xsh, watch->node, watch->key, watch->token,
                    errp);

    notifier_remove(&watch->notifier);
    free_watch(watch);
}

static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
                                   const char *key, XenWatchHandler handler,
                                   void *opaque, Error **errp)
{
    trace_xen_bus_add_watch(node, key);

    return watch_list_add(xenbus->watch_list, node, key, handler, opaque,
                          errp);
}

static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
                                 Error **errp)
{
    trace_xen_bus_remove_watch(watch->node, watch->key);

    watch_list_remove(xenbus->watch_list, watch, errp);
}

static void xen_bus_backend_create(XenBus *xenbus, const char *type,
                                   const char *name, char *path,
                                   Error **errp)
@@ -338,35 +396,14 @@ static void xen_bus_unrealize(BusState *bus, Error **errp)
        xenbus->backend_watch = NULL;
    }

    if (!xenbus->xsh) {
        return;
    if (xenbus->watch_list) {
        watch_list_destroy(xenbus->watch_list);
        xenbus->watch_list = NULL;
    }

    qemu_set_fd_handler(xs_fileno(xenbus->xsh), NULL, NULL, NULL);

    if (xenbus->xsh) {
        xs_close(xenbus->xsh);
    }

static void xen_bus_watch(void *opaque)
{
    XenBus *xenbus = opaque;
    char **v;
    const char *token;

    g_assert(xenbus->xsh);

    v = xs_check_watch(xenbus->xsh);
    if (!v) {
        return;
    }

    token = v[XS_WATCH_TOKEN];

    trace_xen_bus_watch(token);

    notifier_list_notify(&xenbus->watch_notifiers, (void *)token);

    free(v);
}

static void xen_bus_realize(BusState *bus, Error **errp)
@@ -390,9 +427,7 @@ static void xen_bus_realize(BusState *bus, Error **errp)
        xenbus->backend_id = 0; /* Assume lack of node means dom0 */
    }

    notifier_list_init(&xenbus->watch_notifiers);
    qemu_set_fd_handler(xs_fileno(xenbus->xsh), xen_bus_watch, NULL,
                        xenbus);
    xenbus->watch_list = watch_list_create(xenbus->xsh);

    module_call_init(MODULE_INIT_XEN_BACKEND);

+2 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

typedef void (*XenWatchHandler)(void *opaque);

typedef struct XenWatchList XenWatchList;
typedef struct XenWatch XenWatch;
typedef struct XenEventChannel XenEventChannel;

@@ -63,7 +64,7 @@ typedef struct XenBus {
    BusState qbus;
    domid_t backend_id;
    struct xs_handle *xsh;
    NotifierList watch_notifiers;
    XenWatchList *watch_list;
    XenWatch *backend_watch;
} XenBus;

+2 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ void notifier_remove(Notifier *notifier);

void notifier_list_notify(NotifierList *list, void *data);

bool notifier_list_empty(NotifierList *list);

/* Same as Notifier but allows .notify() to return errors */
typedef struct NotifierWithReturn NotifierWithReturn;

+5 −0
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ void notifier_list_notify(NotifierList *list, void *data)
    }
}

bool notifier_list_empty(NotifierList *list)
{
    return QLIST_EMPTY(&list->notifiers);
}

void notifier_with_return_list_init(NotifierWithReturnList *list)
{
    QLIST_INIT(&list->notifiers);