diff options
author | Chunyan Liu <cyliu@suse.com> | 2014-06-30 14:29:58 +0800 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2014-07-01 10:15:12 +0200 |
commit | 4ab1559085d688dddf4de77f1ead3102e243e668 (patch) | |
tree | c02aaa834a94aace2ef773462cea3b4829cc48a9 /block/vdi.c | |
parent | 8698e110f8aa1cdf8ba1afdda8f2658333a4ab01 (diff) | |
download | qemu-4ab1559085d688dddf4de77f1ead3102e243e668.zip qemu-4ab1559085d688dddf4de77f1ead3102e243e668.tar.gz qemu-4ab1559085d688dddf4de77f1ead3102e243e668.tar.bz2 |
qemu-img create: add 'nocow' option
Add 'nocow' option so that users could have a chance to set NOCOW flag to
newly created files. It's useful on btrfs file system to enhance performance.
Btrfs has low performance when hosting VM images, even more when the guest
in those VM are also using btrfs as file system. One way to mitigate this bad
performance is to turn off COW attributes on VM files. Generally, there are
two ways to turn off NOCOW on btrfs: a) by mounting fs with nodatacow, then
all newly created files will be NOCOW. b) per file. Add the NOCOW file
attribute. It could only be done to empty or new files.
This patch tries the second way, according to the option, it could add NOCOW
per file.
For most block drivers, since the create file step is in raw-posix.c, so we
can do setting NOCOW flag ioctl in raw-posix.c only.
But there are some exceptions, like block/vpc.c and block/vdi.c, they are
creating file by calling qemu_open directly. For them, do the same setting
NOCOW flag ioctl work in them separately.
[Fixed up 082.out due to the new 'nocow' creation option
--Stefan]
Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/vdi.c')
-rw-r--r-- | block/vdi.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/block/vdi.c b/block/vdi.c index 01fe22e..197bd77 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -53,6 +53,13 @@ #include "block/block_int.h" #include "qemu/module.h" #include "migration/migration.h" +#ifdef __linux__ +#include <linux/fs.h> +#include <sys/ioctl.h> +#ifndef FS_NOCOW_FL +#define FS_NOCOW_FL 0x00800000 /* Do not cow file */ +#endif +#endif #if defined(CONFIG_UUID) #include <uuid/uuid.h> @@ -683,6 +690,7 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp) VdiHeader header; size_t i; size_t bmap_size; + bool nocow = false; logout("\n"); @@ -699,6 +707,7 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp) image_type = VDI_TYPE_STATIC; } #endif + nocow = qemu_opt_get_bool_del(opts, BLOCK_OPT_NOCOW, false); if (bytes > VDI_DISK_SIZE_MAX) { result = -ENOTSUP; @@ -716,6 +725,21 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp) goto exit; } + if (nocow) { +#ifdef __linux__ + /* Set NOCOW flag to solve performance issue on fs like btrfs. + * This is an optimisation. The FS_IOC_SETFLAGS ioctl return value will + * be ignored since any failure of this operation should not block the + * left work. + */ + int attr; + if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0) { + attr |= FS_NOCOW_FL; + ioctl(fd, FS_IOC_SETFLAGS, &attr); + } +#endif + } + /* We need enough blocks to store the given disk size, so always round up. */ blocks = (bytes + block_size - 1) / block_size; @@ -818,6 +842,11 @@ static QemuOptsList vdi_create_opts = { .def_value_str = "off" }, #endif + { + .name = BLOCK_OPT_NOCOW, + .type = QEMU_OPT_BOOL, + .help = "Turn off copy-on-write (valid only on btrfs)" + }, /* TODO: An additional option to set UUID values might be useful. */ { /* end of list */ } } |