]> xenbits.xensource.com Git - libvirt.git/commitdiff
storage: Support preallocate the new capacity for vol-resize
authorOsier Yang <jyang@redhat.com>
Fri, 31 May 2013 05:16:14 +0000 (13:16 +0800)
committerOsier Yang <jyang@redhat.com>
Wed, 5 Jun 2013 10:35:55 +0000 (18:35 +0800)
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
src/storage/storage_driver.c
src/util/virstoragefile.c
src/util/virstoragefile.h

index 1a85afc3abc0faf85fa0acb333ca7d547b699f11..b1efa5093381cb0a98ac101809625d6b8ba53a77 100644 (file)
@@ -1246,13 +1246,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 = {
index a2b0c2125d125c345ed78f1213d5cd75d1f0fccc..e7516eb040e1a5b5760f67538bcf8ca751d006c7 100644 (file)
@@ -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);
index f0e91146dbddcd450ed733f883fdea8eb9c05a9b..bf668c89dd4750d4d9c15c07045268e75dfcbaf5 100644 (file)
@@ -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 '%s'"), 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) {
index ffe7a54039edc803006525c3ab4bb52308210b56..c195c9a270aefa983591a102f00753cd224c9a24 100644 (file)
@@ -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),