mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-04 21:47:16 +03:00
storage: cache backing chain while qemu domain is live
Technically, we should not be re-probing any file that qemu might be currently writing to. As such, we should cache the backing file chain prior to starting qemu. This patch adds the cache, but does not use it until the next patch. Ultimately, we want to also store the chain in domain XML, so that it is remembered across libvirtd restarts, and so that the only kosher way to modify the backing chain of an offline domain will be through libvirt API calls, but we aren't there yet. So for now, we merely invalidate the cache any time we do a live operation that alters the chain (block-pull, block-commit, external disk snapshot), as well as tear down the cache when the domain is not running. * src/conf/domain_conf.h (_virDomainDiskDef): New field. * src/conf/domain_conf.c (virDomainDiskDefFree): Clean new field. * src/qemu/qemu_domain.h (qemuDomainDetermineDiskChain): New prototype. * src/qemu/qemu_domain.c (qemuDomainDetermineDiskChain): New function. * src/qemu/qemu_driver.c (qemuDomainAttachDeviceDiskLive) (qemuDomainChangeDiskMediaLive): Pre-populate chain. (qemuDomainSnapshotCreateSingleDiskActive): Uncache chain before snapshot. * src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Update chain after block pull.
This commit is contained in:
parent
5eaf605447
commit
4d34c92947
@ -975,6 +975,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
|
||||
VIR_FREE(def->src);
|
||||
VIR_FREE(def->dst);
|
||||
VIR_FREE(def->driverName);
|
||||
virStorageFileFreeMetadata(def->backingChain);
|
||||
VIR_FREE(def->mirror);
|
||||
VIR_FREE(def->auth.username);
|
||||
VIR_FREE(def->wwn);
|
||||
|
@ -47,6 +47,7 @@
|
||||
# include "virobject.h"
|
||||
# include "device_conf.h"
|
||||
# include "bitmap.h"
|
||||
# include "storage_file.h"
|
||||
|
||||
/* forward declarations of all device types, required by
|
||||
* virDomainDeviceDef
|
||||
@ -568,6 +569,7 @@ struct _virDomainDiskDef {
|
||||
} auth;
|
||||
char *driverName;
|
||||
int format; /* enum virStorageFileFormat */
|
||||
virStorageFileMetadataPtr backingChain;
|
||||
|
||||
char *mirror;
|
||||
int mirrorFormat; /* enum virStorageFileFormat */
|
||||
|
@ -2012,3 +2012,29 @@ qemuDomainCleanupRun(struct qemud_driver *driver,
|
||||
priv->ncleanupCallbacks = 0;
|
||||
priv->ncleanupCallbacks_max = 0;
|
||||
}
|
||||
|
||||
int
|
||||
qemuDomainDetermineDiskChain(struct qemud_driver *driver,
|
||||
virDomainDiskDefPtr disk,
|
||||
bool force)
|
||||
{
|
||||
bool probe = driver->allowDiskFormatProbing;
|
||||
|
||||
if (!disk->src)
|
||||
return 0;
|
||||
|
||||
if (disk->backingChain) {
|
||||
if (force) {
|
||||
virStorageFileFreeMetadata(disk->backingChain);
|
||||
disk->backingChain = NULL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
disk->backingChain = virStorageFileGetMetadata(disk->src, disk->format,
|
||||
driver->user, driver->group,
|
||||
probe);
|
||||
if (!disk->backingChain)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -343,6 +343,9 @@ bool qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv,
|
||||
int qemuDomainCheckDiskPresence(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
bool start_with_state);
|
||||
int qemuDomainDetermineDiskChain(struct qemud_driver *driver,
|
||||
virDomainDiskDefPtr disk,
|
||||
bool force);
|
||||
|
||||
int qemuDomainCleanupAdd(virDomainObjPtr vm,
|
||||
qemuDomainCleanupCallback cb);
|
||||
|
@ -5816,6 +5816,9 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
|
||||
goto end;
|
||||
|
||||
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
|
||||
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
@ -6044,6 +6047,9 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
|
||||
virCgroupPtr cgroup = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
|
||||
goto end;
|
||||
|
||||
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
|
||||
if (virCgroupForDomain(driver->cgroup,
|
||||
vm->def->name, &cgroup, 0) != 0) {
|
||||
@ -10789,6 +10795,14 @@ qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver,
|
||||
disk->src = source;
|
||||
origdriver = disk->format;
|
||||
disk->format = VIR_STORAGE_FILE_RAW; /* Don't want to probe backing files */
|
||||
/* XXX Here, we know we are about to alter disk->backingChain if
|
||||
* successful, so we nuke the existing chain so that future
|
||||
* commands will recompute it. Better would be storing the chain
|
||||
* ourselves rather than reprobing, but this requires modifying
|
||||
* domain_conf and our XML to fully track the chain across
|
||||
* libvirtd restarts. */
|
||||
virStorageFileFreeMetadata(disk->backingChain);
|
||||
disk->backingChain = NULL;
|
||||
|
||||
if (virDomainLockDiskAttach(driver->lockManager, driver->uri,
|
||||
vm, disk) < 0)
|
||||
|
@ -909,6 +909,14 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
if (disk) {
|
||||
path = disk->src;
|
||||
event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
|
||||
/* XXX If we completed a block pull, then recompute the cached
|
||||
* backing chain to match. Better would be storing the chain
|
||||
* ourselves rather than reprobing, but this requires
|
||||
* modifying domain_conf and our XML to fully track the chain
|
||||
* across libvirtd restarts. */
|
||||
if (type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL &&
|
||||
status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
|
||||
qemuDomainDetermineDiskChain(driver, disk, true);
|
||||
}
|
||||
|
||||
virDomainObjUnlock(vm);
|
||||
|
Loading…
x
Reference in New Issue
Block a user