* include/libvirt/libvirt.h.in (virDomainCreateFlags): Add a flag.
(virDomainRestoreFlags): New prototype.
* src/libvirt.c (virDomainRestoreFlags): New function.
* src/libvirt_public.syms: Export it.
* src/driver.h (virDrvDomainRestoreFlags): New driver callback.
---
I'm debating whether to squash this into 1/8, or leave it separate.
include/libvirt/libvirt.h.in | 8 ++++-
src/driver.h | 6 +++
src/libvirt.c | 81 ++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 1 +
4 files changed, 95 insertions(+), 1 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index d9a8694..43881b3 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -235,6 +235,7 @@ 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_START_DIRECT = 1 << 2, /* Use O_DIRECT while restoring */
} virDomainCreateFlags;
@@ -945,7 +946,8 @@ int virDomainResume (virDomainPtr
domain);
/**
* virDomainSaveFlagValues:
- * Flags for use in virDomainSaveFlags and virDomainManagedSave.
+ * Flags for use in virDomainSaveFlags(), virDomainManagedSave(), and
+ * virDomainRestoreFlags().
*/
typedef enum {
VIR_DOMAIN_SAVE_DIRECT = 1 << 0, /* Use O_DIRECT while saving */
@@ -959,6 +961,10 @@ int virDomainSaveFlags (virDomainPtr
domain,
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
diff --git a/src/driver.h b/src/driver.h
index 7615daa..731c3c4 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -186,6 +186,11 @@ 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,
unsigned int flags);
@@ -717,6 +722,7 @@ struct _virDriver {
virDrvDomainSave domainSave;
virDrvDomainSaveFlags domainSaveFlags;
virDrvDomainRestore domainRestore;
+ virDrvDomainRestoreFlags domainRestoreFlags;
virDrvDomainCoreDump domainCoreDump;
virDrvDomainScreenshot domainScreenshot;
virDrvDomainSetVcpus domainSetVcpus;
diff --git a/src/libvirt.c b/src/libvirt.c
index 75d174d..bfe103b 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -2382,6 +2382,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
@@ -2433,6 +2435,79 @@ error:
}
/**
+ * 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 virDomainSaveFlagValues
+ *
+ * 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_DIRECT, then libvirt will attempt
+ * to use O_DIRECT I/O while restoring the file; 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
* @to: path for the core file
@@ -6651,6 +6726,12 @@ error:
* libvirtd daemon. Any domains marked for auto destroy will
* block attempts at migration or save-to-file
*
+ * If the VIR_DOMAIN_START_DIRECT flag is set, and there is a
+ * managed save file for this domain (created by virDomainManagedSave),
+ * then libvirt will attempt to use O_DIRECT I/O while loading the file;
+ * 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
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 0d31b94..ffbc234 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -468,6 +468,7 @@ LIBVIRT_0.9.3 {
LIBVIRT_0.9.4 {
global:
+ virDomainRestoreFlags;
virDomainSaveFlags;
} LIBVIRT_0.9.3;
--
1.7.4.4