bool hook_taint = false;
bool reset_nvram = false;
bool sparse = false;
+ bool bypass_cache = (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0;
g_autoptr(qemuMigrationParams) restoreParams = NULL;
virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
(flags & VIR_DOMAIN_SAVE_BYPASS_CACHE))))
goto cleanup;
- fd = qemuSaveImageOpen(driver, path,
- (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
- sparse, &wrapperFd, false);
- if (fd < 0)
- goto cleanup;
+ if (sparse) {
+ if ((fd = qemuSaveImageOpen(driver, path, bypass_cache, NULL, false)) < 0)
+ goto cleanup;
+
+ /* In sparse mode the FD needs to be a real file as qemu accesses it
+ * directly thus:
+ * - ensure that we actualy got a file FD
+ * - there's no need to seek it as qemu does it itself
+ */
+ if (!virFileFDIsRegular(fd)) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("path '%1$s' can't be opened directly (without the use of helper proces) which is incompatible with 'sparse' save image"),
+ path);
+ goto cleanup;
+ }
+ } else {
+ if ((fd = qemuSaveImageOpen(driver, path, bypass_cache, &wrapperFd, false)) < 0)
+ goto cleanup;
+
+ /* When virFileWrapperFD is used 'fd' can't be seeked so to make it
+ * point to the data read the header */
+ if (qemuSaveImageFDSkipHeader(fd) < 0)
+ goto cleanup;
+ }
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
int hookret;
conn, &def, &data) < 0)
goto cleanup;
- fd = qemuSaveImageOpen(driver, path, false, false, NULL, true);
+ fd = qemuSaveImageOpen(driver, path, false, NULL, true);
if (fd < 0)
goto cleanup;
}
+int
+qemuSaveImageFDSkipHeader(int fd)
+{
+ return qemuSaveImageReadHeader(fd, NULL);
+}
+
+
/**
* qemuSaveImageDecompressionStart:
* @data: data from memory state file
* @driver: qemu driver data
* @path: path of the save image
* @bypass_cache: bypass cache when opening the file
- * @sparse: Image contains mapped-ram save format
* @wrapperFd: returns the file wrapper structure
* @open_write: open the file for writing (for updates)
*
qemuSaveImageOpen(virQEMUDriver *driver,
const char *path,
bool bypass_cache,
- bool sparse,
virFileWrapperFd **wrapperFd,
bool open_write)
{
if ((fd = qemuDomainOpenFile(cfg, NULL, path, oflags, NULL)) < 0)
return -1;
- /* If sparse, no need for the iohelper or positioning the file pointer. */
- if (!sparse) {
- if (bypass_cache &&
- !(*wrapperFd = virFileWrapperFdNew(&fd, path,
- VIR_FILE_WRAPPER_BYPASS_CACHE)))
- return -1;
+ if (wrapperFd) {
+ unsigned int fdflags = VIR_FILE_WRAPPER_NON_BLOCKING;
+
+ if (bypass_cache)
+ fdflags |= VIR_FILE_WRAPPER_BYPASS_CACHE;
- /* Read the header to position the file pointer for QEMU. Unfortunately we
- * can't use lseek with virFileWrapperFD. */
- if (qemuSaveImageReadHeader(fd, NULL) < 0)
+ if (!(*wrapperFd = virFileWrapperFdNew(&fd, path, fdflags)))
return -1;
}
qemuSaveImageOpen(virQEMUDriver *driver,
const char *path,
bool bypass_cache,
- bool sparse,
virFileWrapperFd **wrapperFd,
bool open_write)
ATTRIBUTE_NONNULL(2);
unsigned int flags,
virDomainAsyncJob asyncJob);
+int
+qemuSaveImageFDSkipHeader(int fd);
+
int
virQEMUSaveDataWrite(virQEMUSaveData *data,
int fd,
typedef struct _qemuSnapshotRevertMemoryData {
int fd;
char *path;
+ virFileWrapperFd *wrapperFd;
virQEMUSaveData *data;
} qemuSnapshotRevertMemoryData;
qemuSnapshotClearRevertMemoryData(qemuSnapshotRevertMemoryData *memdata)
{
VIR_FORCE_CLOSE(memdata->fd);
+ ignore_value(virFileWrapperFdClose(memdata->wrapperFd));
+ virFileWrapperFdFree(memdata->wrapperFd);
virQEMUSaveDataFree(memdata->data);
}
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(qemuSnapshotRevertMemoryData, qemuSnapshotClearRevertMemoryData);
return -1;
memdata->fd = qemuSaveImageOpen(driver, memdata->path,
- false, false, NULL, false);
+ false, &memdata->wrapperFd, false);
if (memdata->fd < 0)
return -1;
+ /* If 'wrapperFd' is used the FD can't be seeked so we need to make
+ * it point to the actual data, thus seek across the header */
+ if (qemuSaveImageFDSkipHeader(memdata->fd) < 0)
+ return -1;
+
if (!virDomainDefCheckABIStability(savedef, domdef, driver->xmlopt))
return -1;
}
bool defined = false;
int rc;
g_autoptr(virDomainSnapshotDef) tmpsnapdef = NULL;
- g_auto(qemuSnapshotRevertMemoryData) memdata = { -1, NULL, NULL };
+ g_auto(qemuSnapshotRevertMemoryData) memdata = { .fd = -1 };
bool started = false;
start_flags |= VIR_QEMU_PROCESS_START_PAUSED;