mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
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:
parent
70fe129546
commit
aa2a4cff7c
@ -1246,13 +1246,24 @@ virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
unsigned long long capacity,
|
unsigned long long capacity,
|
||||||
unsigned int flags)
|
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,
|
return virStorageBackendFilesystemResizeQemuImg(vol->target.path,
|
||||||
capacity);
|
capacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virStorageBackend virStorageBackendDirectory = {
|
virStorageBackend virStorageBackendDirectory = {
|
||||||
|
@ -1761,7 +1761,8 @@ storageVolResize(virStorageVolPtr obj,
|
|||||||
unsigned long long abs_capacity;
|
unsigned long long abs_capacity;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
virCheckFlags(VIR_STORAGE_VOL_RESIZE_DELTA, -1);
|
virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
|
||||||
|
VIR_STORAGE_VOL_RESIZE_DELTA, -1);
|
||||||
|
|
||||||
storageDriverLock(driver);
|
storageDriverLock(driver);
|
||||||
pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
|
pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
|
||||||
|
@ -45,6 +45,9 @@
|
|||||||
#include "virendian.h"
|
#include "virendian.h"
|
||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
#include "virutil.h"
|
#include "virutil.h"
|
||||||
|
#if HAVE_SYS_SYSCALL_H
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
||||||
|
|
||||||
@ -1038,19 +1041,48 @@ virStorageFileFreeMetadata(virStorageFileMetadata *meta)
|
|||||||
* Change the capacity of the raw storage file at 'path'.
|
* Change the capacity of the raw storage file at 'path'.
|
||||||
*/
|
*/
|
||||||
int
|
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 fd = -1;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
int rc;
|
||||||
|
off_t offset = orig_capacity;
|
||||||
|
off_t len = capacity - orig_capacity;
|
||||||
|
|
||||||
if ((fd = open(path, O_RDWR)) < 0) {
|
if ((fd = open(path, O_RDWR)) < 0) {
|
||||||
virReportSystemError(errno, _("Unable to open '%s'"), path);
|
virReportSystemError(errno, _("Unable to open '%s'"), path);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ftruncate(fd, capacity) < 0) {
|
if (pre_allocate) {
|
||||||
virReportSystemError(errno, _("Failed to truncate file '%s'"), path);
|
#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;
|
goto cleanup;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (ftruncate(fd, capacity) < 0) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to truncate file '%s'"), path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_CLOSE(fd) < 0) {
|
if (VIR_CLOSE(fd) < 0) {
|
||||||
|
@ -89,7 +89,10 @@ const char *virStorageFileChainLookup(virStorageFileMetadataPtr chain,
|
|||||||
|
|
||||||
void virStorageFileFreeMetadata(virStorageFileMetadataPtr meta);
|
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 {
|
enum {
|
||||||
VIR_STORAGE_FILE_SHFS_NFS = (1 << 0),
|
VIR_STORAGE_FILE_SHFS_NFS = (1 << 0),
|
||||||
|
Loading…
Reference in New Issue
Block a user