xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Juergen Gross <jgross@suse.com>
To: xen-devel@lists.xen.org
Cc: Juergen Gross <jgross@suse.com>,
	wei.liu2@citrix.com, ian.jackson@eu.citrix.com
Subject: [PATCH 1/6] libxl: add "merge" function to generic device type support
Date: Tue, 12 Jul 2016 17:30:39 +0200	[thread overview]
Message-ID: <1468337444-24108-2-git-send-email-jgross@suse.com> (raw)
In-Reply-To: <1468337444-24108-1-git-send-email-jgross@suse.com>

Instead of using a macro generating the code to merge xenstore and
json configuration data, use the generic device type support for
this purpose.

This requires to add some accessor functions to the framework and
a structure for disks (as disks are added separately they didn't need
such a structure up to now).

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 tools/libxl/libxl.c          | 181 ++++++++++++++++++++++++-------------------
 tools/libxl/libxl_create.c   |  18 +++--
 tools/libxl/libxl_internal.h |  52 +++++++++++--
 tools/libxl/libxl_pci.c      |   8 +-
 tools/libxl/libxl_pvusb.c    |  12 +++
 5 files changed, 181 insertions(+), 90 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 2cf7451..07b96c7 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -7371,93 +7371,68 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
      *    entry retrieved from xenstore while "dst" points to the entry
      *    retrieve from JSON.
      */
-#define MERGE(type, ptr, compare, merge)                                \
-    do {                                                                \
-        libxl_device_##type *p = NULL;                                  \
-        int i, j, num;                                                  \
-                                                                        \
-        p = libxl_device_##type##_list(CTX, domid, &num);               \
-        if (p == NULL) {                                                \
-            LOG(DEBUG,                                                  \
-                "no %s from xenstore for domain %d",                    \
-                #type, domid);                                          \
-        }                                                               \
-                                                                        \
-        for (i = 0; i < d_config->num_##ptr; i++) {                     \
-            libxl_device_##type *q = &d_config->ptr[i];                 \
-            for (j = 0; j < num; j++) {                                 \
-                if (compare(&p[j], q))                                  \
-                    break;                                              \
-            }                                                           \
-                                                                        \
-            if (j < num) {         /* found in xenstore */              \
-                libxl_device_##type *dst, *src;                         \
-                dst = q;                                                \
-                src = &p[j];                                            \
-                merge;                                                  \
-            } else {                /* not found in xenstore */         \
-                LOG(WARN,                                               \
-                "Device present in JSON but not in xenstore, ignored"); \
-                                                                        \
-                libxl_device_##type##_dispose(q);                       \
-                                                                        \
-                for (j = i; j < d_config->num_##ptr - 1; j++)           \
-                    memcpy(&d_config->ptr[j], &d_config->ptr[j+1],      \
-                           sizeof(libxl_device_##type));                \
-                                                                        \
-                d_config->ptr =                                         \
-                    libxl__realloc(NOGC, d_config->ptr,                 \
-                                   sizeof(libxl_device_##type) *        \
-                                   (d_config->num_##ptr - 1));          \
-                                                                        \
-                /* rewind counters */                                   \
-                d_config->num_##ptr--;                                  \
-                i--;                                                    \
-            }                                                           \
-        }                                                               \
-                                                                        \
-        for (i = 0; i < num; i++)                                       \
-            libxl_device_##type##_dispose(&p[i]);                       \
-        free(p);                                                        \
-    } while (0);
+    {
+        const struct libxl_device_type *dt;
+        int idx;
 
-    MERGE(nic, nics, COMPARE_DEVID, {});
+        for (idx = 0;; idx++) {
+            void *p = NULL;
+            void **devs;
+            int i, j, num;
+            int *num_dev;
 
-    MERGE(vtpm, vtpms, COMPARE_DEVID, {});
+            dt = device_type_tbl[idx];
+            if (!dt)
+                break;
 
-    MERGE(pci, pcidevs, COMPARE_PCI, {});
+            if (!dt->list || !dt->compare)
+                continue;
 
-    MERGE(usbctrl, usbctrls, COMPARE_USBCTRL, {});
+            num_dev = libxl__device_type_get_num(dt, d_config);
+            p = dt->list(CTX, domid, &num);
+            if (p == NULL) {
+                LOG(DEBUG, "no %s from xenstore for domain %d",
+                    dt->type, domid);
+            }
+            devs = libxl__device_type_get_ptr(dt, d_config);
+
+            for (i = 0; i < *num_dev; i++) {
+                void *q;
+
+                q = libxl__device_type_get_elem(dt, d_config, i);
+                for (j = 0; j < num; j++) {
+                    if (dt->compare(p + dt->dev_elem_size * j, q))
+                        break;
+                }
+
+                if (j < num) {         /* found in xenstore */
+                    if (dt->merge)
+                        dt->merge(ctx, p + dt->dev_elem_size * j, q);
+                } else {                /* not found in xenstore */
+                    LOG(WARN,
+                        "Device present in JSON but not in xenstore, ignored");
+
+                    dt->dispose(q);
+
+                    for (j = i; j < *num_dev - 1; j++)
+                        memcpy(libxl__device_type_get_elem(dt, d_config, j),
+                               libxl__device_type_get_elem(dt, d_config, j+1),
+                               dt->dev_elem_size);
 
-    MERGE(usbdev, usbdevs, COMPARE_USB, {});
+                    /* rewind counters */
+                    (*num_dev)--;
+                    i--;
 
-    /* Take care of removable device. We maintain invariant in the
-     * insert / remove operation so that:
-     * 1. if xenstore is "empty" while JSON is not, the result
-     *    is "empty"
-     * 2. if xenstore has a different media than JSON, use the
-     *    one in JSON
-     * 3. if xenstore and JSON have the same media, well, you
-     *    know the answer :-)
-     *
-     * Currently there is only one removable device -- CDROM.
-     * Look for libxl_cdrom_insert for reference.
-     */
-    MERGE(disk, disks, COMPARE_DISK, {
-            if (src->removable) {
-                if (!src->pdev_path || *src->pdev_path == '\0') {
-                    /* 1, no media in drive */
-                    free(dst->pdev_path);
-                    dst->pdev_path = libxl__strdup(NOGC, "");
-                    dst->format = LIBXL_DISK_FORMAT_EMPTY;
-                } else {
-                    /* 2 and 3, use JSON, no need to touch anything */
-                    ;
+                    *devs = libxl__realloc(NOGC, *devs,
+                                           dt->dev_elem_size * *num_dev);
                 }
             }
-        });
 
-#undef MERGE
+            for (i = 0; i < num; i++)
+                dt->dispose(p + dt->dev_elem_size * i);
+            free(p);
+        }
+    }
 
 out:
     if (lock) libxl__unlock_domain_userdata(lock);
@@ -7466,6 +7441,56 @@ out:
     return rc;
 }
 
+static int libxl_device_disk_compare(libxl_device_disk *d1,
+                                     libxl_device_disk *d2)
+{
+    return COMPARE_DISK(d1, d2);
+}
+
+/* Take care of removable device. We maintain invariant in the
+ * insert / remove operation so that:
+ * 1. if xenstore is "empty" while JSON is not, the result
+ *    is "empty"
+ * 2. if xenstore has a different media than JSON, use the
+ *    one in JSON
+ * 3. if xenstore and JSON have the same media, well, you
+ *    know the answer :-)
+ *
+ * Currently there is only one removable device -- CDROM.
+ * Look for libxl_cdrom_insert for reference.
+ */
+static void libxl_device_disk_merge(libxl_ctx *ctx, void *d1, void *d2)
+{
+    GC_INIT(ctx);
+    libxl_device_disk *src = d1;
+    libxl_device_disk *dst = d2;
+
+    if (src->removable) {
+        if (!src->pdev_path || *src->pdev_path == '\0') {
+            /* 1, no media in drive */
+            free(dst->pdev_path);
+            dst->pdev_path = libxl__strdup(NOGC, "");
+            dst->format = LIBXL_DISK_FORMAT_EMPTY;
+        } else {
+            /* 2 and 3, use JSON, no need to touch anything */
+            ;
+        }
+    }
+}
+
+static int libxl_device_nic_compare(libxl_device_nic *d1,
+                                    libxl_device_nic *d2)
+{
+    return COMPARE_DEVID(d1, d2);
+}
+
+static int libxl_device_vtpm_compare(libxl_device_vtpm *d1,
+                                     libxl_device_vtpm *d2)
+{
+    return COMPARE_DEVID(d1, d2);
+}
+
+DEFINE_DEVICE_TYPE_STRUCT(disk, .merge = libxl_device_disk_merge);
 DEFINE_DEVICE_TYPE_STRUCT(nic);
 DEFINE_DEVICE_TYPE_STRUCT(vtpm);
 
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 828f254..40dac1a 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1420,15 +1420,19 @@ out:
     aodev->callback(egc, aodev);
 }
 
+#define libxl_device_dtdev_list NULL
+#define libxl_device_dtdev_compare NULL
 static DEFINE_DEVICE_TYPE_STRUCT(dtdev);
 
-static const struct libxl_device_type *device_type_tbl[] = {
+const struct libxl_device_type *device_type_tbl[] = {
+    &libxl__disk_devtype,
     &libxl__nic_devtype,
     &libxl__vtpm_devtype,
     &libxl__usbctrl_devtype,
     &libxl__usbdev_devtype,
     &libxl__pcidev_devtype,
     &libxl__dtdev_devtype,
+    NULL
 };
 
 static void domcreate_attach_devices(libxl__egc *egc,
@@ -1448,9 +1452,9 @@ static void domcreate_attach_devices(libxl__egc *egc,
     }
 
     dcs->device_type_idx++;
-    if (dcs->device_type_idx < ARRAY_SIZE(device_type_tbl)) {
-        dt = device_type_tbl[dcs->device_type_idx];
-        if (*(int *)((void *)d_config + dt->num_offset) > 0) {
+    dt = device_type_tbl[dcs->device_type_idx];
+    if (dt) {
+        if (*libxl__device_type_get_num(dt, d_config) > 0) {
             /* Attach devices */
             libxl__multidev_begin(ao, &dcs->multidev);
             dcs->multidev.callback = domcreate_attach_devices;
@@ -1497,7 +1501,11 @@ static void domcreate_devmodel_started(libxl__egc *egc,
         }
     }
 
-    dcs->device_type_idx = -1;
+    /*
+     * Setting dcs->device_type_idx to 0 will skip disks, those have been
+     * already added.
+     */
+    dcs->device_type_idx = 0;
     domcreate_attach_devices(egc, &dcs->multidev, 0);
     return;
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 5347b69..1a62d6f 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3441,23 +3441,63 @@ _hidden void libxl__bootloader_run(libxl__egc*, libxl__bootloader_state *st);
 
 struct libxl_device_type {
     char *type;
-    int num_offset;   /* Offset of # of devices in libxl_domain_config */
+    int ptr_offset;    /* Offset of device array ptr in libxl_domain_config */
+    int num_offset;    /* Offset of # of devices in libxl_domain_config */
+    int dev_elem_size; /* Size of one device element in array */
     void (*add)(libxl__egc *, libxl__ao *, uint32_t, libxl_domain_config *,
                 libxl__multidev *);
+    void *(*list)(libxl_ctx *, uint32_t, int *);
+    void (*dispose)(void *);
+    int (*compare)(void *, void *);
+    void (*merge)(libxl_ctx *, void *, void *);
 };
 
-#define DEFINE_DEVICE_TYPE_STRUCT(name)                                 \
-    const struct libxl_device_type libxl__ ## name ## _devtype = {      \
-        .type       = #name,                                            \
-        .num_offset = offsetof(libxl_domain_config, num_ ## name ## s), \
-        .add        = libxl__add_ ## name ## s,                         \
+#define DEFINE_DEVICE_TYPE_STRUCT_X(name, sname, ...)                          \
+    const struct libxl_device_type libxl__ ## name ## _devtype = {             \
+        .type          = #sname,                                               \
+        .ptr_offset    = offsetof(libxl_domain_config, name ## s),             \
+        .num_offset    = offsetof(libxl_domain_config, num_ ## name ## s),     \
+        .dev_elem_size = sizeof(libxl_device_ ## sname),                       \
+        .add           = libxl__add_ ## name ## s,                             \
+        .list          = (void *(*)(libxl_ctx *, uint32_t, int *))             \
+                         libxl_device_ ## sname ## _list,                      \
+        .dispose       = (void (*)(void *))libxl_device_ ## sname ## _dispose, \
+        .compare       = (int (*)(void *, void *))                             \
+                         libxl_device_ ## sname ## _compare,                   \
+        __VA_ARGS__                                                            \
     }
 
+#define DEFINE_DEVICE_TYPE_STRUCT(name, ...)                                   \
+    DEFINE_DEVICE_TYPE_STRUCT_X(name, name, __VA_ARGS__)
+
+static inline void **libxl__device_type_get_ptr(
+    const struct libxl_device_type *dt, const libxl_domain_config *d_config)
+{
+    return (void **)((void *)d_config + dt->ptr_offset);
+}
+
+static inline void *libxl__device_type_get_elem(
+    const struct libxl_device_type *dt, const libxl_domain_config *d_config,
+    int e)
+{
+    return *libxl__device_type_get_ptr(dt, d_config) + dt->dev_elem_size * e;
+}
+
+static inline int *libxl__device_type_get_num(
+    const struct libxl_device_type *dt, const libxl_domain_config *d_config)
+{
+    return (int *)((void *)d_config + dt->num_offset);
+}
+
+extern const struct libxl_device_type libxl__disk_devtype;
 extern const struct libxl_device_type libxl__nic_devtype;
 extern const struct libxl_device_type libxl__vtpm_devtype;
 extern const struct libxl_device_type libxl__usbctrl_devtype;
 extern const struct libxl_device_type libxl__usbdev_devtype;
 extern const struct libxl_device_type libxl__pcidev_devtype;
+
+extern const struct libxl_device_type *device_type_tbl[];
+
 /*----- Domain destruction -----*/
 
 /* Domain destruction has been split into two functions:
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
index 9676687..22398a4 100644
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -1698,7 +1698,13 @@ int libxl__grant_vga_iomem_permission(libxl__gc *gc, const uint32_t domid,
     return 0;
 }
 
-DEFINE_DEVICE_TYPE_STRUCT(pcidev);
+static int libxl_device_pci_compare(libxl_device_pci *d1,
+                                    libxl_device_pci *d2)
+{
+    return COMPARE_PCI(d1, d2);
+}
+
+DEFINE_DEVICE_TYPE_STRUCT_X(pcidev, pci);
 
 /*
  * Local variables:
diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
index 41ea6bc..48a4cec 100644
--- a/tools/libxl/libxl_pvusb.c
+++ b/tools/libxl/libxl_pvusb.c
@@ -1675,6 +1675,18 @@ out:
     return rc;
 }
 
+static int libxl_device_usbctrl_compare(libxl_device_usbctrl *d1,
+                                        libxl_device_usbctrl *d2)
+{
+    return COMPARE_USBCTRL(d1, d2);
+}
+
+static int libxl_device_usbdev_compare(libxl_device_usbdev *d1,
+                                       libxl_device_usbdev *d2)
+{
+    return COMPARE_USB(d1, d2);
+}
+
 DEFINE_DEVICE_TYPE_STRUCT(usbctrl);
 DEFINE_DEVICE_TYPE_STRUCT(usbdev);
 
-- 
2.6.6


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

  reply	other threads:[~2016-07-12 15:30 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-12 15:30 [PATCH 0/6] libxl: extend device type framework Juergen Gross
2016-07-12 15:30 ` Juergen Gross [this message]
2016-07-25 10:45   ` [PATCH 1/6] libxl: add "merge" function to generic device type support Wei Liu
2017-01-19 16:14   ` Olaf Hering
2017-01-19 16:19     ` Wei Liu
2017-01-19 16:51       ` Juergen Gross
2016-07-12 15:30 ` [PATCH 2/6] libxl: add "pv device mode needed" support to device type framework Juergen Gross
2016-07-25 10:46   ` Wei Liu
2016-07-12 15:30 ` [PATCH 3/6] libxl: move library pvusb specific code into libxl_pvusb.c Juergen Gross
2016-07-25 10:46   ` Wei Liu
2016-07-12 15:30 ` [PATCH 4/6] libxl: split libxl vtpm code into one source Juergen Gross
2016-07-25 10:46   ` Wei Liu
2016-07-12 15:30 ` [PATCH 5/6] libxl: add config update callback to device type framework Juergen Gross
2016-07-25 10:46   ` Wei Liu
2016-07-12 15:30 ` [PATCH 6/6] libxl: move common nic stuff into one source Juergen Gross
2016-07-25 10:46   ` Wei Liu
2016-07-21 13:12 ` [PATCH 0/6] libxl: extend device type framework Juergen Gross
2016-07-27 11:45 ` Wei Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1468337444-24108-2-git-send-email-jgross@suse.com \
    --to=jgross@suse.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).