storage: Support preallocate the new capacity for vol-resize

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.
This commit is contained in:
Osier Yang 2013-05-31 13:16:14 +08:00
parent 70fe129546
commit aa2a4cff7c
4 changed files with 56 additions and 9 deletions

View 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 = {

View 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);

View 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) {

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