mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 11:31:16 +00:00
backup: Allow for lists of checkpoint objects
Create a new file for managing a list of checkpoint objects, borrowing heavily from existing virDomainSnapshotObjList paradigms. Note that while snapshots definitely have a use case for multiple children to a single parent (create a base snapshot, create a child snapshot, revert to the base, then create another child snapshot), it's harder to predict how checkpoints will play out with reverting to prior points in time. Thus, in initial use, given a list of checkpoints, you never have more than one child, and we can treat the most-recent leaf node as the parent of the next node creation, without having to expose a notion of a current node in XML or public API. However, as the snapshot machinery is already generic, it is easier to reuse the generic machinery that tracks relations between domain moments than it is to open-code a new list-management scheme just for checkpoints (hence, we still have internal functions related to a current checkpoint, even though that has no observable effect externally, as well as the addition of a function to easily find the lone leaf in the list to use as the current checkpoint). Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
1a4df34a0f
commit
2795d85647
@ -36,6 +36,8 @@ DOMAIN_CONF_SOURCES = \
|
|||||||
conf/numa_conf.c \
|
conf/numa_conf.c \
|
||||||
conf/numa_conf.h \
|
conf/numa_conf.h \
|
||||||
conf/virconftypes.h \
|
conf/virconftypes.h \
|
||||||
|
conf/virdomaincheckpointobjlist.c \
|
||||||
|
conf/virdomaincheckpointobjlist.h \
|
||||||
conf/virdomainobjlist.c \
|
conf/virdomainobjlist.c \
|
||||||
conf/virdomainobjlist.h \
|
conf/virdomainobjlist.h \
|
||||||
conf/virdomainmomentobjlist.c \
|
conf/virdomainmomentobjlist.c \
|
||||||
|
@ -105,6 +105,12 @@ typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
|
|||||||
typedef struct _virDomainCheckpointDef virDomainCheckpointDef;
|
typedef struct _virDomainCheckpointDef virDomainCheckpointDef;
|
||||||
typedef virDomainCheckpointDef *virDomainCheckpointDefPtr;
|
typedef virDomainCheckpointDef *virDomainCheckpointDefPtr;
|
||||||
|
|
||||||
|
typedef struct _virDomainCheckpointObj virDomainCheckpointObj;
|
||||||
|
typedef virDomainCheckpointObj *virDomainCheckpointObjPtr;
|
||||||
|
|
||||||
|
typedef struct _virDomainCheckpointObjList virDomainCheckpointObjList;
|
||||||
|
typedef virDomainCheckpointObjList *virDomainCheckpointObjListPtr;
|
||||||
|
|
||||||
typedef struct _virDomainChrDef virDomainChrDef;
|
typedef struct _virDomainChrDef virDomainChrDef;
|
||||||
typedef virDomainChrDef *virDomainChrDefPtr;
|
typedef virDomainChrDef *virDomainChrDefPtr;
|
||||||
|
|
||||||
|
243
src/conf/virdomaincheckpointobjlist.c
Normal file
243
src/conf/virdomaincheckpointobjlist.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
* virdomaincheckpointobjlist.c: handle a tree of checkpoint objects
|
||||||
|
* (derived from virdomainsnapshotobjlist.c)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2019 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* 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 "internal.h"
|
||||||
|
#include "virdomaincheckpointobjlist.h"
|
||||||
|
#include "checkpoint_conf.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "virerror.h"
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_DOMAIN_CHECKPOINT
|
||||||
|
|
||||||
|
VIR_LOG_INIT("conf.virdomaincheckpointobjlist");
|
||||||
|
|
||||||
|
struct _virDomainCheckpointObjList {
|
||||||
|
virDomainMomentObjListPtr base;
|
||||||
|
};
|
||||||
|
|
||||||
|
virDomainMomentObjPtr
|
||||||
|
virDomainCheckpointAssignDef(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainCheckpointDefPtr def)
|
||||||
|
{
|
||||||
|
return virDomainMomentAssignDef(checkpoints->base, &def->parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
virDomainCheckpointFilter(virDomainMomentObjPtr obj ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
/* For now, we have no further filters than what the common code handles. */
|
||||||
|
virCheckFlags(0, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virDomainCheckpointObjListPtr
|
||||||
|
virDomainCheckpointObjListNew(void)
|
||||||
|
{
|
||||||
|
virDomainCheckpointObjListPtr checkpoints;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(checkpoints) < 0)
|
||||||
|
return NULL;
|
||||||
|
checkpoints->base = virDomainMomentObjListNew();
|
||||||
|
if (!checkpoints->base) {
|
||||||
|
VIR_FREE(checkpoints);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return checkpoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virDomainCheckpointObjListFree(virDomainCheckpointObjListPtr checkpoints)
|
||||||
|
{
|
||||||
|
if (!checkpoints)
|
||||||
|
return;
|
||||||
|
virDomainMomentObjListFree(checkpoints->base);
|
||||||
|
VIR_FREE(checkpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainCheckpointObjListGetNames(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr from,
|
||||||
|
char **const names,
|
||||||
|
int maxnames,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
/* We intentionally chose our public flags to match the common flags */
|
||||||
|
verify(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS ==
|
||||||
|
(int) VIR_DOMAIN_MOMENT_LIST_ROOTS);
|
||||||
|
verify(VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL ==
|
||||||
|
(int) VIR_DOMAIN_MOMENT_LIST_TOPOLOGICAL);
|
||||||
|
verify(VIR_DOMAIN_CHECKPOINT_LIST_LEAVES ==
|
||||||
|
(int) VIR_DOMAIN_MOMENT_LIST_LEAVES);
|
||||||
|
verify(VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES ==
|
||||||
|
(int) VIR_DOMAIN_MOMENT_LIST_NO_LEAVES);
|
||||||
|
|
||||||
|
return virDomainMomentObjListGetNames(checkpoints->base, from, names,
|
||||||
|
maxnames, flags,
|
||||||
|
virDomainCheckpointFilter, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virDomainMomentObjPtr
|
||||||
|
virDomainCheckpointFindByName(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
return virDomainMomentFindByName(checkpoints->base, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the current checkpoint, or NULL */
|
||||||
|
virDomainMomentObjPtr
|
||||||
|
virDomainCheckpointGetCurrent(virDomainCheckpointObjListPtr checkpoints)
|
||||||
|
{
|
||||||
|
return virDomainMomentGetCurrent(checkpoints->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the current checkpoint's name, or NULL */
|
||||||
|
const char *
|
||||||
|
virDomainCheckpointGetCurrentName(virDomainCheckpointObjListPtr checkpoints)
|
||||||
|
{
|
||||||
|
return virDomainMomentGetCurrentName(checkpoints->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Update the current checkpoint, using NULL if no current remains */
|
||||||
|
void
|
||||||
|
virDomainCheckpointSetCurrent(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr checkpoint)
|
||||||
|
{
|
||||||
|
virDomainMomentSetCurrent(checkpoints->base, checkpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove checkpoint from the list; return true if it was current */
|
||||||
|
bool
|
||||||
|
virDomainCheckpointObjListRemove(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr checkpoint)
|
||||||
|
{
|
||||||
|
return virDomainMomentObjListRemove(checkpoints->base, checkpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove all checkpoints tracked in the list */
|
||||||
|
void
|
||||||
|
virDomainCheckpointObjListRemoveAll(virDomainCheckpointObjListPtr checkpoints)
|
||||||
|
{
|
||||||
|
return virDomainMomentObjListRemoveAll(checkpoints->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virDomainCheckpointForEach(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virHashIterator iter,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
return virDomainMomentForEach(checkpoints->base, iter, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Populate parent link of a given checkpoint. */
|
||||||
|
void
|
||||||
|
virDomainCheckpointLinkParent(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr chk)
|
||||||
|
{
|
||||||
|
return virDomainMomentLinkParent(checkpoints->base, chk);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Populate parent link and child count of all checkpoints, with all
|
||||||
|
* assigned defs having relations starting as 0/NULL. Return 0 on
|
||||||
|
* success, -1 if a parent is missing or if a circular relationship
|
||||||
|
* was requested. Set leaf to the end of the chain, if there is
|
||||||
|
* exactly one such leaf. */
|
||||||
|
int
|
||||||
|
virDomainCheckpointUpdateRelations(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr *leaf)
|
||||||
|
{
|
||||||
|
int ret = virDomainMomentUpdateRelations(checkpoints->base);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
*leaf = virDomainMomentFindLeaf(checkpoints->base);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virDomainCheckpointCheckCycles(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainCheckpointDefPtr def,
|
||||||
|
const char *domname)
|
||||||
|
{
|
||||||
|
return virDomainMomentCheckCycles(checkpoints->base, &def->parent, domname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virDomainListCheckpoints(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr from,
|
||||||
|
virDomainPtr dom,
|
||||||
|
virDomainCheckpointPtr **chks,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int count = virDomainCheckpointObjListGetNames(checkpoints, from, NULL,
|
||||||
|
0, flags);
|
||||||
|
virDomainCheckpointPtr *list = NULL;
|
||||||
|
char **names;
|
||||||
|
int ret = -1;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!chks || count < 0)
|
||||||
|
return count;
|
||||||
|
if (VIR_ALLOC_N(names, count) < 0 ||
|
||||||
|
VIR_ALLOC_N(list, count + 1) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainCheckpointObjListGetNames(checkpoints, from, names, count,
|
||||||
|
flags) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
if ((list[i] = virGetDomainCheckpoint(dom, names[i])) == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = count;
|
||||||
|
*chks = list;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
VIR_FREE(names[i]);
|
||||||
|
VIR_FREE(names);
|
||||||
|
if (ret < 0 && list) {
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
virObjectUnref(list[i]);
|
||||||
|
VIR_FREE(list);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
96
src/conf/virdomaincheckpointobjlist.h
Normal file
96
src/conf/virdomaincheckpointobjlist.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* virdomaincheckpointobjlist.h: handle a tree of checkpoint objects
|
||||||
|
* (derived from virdomainsnapshotobjlist.h)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2019 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "virdomainmomentobjlist.h"
|
||||||
|
#include "virbuffer.h"
|
||||||
|
|
||||||
|
virDomainCheckpointObjListPtr
|
||||||
|
virDomainCheckpointObjListNew(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
virDomainCheckpointObjListFree(virDomainCheckpointObjListPtr checkpoints);
|
||||||
|
|
||||||
|
virDomainMomentObjPtr
|
||||||
|
virDomainCheckpointAssignDef(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainCheckpointDefPtr def);
|
||||||
|
|
||||||
|
virDomainMomentObjPtr
|
||||||
|
virDomainCheckpointFindByName(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
virDomainMomentObjPtr
|
||||||
|
virDomainCheckpointGetCurrent(virDomainCheckpointObjListPtr checkpoints);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
virDomainCheckpointGetCurrentName(virDomainCheckpointObjListPtr checkpoints);
|
||||||
|
|
||||||
|
void
|
||||||
|
virDomainCheckpointSetCurrent(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr checkpoint);
|
||||||
|
|
||||||
|
bool
|
||||||
|
virDomainCheckpointObjListRemove(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr checkpoint);
|
||||||
|
|
||||||
|
void
|
||||||
|
virDomainCheckpointObjListRemoveAll(virDomainCheckpointObjListPtr checkpoints);
|
||||||
|
|
||||||
|
int
|
||||||
|
virDomainCheckpointForEach(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virHashIterator iter,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
void
|
||||||
|
virDomainCheckpointLinkParent(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr chk);
|
||||||
|
|
||||||
|
int
|
||||||
|
virDomainCheckpointUpdateRelations(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr *leaf);
|
||||||
|
|
||||||
|
int
|
||||||
|
virDomainCheckpointCheckCycles(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainCheckpointDefPtr def,
|
||||||
|
const char *domname);
|
||||||
|
|
||||||
|
#define VIR_DOMAIN_CHECKPOINT_FILTERS_LEAVES \
|
||||||
|
(VIR_DOMAIN_CHECKPOINT_LIST_LEAVES | \
|
||||||
|
VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES)
|
||||||
|
|
||||||
|
#define VIR_DOMAIN_CHECKPOINT_FILTERS_ALL \
|
||||||
|
(VIR_DOMAIN_CHECKPOINT_FILTERS_LEAVES)
|
||||||
|
|
||||||
|
int
|
||||||
|
virDomainListCheckpoints(virDomainCheckpointObjListPtr checkpoints,
|
||||||
|
virDomainMomentObjPtr from,
|
||||||
|
virDomainPtr dom,
|
||||||
|
virDomainCheckpointPtr **objs,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
|
static inline virDomainCheckpointDefPtr
|
||||||
|
virDomainCheckpointObjGetDef(virDomainMomentObjPtr obj)
|
||||||
|
{
|
||||||
|
return (virDomainCheckpointDefPtr) obj->def;
|
||||||
|
}
|
@ -31,8 +31,8 @@
|
|||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
|
|
||||||
/* FIXME: using virObject would allow us to not need this */
|
/* FIXME: using virObject would allow us to not need this */
|
||||||
#include "snapshot_conf.h"
|
|
||||||
#include "virdomainsnapshotobjlist.h"
|
#include "virdomainsnapshotobjlist.h"
|
||||||
|
#include "virdomaincheckpointobjlist.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
||||||
|
|
||||||
@ -589,3 +589,18 @@ virDomainMomentCheckCycles(virDomainMomentObjListPtr list,
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If there is exactly one leaf node, return that node. */
|
||||||
|
virDomainMomentObjPtr
|
||||||
|
virDomainMomentFindLeaf(virDomainMomentObjListPtr list)
|
||||||
|
{
|
||||||
|
virDomainMomentObjPtr moment = &list->metaroot;
|
||||||
|
|
||||||
|
if (moment->nchildren != 1)
|
||||||
|
return NULL;
|
||||||
|
while (moment->nchildren == 1)
|
||||||
|
moment = moment->first_child;
|
||||||
|
if (moment->nchildren == 0)
|
||||||
|
return moment;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -121,3 +121,4 @@ int virDomainMomentUpdateRelations(virDomainMomentObjListPtr moments);
|
|||||||
int virDomainMomentCheckCycles(virDomainMomentObjListPtr list,
|
int virDomainMomentCheckCycles(virDomainMomentObjListPtr list,
|
||||||
virDomainMomentDefPtr def,
|
virDomainMomentDefPtr def,
|
||||||
const char *domname);
|
const char *domname);
|
||||||
|
virDomainMomentObjPtr virDomainMomentFindLeaf(virDomainMomentObjListPtr list);
|
||||||
|
@ -983,6 +983,22 @@ virChrdevFree;
|
|||||||
virChrdevOpen;
|
virChrdevOpen;
|
||||||
|
|
||||||
|
|
||||||
|
# conf/virdomaincheckpointobjlist.h
|
||||||
|
virDomainCheckpointAssignDef;
|
||||||
|
virDomainCheckpointFindByName;
|
||||||
|
virDomainCheckpointForEach;
|
||||||
|
virDomainCheckpointGetCurrent;
|
||||||
|
virDomainCheckpointGetCurrentName;
|
||||||
|
virDomainCheckpointLinkParent;
|
||||||
|
virDomainCheckpointObjListFree;
|
||||||
|
virDomainCheckpointObjListNew;
|
||||||
|
virDomainCheckpointObjListRemove;
|
||||||
|
virDomainCheckpointObjListRemoveAll;
|
||||||
|
virDomainCheckpointSetCurrent;
|
||||||
|
virDomainCheckpointUpdateRelations;
|
||||||
|
virDomainListCheckpoints;
|
||||||
|
|
||||||
|
|
||||||
# conf/virdomainmomentobjlist.h
|
# conf/virdomainmomentobjlist.h
|
||||||
virDomainMomentDropChildren;
|
virDomainMomentDropChildren;
|
||||||
virDomainMomentDropParent;
|
virDomainMomentDropParent;
|
||||||
|
Loading…
Reference in New Issue
Block a user