The CreateRaw function has some 'file' only assumptions, so break the agnostic cloning bits to a separate function. --- src/storage_backend.c | 160 ++++++++++++++++++++++++++++--------------------- 1 files changed, 92 insertions(+), 68 deletions(-) diff --git a/src/storage_backend.c b/src/storage_backend.c index aea6105..868c297 100644 --- a/src/storage_backend.c +++ b/src/storage_backend.c @@ -101,6 +101,95 @@ enum { TOOL_QCOW_CREATE, }; +static int +virStorageBackendCopyToFD(virConnectPtr conn, + virStorageVolDefPtr vol, + virStorageVolDefPtr inputvol, + int fd, + unsigned long long *total) +{ + int inputfd = -1; + int amtread = -1; + int ret = -1; + unsigned long long remain; + size_t bytes = 1024 * 1024; + char zerobuf[512]; + char *buf = NULL; + + 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; + } + } + + bzero(&zerobuf, sizeof(zerobuf)); + + if (VIR_ALLOC_N(buf, bytes) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + remain = *total; + + 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 (inputfd != -1 && close(inputfd) < 0) { + virReportSystemError(conn, errno, + _("cannot close file '%s'"), + inputvol->target.path); + goto cleanup; + } + inputfd = -1; + + *total -= remain; + ret = 0; + +cleanup: + if (inputfd != -1) + close(inputfd); + + return ret; +} + int virStorageBackendCreateRaw(virConnectPtr conn, virStorageVolDefPtr vol, @@ -108,7 +197,6 @@ virStorageBackendCreateRaw(virConnectPtr conn, unsigned int flags ATTRIBUTE_UNUSED) { int fd = -1; - int inputfd = -1; int ret = -1; unsigned long long remain; char *buf = NULL; @@ -121,15 +209,6 @@ virStorageBackendCreateRaw(virConnectPtr conn, 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) { @@ -141,55 +220,10 @@ virStorageBackendCreateRaw(virConnectPtr conn, 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); + if (inputvol) { + int res = virStorageBackendCopyToFD(conn, vol, inputvol, fd, &remain); + if (res < 0) 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 */ @@ -220,20 +254,10 @@ virStorageBackendCreateRaw(virConnectPtr conn, } 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; -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list