storage: Move most of the FS creation functions to common backend.

These will be used by other pool cloning implementations.
This commit is contained in:
Cole Robinson 2009-07-16 12:09:26 -04:00
parent 1b16bf4ec7
commit 6d7d465a04
3 changed files with 436 additions and 418 deletions

View File

@ -95,6 +95,419 @@ static virStorageBackendPtr backends[] = {
NULL
};
static int track_allocation_progress = 0;
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);
}
}
if (remain) {
if (track_allocation_progress) {
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;
}
} else { /* No progress bars to be shown */
int r;
if ((r = safezero(fd, 0, 0, remain)) != 0) {
virReportSystemError(conn, r,
_("cannot fill file '%s'"),
vol->target.path);
goto cleanup;
}
}
}
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)

View File

@ -40,6 +40,22 @@ 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;

View File

@ -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,12 +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);
static int track_allocation_progress = 0;
/* Either 'magic' or 'extension' *must* be provided */
struct FileTypeInfo {
int type; /* One of the constants above */
@ -1018,157 +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 */
if (remain) {
if (track_allocation_progress) {
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;
}
} else { /* No progress bars to be shown */
int r;
if ((r = safezero(fd, 0, 0, remain)) != 0) {
virReportSystemError(conn, r,
_("cannot fill file '%s'"),
vol->target.path);
goto cleanup;
}
}
}
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) {
@ -1189,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,
@ -1450,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,