[libvirt] [PATCH 1/3] storage: Support preallocate the new capacity for vol-resize

Michal Privoznik mprivozn at redhat.com
Tue Jun 4 15:19:37 UTC 2013


On 31.05.2013 07:16, Osier Yang wrote:
> 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);

fails synax-check. s/path/%s/

> +            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),
> 

ACK

Michal




More information about the libvir-list mailing list