]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
save: new public API to bypass file system cache on save/restore
authorEric Blake <eblake@redhat.com>
Wed, 6 Jul 2011 18:10:11 +0000 (12:10 -0600)
committerEric Blake <eblake@redhat.com>
Thu, 21 Jul 2011 16:34:51 +0000 (10:34 -0600)
In order to choose whether to use O_DIRECT when saving a domain image
to a file, we need a new flag.  But virDomainSave was implemented
before our policy of all new APIs having a flag argument.  Likewise
for virDomainRestore when restoring from a file.

The new flag name is chosen as CACHE_BYPASS so as not to preclude
a future solution that uses posix_fadvise once the Linux kernel has
a smarter implementation of that interface.

* include/libvirt/libvirt.h.in (virDomainCreateFlags)
(virDomainCoreDumpFlags): Add a flag.
(virDomainSaveFlags, virDomainRestoreFlags): New prototypes.
* src/libvirt.c (virDomainSaveFlags, virDomainRestoreFlags): New API.
* src/libvirt_public.syms: Export them.
* src/driver.h (virDrvDomainSaveFlags, virDrvDomainRestoreFlags):
New driver callbacks.

include/libvirt/libvirt.h.in
src/driver.h
src/libvirt.c
src/libvirt_public.syms

index 6afd59160ee9180809b6d61a84e53eb260f97c60..8fa7daec8576501b8ee04239df1436c2ac9fbca4 100644 (file)
@@ -232,9 +232,10 @@ typedef virDomainInfo *virDomainInfoPtr;
  * Domain.
  */
 typedef enum {
-    VIR_DOMAIN_NONE         = 0,      /* Default behavior */
-    VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */
-    VIR_DOMAIN_START_AUTODESTROY = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */
+    VIR_DOMAIN_NONE               = 0,      /* Default behavior */
+    VIR_DOMAIN_START_PAUSED       = 1 << 0, /* Launch guest in paused state */
+    VIR_DOMAIN_START_AUTODESTROY  = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */
+    VIR_DOMAIN_START_BYPASS_CACHE = 1 << 2, /* Avoid file system cache pollution */
 } virDomainCreateFlags;
 
 
@@ -657,8 +658,9 @@ typedef virDomainMemoryStatStruct *virDomainMemoryStatPtr;
 
 /* Domain core dump flags. */
 typedef enum {
-    VIR_DUMP_CRASH   = (1 << 0), /* crash after dump */
-    VIR_DUMP_LIVE    = (1 << 1), /* live dump */
+    VIR_DUMP_CRASH        = (1 << 0), /* crash after dump */
+    VIR_DUMP_LIVE         = (1 << 1), /* live dump */
+    VIR_DUMP_BYPASS_CACHE = (1 << 2), /* avoid file system cache pollution */
 } virDomainCoreDumpFlags;
 
 /* Domain migration flags. */
@@ -941,10 +943,28 @@ int                     virDomainResume         (virDomainPtr domain);
 /*
  * Domain save/restore
  */
+
+/**
+ * virDomainSaveRestoreFlags:
+ * Flags for use in virDomainSaveFlags(), virDomainManagedSave(), and
+ * virDomainRestoreFlags().
+ */
+typedef enum {
+    VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution */
+} virDomainSaveRestoreFlags;
+
 int                     virDomainSave           (virDomainPtr domain,
                                                  const char *to);
+int                     virDomainSaveFlags      (virDomainPtr domain,
+                                                 const char *to,
+                                                 const char *dxml,
+                                                 unsigned int flags);
 int                     virDomainRestore        (virConnectPtr conn,
                                                  const char *from);
+int                     virDomainRestoreFlags   (virConnectPtr conn,
+                                                 const char *from,
+                                                 const char *dxml,
+                                                 unsigned int flags);
 
 /*
  * Managed domain save
index 4c4955f78b6dc515577e363442eb57864e66dd58..d931c9b9b75941ea5c42c3328d48774138ddc617 100644 (file)
@@ -177,9 +177,19 @@ typedef int
 typedef int
         (*virDrvDomainSave)            (virDomainPtr domain,
                                          const char *to);
+typedef int
+        (*virDrvDomainSaveFlags)       (virDomainPtr domain,
+                                         const char *to,
+                                         const char *dxml,
+                                         unsigned int flags);
 typedef int
         (*virDrvDomainRestore)         (virConnectPtr conn,
                                          const char *from);
+typedef int
+        (*virDrvDomainRestoreFlags)    (virConnectPtr conn,
+                                         const char *from,
+                                         const char *dxml,
+                                         unsigned int flags);
 typedef int
         (*virDrvDomainCoreDump)                (virDomainPtr domain,
                                          const char *to,
@@ -714,7 +724,9 @@ struct _virDriver {
     virDrvDomainGetState       domainGetState;
     virDrvDomainGetControlInfo  domainGetControlInfo;
     virDrvDomainSave           domainSave;
+    virDrvDomainSaveFlags      domainSaveFlags;
     virDrvDomainRestore                domainRestore;
+    virDrvDomainRestoreFlags   domainRestoreFlags;
     virDrvDomainCoreDump        domainCoreDump;
     virDrvDomainScreenshot      domainScreenshot;
     virDrvDomainSetVcpus               domainSetVcpus;
index 16a9a027c3c2e26069155a558ec03b01dc8d02bf..67041c67295154d8a6ace00191b2c503576e97be 100644 (file)
@@ -2242,6 +2242,8 @@ error:
  * listed as running anymore (this may be a problem).
  * Use virDomainRestore() to restore a domain after saving.
  *
+ * See virDomainSaveFlags() for more control.
+ *
  * Returns 0 in case of success and -1 in case of failure.
  */
 int
@@ -2295,6 +2297,85 @@ error:
     return -1;
 }
 
+/**
+ * virDomainSaveFlags:
+ * @domain: a domain object
+ * @to: path for the output file
+ * @dxml: (optional) XML config for adjusting guest xml used on restore
+ * @flags: bitwise-OR of virDomainSaveRestoreFlags
+ *
+ * This method will suspend a domain and save its memory contents to
+ * a file on disk. After the call, if successful, the domain is not
+ * listed as running anymore (this may be a problem).
+ * Use virDomainRestore() to restore a domain after saving.
+ *
+ * If the hypervisor supports it, @dxml can be used to alter
+ * host-specific portions of the domain XML that will be used when
+ * restoring an image.  For example, it is possible to alter the
+ * backing filename that is associated with a disk device, in order to
+ * prepare for file renaming done as part of backing up the disk
+ * device while the domain is stopped.
+ *
+ * If @flags includes VIR_DOMAIN_SAVE_BYPASS_CACHE, then libvirt will
+ * attempt to bypass the file system cache while creating the file, or
+ * fail if it cannot do so for the given system; this can allow less
+ * pressure on file system cache, but also risks slowing saves to NFS.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainSaveFlags(virDomainPtr domain, const char *to,
+                   const char *dxml, unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "to=%s dxml=%s flags=%x",
+                     to, NULLSTR(dxml), flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+    conn = domain->conn;
+    if (to == NULL) {
+        virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainSaveFlags) {
+        int ret;
+        char *absolute_to;
+
+        /* We must absolutize the file path as the save is done out of process */
+        if (virFileAbsPath(to, &absolute_to) < 0) {
+            virLibConnError(VIR_ERR_INTERNAL_ERROR,
+                            _("could not build absolute output file path"));
+            goto error;
+        }
+
+        ret = conn->driver->domainSaveFlags(domain, absolute_to, dxml, flags);
+
+        VIR_FREE(absolute_to);
+
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(domain->conn);
+    return -1;
+}
+
 /**
  * virDomainRestore:
  * @conn: pointer to the hypervisor connection
@@ -2302,6 +2383,8 @@ error:
  *
  * This method will restore a domain saved to disk by virDomainSave().
  *
+ * See virDomainRestoreFlags() for more control.
+ *
  * Returns 0 in case of success and -1 in case of failure.
  */
 int
@@ -2352,6 +2435,80 @@ error:
     return -1;
 }
 
+/**
+ * virDomainRestoreFlags:
+ * @conn: pointer to the hypervisor connection
+ * @from: path to the input file
+ * @dxml: (optional) XML config for adjusting guest xml used on restore
+ * @flags: bitwise-OR of virDomainSaveRestoreFlags
+ *
+ * This method will restore a domain saved to disk by virDomainSave().
+ *
+ * If the hypervisor supports it, @dxml can be used to alter
+ * host-specific portions of the domain XML that will be used when
+ * restoring an image.  For example, it is possible to alter the
+ * backing filename that is associated with a disk device, in order to
+ * prepare for file renaming done as part of backing up the disk
+ * device while the domain is stopped.
+ *
+ * If @flags includes VIR_DOMAIN_SAVE_BYPASS_CACHE, then libvirt will
+ * attempt to bypass the file system cache while restoring the file, or
+ * fail if it cannot do so for the given system; this can allow less
+ * pressure on file system cache, but also risks slowing saves to NFS.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainRestoreFlags(virConnectPtr conn, const char *from, const char *dxml,
+    unsigned int flags)
+{
+    VIR_DEBUG("conn=%p, from=%s, dxml=%s, flags=%x",
+              conn, from, NULLSTR(dxml), flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+    if (from == NULL) {
+        virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainRestoreFlags) {
+        int ret;
+        char *absolute_from;
+
+        /* We must absolutize the file path as the restore is done out of process */
+        if (virFileAbsPath(from, &absolute_from) < 0) {
+            virLibConnError(VIR_ERR_INTERNAL_ERROR,
+                            _("could not build absolute input file path"));
+            goto error;
+        }
+
+        ret = conn->driver->domainRestoreFlags(conn, absolute_from, dxml,
+                                               flags);
+
+        VIR_FREE(absolute_from);
+
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(conn);
+    return -1;
+}
+
 /**
  * virDomainCoreDump:
  * @domain: a domain object
@@ -2362,6 +2519,17 @@ error:
  * Note that for remote Xen Daemon the file path will be interpreted in
  * the remote host.
  *
+ * If @flags includes VIR_DUMP_CRASH, then leave the guest shut off with
+ * a crashed state after the dump completes.  If @flags includes
+ * VIR_DUMP_LIVE, then make the core dump while continuing to allow
+ * the guest to run; otherwise, the guest is suspended during the dump.
+ * The above two flags are mutually exclusive.
+ *
+ * Additionally, if @flags includes VIR_DUMP_BYPASS_CACHE, then libvirt
+ * will attempt to bypass the file system cache while creating the file,
+ * or fail if it cannot do so for the given system; this can allow less
+ * pressure on file system cache, but also risks slowing saves to NFS.
+ *
  * Returns 0 in case of success and -1 in case of failure.
  */
 int
@@ -6612,6 +6780,12 @@ error:
  * libvirtd daemon. Any domains marked for auto destroy will
  * block attempts at migration or save-to-file
  *
+ * If the VIR_DOMAIN_START_BYPASS_CACHE flag is set, and there is a
+ * managed save file for this domain (created by virDomainManagedSave()),
+ * then libvirt will attempt to bypass the file system cache while restoring
+ * the file, or fail if it cannot do so for the given system; this can allow
+ * less pressure on file system cache, but also risks slowing loads from NFS.
+ *
  * Returns 0 in case of success, -1 in case of error
  */
 int
@@ -14837,7 +15011,7 @@ error:
 /**
  * virDomainManagedSave:
  * @dom: pointer to the domain
- * @flags: optional flags currently unused
+ * @flags: bitwise-OR of virDomainSaveRestoreFlags
  *
  * This method will suspend a domain and save its memory contents to
  * a file on disk. After the call, if successful, the domain is not
@@ -14847,6 +15021,11 @@ error:
  * restarted (automatically or via an explicit libvirt call).
  * As a result any running domain is sure to not have a managed saved image.
  *
+ * If @flags includes VIR_DOMAIN_SAVE_BYPASS_CACHE, then libvirt will
+ * attempt to bypass the file system cache while creating the file, or
+ * fail if it cannot do so for the given system; this can allow less
+ * pressure on file system cache, but also risks slowing saves to NFS.
+ *
  * Returns 0 in case of success or -1 in case of failure
  */
 int virDomainManagedSave(virDomainPtr dom, unsigned int flags)
index 5cc480ef5b326dedbcecd843bc2551201b6ea34a..6935140df85e8de1bb58321504875b9e62a71669 100644 (file)
@@ -468,6 +468,8 @@ LIBVIRT_0.9.3 {
 
 LIBVIRT_0.9.4 {
     global:
+        virDomainRestoreFlags;
+        virDomainSaveFlags;
         virDomainUndefineFlags;
 } LIBVIRT_0.9.3;