mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-04-26 15:14:42 +00:00
qemu: backup: Move fetching of checkpoint list for incremental backup
Fetch the checkpoint list for every disk specifically based on the new per-disk 'incremental' field. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
b8295160c3
commit
15c5ed8ba6
@ -173,6 +173,50 @@ qemuBackupDiskDataCleanup(virDomainObjPtr vm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBackupBeginCollectIncrementalCheckpoints:
|
||||||
|
* @vm: domain object
|
||||||
|
* @incrFrom: name of checkpoint representing starting point of incremental backup
|
||||||
|
*
|
||||||
|
* Returns a NULL terminated list of pointers to checkpoint definitions in
|
||||||
|
* chronological order starting from the 'current' checkpoint until reaching
|
||||||
|
* @incrFrom.
|
||||||
|
*/
|
||||||
|
static virDomainMomentDefPtr *
|
||||||
|
qemuBackupBeginCollectIncrementalCheckpoints(virDomainObjPtr vm,
|
||||||
|
const char *incrFrom)
|
||||||
|
{
|
||||||
|
virDomainMomentObjPtr n = virDomainCheckpointGetCurrent(vm->checkpoints);
|
||||||
|
g_autofree virDomainMomentDefPtr *incr = NULL;
|
||||||
|
size_t nincr = 0;
|
||||||
|
|
||||||
|
while (n) {
|
||||||
|
virDomainMomentDefPtr def = n->def;
|
||||||
|
|
||||||
|
if (VIR_APPEND_ELEMENT_COPY(incr, nincr, def) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (STREQ(def->name, incrFrom)) {
|
||||||
|
def = NULL;
|
||||||
|
if (VIR_APPEND_ELEMENT_COPY(incr, nincr, def) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_steal_pointer(&incr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!n->def->parent_name)
|
||||||
|
break;
|
||||||
|
|
||||||
|
n = virDomainCheckpointFindByName(vm->checkpoints, n->def->parent_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
|
_("could not locate checkpoint '%s' for incremental backup"),
|
||||||
|
incrFrom);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuBackupGetBitmapMergeRange(virStorageSourcePtr from,
|
qemuBackupGetBitmapMergeRange(virStorageSourcePtr from,
|
||||||
const char *bitmapname,
|
const char *bitmapname,
|
||||||
@ -334,11 +378,11 @@ qemuBackupDiskPrepareDataOne(virDomainObjPtr vm,
|
|||||||
struct qemuBackupDiskData *dd,
|
struct qemuBackupDiskData *dd,
|
||||||
virJSONValuePtr actions,
|
virJSONValuePtr actions,
|
||||||
bool pull,
|
bool pull,
|
||||||
virDomainMomentDefPtr *incremental,
|
|
||||||
virHashTablePtr blockNamedNodeData,
|
virHashTablePtr blockNamedNodeData,
|
||||||
virQEMUDriverConfigPtr cfg)
|
virQEMUDriverConfigPtr cfg)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
g_autofree virDomainMomentDefPtr *incremental = NULL;
|
||||||
|
|
||||||
/* set data structure */
|
/* set data structure */
|
||||||
dd->backupdisk = backupdisk;
|
dd->backupdisk = backupdisk;
|
||||||
@ -363,7 +407,8 @@ qemuBackupDiskPrepareDataOne(virDomainObjPtr vm,
|
|||||||
* pull mode:
|
* pull mode:
|
||||||
* both: original disk
|
* both: original disk
|
||||||
*/
|
*/
|
||||||
if (pull || (incremental && dd->store->format >= VIR_STORAGE_FILE_BACKING)) {
|
if (pull || (dd->backupdisk->incremental &&
|
||||||
|
dd->store->format >= VIR_STORAGE_FILE_BACKING)) {
|
||||||
dd->backingStore = dd->domdisk->src;
|
dd->backingStore = dd->domdisk->src;
|
||||||
} else {
|
} else {
|
||||||
dd->backingStore = dd->terminator = virStorageSourceNew();
|
dd->backingStore = dd->terminator = virStorageSourceNew();
|
||||||
@ -375,7 +420,10 @@ qemuBackupDiskPrepareDataOne(virDomainObjPtr vm,
|
|||||||
if (qemuDomainPrepareStorageSourceBlockdev(NULL, dd->store, priv, cfg) < 0)
|
if (qemuDomainPrepareStorageSourceBlockdev(NULL, dd->store, priv, cfg) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (incremental) {
|
if (dd->backupdisk->incremental) {
|
||||||
|
if (!(incremental = qemuBackupBeginCollectIncrementalCheckpoints(vm, dd->backupdisk->incremental)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (dd->backupdisk->exportbitmap)
|
if (dd->backupdisk->exportbitmap)
|
||||||
dd->incrementalBitmap = g_strdup(dd->backupdisk->exportbitmap);
|
dd->incrementalBitmap = g_strdup(dd->backupdisk->exportbitmap);
|
||||||
else
|
else
|
||||||
@ -444,7 +492,6 @@ qemuBackupDiskPrepareDataOnePull(virJSONValuePtr actions,
|
|||||||
static ssize_t
|
static ssize_t
|
||||||
qemuBackupDiskPrepareData(virDomainObjPtr vm,
|
qemuBackupDiskPrepareData(virDomainObjPtr vm,
|
||||||
virDomainBackupDefPtr def,
|
virDomainBackupDefPtr def,
|
||||||
virDomainMomentDefPtr *incremental,
|
|
||||||
virHashTablePtr blockNamedNodeData,
|
virHashTablePtr blockNamedNodeData,
|
||||||
virJSONValuePtr actions,
|
virJSONValuePtr actions,
|
||||||
virQEMUDriverConfigPtr cfg,
|
virQEMUDriverConfigPtr cfg,
|
||||||
@ -467,8 +514,7 @@ qemuBackupDiskPrepareData(virDomainObjPtr vm,
|
|||||||
ndisks++;
|
ndisks++;
|
||||||
|
|
||||||
if (qemuBackupDiskPrepareDataOne(vm, backupdisk, dd, actions, pull,
|
if (qemuBackupDiskPrepareDataOne(vm, backupdisk, dd, actions, pull,
|
||||||
incremental, blockNamedNodeData,
|
blockNamedNodeData, cfg) < 0)
|
||||||
cfg) < 0)
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (pull) {
|
if (pull) {
|
||||||
@ -625,50 +671,6 @@ qemuBackupBeginPullExportDisks(virDomainObjPtr vm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* qemuBackupBeginCollectIncrementalCheckpoints:
|
|
||||||
* @vm: domain object
|
|
||||||
* @incrFrom: name of checkpoint representing starting point of incremental backup
|
|
||||||
*
|
|
||||||
* Returns a NULL terminated list of pointers to checkpoint definitions in
|
|
||||||
* chronological order starting from the 'current' checkpoint until reaching
|
|
||||||
* @incrFrom.
|
|
||||||
*/
|
|
||||||
static virDomainMomentDefPtr *
|
|
||||||
qemuBackupBeginCollectIncrementalCheckpoints(virDomainObjPtr vm,
|
|
||||||
const char *incrFrom)
|
|
||||||
{
|
|
||||||
virDomainMomentObjPtr n = virDomainCheckpointGetCurrent(vm->checkpoints);
|
|
||||||
g_autofree virDomainMomentDefPtr *incr = NULL;
|
|
||||||
size_t nincr = 0;
|
|
||||||
|
|
||||||
while (n) {
|
|
||||||
virDomainMomentDefPtr def = n->def;
|
|
||||||
|
|
||||||
if (VIR_APPEND_ELEMENT_COPY(incr, nincr, def) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (STREQ(def->name, incrFrom)) {
|
|
||||||
def = NULL;
|
|
||||||
if (VIR_APPEND_ELEMENT_COPY(incr, nincr, def) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return g_steal_pointer(&incr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!n->def->parent_name)
|
|
||||||
break;
|
|
||||||
|
|
||||||
n = virDomainCheckpointFindByName(vm->checkpoints, n->def->parent_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
||||||
_("could not locate checkpoint '%s' for incremental backup"),
|
|
||||||
incrFrom);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
qemuBackupJobTerminate(virDomainObjPtr vm,
|
qemuBackupJobTerminate(virDomainObjPtr vm,
|
||||||
qemuDomainJobStatus jobstatus)
|
qemuDomainJobStatus jobstatus)
|
||||||
@ -802,7 +804,6 @@ qemuBackupBegin(virDomainObjPtr vm,
|
|||||||
bool pull = false;
|
bool pull = false;
|
||||||
virDomainMomentObjPtr chk = NULL;
|
virDomainMomentObjPtr chk = NULL;
|
||||||
g_autoptr(virDomainCheckpointDef) chkdef = NULL;
|
g_autoptr(virDomainCheckpointDef) chkdef = NULL;
|
||||||
g_autofree virDomainMomentDefPtr *incremental = NULL;
|
|
||||||
g_autoptr(virJSONValue) actions = NULL;
|
g_autoptr(virJSONValue) actions = NULL;
|
||||||
struct qemuBackupDiskData *dd = NULL;
|
struct qemuBackupDiskData *dd = NULL;
|
||||||
ssize_t ndd = 0;
|
ssize_t ndd = 0;
|
||||||
@ -870,10 +871,6 @@ qemuBackupBegin(virDomainObjPtr vm,
|
|||||||
if (virDomainBackupAlignDisks(def, vm->def, suffix) < 0)
|
if (virDomainBackupAlignDisks(def, vm->def, suffix) < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
if (def->incremental &&
|
|
||||||
!(incremental = qemuBackupBeginCollectIncrementalCheckpoints(vm, def->incremental)))
|
|
||||||
goto endjob;
|
|
||||||
|
|
||||||
actions = virJSONValueNewArray();
|
actions = virJSONValueNewArray();
|
||||||
|
|
||||||
/* The 'chk' checkpoint must be rolled back if the transaction command
|
/* The 'chk' checkpoint must be rolled back if the transaction command
|
||||||
@ -887,7 +884,7 @@ qemuBackupBegin(virDomainObjPtr vm,
|
|||||||
if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_BACKUP)))
|
if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_BACKUP)))
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
if ((ndd = qemuBackupDiskPrepareData(vm, def, incremental, blockNamedNodeData,
|
if ((ndd = qemuBackupDiskPrepareData(vm, def, blockNamedNodeData,
|
||||||
actions, cfg, &dd)) <= 0) {
|
actions, cfg, &dd)) <= 0) {
|
||||||
if (ndd == 0) {
|
if (ndd == 0) {
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user