The document for "vol-resize" says the new capacity will be sparse unless "--allocate" is specified, however, the "--allocate" flag is never implemented. This implements the "--allocate" flag for fs backend's raw type volume, based on posix_fallocate and the syscall SYS_fallocate. --- src/storage/storage_backend_fs.c | 19 +++++++++++++++---- src/storage/storage_driver.c | 3 ++- src/util/virstoragefile.c | 38 +++++++++++++++++++++++++++++++++++--- src/util/virstoragefile.h | 5 ++++- 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 1379f17..78f5d53 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -1245,13 +1245,24 @@ virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long long capacity, unsigned int flags) { - virCheckFlags(0, -1); + virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE, -1); + + bool pre_allocate = flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE; + + if (vol->target.format == VIR_STORAGE_FILE_RAW) { + return virStorageFileResize(vol->target.path, capacity, + vol->capacity, pre_allocate); + } else { + if (pre_allocate) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("preallocate is only supported for raw " + "type volume")); + return -1; + } - if (vol->target.format == VIR_STORAGE_FILE_RAW) - return virStorageFileResize(vol->target.path, capacity); - else return virStorageBackendFilesystemResizeQemuImg(vol->target.path, capacity); + } } virStorageBackend virStorageBackendDirectory = { diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index a2b0c21..e7516eb 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1761,7 +1761,8 @@ storageVolResize(virStorageVolPtr obj, unsigned long long abs_capacity; int ret = -1; - virCheckFlags(VIR_STORAGE_VOL_RESIZE_DELTA, -1); + virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE | + VIR_STORAGE_VOL_RESIZE_DELTA, -1); storageDriverLock(driver); pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index f0e9114..e42eb77 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -45,6 +45,9 @@ #include "virendian.h" #include "virstring.h" #include "virutil.h" +#if HAVE_SYS_SYSCALL_H +# include <sys/syscall.h> +#endif #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -1038,19 +1041,48 @@ virStorageFileFreeMetadata(virStorageFileMetadata *meta) * Change the capacity of the raw storage file at 'path'. */ int -virStorageFileResize(const char *path, unsigned long long capacity) +virStorageFileResize(const char *path, + unsigned long long capacity, + unsigned long long orig_capacity, + bool pre_allocate) { int fd = -1; int ret = -1; + int rc; + off_t offset = orig_capacity; + off_t len = capacity - orig_capacity; if ((fd = open(path, O_RDWR)) < 0) { virReportSystemError(errno, _("Unable to open '%s'"), path); goto cleanup; } - if (ftruncate(fd, capacity) < 0) { - virReportSystemError(errno, _("Failed to truncate file '%s'"), path); + if (pre_allocate) { +#if HAVE_POSIX_FALLOCATE + if ((rc = posix_fallocate(fd, offset, len)) != 0) { + virReportSystemError(rc, + _("Failed to pre-allocate space for " + "file '%s'"), path); + goto cleanup; + } +#elif HAVE_SYS_SYSCALL_H && defined(SYS_fallocate) + if (syscall(SYS_fallocate, fd, 0, offset, len) != 0) { + virReportSystemError(errno, + _("Failed to preallocate space for " + "file 'path'"), path); + goto cleanup; + } +#else + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("preallocate is not supported on this platform")) goto cleanup; +#endif + } else { + if (ftruncate(fd, capacity) < 0) { + virReportSystemError(errno, + _("Failed to truncate file '%s'"), path); + goto cleanup; + } } if (VIR_CLOSE(fd) < 0) { diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index ffe7a54..c195c9a 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -89,7 +89,10 @@ const char *virStorageFileChainLookup(virStorageFileMetadataPtr chain, void virStorageFileFreeMetadata(virStorageFileMetadataPtr meta); -int virStorageFileResize(const char *path, unsigned long long capacity); +int virStorageFileResize(const char *path, + unsigned long long capacity, + unsigned long long orig_capacity, + bool pre_allocate); enum { VIR_STORAGE_FILE_SHFS_NFS = (1 << 0), -- 1.8.1.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list