On Fri, Oct 12, 2018 at 00:10:08 -0500, Eric Blake wrote: > Introduce a bunch of new public APIs related to backup checkpoints. > Checkpoints are modeled heavily after virDomainSnapshotPtr (both > represent a point in time of the guest), although a snapshot exists > with the intent of rolling back to that state, while a checkpoint > exists to make it possible to create an incremental backup at a later > time. > > The full list of new API: > virDomainCheckpointCreateXML; > virDomainCheckpointCurrent; > virDomainCheckpointDelete; > virDomainCheckpointFree; > virDomainCheckpointGetConnect; > virDomainCheckpointGetDomain; > virDomainCheckpointGetParent; > virDomainCheckpointGetXMLDesc; > virDomainCheckpointHasMetadata; > virDomainCheckpointIsCurrent; > virDomainCheckpointListChildren; > virDomainCheckpointLookupByName; > virDomainCheckpointRef; > virDomainHasCurrentCheckpoint; > virDomainListCheckpoints; > virDomainCheckpointGetName; > > Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> > --- > include/libvirt/libvirt-domain-checkpoint.h | 156 +++++ > include/libvirt/libvirt.h | 5 +- > src/driver-hypervisor.h | 60 +- > docs/Makefile.am | 3 + > docs/apibuild.py | 2 + > docs/docs.html.in | 1 + > libvirt.spec.in | 1 + > mingw-libvirt.spec.in | 2 + > po/POTFILES | 1 + > src/Makefile.am | 2 + > src/libvirt-domain-checkpoint.c | 723 ++++++++++++++++++++ > src/libvirt_public.syms | 20 + > 12 files changed, 972 insertions(+), 4 deletions(-) > create mode 100644 include/libvirt/libvirt-domain-checkpoint.h > create mode 100644 src/libvirt-domain-checkpoint.c > > diff --git a/include/libvirt/libvirt-domain-checkpoint.h b/include/libvirt/libvirt-domain-checkpoint.h > new file mode 100644 > index 0000000000..cfca8f4b7f > --- /dev/null > +++ b/include/libvirt/libvirt-domain-checkpoint.h > @@ -0,0 +1,156 @@ > +/* > + * libvirt-domain-checkpoint.h > + * Summary: APIs for management of domain checkpoints > + * Description: Provides APIs for the management of domain checkpoints > + * Author: Eric Blake <eblake@xxxxxxxxxx> > + * > + * Copyright (C) 2006-2018 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.1 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, see > + * <http://www.gnu.org/licenses/>. > + */ > + > +#ifndef __VIR_LIBVIRT_DOMAIN_CHECKPOINT_H__ > +# define __VIR_LIBVIRT_DOMAIN_CHECKPOINT_H__ > + > +# ifndef __VIR_LIBVIRT_H_INCLUDES__ > +# error "Don't include this file directly, only use libvirt/libvirt.h" > +# endif > + > +/** > + * virDomainCheckpoint: > + * > + * A virDomainCheckpoint is a private structure representing a checkpoint of > + * a domain. A checkpoint is useful for tracking which portions of the > + * domain disks have been altered since a point in time, but by itself does > + * not allow reverting back to that point in time. > + */ > +typedef struct _virDomainCheckpoint virDomainCheckpoint; > + > +/** > + * virDomainCheckpointPtr: > + * > + * A virDomainCheckpointPtr is pointer to a virDomainCheckpoint > + * private structure, and is the type used to reference a domain > + * checkpoint in the API. > + */ > +typedef virDomainCheckpoint *virDomainCheckpointPtr; > + > +const char *virDomainCheckpointGetName(virDomainCheckpointPtr checkpoint); > +virDomainPtr virDomainCheckpointGetDomain(virDomainCheckpointPtr checkpoint); > +virConnectPtr virDomainCheckpointGetConnect(virDomainCheckpointPtr checkpoint); > + > +typedef enum { > + VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE = (1 << 0), /* Restore or alter > + metadata */ > + VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT = (1 << 1), /* With redefine, make > + checkpoint current */ > + VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA = (1 << 2), /* Make checkpoint without > + remembering it */ Is this worth adding? Will there be a way to start an incremental backup without a previously existing libvirt checkpoint (thus having metadata)? > + /* TODO: VIR_DOMAIN_CHECKPOINT_CREATE_QUIESCE */ > +} virDomainCheckpointCreateFlags; > + > +/* Create a checkpoint using the current VM state. */ > +virDomainCheckpointPtr virDomainCheckpointCreateXML(virDomainPtr domain, > + const char *xmlDesc, > + unsigned int flags); > + > +typedef enum { > + VIR_DOMAIN_CHECKPOINT_XML_SECURE = (1 << 0), /* Include sensitive data */ > + VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN = (1 << 1), /* Suppress <domain> > + subelement */ > + VIR_DOMAIN_CHECKPOINT_XML_SIZE = (1 << 2), /* Include dynamic > + per-<disk> size */ > +} virDomainCheckpointXMLFlags; > + > +/* Dump the XML of a checkpoint */ > +char *virDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint, > + unsigned int flags); > + > +/** > + * virDomainCheckpointListFlags: > + * > + * Flags valid for virDomainListCheckpoints() and > + * virDomainCheckpointListChildren(). Note that the interpretation of > + * flag (1<<0) depends on which function it is passed to; but serves > + * to toggle the per-call default of whether the listing is shallow or > + * recursive. Remaining bits come in groups; if all bits from a group > + * are 0, then that group is not used to filter results. */ > +typedef enum { > + VIR_DOMAIN_CHECKPOINT_LIST_ROOTS = (1 << 0), /* Filter by checkpoints > + with no parents, when > + listing a domain */ > + VIR_DOMAIN_CHECKPOINT_LIST_DESCENDANTS = (1 << 0), /* List all descendants, > + not just children, when > + listing a checkpoint */ > + > + VIR_DOMAIN_CHECKPOINT_LIST_LEAVES = (1 << 1), /* Filter by checkpoints > + with no children */ > + VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES = (1 << 2), /* Filter by checkpoints > + that have children */ > + > + VIR_DOMAIN_CHECKPOINT_LIST_METADATA = (1 << 3), /* Filter by checkpoints > + which have metadata */ > + VIR_DOMAIN_CHECKPOINT_LIST_NO_METADATA = (1 << 4), /* Filter by checkpoints > + with no metadata */ > +} virDomainCheckpointListFlags; > + > +/* Get all checkpoint objects for this domain */ > +int virDomainListCheckpoints(virDomainPtr domain, > + virDomainCheckpointPtr **checkpoints, > + unsigned int flags); > + > +/* Get all checkpoint object children for this checkpoint */ > +int virDomainCheckpointListChildren(virDomainCheckpointPtr checkpoint, > + virDomainCheckpointPtr **children, > + unsigned int flags); > + > +/* Get a handle to a named checkpoint */ > +virDomainCheckpointPtr virDomainCheckpointLookupByName(virDomainPtr domain, > + const char *name, > + unsigned int flags); > + > +/* Check whether a domain has a checkpoint which is currently used */ > +int virDomainHasCurrentCheckpoint(virDomainPtr domain, unsigned int flags); > + > +/* Get a handle to the current checkpoint */ > +virDomainCheckpointPtr virDomainCheckpointCurrent(virDomainPtr domain, > + unsigned int flags); > + > +/* Get a handle to the parent checkpoint, if one exists */ > +virDomainCheckpointPtr virDomainCheckpointGetParent(virDomainCheckpointPtr checkpoint, > + unsigned int flags); > + > +/* Determine if a checkpoint is the current checkpoint of its domain. */ > +int virDomainCheckpointIsCurrent(virDomainCheckpointPtr checkpoint, > + unsigned int flags); > + > +/* Determine if checkpoint has metadata that would prevent domain deletion. */ > +int virDomainCheckpointHasMetadata(virDomainCheckpointPtr checkpoint, > + unsigned int flags); > + > +/* Delete a checkpoint */ > +typedef enum { > + VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN = (1 << 0), /* Also delete children */ > + VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY = (1 << 1), /* Delete just metadata */ > + VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY = (1 << 2), /* Delete just children */ > +} virDomainCheckpointDeleteFlags; > + > +int virDomainCheckpointDelete(virDomainCheckpointPtr checkpoint, > + unsigned int flags); > + > +int virDomainCheckpointRef(virDomainCheckpointPtr checkpoint); > +int virDomainCheckpointFree(virDomainCheckpointPtr checkpoint); > + > +#endif /* __VIR_LIBVIRT_DOMAIN_CHECKPOINT_H__ */ > diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h > index 26887a40e7..4e7da0afc4 100644 > --- a/include/libvirt/libvirt.h > +++ b/include/libvirt/libvirt.h > @@ -4,7 +4,7 @@ > * Description: Provides the interfaces of the libvirt library to handle > * virtualized domains > * > - * Copyright (C) 2005-2006, 2010-2014 Red Hat, Inc. > + * Copyright (C) 2005-2006, 2010-2018 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 > @@ -36,8 +36,7 @@ extern "C" { > # include <libvirt/libvirt-common.h> > # include <libvirt/libvirt-host.h> > # include <libvirt/libvirt-domain.h> > -typedef struct _virDomainCheckpoint virDomainCheckpoint; > -typedef virDomainCheckpoint *virDomainCheckpointPtr; This should be part of the patch adding the data structure. > +# include <libvirt/libvirt-domain-checkpoint.h> > # include <libvirt/libvirt-domain-snapshot.h> > # include <libvirt/libvirt-event.h> > # include <libvirt/libvirt-interface.h> [...] > diff --git a/src/libvirt-domain-checkpoint.c b/src/libvirt-domain-checkpoint.c > new file mode 100644 > index 0000000000..8a7b5b3c56 > --- /dev/null > +++ b/src/libvirt-domain-checkpoint.c > @@ -0,0 +1,723 @@ > +/* > + * libvirt-domain-checkpoint.c: entry points for virDomainCheckpointPtr APIs > + * > + * Copyright (C) 2006-2014, 2018 Red Hat, Inc. For a new file? > + * > + * 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.1 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, see > + * <http://www.gnu.org/licenses/>. > + */ > + > +#include <config.h> > + > +#include "datatypes.h" > +#include "virlog.h" > + > +VIR_LOG_INIT("libvirt.domain-checkpoint"); > + > +#define VIR_FROM_THIS VIR_FROM_DOMAIN_CHECKPOINT > + > +/** > + * virDomainCheckpointGetName: > + * @checkpoint: a checkpoint object > + * > + * Get the public name for that checkpoint > + * > + * Returns a pointer to the name or NULL, the string need not be deallocated > + * as its lifetime will be the same as the checkpoint object. > + */ > +const char * > +virDomainCheckpointGetName(virDomainCheckpointPtr checkpoint) > +{ > + VIR_DEBUG("checkpoint=%p", checkpoint); > + > + virResetLastError(); > + > + virCheckDomainCheckpointReturn(checkpoint, NULL); > + > + return checkpoint->name; > +} > + > + > +/** > + * virDomainCheckpointGetDomain: > + * @checkpoint: a checkpoint object > + * > + * Provides the domain pointer associated with a checkpoint. The > + * reference counter on the domain is not increased by this > + * call. > + * > + * Returns the domain or NULL. > + */ > +virDomainPtr > +virDomainCheckpointGetDomain(virDomainCheckpointPtr checkpoint) > +{ > + VIR_DEBUG("checkpoint=%p", checkpoint); > + > + virResetLastError(); > + > + virCheckDomainCheckpointReturn(checkpoint, NULL); > + > + return checkpoint->domain; > +} > + > + > +/** > + * virDomainCheckpointGetConnect: > + * @checkpoint: a checkpoint object > + * > + * Provides the connection pointer associated with a checkpoint. The > + * reference counter on the connection is not increased by this > + * call. > + * > + * Returns the connection or NULL. > + */ > +virConnectPtr > +virDomainCheckpointGetConnect(virDomainCheckpointPtr checkpoint) This does not seem to be very useful. Users always can do a two step lookup. > +{ > + VIR_DEBUG("checkpoint=%p", checkpoint); > + > + virResetLastError(); > + > + virCheckDomainCheckpointReturn(checkpoint, NULL); > + > + return checkpoint->domain->conn; > +} > + > + > +/** > + * virDomainCheckpointCreateXML: > + * @domain: a domain object > + * @xmlDesc: description of the checkpoint to create > + * @flags: bitwise-OR of supported virDomainCheckpointCreateFlags > + * > + * Create a new checkpoint using @xmlDesc on a running @domain. > + * Typically, it is more common to create a new checkpoint as part of > + * kicking off a backup job with virDomainBackupBegin(); however, it > + * is also possible to start a checkpoint without a backup. > + * > + * See <a href=formatcheckpoint.html#CheckpointAttributes">Checkpoint XML</a> > + * for more details on @xmlDesc. In particular, some hypervisors may require > + * particular disk formats, such as qcow2, in order to support this > + * command; where @xmlDesc can be used to limit the checkpoint to a working > + * subset of the domain's disks. > + * > + * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE, then this > + * is a request to reinstate checkpoint metadata that was previously > + * discarded, rather than creating a new checkpoint. When redefining > + * checkpoint metadata, the current checkpoint will not be altered > + * unless the VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT flag is also > + * present. It is an error to request the > + * VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT flag without > + * VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE. > + * > + * If @flags includes VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA, then > + * the domain's disk images are modified according to @xmlDesc, but > + * then the just-created checkpoint has its metadata deleted. This > + * flag is incompatible with VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE. > + * > + * Returns an (opaque) new virDomainCheckpointPtr on success, or NULL > + * on failure. > + */ > +virDomainCheckpointPtr > +virDomainCheckpointCreateXML(virDomainPtr domain, > + const char *xmlDesc, > + unsigned int flags) > +{ > + virConnectPtr conn; > + > + VIR_DOMAIN_DEBUG(domain, "xmlDesc=%s, flags=0x%x", xmlDesc, flags); > + > + virResetLastError(); > + > + virCheckDomainReturn(domain, NULL); > + conn = domain->conn; > + > + virCheckNonNullArgGoto(xmlDesc, error); > + virCheckReadOnlyGoto(conn->flags, error); > + > + VIR_REQUIRE_FLAG_GOTO(VIR_DOMAIN_CHECKPOINT_CREATE_CURRENT, > + VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE, > + error); > + > + VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_CHECKPOINT_CREATE_REDEFINE, > + VIR_DOMAIN_CHECKPOINT_CREATE_NO_METADATA, > + error); > + > + if (conn->driver->domainCheckpointCreateXML) { > + virDomainCheckpointPtr ret; > + ret = conn->driver->domainCheckpointCreateXML(domain, xmlDesc, flags); > + if (!ret) > + goto error; > + return ret; > + } > + > + virReportUnsupportedError(); > + error: > + virDispatchError(conn); > + return NULL; > +} > + > + > +/** > + * virDomainCheckpointGetXMLDesc: > + * @checkpoint: a domain checkpoint object > + * @flags: bitwise-OR of supported virDomainCheckpointXMLFlags > + * > + * Provide an XML description of the domain checkpoint. > + * > + * No security-sensitive data will be included unless @flags contains > + * VIR_DOMAIN_CHECKPOINT_XML_SECURE; this flag is rejected on read-only > + * connections. As discussed in other places, I'm not convinced that storing a domain is needed with backups. > + * > + * Normally, the XML description includes an element giving a full > + * description of the domain at the time the snapshot was created; to Missed reference to snapshots. > + * reduce parsing time, it will be suppressed when @flags contains > + * VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN. > + * > + * By default, the XML description contains only static information that > + * does not change over time. However, when @flags contains > + * VIR_DOMAIN_CHECKPOINT_XML_SIZE, each <disk> listing adds an additional > + * attribute that shows an estimate of the current size in bytes that > + * have been dirtied between the time the checkpoint was created and the > + * current point in time. > + * > + * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. > + * the caller must free() the returned value. > + */ > +char * > +virDomainCheckpointGetXMLDesc(virDomainCheckpointPtr checkpoint, > + unsigned int flags) > +{ > + virConnectPtr conn; > + VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags); > + > + virResetLastError(); > + > + virCheckDomainCheckpointReturn(checkpoint, NULL); > + conn = checkpoint->domain->conn; > + > + if ((conn->flags & VIR_CONNECT_RO) && > + (flags & VIR_DOMAIN_CHECKPOINT_XML_SECURE)) { > + virReportError(VIR_ERR_OPERATION_DENIED, "%s", > + _("virDomainCheckpointGetXMLDesc with secure flag")); > + goto error; > + } > + > + if (conn->driver->domainCheckpointGetXMLDesc) { > + char *ret; > + ret = conn->driver->domainCheckpointGetXMLDesc(checkpoint, flags); > + if (!ret) > + goto error; > + return ret; > + } > + > + virReportUnsupportedError(); > + error: > + virDispatchError(conn); > + return NULL; > +} > + > + > +/** > + * virDomainListCheckpoints: > + * @domain: a domain object > + * @checkpoints: pointer to variable to store the array containing checkpoint > + * objects, or NULL if the list is not required (just returns > + * number of checkpoints) > + * @flags: bitwise-OR of supported virDomainCheckpoinListFlags s/virDomainCheckpoinListFlags/virDomainCheckpointListFlags/ > + * > + * Collect the list of domain checkpoints for the given domain, and allocate > + * an array to store those objects. > + * > + * By default, this command covers all checkpoints; it is also possible to > + * limit things to just checkpoints with no parents, when @flags includes > + * VIR_DOMAIN_CHECKPOINT_LIST_ROOTS. Additional filters are provided in > + * groups, where each group contains bits that describe mutually exclusive > + * attributes of a checkpoint, and where all bits within a group describe > + * all possible checkpoints. Some hypervisors might reject explicit bits > + * from a group where the hypervisor cannot make a distinction. For a > + * group supported by a given hypervisor, the behavior when no bits of a > + * group are set is identical to the behavior when all bits in that group > + * are set. When setting bits from more than one group, it is possible to > + * select an impossible combination, in that case a hypervisor may return > + * either 0 or an error. > + * > + * The first group of @flags is VIR_DOMAIN_CHECKPOINT_LIST_LEAVES and > + * VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES, to filter based on checkpoints that > + * have no further children (a leaf checkpoint). > + * > + * The next group of @flags is VIR_DOMAIN_CHECKPOINT_LIST_METADATA and > + * VIR_DOMAIN_CHECKPOINT_LIST_NO_METADATA, for filtering checkpoints based on > + * whether they have metadata that would prevent the removal of the last > + * reference to a domain. > + * > + * Returns the number of domain checkpoints found or -1 and sets @checkpoints > + * to NULL in case of error. On success, the array stored into @checkpoints > + * is guaranteed to have an extra allocated element set to NULL but not > + * included in the return count, to make iteration easier. The caller is > + * responsible for calling virDomainCheckpointFree() on each array element, > + * then calling free() on @checkpoints. > + */ > +int > +virDomainListCheckpoints(virDomainPtr domain, > + virDomainCheckpointPtr **checkpoints, > + unsigned int flags) > +{ > + virConnectPtr conn; > + > + VIR_DOMAIN_DEBUG(domain, "checkpoints=%p, flags=0x%x", checkpoints, flags); > + > + virResetLastError(); > + > + if (checkpoints) > + *checkpoints = NULL; > + > + virCheckDomainReturn(domain, -1); > + conn = domain->conn; > + > + if (conn->driver->domainListCheckpoints) { > + int ret = conn->driver->domainListCheckpoints(domain, checkpoints, > + flags); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virReportUnsupportedError(); > + error: > + virDispatchError(conn); > + return -1; > +} [...] > +/** > + * virDomainCheckpointIsCurrent: > + * @checkpoint: a checkpoint object > + * @flags: extra flags; not used yet, so callers should always pass 0 > + * > + * Determine if the given checkpoint is the domain's current checkpoint. See > + * also virDomainHasCurrentCheckpoint(). Depending on whether 'current checkpoint' makes sense this might not be needed. > + * > + * Returns 1 if current, 0 if not current, or -1 on error. > + */ > +int > +virDomainCheckpointIsCurrent(virDomainCheckpointPtr checkpoint, > + unsigned int flags) > +{ > + virConnectPtr conn; > + > + VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags); > + > + virResetLastError(); > + > + virCheckDomainCheckpointReturn(checkpoint, -1); > + conn = checkpoint->domain->conn; > + > + if (conn->driver->domainCheckpointIsCurrent) { > + int ret; > + ret = conn->driver->domainCheckpointIsCurrent(checkpoint, flags); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virReportUnsupportedError(); > + error: > + virDispatchError(conn); > + return -1; > +} > + > + > +/** > + * virDomainCheckpointHasMetadata: > + * @checkpoint: a checkpoint object > + * @flags: extra flags; not used yet, so callers should always pass 0 > + * > + * Determine if the given checkpoint is associated with libvirt metadata > + * that would prevent the deletion of the domain. Given that we've never implemented metadata-less snapshots do we expect this to happen with checkpoints? > + * Returns 1 if the checkpoint has metadata, 0 if the checkpoint exists without > + * help from libvirt, or -1 on error. > + */ > +int > +virDomainCheckpointHasMetadata(virDomainCheckpointPtr checkpoint, > + unsigned int flags) > +{ > + virConnectPtr conn; > + > + VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags); > + > + virResetLastError(); > + > + virCheckDomainCheckpointReturn(checkpoint, -1); > + conn = checkpoint->domain->conn; > + > + if (conn->driver->domainCheckpointHasMetadata) { > + int ret; > + ret = conn->driver->domainCheckpointHasMetadata(checkpoint, flags); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virReportUnsupportedError(); > + error: > + virDispatchError(conn); > + return -1; > +} > + > + > +/** > + * virDomainCheckpointDelete: > + * @checkpoint: the checkpoint to remove > + * @flags: not used yet, pass 0 > + * @flags: bitwise-OR of supported virDomainCheckpointDeleteFlags @flags present twice > + * > + * Removes a checkpoint from the domain. > + * > + * When removing a checkpoint, the record of which portions of the > + * disk were dirtied after the checkpoint will be merged into the > + * record tracked by the parent checkpoint, if any. So as a high-level question, since from the APIs added here is clear that we expect tree-like topologies of checkpoints. Does merging of the data _into_ the parent invalidate any other children? This is a big problem we'll be facing when doing external snapshot reversion. > Likewise, if the > + * checkpoint being deleted was the current checkpoint, the parent > + * checkpoint becomes the new current checkpoint. > + * > + * If @flags includes VIR_DOMAIN_CHECKPOINT_DELETE_METADATA_ONLY, then > + * any checkpoint metadata tracked by libvirt is removed while keeping > + * the checkpoint contents intact; if a hypervisor does not require > + * any libvirt metadata to track checkpoints, then this flag is > + * silently ignored. > + * > + * Returns 0 on success, -1 on error. > + */ > +int > +virDomainCheckpointDelete(virDomainCheckpointPtr checkpoint, > + unsigned int flags) > +{ > + virConnectPtr conn; > + > + VIR_DEBUG("checkpoint=%p, flags=0x%x", checkpoint, flags); > + > + virResetLastError(); > + > + virCheckDomainCheckpointReturn(checkpoint, -1); > + conn = checkpoint->domain->conn; > + > + virCheckReadOnlyGoto(conn->flags, error); > + > + VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN, > + VIR_DOMAIN_CHECKPOINT_DELETE_CHILDREN_ONLY, > + error); > + > + if (conn->driver->domainCheckpointDelete) { > + int ret = conn->driver->domainCheckpointDelete(checkpoint, flags); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virReportUnsupportedError(); > + error: > + virDispatchError(conn); > + return -1; > +}
Attachment:
signature.asc
Description: PGP signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list