[libvirt] [PATCHv8 09/11] blockjob: allow for existing files in block-copy

Eric Blake eblake at redhat.com
Sat Oct 20 21:47:18 UTC 2012


Support the REUSE_EXT flag, in part by copying sanity checks from
snapshot code.  This code introduces a case of probing an external
file for its type; such an action would be a security risk if the
existing file is supposed to be raw but the contents resemble some
other format; however, since the virDomainBlockRebase API has a
flag to force treating the file as raw rather than probe, we can
assume that probing is safe in all other instances.

* src/qemu/qemu_driver.c (qemuDomainBlockRebase): Allow REUSE_EXT
flag.
(qemuDomainBlockCopy): Wire up flag, and add some sanity checks.
---

v8: use backing chain for better analysis of external file

 src/qemu/qemu_driver.c | 40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bcbece2..13cba61 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12860,9 +12860,11 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
     int ret = -1;
     int idx;
     bool reopen;
+    struct stat st;

     /* Preliminaries: find the disk we are editing, sanity checks */
-    virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW, -1);
+    virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
+                  VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1);

     if (!(vm = qemuDomObjFromDomain(dom)))
         goto cleanup;
@@ -12925,12 +12927,39 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
     }

     /* Prepare the destination file.  */
+    if (stat(dest, &st) < 0) {
+        if (errno != ENOENT) {
+            virReportSystemError(errno, _("unable to stat for disk %s: %s"),
+                                 disk->dst, dest);
+            goto endjob;
+        } else if (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) {
+            virReportSystemError(errno,
+                                 _("missing destination file for disk %s: %s"),
+                                 disk->dst, dest);
+            goto endjob;
+        }
+    } else if (!S_ISBLK(st.st_mode) && st.st_size &&
+               !(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("external destination file for disk %s already "
+                         "exists and is not a block device: %s"),
+                       disk->dst, dest);
+        goto endjob;
+    }
+
     /* XXX We also need to add security labeling, lock manager lease,
-     * and auditing of those events, as well as to support reuse of
-     * existing images, including probing the existing format of an
-     * existing image.  */
+     * and auditing of those events.  */
     if (!format) {
-        disk->mirrorFormat = disk->format;
+        if (flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) {
+            /* If the user passed the REUSE_EXT flag, then either they
+             * also passed the RAW flag (and format is non-NULL), or
+             * it is safe for us to probe the format from the file
+             * that we will be using.  */
+            disk->mirrorFormat = virStorageFileProbeFormat(dest, driver->user,
+                                                           driver->group);
+        } else {
+            disk->mirrorFormat = disk->format;
+        }
         if (disk->mirrorFormat > 0)
             format = virStorageFileFormatTypeToString(disk->mirrorFormat);
     } else {
@@ -12975,6 +13004,7 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
                       unsigned long bandwidth, unsigned int flags)
 {
     virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
+                  VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
                   VIR_DOMAIN_BLOCK_REBASE_COPY |
                   VIR_DOMAIN_BLOCK_REBASE_COPY_RAW, -1);

-- 
1.7.11.7




More information about the libvir-list mailing list