
At 2016-12-08 20:08:11, "Peter Krempa" <pkrempa@redhat.com> wrote:
On Sat, Dec 03, 2016 at 17:45:47 +0800, Chen Hanxiao wrote:
From: Chen Hanxiao <chenhanxiao@gmail.com>
Base upon patches from Roy Keene <rkeene@knightpoint.com>
Currently qemuDomainSaveMemory can save vm's config and memory to fd. It writes a magic QEMU_SAVE_PARTIAL firstly, then re-open it to change QEMU_SAVE_PARTIAL as QEMU_SAVE_MAGIC after a success write.
For pipes this is not possible, attempting to re-open the pipe will not connect you to the same consumer. Seeking is also not possible on a pipe.
This patch introduce VIR_DOMAIN_SAVE_PIPE. If set, write QEMU_SAVE_MAGIC directly. Try to write a regular file with VIR_DOMAIN_SAVE_PIPE is not supportted.
This is useful to me for saving a VM state directly to Ceph RBD images without having an intermediate file.
Cc: Roy Keene <rkeene@knightpoint.com> Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- include/libvirt/libvirt-domain.h | 1 + src/qemu/qemu_driver.c | 71 ++++++++++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index a8435ab..c3e4c15 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1169,6 +1169,7 @@ typedef enum { VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution */ VIR_DOMAIN_SAVE_RUNNING = 1 << 1, /* Favor running over paused */ VIR_DOMAIN_SAVE_PAUSED = 1 << 2, /* Favor paused over running */ + VIR_DOMAIN_SAVE_PIPE = 1 << 3, /* Output is a pipe */
It doesn't have necessarily to be a pipe.
We need a flag to specify that we need to write QEMU_SAVE_MAGIC directly. Any suggestion for the name of this flag?
} virDomainSaveRestoreFlags;
int virDomainSave (virDomainPtr domain,
[snip]
+ + /* + * Determine if this file is a PIPE, which could not be reopen. + */ + if (virFileExists(path)) { + fd = qemuOpenFile(driver, vm, path, O_RDONLY | O_NONBLOCK, NULL, NULL); + if (fd < 0) + goto cleanup; + if (fstat(fd, &statbuf) < 0) + goto cleanup; + if (S_ISFIFO(statbuf.st_mode)) {
You should not try to check this. If the user wishes to write the complete header right away, then we should obey it and not have to check prior to do so.
My concern is that when we write to a pipe/fifo, if no one read it, we will hang. We should prevent from doing this only when we specify a flag. Regards, - Chen
+ if (flags & VIR_DOMAIN_SAVE_PIPE) { + canReopen = false; + } else { + virReportSystemError(EINVAL, _("%s is not PIPE"), path); + goto cleanup; + } + } + VIR_FORCE_CLOSE(fd); + } + fd = qemuOpenFile(driver, vm, path, O_WRONLY | O_TRUNC | O_CREAT | directFlag, &needUnlink, &bypassSecurityDriver);