* 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list