With this, it is now possible to create external snapshots even
when SELinux is enforcing, and to protect the new file with a
lock manager.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive): Create and register
new file with proper permissions and locks.
(qemuDomainSnapshotCreateDiskActive): Update caller.
---
I ran out of time to thoroughly test this today, but wanted to at least
get it posted. Once I test it, I'll post the v3 of my series.
Oh, and it looks like I don't have any way to conditionally unlink()
a just-created file; maybe I should revisit 42/26 to pass yet another
bool * parameter that gets updated based on whether a file was created
vs. a block device reused.
src/qemu/qemu_driver.c | 41 ++++++++++++++++++++++++++++++++++++++---
1 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c11f08e..cba5929 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -87,6 +87,7 @@
#include "configmake.h"
#include "threadpool.h"
#include "locking/lock_manager.h"
+#include "locking/domain_lock.h"
#include "virkeycode.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -8808,7 +8809,8 @@ cleanup:
/* The domain is expected to hold monitor lock. */
static int
-qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm,
+qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver,
+ virDomainObjPtr vm,
virDomainSnapshotDiskDefPtr snap,
virDomainDiskDefPtr disk)
{
@@ -8817,6 +8819,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm,
char *source = NULL;
char *driverType = NULL;
int ret = -1;
+ int fd = -1;
+ char *origsrc = NULL;
+ char *origdriver = NULL;
if (snap->snapshot != VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL) {
VIR_ERROR("unexpected code path");
@@ -8831,7 +8836,33 @@ qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm,
goto cleanup;
}
- /* XXX create new file and set selinux labels */
+ /* create the stub file and set selinux labels; manipulate disk in
+ * place, in a way that can be reverted on failure. */
+ fd = qemuOpenFile(driver, source, NULL, NULL, false);
+ if (fd < 0)
+ goto cleanup;
+ VIR_FORCE_CLOSE(fd);
+
+ origsrc = disk->src;
+ disk->src = source;
+ origdriver = disk->driverType;
+ disk->driverType = driverType;
+
+ if (virDomainLockDiskAttach(driver->lockManager, vm, disk) < 0)
+ goto cleanup;
+ if (virSecurityManagerSetImageLabel(driver->securityManager, vm,
+ disk) < 0) {
+ if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
+ VIR_WARN("Unable to release lock on %s", source);
+ goto cleanup;
+ }
+
+ disk->src = origsrc;
+ origsrc = NULL;
+ disk->driverType = driverType;
+ origdriver = NULL;
+
+ /* create the actual snapshot */
ret = qemuMonitorDiskSnapshot(priv->mon, device, source);
virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0);
if (ret < 0)
@@ -8851,6 +8882,10 @@ qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm,
* configuration changes awaiting the next boot? */
cleanup:
+ if (origsrc) {
+ disk->src = origsrc;
+ disk->driverType = driverType;
+ }
VIR_FREE(device);
VIR_FREE(source);
VIR_FREE(driverType);
@@ -8902,7 +8937,7 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
if (snap->def->disks[i].snapshot == VIR_DOMAIN_DISK_SNAPSHOT_NO)
continue;
- ret = qemuDomainSnapshotCreateSingleDiskActive(vm,
+ ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
&snap->def->disks[i],
vm->def->disks[i]);
if (ret < 0)
--
1.7.4.4