[Libguestfs] [PATCH 1/2] src: start unifying version handling

Pino Toscano ptoscano at redhat.com
Wed May 18 10:31:25 UTC 2016


Introduce a new struct version with few helper functions for it: this
allows to "atomically" represent a version number, without different
variables to be used and checked together.

Add a initialization function from a libvirt-style version number, and
apply it for the qemu and libvirt versions in the direct and libvirt
backends.
---
v2 changes:
- guestfs_int_version_is -> guestfs_int_version_ge
- moved method declarations at the end of guestfs-internal.h

 src/Makefile.am        |  1 +
 src/guestfs-internal.h | 14 +++++++++++++-
 src/launch-direct.c    | 28 ++++++++++-----------------
 src/launch-libvirt.c   | 43 +++++++++++++++++++++++-------------------
 src/version.c          | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 99 insertions(+), 38 deletions(-)
 create mode 100644 src/version.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 7a694ca..d2879f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -133,6 +133,7 @@ libguestfs_la_SOURCES = \
 	umask.c \
 	wait.c \
 	whole-file.c \
+	version.c \
 	libguestfs.syms
 
 libguestfs_la_CPPFLAGS = \
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index d4e4e3c..6b3cfdf 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -509,6 +509,12 @@ struct guestfs_h
   size_t nr_features;
 };
 
+struct version {
+  int v_major;
+  int v_minor;
+  int v_micro;
+};
+
 /* Per-filesystem data stored for inspect_os. */
 enum inspect_os_format {
   OS_FORMAT_UNKNOWN = 0,
@@ -903,7 +909,7 @@ extern void guestfs_int_cleanup_cmd_close (struct command **);
 
 /* launch-direct.c */
 extern char *guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *src);
-extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv, unsigned long qemu_version);
+extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv, const struct version *qemu_version);
 extern char *guestfs_int_qemu_escape_param (guestfs_h *g, const char *param);
 
 /* launch-*.c constructors */
@@ -924,4 +930,10 @@ extern int guestfs_int_getumask (guestfs_h *g);
 extern int guestfs_int_waitpid (guestfs_h *g, pid_t pid, int *status, const char *errmsg);
 extern void guestfs_int_waitpid_noerror (pid_t pid);
 
+/* version.c */
+extern void guestfs_int_version_from_libvirt (struct version *v, int vernum);
+extern void guestfs_int_version_from_values (struct version *v, int maj, int min, int mic);
+extern bool guestfs_int_version_ge (const struct version *v, int maj, int min, int mic);
+#define version_init_null(v) guestfs_int_version_from_values (v, 0, 0, 0)
+
 #endif /* GUESTFS_INTERNAL_H_ */
diff --git a/src/launch-direct.c b/src/launch-direct.c
index 1b012cf..64967d2 100644
--- a/src/launch-direct.c
+++ b/src/launch-direct.c
@@ -62,7 +62,7 @@ struct backend_direct_data {
   char *qemu_devices;         /* Output of qemu -device ? */
 
   /* qemu version (0, 0 if unable to parse). */
-  int qemu_version_major, qemu_version_minor;
+  struct version qemu_version;
 
   int virtio_scsi;        /* See function qemu_supports_virtio_scsi */
 
@@ -420,8 +420,7 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
   if (qemu_supports (g, data, "-no-hpet")) {
     ADD_CMDLINE ("-no-hpet");
   }
-  if (data->qemu_version_major < 1 ||
-      (data->qemu_version_major == 1 && data->qemu_version_minor <= 2))
+  if (!guestfs_int_version_ge (&data->qemu_version, 1, 3, 0))
     ADD_CMDLINE ("-no-kvm-pit-reinjection");
   else {
     /* New non-deprecated way, added in qemu >= 1.3. */
@@ -472,8 +471,6 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
 
     if (!drv->overlay) {
       const char *discard_mode = "";
-      int major = data->qemu_version_major, minor = data->qemu_version_minor;
-      unsigned long qemu_version = major * 1000000 + minor * 1000;
 
       switch (drv->discard) {
       case discard_disable:
@@ -483,14 +480,14 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
          */
         break;
       case discard_enable:
-        if (!guestfs_int_discard_possible (g, drv, qemu_version))
+        if (!guestfs_int_discard_possible (g, drv, &data->qemu_version))
           goto cleanup0;
         /*FALLTHROUGH*/
       case discard_besteffort:
         /* I believe from reading the code that this is always safe as
          * long as qemu >= 1.5.
          */
-        if (major > 1 || (major == 1 && minor >= 5))
+        if (guestfs_int_version_ge (&data->qemu_version, 1, 5, 0))
           discard_mode = ",discard=unmap";
         break;
       }
@@ -1002,8 +999,7 @@ parse_qemu_version (guestfs_h *g, struct backend_direct_data *data)
   CLEANUP_FREE char *major_s = NULL, *minor_s = NULL;
   int major_i, minor_i;
 
-  data->qemu_version_major = 0;
-  data->qemu_version_minor = 0;
+  version_init_null (&data->qemu_version);
 
   if (!data->qemu_help)
     return;
@@ -1023,8 +1019,7 @@ parse_qemu_version (guestfs_h *g, struct backend_direct_data *data)
   if (minor_i == -1)
     goto parse_failed;
 
-  data->qemu_version_major = major_i;
-  data->qemu_version_minor = minor_i;
+  guestfs_int_version_from_values (&data->qemu_version, major_i, minor_i, 0);
 
   debug (g, "qemu version %d.%d", major_i, minor_i);
 }
@@ -1094,7 +1089,7 @@ static int
 old_or_broken_virtio_scsi (guestfs_h *g, struct backend_direct_data *data)
 {
   /* qemu 1.1 claims to support virtio-scsi but in reality it's broken. */
-  if (data->qemu_version_major == 1 && data->qemu_version_minor < 2)
+  if (!guestfs_int_version_ge (&data->qemu_version, 1, 2, 0))
     return 1;
 
   return 0;
@@ -1384,22 +1379,19 @@ guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *sr
  * It returns 0 if not possible and sets the error to the reason why.
  *
  * This function is called when the user set discard == "enable".
- *
- * qemu_version is the version of qemu in the form returned by libvirt:
- * major * 1,000,000 + minor * 1,000 + release
  */
 bool
 guestfs_int_discard_possible (guestfs_h *g, struct drive *drv,
-			      unsigned long qemu_version)
+			      const struct version *qemu_version)
 {
   /* qemu >= 1.5.  This was the first version that supported the
    * discard option on -drive at all.
    */
-  bool qemu15 = qemu_version >= 1005000;
+  bool qemu15 = guestfs_int_version_ge (qemu_version, 1, 5, 0);
   /* qemu >= 1.6.  This was the first version that supported unmap on
    * qcow2 backing files.
    */
-  bool qemu16 = qemu_version >= 1006000;
+  bool qemu16 = guestfs_int_version_ge (qemu_version, 1, 6, 0);
 
   if (!qemu15)
     NOT_SUPPORTED (g, false,
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index dba28b4..05ab6a6 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -118,8 +118,8 @@ struct backend_libvirt_data {
   char *network_bridge;
   char name[DOMAIN_NAME_LEN];   /* random name */
   bool is_kvm;                  /* false = qemu, true = kvm (from capabilities)*/
-  unsigned long libvirt_version; /* libvirt version */
-  unsigned long qemu_version;   /* qemu version (from libvirt) */
+  struct version libvirt_version; /* libvirt version */
+  struct version qemu_version;  /* qemu version (from libvirt) */
   struct secret *secrets;       /* list of secrets */
   size_t nr_secrets;
   char *uefi_code;		/* UEFI (firmware) code and variables. */
@@ -253,6 +253,7 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
   int r;
   uint32_t size;
   CLEANUP_FREE void *buf = NULL;
+  unsigned long version_number;
 
   params.current_proc_is_root = geteuid () == 0;
 
@@ -262,13 +263,16 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
     return -1;
   }
 
-  virGetVersion (&data->libvirt_version, NULL, NULL);
-  debug (g, "libvirt version = %lu (%lu.%lu.%lu)",
-         data->libvirt_version,
-         data->libvirt_version / 1000000UL,
-         data->libvirt_version / 1000UL % 1000UL,
-         data->libvirt_version % 1000UL);
-  if (data->libvirt_version < MIN_LIBVIRT_VERSION) {
+  virGetVersion (&version_number, NULL, NULL);
+  guestfs_int_version_from_libvirt (&data->libvirt_version, version_number);
+  debug (g, "libvirt version = %lu (%d.%d.%d)",
+         version_number,
+         data->libvirt_version.v_major,
+         data->libvirt_version.v_minor,
+         data->libvirt_version.v_micro);
+  if (!guestfs_int_version_ge (&data->libvirt_version,
+                               MIN_LIBVIRT_MAJOR, MIN_LIBVIRT_MINOR,
+                               MIN_LIBVIRT_MICRO)) {
     error (g, _("you must have libvirt >= %d.%d.%d "
                 "to use the 'libvirt' backend"),
            MIN_LIBVIRT_MAJOR, MIN_LIBVIRT_MINOR, MIN_LIBVIRT_MICRO);
@@ -315,16 +319,17 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
   virConnSetErrorFunc (conn, NULL, ignore_errors);
 
   /* Get hypervisor (hopefully qemu) version. */
-  if (virConnectGetVersion (conn, &data->qemu_version) == 0) {
-    debug (g, "qemu version (reported by libvirt) = %lu (%lu.%lu.%lu)",
-           data->qemu_version,
-           data->qemu_version / 1000000UL,
-           data->qemu_version / 1000UL % 1000UL,
-           data->qemu_version % 1000UL);
+  if (virConnectGetVersion (conn, &version_number) == 0) {
+    guestfs_int_version_from_libvirt (&data->qemu_version, version_number);
+    debug (g, "qemu version (reported by libvirt) = %lu (%d.%d.%d)",
+           version_number,
+           data->qemu_version.v_major,
+           data->qemu_version.v_minor,
+           data->qemu_version.v_micro);
   }
   else {
     libvirt_debug (g, "unable to read qemu version from libvirt");
-    data->qemu_version = 0;
+    version_init_null (&data->qemu_version);
   }
 
   debug (g, "get libvirt capabilities");
@@ -1259,7 +1264,7 @@ construct_libvirt_xml_devices (guestfs_h *g,
      * requires Cole Robinson's patch to permit /dev/urandom to be
      * used, which was added in libvirt 1.3.4.
      */
-    if (params->data->libvirt_version >= 1003004) {
+    if (guestfs_int_version_ge (&params->data->libvirt_version, 1, 3, 4)) {
       start_element ("rng") {
         attribute ("model", "virtio");
         start_element ("backend") {
@@ -1574,14 +1579,14 @@ construct_libvirt_xml_disk_driver_qemu (guestfs_h *g,
      */
     break;
   case discard_enable:
-    if (!guestfs_int_discard_possible (g, drv, data->qemu_version))
+    if (!guestfs_int_discard_possible (g, drv, &data->qemu_version))
       return -1;
     /*FALLTHROUGH*/
   case discard_besteffort:
     /* I believe from reading the code that this is always safe as
      * long as qemu >= 1.5.
      */
-    if (data->qemu_version >= 1005000)
+    if (guestfs_int_version_ge (&data->qemu_version, 1, 5, 0))
       discard_unmap = true;
     break;
   }
diff --git a/src/version.c b/src/version.c
new file mode 100644
index 0000000..f10bbc0
--- /dev/null
+++ b/src/version.c
@@ -0,0 +1,51 @@
+/* libguestfs
+ * Copyright (C) 2016 Red Hat Inc.
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+
+/**
+ * This file provides simple version number management.
+ */
+
+#define VERSION_TO_NUMBER(maj, min, mic) ((maj) * 1000000 + (min) * 1000 + (mic))
+#define VERSION_STRUCT_TO_NUMBER(v) VERSION_TO_NUMBER((v)->v_major, (v)->v_minor, (v)->v_micro)
+
+void
+guestfs_int_version_from_libvirt (struct version *v, int vernum)
+{
+  v->v_major = vernum / 1000000UL;
+  v->v_minor = vernum / 1000UL % 1000UL;
+  v->v_micro = vernum % 1000UL;
+}
+
+void
+guestfs_int_version_from_values (struct version *v, int maj, int min, int mic)
+{
+  v->v_major = maj;
+  v->v_minor = min;
+  v->v_micro = mic;
+}
+
+bool
+guestfs_int_version_ge (const struct version *v, int maj, int min, int mic)
+{
+  return VERSION_STRUCT_TO_NUMBER(v) >= VERSION_TO_NUMBER(maj, min, mic);
+}
-- 
2.5.5




More information about the Libguestfs mailing list