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

Osier Yang jyang at redhat.com
Fri May 31 05:16:14 UTC 2013


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




More information about the libvir-list mailing list