提交 f0a5eaf3 编写于 作者: E Eric Blake

save: let qemu driver manipulate save files

The goal here is that save-image-dumpxml fed back to
save-image-define should not change the save file; anywhere that
this is not the case is probably a bug in domain_conf.c.

* src/qemu/qemu_driver.c (qemuDomainSaveImageGetXMLDesc)
(qemuDomainSaveImageDefineXML): New functions.
(qemuDomainSaveImageOpen): Add parameter.
(qemuDomainRestoreFlags, qemuDomainObjRestore): Adjust clients.
上级 0ea479f8
...@@ -3722,29 +3722,32 @@ cleanup: ...@@ -3722,29 +3722,32 @@ cleanup:
return ret; return ret;
} }
static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(6) /* Return -1 on failure, -2 if edit was specified but xmlin does not
* represent any changes, and opened fd on all other success. */
static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
qemuDomainSaveImageOpen(struct qemud_driver *driver, qemuDomainSaveImageOpen(struct qemud_driver *driver,
const char *path, const char *path,
virDomainDefPtr *ret_def, virDomainDefPtr *ret_def,
struct qemud_save_header *ret_header, struct qemud_save_header *ret_header,
bool bypass_cache, virFileDirectFdPtr *directFd, bool bypass_cache, virFileDirectFdPtr *directFd,
const char *xmlin) const char *xmlin, bool edit)
{ {
int fd; int fd;
struct qemud_save_header header; struct qemud_save_header header;
char *xml = NULL; char *xml = NULL;
virDomainDefPtr def = NULL; virDomainDefPtr def = NULL;
int directFlag = 0; int oflags = edit ? O_RDWR : O_RDONLY;
if (bypass_cache) { if (bypass_cache) {
directFlag = virFileDirectFdFlag(); int directFlag = virFileDirectFdFlag();
if (directFlag < 0) { if (directFlag < 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("bypass cache unsupported by this system")); _("bypass cache unsupported by this system"));
goto error; goto error;
} }
oflags |= directFlag;
} }
if ((fd = virFileOpenAs(path, O_RDONLY | directFlag, 0, if ((fd = virFileOpenAs(path, oflags, 0,
getuid(), getgid(), 0)) < 0) { getuid(), getgid(), 0)) < 0) {
if ((fd != -EACCES && fd != -EPERM) || if ((fd != -EACCES && fd != -EPERM) ||
driver->user == getuid()) { driver->user == getuid()) {
...@@ -3755,7 +3758,7 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver, ...@@ -3755,7 +3758,7 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver,
/* Opening as root failed, but qemu runs as a different user /* Opening as root failed, but qemu runs as a different user
* that might have better luck. */ * that might have better luck. */
if ((fd = virFileOpenAs(path, O_RDONLY | directFlag, 0, if ((fd = virFileOpenAs(path, oflags, 0,
driver->user, driver->group, driver->user, driver->group,
VIR_FILE_OPEN_AS_UID)) < 0) { VIR_FILE_OPEN_AS_UID)) < 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
...@@ -3807,6 +3810,15 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver, ...@@ -3807,6 +3810,15 @@ qemuDomainSaveImageOpen(struct qemud_driver *driver,
goto error; goto error;
} }
if (edit && STREQ(xml, xmlin)) {
VIR_FREE(xml);
if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, _("cannot close file: %s"), path);
goto error;
}
return -2;
}
/* Create a domain from this XML */ /* Create a domain from this XML */
if (!(def = virDomainDefParseString(driver->caps, xml, if (!(def = virDomainDefParseString(driver->caps, xml,
QEMU_EXPECTED_VIRT_TYPES, QEMU_EXPECTED_VIRT_TYPES,
...@@ -3965,7 +3977,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, ...@@ -3965,7 +3977,7 @@ qemuDomainRestoreFlags(virConnectPtr conn,
fd = qemuDomainSaveImageOpen(driver, path, &def, &header, fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
(flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
&directFd, dxml); &directFd, dxml, false);
if (fd < 0) if (fd < 0)
goto cleanup; goto cleanup;
...@@ -4011,6 +4023,98 @@ qemuDomainRestore(virConnectPtr conn, ...@@ -4011,6 +4023,98 @@ qemuDomainRestore(virConnectPtr conn,
return qemuDomainRestoreFlags(conn, path, NULL, 0); return qemuDomainRestoreFlags(conn, path, NULL, 0);
} }
static char *
qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
unsigned int flags)
{
struct qemud_driver *driver = conn->privateData;
char *ret = NULL;
virDomainDefPtr def = NULL;
int fd = -1;
struct qemud_save_header header;
/* We only take subset of virDomainDefFormat flags. */
virCheckFlags(VIR_DOMAIN_XML_SECURE, NULL);
qemuDriverLock(driver);
fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
NULL, false);
if (fd < 0)
goto cleanup;
ret = qemuDomainDefFormatXML(driver, def, flags);
cleanup:
virDomainDefFree(def);
VIR_FORCE_CLOSE(fd);
qemuDriverUnlock(driver);
return ret;
}
static int
qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
const char *dxml, unsigned int flags)
{
struct qemud_driver *driver = conn->privateData;
int ret = -1;
virDomainDefPtr def = NULL;
int fd = -1;
struct qemud_save_header header;
char *xml = NULL;
size_t len;
virCheckFlags(0, -1);
qemuDriverLock(driver);
fd = qemuDomainSaveImageOpen(driver, path, &def, &header, false, NULL,
dxml, true);
if (fd < 0) {
/* Check for special case of no change needed. */
if (fd == -2)
ret = 0;
goto cleanup;
}
xml = qemuDomainDefFormatXML(driver, def, (VIR_DOMAIN_XML_INACTIVE |
VIR_DOMAIN_XML_SECURE));
if (!xml)
goto cleanup;
len = strlen(xml) + 1;
if (len > header.xml_len) {
qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("new xml too large to fit in file"));
goto cleanup;
}
if (VIR_EXPAND_N(xml, len, header.xml_len - len) < 0) {
virReportOOMError();
goto cleanup;
}
if (lseek(fd, sizeof(header), SEEK_SET) != sizeof(header)) {
virReportSystemError(errno, _("cannot seek in '%s'"), path);
goto cleanup;
}
if (safewrite(fd, xml, len) != len ||
VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, _("failed to write xml to '%s'"), path);
goto cleanup;
}
ret = 0;
cleanup:
virDomainDefFree(def);
VIR_FORCE_CLOSE(fd);
VIR_FREE(xml);
qemuDriverUnlock(driver);
return ret;
}
static int static int
qemuDomainObjRestore(virConnectPtr conn, qemuDomainObjRestore(virConnectPtr conn,
struct qemud_driver *driver, struct qemud_driver *driver,
...@@ -4025,7 +4129,7 @@ qemuDomainObjRestore(virConnectPtr conn, ...@@ -4025,7 +4129,7 @@ qemuDomainObjRestore(virConnectPtr conn,
virFileDirectFdPtr directFd = NULL; virFileDirectFdPtr directFd = NULL;
fd = qemuDomainSaveImageOpen(driver, path, &def, &header, fd = qemuDomainSaveImageOpen(driver, path, &def, &header,
bypass_cache, &directFd, NULL); bypass_cache, &directFd, NULL, false);
if (fd < 0) if (fd < 0)
goto cleanup; goto cleanup;
...@@ -9298,6 +9402,8 @@ static virDriver qemuDriver = { ...@@ -9298,6 +9402,8 @@ static virDriver qemuDriver = {
.domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */ .domainSaveFlags = qemuDomainSaveFlags, /* 0.9.4 */
.domainRestore = qemuDomainRestore, /* 0.2.0 */ .domainRestore = qemuDomainRestore, /* 0.2.0 */
.domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */ .domainRestoreFlags = qemuDomainRestoreFlags, /* 0.9.4 */
.domainSaveImageGetXMLDesc = qemuDomainSaveImageGetXMLDesc, /* 0.9.4 */
.domainSaveImageDefineXML = qemuDomainSaveImageDefineXML, /* 0.9.4 */
.domainCoreDump = qemudDomainCoreDump, /* 0.7.0 */ .domainCoreDump = qemudDomainCoreDump, /* 0.7.0 */
.domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */ .domainScreenshot = qemuDomainScreenshot, /* 0.9.2 */
.domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */ .domainSetVcpus = qemuDomainSetVcpus, /* 0.4.4 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册