diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/commit.c | 9 | ||||
-rw-r--r-- | block/cow.c | 7 | ||||
-rw-r--r-- | block/qed.c | 6 | ||||
-rw-r--r-- | block/raw-posix.c | 25 | ||||
-rw-r--r-- | block/stream.c | 11 | ||||
-rw-r--r-- | block/vdi.c | 29 | ||||
-rw-r--r-- | block/vmdk.c | 6 | ||||
-rw-r--r-- | block/vpc.c | 29 |
8 files changed, 104 insertions, 18 deletions
diff --git a/block/commit.c b/block/commit.c index 5c09f4444e..91517d3512 100644 --- a/block/commit.c +++ b/block/commit.c @@ -37,6 +37,7 @@ typedef struct CommitBlockJob { BlockdevOnError on_error; int base_flags; int orig_overlay_flags; + char *backing_file_str; } CommitBlockJob; static int coroutine_fn commit_populate(BlockDriverState *bs, @@ -141,7 +142,7 @@ wait: if (!block_job_is_cancelled(&s->common) && sector_num == end) { /* success */ - ret = bdrv_drop_intermediate(active, top, base); + ret = bdrv_drop_intermediate(active, top, base, s->backing_file_str); } exit_free_buf: @@ -158,7 +159,7 @@ exit_restore_reopen: if (overlay_bs && s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) { bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL); } - + g_free(s->backing_file_str); block_job_completed(&s->common, ret); } @@ -182,7 +183,7 @@ static const BlockJobDriver commit_job_driver = { void commit_start(BlockDriverState *bs, BlockDriverState *base, BlockDriverState *top, int64_t speed, BlockdevOnError on_error, BlockDriverCompletionFunc *cb, - void *opaque, Error **errp) + void *opaque, const char *backing_file_str, Error **errp) { CommitBlockJob *s; BlockReopenQueue *reopen_queue = NULL; @@ -244,6 +245,8 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, s->base_flags = orig_base_flags; s->orig_overlay_flags = orig_overlay_flags; + s->backing_file_str = g_strdup(backing_file_str); + s->on_error = on_error; s->common.co = qemu_coroutine_create(commit_run); diff --git a/block/cow.c b/block/cow.c index 8f81ee6d56..6ee483327f 100644 --- a/block/cow.c +++ b/block/cow.c @@ -332,7 +332,7 @@ static int cow_create(const char *filename, QemuOpts *opts, Error **errp) char *image_filename = NULL; Error *local_err = NULL; int ret; - BlockDriverState *cow_bs; + BlockDriverState *cow_bs = NULL; /* Read out options */ image_sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512; @@ -344,7 +344,6 @@ static int cow_create(const char *filename, QemuOpts *opts, Error **errp) goto exit; } - cow_bs = NULL; ret = bdrv_open(&cow_bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err); if (ret < 0) { @@ -383,7 +382,9 @@ static int cow_create(const char *filename, QemuOpts *opts, Error **errp) exit: g_free(image_filename); - bdrv_unref(cow_bs); + if (cow_bs) { + bdrv_unref(cow_bs); + } return ret; } diff --git a/block/qed.c b/block/qed.c index eddae929eb..b69374b6a2 100644 --- a/block/qed.c +++ b/block/qed.c @@ -567,7 +567,7 @@ static void bdrv_qed_close(BlockDriverState *bs) static int qed_create(const char *filename, uint32_t cluster_size, uint64_t image_size, uint32_t table_size, const char *backing_file, const char *backing_fmt, - Error **errp) + QemuOpts *opts, Error **errp) { QEDHeader header = { .magic = QED_MAGIC, @@ -586,7 +586,7 @@ static int qed_create(const char *filename, uint32_t cluster_size, int ret = 0; BlockDriverState *bs; - ret = bdrv_create_file(filename, NULL, &local_err); + ret = bdrv_create_file(filename, opts, &local_err); if (ret < 0) { error_propagate(errp, local_err); return ret; @@ -682,7 +682,7 @@ static int bdrv_qed_create(const char *filename, QemuOpts *opts, Error **errp) } ret = qed_create(filename, cluster_size, image_size, table_size, - backing_file, backing_fmt, errp); + backing_file, backing_fmt, opts, errp); finish: g_free(backing_file); diff --git a/block/raw-posix.c b/block/raw-posix.c index dacf4fbbc8..825a0c878f 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -55,6 +55,9 @@ #include <linux/cdrom.h> #include <linux/fd.h> #include <linux/fs.h> +#ifndef FS_NOCOW_FL +#define FS_NOCOW_FL 0x00800000 /* Do not cow file */ +#endif #endif #ifdef CONFIG_FIEMAP #include <linux/fiemap.h> @@ -1278,12 +1281,14 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp) int fd; int result = 0; int64_t total_size = 0; + bool nocow = false; strstart(filename, "file:", &filename); /* Read out options */ total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE; + nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false); fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -1291,6 +1296,21 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp) result = -errno; error_setg_errno(errp, -result, "Could not create file"); } else { + 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 + } + if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) { result = -errno; error_setg_errno(errp, -result, "Could not resize file"); @@ -1477,6 +1497,11 @@ static QemuOptsList raw_create_opts = { .type = QEMU_OPT_SIZE, .help = "Virtual disk size" }, + { + .name = BLOCK_OPT_NOCOW, + .type = QEMU_OPT_BOOL, + .help = "Turn off copy-on-write (valid only on btrfs)" + }, { /* end of list */ } } }; diff --git a/block/stream.c b/block/stream.c index 043340994d..34de8ba0d9 100644 --- a/block/stream.c +++ b/block/stream.c @@ -32,7 +32,7 @@ typedef struct StreamBlockJob { RateLimit limit; BlockDriverState *base; BlockdevOnError on_error; - char backing_file_id[1024]; + char *backing_file_str; } StreamBlockJob; static int coroutine_fn stream_populate(BlockDriverState *bs, @@ -186,7 +186,7 @@ wait: if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) { const char *base_id = NULL, *base_fmt = NULL; if (base) { - base_id = s->backing_file_id; + base_id = s->backing_file_str; if (base->drv) { base_fmt = base->drv->format_name; } @@ -196,6 +196,7 @@ wait: } qemu_vfree(buf); + g_free(s->backing_file_str); block_job_completed(&s->common, ret); } @@ -217,7 +218,7 @@ static const BlockJobDriver stream_job_driver = { }; void stream_start(BlockDriverState *bs, BlockDriverState *base, - const char *base_id, int64_t speed, + const char *backing_file_str, int64_t speed, BlockdevOnError on_error, BlockDriverCompletionFunc *cb, void *opaque, Error **errp) @@ -237,9 +238,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base, } s->base = base; - if (base_id) { - pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id); - } + s->backing_file_str = g_strdup(backing_file_str); s->on_error = on_error; s->common.co = qemu_coroutine_create(stream_run); diff --git a/block/vdi.c b/block/vdi.c index 01fe22ebe8..197bd77c97 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 */ } } diff --git a/block/vmdk.c b/block/vmdk.c index d0de0193fc..27a78daa02 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1529,7 +1529,7 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs, static int vmdk_create_extent(const char *filename, int64_t filesize, bool flat, bool compress, bool zeroed_grain, - Error **errp) + QemuOpts *opts, Error **errp) { int ret, i; BlockDriverState *bs = NULL; @@ -1539,7 +1539,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, uint32_t *gd_buf = NULL; int gd_buf_size; - ret = bdrv_create_file(filename, NULL, &local_err); + ret = bdrv_create_file(filename, opts, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto exit; @@ -1845,7 +1845,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) path, desc_filename); if (vmdk_create_extent(ext_filename, size, - flat, compress, zeroed_grain, errp)) { + flat, compress, zeroed_grain, opts, errp)) { ret = -EINVAL; goto exit; } diff --git a/block/vpc.c b/block/vpc.c index 798d8540db..8b376a40be 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -29,6 +29,13 @@ #if defined(CONFIG_UUID) #include <uuid/uuid.h> #endif +#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 /**************************************************************/ @@ -751,6 +758,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) int64_t total_size; int disk_type; int ret = -EIO; + bool nocow = false; /* Read out options */ total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); @@ -767,6 +775,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) } else { disk_type = VHD_DYNAMIC; } + nocow = qemu_opt_get_bool_del(opts, BLOCK_OPT_NOCOW, false); /* Create the file */ fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); @@ -775,6 +784,21 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) goto out; } + 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 + } + /* * Calculate matching total_size and geometry. Increase the number of * sectors requested until we get enough (or fail). This ensures that @@ -884,6 +908,11 @@ static QemuOptsList vpc_create_opts = { "Type of virtual hard disk format. Supported formats are " "{dynamic (default) | fixed} " }, + { + .name = BLOCK_OPT_NOCOW, + .type = QEMU_OPT_BOOL, + .help = "Turn off copy-on-write (valid only on btrfs)" + }, { /* end of list */ } } }; |