[libvirt] [PATCH 3/9] storage: Move most of the FS creation functions to common backend.

Cole Robinson crobinso at redhat.com
Fri Jul 10 20:47:00 UTC 2009


These will be used by other pool cloning implementations.
---
 src/storage_backend.c    |  397 ++++++++++++++++++++++++++++++++++++++++++++
 src/storage_backend.h    |   17 ++
 src/storage_backend_fs.c |  408 +---------------------------------------------
 3 files changed, 421 insertions(+), 401 deletions(-)

diff --git a/src/storage_backend.c b/src/storage_backend.c
index 953928e..59a24e1 100644
--- a/src/storage_backend.c
+++ b/src/storage_backend.c
@@ -95,6 +95,403 @@ static virStorageBackendPtr backends[] = {
     NULL
 };
 
+enum {
+    TOOL_QEMU_IMG,
+    TOOL_KVM_IMG,
+    TOOL_QCOW_CREATE,
+};
+
+int
+virStorageBackendCreateRaw(virConnectPtr conn,
+                           virStorageVolDefPtr vol,
+                           virStorageVolDefPtr inputvol)
+{
+    int fd = -1;
+    int inputfd = -1;
+    int ret = -1;
+    unsigned long long remain;
+    char *buf = NULL;
+
+    if ((fd = open(vol->target.path, O_RDWR | O_CREAT | O_EXCL,
+                   vol->target.perms.mode)) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot create path '%s'"),
+                             vol->target.path);
+        goto cleanup;
+    }
+
+    if (inputvol) {
+        if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
+            virReportSystemError(conn, errno,
+                                 _("could not open input path '%s'"),
+                                 inputvol->target.path);
+            goto cleanup;
+        }
+    }
+
+    /* Seek to the final size, so the capacity is available upfront
+     * for progress reporting */
+    if (ftruncate(fd, vol->capacity) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot extend file '%s'"),
+                             vol->target.path);
+        goto cleanup;
+    }
+
+    remain = vol->allocation;
+
+    if (inputfd != -1) {
+        int amtread = -1;
+        size_t bytes = 1024 * 1024;
+        char zerobuf[512];
+
+        bzero(&zerobuf, sizeof(zerobuf));
+
+        if (VIR_ALLOC_N(buf, bytes) < 0) {
+            virReportOOMError(conn);
+            goto cleanup;
+        }
+
+        while (amtread != 0) {
+            int amtleft;
+
+            if (remain < bytes)
+                bytes = remain;
+
+            if ((amtread = saferead(inputfd, buf, bytes)) < 0) {
+                virReportSystemError(conn, errno,
+                                     _("failed reading from file '%s'"),
+                                     inputvol->target.path);
+                goto cleanup;
+            }
+            remain -= amtread;
+
+            /* Loop over amt read in 512 byte increments, looking for sparse
+             * blocks */
+            amtleft = amtread;
+            do {
+                int interval = ((512 > amtleft) ? amtleft : 512);
+                int offset = amtread - amtleft;
+
+                if (memcmp(buf+offset, zerobuf, interval) == 0) {
+                    if (lseek(fd, interval, SEEK_CUR) < 0) {
+                        virReportSystemError(conn, errno,
+                                             _("cannot extend file '%s'"),
+                                             vol->target.path);
+                        goto cleanup;
+                    }
+                } else if (safewrite(fd, buf+offset, interval) < 0) {
+                    virReportSystemError(conn, errno,
+                                         _("failed writing to file '%s'"),
+                                         vol->target.path);
+                    goto cleanup;
+
+                }
+            } while ((amtleft -= 512) > 0);
+        }
+    }
+
+    /* Pre-allocate any data if requested */
+    /* XXX slooooooooooooooooow on non-extents-based file systems */
+    while (remain) {
+        /* Allocate in chunks of 512MiB: big-enough chunk
+         * size and takes approx. 9s on ext3. A progress
+         * update every 9s is a fair-enough trade-off
+         */
+        unsigned long long bytes = 512 * 1024 * 1024;
+        int r;
+
+        if (bytes > remain)
+            bytes = remain;
+        if ((r = safezero(fd, 0, vol->allocation - remain, bytes)) != 0) {
+            virReportSystemError(conn, r, _("cannot fill file '%s'"),
+                                 vol->target.path);
+            goto cleanup;
+        }
+        remain -= bytes;
+    }
+
+    if (close(fd) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot close file '%s'"),
+                             vol->target.path);
+        goto cleanup;
+    }
+    fd = -1;
+
+    if (inputfd != -1 && close(inputfd) < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot close file '%s'"),
+                             inputvol->target.path);
+        goto cleanup;
+    }
+    inputfd = -1;
+
+    ret = 0;
+cleanup:
+    if (fd != -1)
+        close(fd);
+    if (inputfd != -1)
+        close(inputfd);
+    VIR_FREE(buf);
+
+    return ret;
+}
+
+static int
+virStorageBackendCreateQemuImg(virConnectPtr conn,
+                               virStorageVolDefPtr vol,
+                               virStorageVolDefPtr inputvol)
+{
+    char size[100];
+    char *create_tool;
+    short use_kvmimg;
+
+    const char *type = virStorageVolFormatFileSystemTypeToString(vol->target.format);
+    const char *backingType = vol->backingStore.path ?
+        virStorageVolFormatFileSystemTypeToString(vol->backingStore.format) : NULL;
+
+    const char *inputBackingPath = (inputvol ? inputvol->backingStore.path
+                                             : NULL);
+    const char *inputPath = inputvol ? inputvol->target.path : NULL;
+    /* Treat input block devices as 'raw' format */
+    const char *inputType = inputPath ?
+                            virStorageVolFormatFileSystemTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ? VIR_STORAGE_VOL_FILE_RAW : inputvol->target.format) :
+                            NULL;
+
+    const char **imgargv;
+    const char *imgargvnormal[] = {
+        NULL, "create",
+        "-f", type,
+        vol->target.path,
+        size,
+        NULL,
+    };
+    /* Extra NULL fields are for including "backingType" when using
+     * kvm-img. It's -F backingType
+     */
+    const char *imgargvbacking[] = {
+        NULL, "create",
+        "-f", type,
+        "-b", vol->backingStore.path,
+        vol->target.path,
+        size,
+        NULL,
+        NULL,
+        NULL
+    };
+    const char *convargv[] = {
+        NULL, "convert",
+        "-f", inputType,
+        "-O", type,
+        inputPath,
+        vol->target.path,
+        NULL,
+    };
+
+    if (type == NULL) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("unknown storage vol type %d"),
+                              vol->target.format);
+        return -1;
+    }
+    if (inputvol && inputType == NULL) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("unknown storage vol type %d"),
+                              inputvol->target.format);
+        return -1;
+    }
+
+    if (vol->backingStore.path) {
+
+        /* XXX: Not strictly required: qemu-img has an option a different
+         * backing store, not really sure what use it serves though, and it
+         * may cause issues with lvm. Untested essentially.
+         */
+        if (inputvol &&
+            (!inputBackingPath ||
+             STRNEQ(inputBackingPath, vol->backingStore.path))) {
+            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                  "%s", _("a different backing store can not "
+                                          "be specified."));
+            return -1;
+        }
+
+        if (backingType == NULL) {
+            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                  _("unknown storage vol backing store type %d"),
+                                  vol->backingStore.format);
+            return -1;
+        }
+        if (access(vol->backingStore.path, R_OK) != 0) {
+            virReportSystemError(conn, errno,
+                                 _("inaccessible backing store volume %s"),
+                                 vol->backingStore.path);
+            return -1;
+        }
+    }
+
+    if ((create_tool = virFindFileInPath("kvm-img")) != NULL)
+        use_kvmimg = 1;
+    else if ((create_tool = virFindFileInPath("qemu-img")) != NULL)
+        use_kvmimg = 0;
+    else {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("unable to find kvm-img or qemu-img"));
+        return -1;
+    }
+
+    if (inputvol) {
+        convargv[0] = create_tool;
+        imgargv = convargv;
+    } else if (vol->backingStore.path) {
+        imgargvbacking[0] = create_tool;
+        if (use_kvmimg) {
+            imgargvbacking[6] = "-F";
+            imgargvbacking[7] = backingType;
+            imgargvbacking[8] = vol->target.path;
+            imgargvbacking[9] = size;
+        }
+        imgargv = imgargvbacking;
+    } else {
+        imgargvnormal[0] = create_tool;
+        imgargv = imgargvnormal;
+    }
+
+
+    /* Size in KB */
+    snprintf(size, sizeof(size), "%llu", vol->capacity/1024);
+
+    if (virRun(conn, imgargv, NULL) < 0) {
+        VIR_FREE(imgargv[0]);
+        return -1;
+    }
+
+    VIR_FREE(imgargv[0]);
+
+    return 0;
+}
+
+/*
+ * Xen removed the fully-functional qemu-img, and replaced it
+ * with a partially functional qcow-create. Go figure ??!?
+ */
+static int
+virStorageBackendCreateQcowCreate(virConnectPtr conn,
+                                  virStorageVolDefPtr vol,
+                                  virStorageVolDefPtr inputvol)
+{
+    char size[100];
+    const char *imgargv[4];
+
+    if (inputvol) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s",
+                              _("cannot copy from volume with qcow-create"));
+        return -1;
+    }
+
+    if (vol->target.format != VIR_STORAGE_VOL_FILE_QCOW2) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("unsupported storage vol type %d"),
+                              vol->target.format);
+        return -1;
+    }
+    if (vol->backingStore.path != NULL) {
+        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
+                              _("copy-on-write image not supported with "
+                              "qcow-create"));
+        return -1;
+    }
+
+    /* Size in MB - yes different units to qemu-img :-( */
+    snprintf(size, sizeof(size), "%llu", vol->capacity/1024/1024);
+
+    imgargv[0] = virFindFileInPath("qcow-create");
+    imgargv[1] = size;
+    imgargv[2] = vol->target.path;
+    imgargv[3] = NULL;
+
+    if (virRun(conn, imgargv, NULL) < 0) {
+        VIR_FREE(imgargv[0]);
+        return -1;
+    }
+
+    VIR_FREE(imgargv[0]);
+
+    return 0;
+}
+
+createFile
+virStorageBackendFSImageToolTypeToFunc(virConnectPtr conn, int tool_type)
+{
+    switch (tool_type) {
+    case TOOL_KVM_IMG:
+    case TOOL_QEMU_IMG:
+        return virStorageBackendCreateQemuImg;
+    case TOOL_QCOW_CREATE:
+        return virStorageBackendCreateQcowCreate;
+    default:
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("Unknown file create tool type '%d'."),
+                              tool_type);
+    }
+
+    return NULL;
+}
+
+int
+virStorageBackendFindFSImageTool(char **tool)
+{
+    int tool_type = -1;
+    char *tmp = NULL;
+
+    if ((tmp = virFindFileInPath("kvm-img")) != NULL) {
+        tool_type = TOOL_KVM_IMG;
+    } else if ((tmp = virFindFileInPath("qemu-img")) != NULL) {
+        tool_type = TOOL_QEMU_IMG;
+    } else if ((tmp = virFindFileInPath("qcow-create")) != NULL) {
+        tool_type = TOOL_QCOW_CREATE;
+    }
+
+    if (tool)
+        *tool = tmp;
+    else
+        VIR_FREE(tmp);
+
+    return tool_type;
+}
+
+createFile
+virStorageBackendGetBuildVolFromFunction(virConnectPtr conn,
+                                         virStorageVolDefPtr vol,
+                                         virStorageVolDefPtr inputvol)
+{
+    int tool_type;
+
+    if (!inputvol)
+        return NULL;
+
+    /* If either volume is a non-raw file vol, we need to use an external
+     * tool for converting
+     */
+    if ((vol->type == VIR_STORAGE_VOL_FILE &&
+         vol->target.format != VIR_STORAGE_VOL_FILE_RAW) ||
+        (inputvol->type == VIR_STORAGE_VOL_FILE &&
+         inputvol->target.format != VIR_STORAGE_VOL_FILE_RAW)) {
+
+        if ((tool_type = virStorageBackendFindFSImageTool(NULL)) != -1) {
+            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                  "%s", _("creation of non-raw file images is "
+                                          "not supported without qemu-img."));
+            return NULL;
+        }
+
+        return virStorageBackendFSImageToolTypeToFunc(conn, tool_type);
+    }
+
+    return virStorageBackendCreateRaw;
+}
 
 #if defined(UDEVADM) || defined(UDEVSETTLE)
 void virWaitForDevices(virConnectPtr conn)
diff --git a/src/storage_backend.h b/src/storage_backend.h
index a3f441c..ec75f41 100644
--- a/src/storage_backend.h
+++ b/src/storage_backend.h
@@ -40,6 +40,23 @@ typedef int (*virStorageBackendRefreshVol)(virConnectPtr conn, virStoragePoolObj
 typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags);
 typedef int (*virStorageBackendBuildVolFrom)(virConnectPtr conn, virStorageVolDefPtr origvol, virStorageVolDefPtr newvol, unsigned int flags);
 
+typedef int (*createFile)(virConnectPtr conn,
+                          virStorageVolDefPtr vol,
+                          virStorageVolDefPtr inputvol);
+
+/* File creation/cloning functions used for cloning between backends */
+int virStorageBackendCreateRaw(virConnectPtr conn,
+                               virStorageVolDefPtr vol,
+                               virStorageVolDefPtr inputvol);
+createFile
+virStorageBackendGetBuildVolFromFunction(virConnectPtr conn,
+                                         virStorageVolDefPtr vol,
+                                         virStorageVolDefPtr inputvol);
+int virStorageBackendFindFSImageTool(char **tool);
+createFile virStorageBackendFSImageToolTypeToFunc(virConnectPtr conn,
+                                                  int tool_type);
+
+
 
 typedef struct _virStorageBackend virStorageBackend;
 typedef virStorageBackend *virStorageBackendPtr;
diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
index c7c1c9c..3b2af59 100644
--- a/src/storage_backend_fs.c
+++ b/src/storage_backend_fs.c
@@ -55,12 +55,6 @@ enum {
     BACKING_STORE_ERROR,
 };
 
-enum {
-    TOOL_QEMU_IMG,
-    TOOL_KVM_IMG,
-    TOOL_QCOW_CREATE,
-};
-
 static int cowGetBackingStore(virConnectPtr, char **,
                               const unsigned char *, size_t);
 static int qcowXGetBackingStore(virConnectPtr, char **,
@@ -68,10 +62,6 @@ static int qcowXGetBackingStore(virConnectPtr, char **,
 static int vmdk4GetBackingStore(virConnectPtr, char **,
                                 const unsigned char *, size_t);
 
-typedef int (*createFile)(virConnectPtr conn,
-                          virStorageVolDefPtr vol,
-                          virStorageVolDefPtr inputvol);
-
 /* Either 'magic' or 'extension' *must* be provided */
 struct FileTypeInfo {
     int type;           /* One of the constants above */
@@ -1016,142 +1006,6 @@ virStorageBackendFileSystemVolCreate(virConnectPtr conn,
     return 0;
 }
 
-static int createRaw(virConnectPtr conn,
-                     virStorageVolDefPtr vol,
-                     virStorageVolDefPtr inputvol) {
-    int fd = -1;
-    int inputfd = -1;
-    int ret = -1;
-    unsigned long long remain;
-    char *buf = NULL;
-
-    if ((fd = open(vol->target.path, O_RDWR | O_CREAT | O_EXCL,
-                   vol->target.perms.mode)) < 0) {
-        virReportSystemError(conn, errno,
-                             _("cannot create path '%s'"),
-                             vol->target.path);
-        goto cleanup;
-    }
-
-    if (inputvol) {
-        if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
-            virReportSystemError(conn, errno,
-                                 _("could not open input path '%s'"),
-                                 inputvol->target.path);
-            goto cleanup;
-        }
-    }
-
-    /* Seek to the final size, so the capacity is available upfront
-     * for progress reporting */
-    if (ftruncate(fd, vol->capacity) < 0) {
-        virReportSystemError(conn, errno,
-                             _("cannot extend file '%s'"),
-                             vol->target.path);
-        goto cleanup;
-    }
-
-    remain = vol->allocation;
-
-    if (inputfd != -1) {
-        int amtread = -1;
-        size_t bytes = 1024 * 1024;
-        char zerobuf[512];
-
-        bzero(&zerobuf, sizeof(zerobuf));
-
-        if (VIR_ALLOC_N(buf, bytes) < 0) {
-            virReportOOMError(conn);
-            goto cleanup;
-        }
-
-        while (amtread != 0) {
-            int amtleft;
-
-            if (remain < bytes)
-                bytes = remain;
-
-            if ((amtread = saferead(inputfd, buf, bytes)) < 0) {
-                virReportSystemError(conn, errno,
-                                     _("failed reading from file '%s'"),
-                                     inputvol->target.path);
-                goto cleanup;
-            }
-            remain -= amtread;
-
-            /* Loop over amt read in 512 byte increments, looking for sparse
-             * blocks */
-            amtleft = amtread;
-            do {
-                int interval = ((512 > amtleft) ? amtleft : 512);
-                int offset = amtread - amtleft;
-
-                if (memcmp(buf+offset, zerobuf, interval) == 0) {
-                    if (lseek(fd, interval, SEEK_CUR) < 0) {
-                        virReportSystemError(conn, errno,
-                                             _("cannot extend file '%s'"),
-                                             vol->target.path);
-                        goto cleanup;
-                    }
-                } else if (safewrite(fd, buf+offset, interval) < 0) {
-                    virReportSystemError(conn, errno,
-                                         _("failed writing to file '%s'"),
-                                         vol->target.path);
-                    goto cleanup;
-
-                }
-            } while ((amtleft -= 512) > 0);
-        }
-    }
-
-    /* Pre-allocate any data if requested */
-    /* XXX slooooooooooooooooow on non-extents-based file systems */
-    while (remain) {
-        /* Allocate in chunks of 512MiB: big-enough chunk
-         * size and takes approx. 9s on ext3. A progress
-         * update every 9s is a fair-enough trade-off
-         */
-        unsigned long long bytes = 512 * 1024 * 1024;
-        int r;
-
-        if (bytes > remain)
-            bytes = remain;
-        if ((r = safezero(fd, 0, vol->allocation - remain, bytes)) != 0) {
-            virReportSystemError(conn, r,
-                                 _("cannot fill file '%s'"),
-                                 vol->target.path);
-            goto cleanup;
-        }
-        remain -= bytes;
-    }
-
-    if (close(fd) < 0) {
-        virReportSystemError(conn, errno,
-                             _("cannot close file '%s'"),
-                             vol->target.path);
-        goto cleanup;
-    }
-    fd = -1;
-
-    if (inputfd != -1 && close(inputfd) < 0) {
-        virReportSystemError(conn, errno,
-                             _("cannot close file '%s'"),
-                             inputvol->target.path);
-        goto cleanup;
-    }
-    inputfd = -1;
-
-    ret = 0;
-cleanup:
-    if (fd != -1)
-        close(fd);
-    if (inputfd != -1)
-        close(inputfd);
-    VIR_FREE(buf);
-
-    return ret;
-}
-
 static int createFileDir(virConnectPtr conn,
                          virStorageVolDefPtr vol,
                          virStorageVolDefPtr inputvol) {
@@ -1172,257 +1026,6 @@ static int createFileDir(virConnectPtr conn,
     return 0;
 }
 
-static int createQemuImg(virConnectPtr conn,
-                         virStorageVolDefPtr vol,
-                         virStorageVolDefPtr inputvol) {
-    char size[100];
-    char *create_tool;
-    short use_kvmimg;
-
-    const char *type = virStorageVolFormatFileSystemTypeToString(vol->target.format);
-    const char *backingType = vol->backingStore.path ?
-        virStorageVolFormatFileSystemTypeToString(vol->backingStore.format) : NULL;
-
-    const char *inputBackingPath = (inputvol ? inputvol->backingStore.path
-                                             : NULL);
-    const char *inputPath = inputvol ? inputvol->target.path : NULL;
-    /* Treat input block devices as 'raw' format */
-    const char *inputType = inputPath ?
-                            virStorageVolFormatFileSystemTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ? VIR_STORAGE_VOL_FILE_RAW : inputvol->target.format) :
-                            NULL;
-
-    const char **imgargv;
-    const char *imgargvnormal[] = {
-        NULL, "create",
-        "-f", type,
-        vol->target.path,
-        size,
-        NULL,
-    };
-    /* Extra NULL fields are for including "backingType" when using
-     * kvm-img. It's -F backingType
-     */
-    const char *imgargvbacking[] = {
-        NULL, "create",
-        "-f", type,
-        "-b", vol->backingStore.path,
-        vol->target.path,
-        size,
-        NULL,
-        NULL,
-        NULL
-    };
-    const char *convargv[] = {
-        NULL, "convert",
-        "-f", inputType,
-        "-O", type,
-        inputPath,
-        vol->target.path,
-        NULL,
-    };
-
-    if (type == NULL) {
-        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                              _("unknown storage vol type %d"),
-                              vol->target.format);
-        return -1;
-    }
-    if (inputvol && inputType == NULL) {
-        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                              _("unknown storage vol type %d"),
-                              inputvol->target.format);
-        return -1;
-    }
-
-    if (vol->backingStore.path) {
-
-        /* XXX: Not strictly required: qemu-img has an option a different
-         * backing store, not really sure what use it serves though, and it
-         * may cause issues with lvm. Untested essentially.
-         */
-        if (inputvol &&
-            (!inputBackingPath ||
-             STRNEQ(inputBackingPath, vol->backingStore.path))) {
-            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                                  "%s", _("a different backing store can not "
-                                          "be specified."));
-            return -1;
-        }
-
-        if (backingType == NULL) {
-            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                                  _("unknown storage vol backing store type %d"),
-                                  vol->backingStore.format);
-            return -1;
-        }
-        if (access(vol->backingStore.path, R_OK) != 0) {
-            virReportSystemError(conn, errno,
-                                 _("inaccessible backing store volume %s"),
-                                 vol->backingStore.path);
-            return -1;
-        }
-    }
-
-    if ((create_tool = virFindFileInPath("kvm-img")) != NULL)
-        use_kvmimg = 1;
-    else if ((create_tool = virFindFileInPath("qemu-img")) != NULL)
-        use_kvmimg = 0;
-    else {
-        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                              _("unable to find kvm-img or qemu-img"));
-        return -1;
-    }
-
-    if (inputvol) {
-        convargv[0] = create_tool;
-        imgargv = convargv;
-    } else if (vol->backingStore.path) {
-        imgargvbacking[0] = create_tool;
-        if (use_kvmimg) {
-            imgargvbacking[6] = "-F";
-            imgargvbacking[7] = backingType;
-            imgargvbacking[8] = vol->target.path;
-            imgargvbacking[9] = size;
-        }
-        imgargv = imgargvbacking;
-    } else {
-        imgargvnormal[0] = create_tool;
-        imgargv = imgargvnormal;
-    }
-
-
-    /* Size in KB */
-    snprintf(size, sizeof(size), "%llu", vol->capacity/1024);
-
-    if (virRun(conn, imgargv, NULL) < 0) {
-        VIR_FREE(imgargv[0]);
-        return -1;
-    }
-
-    VIR_FREE(imgargv[0]);
-
-    return 0;
-}
-
-/*
- * Xen removed the fully-functional qemu-img, and replaced it
- * with a partially functional qcow-create. Go figure ??!?
- */
-static int createQemuCreate(virConnectPtr conn,
-                            virStorageVolDefPtr vol,
-                            virStorageVolDefPtr inputvol) {
-    char size[100];
-    const char *imgargv[4];
-
-    if (inputvol) {
-        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                              "%s",
-                              _("cannot copy from volume with qcow-create"));
-        return -1;
-    }
-
-    if (vol->target.format != VIR_STORAGE_VOL_FILE_QCOW2) {
-        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                              _("unsupported storage vol type %d"),
-                              vol->target.format);
-        return -1;
-    }
-    if (vol->backingStore.path != NULL) {
-        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
-                              _("copy-on-write image not supported with "
-                              "qcow-create"));
-        return -1;
-    }
-
-    /* Size in MB - yes different units to qemu-img :-( */
-    snprintf(size, sizeof(size), "%llu", vol->capacity/1024/1024);
-
-    imgargv[0] = virFindFileInPath("qcow-create");
-    imgargv[1] = size;
-    imgargv[2] = vol->target.path;
-    imgargv[3] = NULL;
-
-    if (virRun(conn, imgargv, NULL) < 0) {
-        VIR_FREE(imgargv[0]);
-        return -1;
-    }
-
-    VIR_FREE(imgargv[0]);
-
-    return 0;
-}
-
-static createFile
-toolTypeToFunction(virConnectPtr conn, int tool_type)
-{
-    switch (tool_type) {
-    case TOOL_KVM_IMG:
-    case TOOL_QEMU_IMG:
-        return createQemuImg;
-    case TOOL_QCOW_CREATE:
-        return createQemuCreate;
-    default:
-        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                              _("Unknown file create tool type '%d'."),
-                              tool_type);
-    }
-
-    return NULL;
-}
-
-static int
-findImageTool(char **tool)
-{
-    int tool_type = -1;
-    char *tmp = NULL;
-
-    if ((tmp = virFindFileInPath("kvm-img")) != NULL) {
-        tool_type = TOOL_KVM_IMG;
-    } else if ((tmp = virFindFileInPath("qemu-img")) != NULL) {
-        tool_type = TOOL_QEMU_IMG;
-    } else if ((tmp = virFindFileInPath("qcow-create")) != NULL) {
-        tool_type = TOOL_QCOW_CREATE;
-    }
-
-    if (tool)
-        *tool = tmp;
-    else
-        VIR_FREE(tmp);
-
-    return tool_type;
-}
-
-static createFile
-buildVolFromFunction(virConnectPtr conn,
-                     virStorageVolDefPtr vol,
-                     virStorageVolDefPtr inputvol)
-{
-    int tool_type;
-
-    if (!inputvol)
-        return NULL;
-
-    /* If either volume is a non-raw file vol, we need to use an external
-     * tool for converting
-     */
-    if ((vol->type == VIR_STORAGE_VOL_FILE &&
-         vol->target.format != VIR_STORAGE_VOL_FILE_RAW) ||
-        (inputvol->type == VIR_STORAGE_VOL_FILE &&
-         inputvol->target.format != VIR_STORAGE_VOL_FILE_RAW)) {
-
-        if ((tool_type = findImageTool(NULL)) != -1) {
-            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                                  "%s", _("creation of non-raw file images is "
-                                          "not supported without qemu-img."));
-            return NULL;
-        }
-
-        return toolTypeToFunction(conn, tool_type);
-    }
-
-    return createRaw;
-}
-
 static int
 _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
                                      virStorageVolDefPtr vol,
@@ -1433,15 +1036,18 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
     int tool_type;
 
     if (inputvol) {
-        create_func = buildVolFromFunction(conn, vol, inputvol);
+        create_func = virStorageBackendGetBuildVolFromFunction(conn, vol,
+                                                               inputvol);
         if (!create_func)
             return -1;
     } else if (vol->target.format == VIR_STORAGE_VOL_FILE_RAW) {
-        create_func = createRaw;
+        create_func = virStorageBackendCreateRaw;
     } else if (vol->target.format == VIR_STORAGE_VOL_FILE_DIR) {
         create_func = createFileDir;
-    } else if ((tool_type = findImageTool(NULL)) != -1) {
-        if ((create_func = toolTypeToFunction(conn, tool_type)) == NULL)
+    } else if ((tool_type = virStorageBackendFindFSImageTool(NULL)) != -1) {
+        create_func = virStorageBackendFSImageToolTypeToFunc(conn, tool_type);
+
+        if (!create_func)
             return -1;
     } else {
         virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-- 
1.6.0.6




More information about the libvir-list mailing list