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