1
The following changes since commit 98bfaac788be0ca63d7d010c8d4ba100ff1d8278:
1
The following changes since commit b2f7a038bb4c4fc5ce6b8486e8513dfd97665e2a:
2
2
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2017-09-01-v3' into staging (2017-09-04 13:28:09 +0100)
3
Merge remote-tracking branch 'remotes/rth/tags/pull-softfloat-20181104' into staging (2018-11-05 10:32:49 +0000)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 83a8c775a8bf134eb18a719322939b74a818d750:
9
for you to fetch changes up to 1240ac558d348f6c7a5752b1a57c1da58e4efe3e:
10
10
11
qcow2: move qcow2_store_persistent_dirty_bitmaps() before cache flushing (2017-09-06 14:40:18 +0200)
11
include: Add a comment to explain the origin of sizes' lookup table (2018-11-05 15:29:59 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches:
15
16
- auto-read-only option to fix commit job when used with -blockdev
17
- Fix help text related qemu-iotests failure (by improving the help text
18
and updating the reference output)
19
- quorum: Add missing checks when adding/removing child nodes
20
- Don't take address of fields in packed structs
21
- vvfat: Fix crash when reporting error about too many files in directory
15
22
16
----------------------------------------------------------------
23
----------------------------------------------------------------
17
Daniel P. Berrange (1):
24
Alberto Garcia (7):
18
block: document semantics of bdrv_co_preadv|pwritev
25
block: replace "discard" literal with BDRV_OPT_DISCARD macro
26
qcow2: Get the request alignment for encrypted images from QCryptoBlock
27
quorum: Remove quorum_err()
28
quorum: Return an error if the blkverify mode has invalid settings
29
iotest: Test the blkverify mode of the Quorum driver
30
quorum: Forbid adding children in blkverify mode
31
iotest: Test x-blockdev-change on a Quorum
19
32
20
Eric Blake (2):
33
Cleber Rosa (1):
21
qcow: Change signature of get_cluster_offset()
34
iotests: make 083 specific to raw
22
qcow: Check failure of bdrv_getlength() and bdrv_truncate()
23
35
24
Manos Pitsidianakis (10):
36
Daniel P. Berrangé (1):
25
block: pass bdrv_* methods to bs->file by default in block filters
37
crypto: initialize sector size even when opening with no IO flag
26
block: remove unused bdrv_media_changed
27
block: remove bdrv_truncate callback in blkdebug
28
block: add default implementations for bdrv_co_get_block_status()
29
block: move ThrottleGroup membership to ThrottleGroupMember
30
block: add aio_context field in ThrottleGroupMember
31
block: tidy ThrottleGroupMember initializations
32
block: convert ThrottleGroup to object with QOM
33
block: add throttle block filter driver
34
qemu-iotests: add 184 for throttle filter driver
35
38
36
Pavel Butsykin (1):
39
Kevin Wolf (12):
37
qcow2: move qcow2_store_persistent_dirty_bitmaps() before cache flushing
40
vpc: Don't leak opts in vpc_open()
41
block: Update flags in bdrv_set_read_only()
42
block: Add auto-read-only option
43
rbd: Close image in qemu_rbd_open() error path
44
block: Require auto-read-only for existing fallbacks
45
nbd: Support auto-read-only option
46
file-posix: Support auto-read-only option
47
curl: Support auto-read-only option
48
gluster: Support auto-read-only option
49
iscsi: Support auto-read-only option
50
block: Make auto-read-only=on default for -drive
51
qemu-iotests: Test auto-read-only with -drive and -blockdev
38
52
39
qapi/block-core.json | 66 +++-
53
Leonid Bloch (2):
40
include/block/block.h | 1 -
54
vdi: Use a literal number of bytes for DEFAULT_CLUSTER_SIZE
41
include/block/block_int.h | 56 ++-
55
include: Add a comment to explain the origin of sizes' lookup table
42
include/block/throttle-groups.h | 52 ++-
43
include/qemu/throttle-options.h | 60 +++-
44
include/qemu/throttle.h | 3 +
45
include/sysemu/block-backend.h | 20 +-
46
block.c | 35 +-
47
block/blkdebug.c | 20 +-
48
block/block-backend.c | 62 ++--
49
block/commit.c | 12 +-
50
block/io.c | 26 ++
51
block/mirror.c | 12 +-
52
block/qapi.c | 8 +-
53
block/qcow.c | 153 ++++----
54
block/qcow2.c | 16 +-
55
block/raw-format.c | 6 -
56
block/throttle-groups.c | 750 ++++++++++++++++++++++++++++++----------
57
block/throttle.c | 237 +++++++++++++
58
blockdev.c | 4 +-
59
tests/test-throttle.c | 111 +++---
60
util/throttle.c | 151 ++++++++
61
block/Makefile.objs | 1 +
62
tests/qemu-iotests/184 | 205 +++++++++++
63
tests/qemu-iotests/184.out | 302 ++++++++++++++++
64
tests/qemu-iotests/group | 1 +
65
26 files changed, 1917 insertions(+), 453 deletions(-)
66
create mode 100644 block/throttle.c
67
create mode 100755 tests/qemu-iotests/184
68
create mode 100644 tests/qemu-iotests/184.out
69
56
57
Li Qiang (1):
58
block: change some function return type to bool
59
60
Max Reitz (5):
61
option: Make option help nicer to read
62
chardev: Indent list of chardevs
63
qdev-monitor: Make device options help nicer
64
object: Make option help nicer to read
65
fw_cfg: Drop newline in @file description
66
67
Peter Maydell (5):
68
block/qcow2: Don't take address of fields in packed structs
69
block/qcow: Don't take address of fields in packed structs
70
block/qcow2-bitmap: Don't take address of fields in packed structs
71
block/vhdx: Don't take address of fields in packed structs
72
block/vdi: Don't take address of fields in packed structs
73
74
Stefan Weil (1):
75
qemu-io-cmds: Fix two format strings
76
77
Thomas Huth (1):
78
block/vvfat: Fix crash when reporting error about too many files in directory
79
80
qapi/block-core.json | 7 +
81
block/vhdx.h | 12 +-
82
include/block/block.h | 5 +-
83
include/qemu/option.h | 2 +-
84
include/qemu/units.h | 18 +
85
include/sysemu/block-backend.h | 6 +-
86
block.c | 60 ++-
87
block/block-backend.c | 8 +-
88
block/bochs.c | 17 +-
89
block/cloop.c | 16 +-
90
block/curl.c | 8 +-
91
block/dmg.c | 16 +-
92
block/file-posix.c | 19 +-
93
block/gluster.c | 12 +-
94
block/iscsi.c | 8 +-
95
block/nbd-client.c | 10 +-
96
block/qcow.c | 18 +-
97
block/qcow2-bitmap.c | 24 +-
98
block/qcow2.c | 66 +--
99
block/quorum.c | 45 +-
100
block/rbd.c | 14 +-
101
block/vdi.c | 68 +--
102
block/vhdx-endian.c | 118 ++---
103
block/vhdx-log.c | 4 +-
104
block/vhdx.c | 18 +-
105
block/vpc.c | 2 +
106
block/vvfat.c | 15 +-
107
blockdev.c | 3 +-
108
chardev/char.c | 2 +-
109
crypto/block-qcow.c | 2 +
110
qdev-monitor.c | 13 +-
111
qemu-img.c | 4 +-
112
qemu-io-cmds.c | 4 +-
113
util/qemu-option.c | 32 +-
114
vl.c | 15 +-
115
tests/qemu-iotests/081 | 116 +++++
116
tests/qemu-iotests/081.out | 70 +++
117
tests/qemu-iotests/082.out | 956 ++++++++++++++++++++---------------------
118
tests/qemu-iotests/083 | 2 +-
119
tests/qemu-iotests/232 | 147 +++++++
120
tests/qemu-iotests/232.out | 59 +++
121
tests/qemu-iotests/group | 1 +
122
42 files changed, 1266 insertions(+), 776 deletions(-)
123
create mode 100755 tests/qemu-iotests/232
124
create mode 100644 tests/qemu-iotests/232.out
125
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
When using the vvfat driver with a directory that contains too many files,
4
QEMU currently crashes. This can be triggered like this for example:
5
6
mkdir /tmp/vvfattest
7
cd /tmp/vvfattest
8
for ((x=0;x<=513;x++)); do mkdir $x; done
9
qemu-system-x86_64 -drive \
10
file.driver=vvfat,file.dir=.,read-only=on,media=cdrom
11
12
Seems like read_directory() is changing the mapping->path variable. Make
13
sure we use the right pointer instead.
14
15
Signed-off-by: Thomas Huth <thuth@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
block/vvfat.c | 4 ++--
19
1 file changed, 2 insertions(+), 2 deletions(-)
20
21
diff --git a/block/vvfat.c b/block/vvfat.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/vvfat.c
24
+++ b/block/vvfat.c
25
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
26
mapping = array_get(&(s->mapping), i);
27
28
if (mapping->mode & MODE_DIRECTORY) {
29
+ char *path = mapping->path;
30
mapping->begin = cluster;
31
if(read_directory(s, i)) {
32
- error_setg(errp, "Could not read directory %s",
33
- mapping->path);
34
+ error_setg(errp, "Could not read directory %s", path);
35
return -1;
36
}
37
mapping = array_get(&(s->mapping), i);
38
--
39
2.19.1
40
41
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
The following functions fail if bs->drv is a filter and does not
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
implement them:
5
6
bdrv_probe_blocksizes
7
bdrv_probe_geometry
8
bdrv_truncate
9
bdrv_has_zero_init
10
bdrv_get_info
11
12
Instead, the call should be passed to bs->file if it exists, to allow
13
filter drivers to support those methods without implementing them. This
14
commit makes `drv->is_filter = true` imply that these callbacks will be
15
forwarded to bs->file by default, so disabling support for these
16
functions must be done explicitly.
17
18
Reviewed-by: Eric Blake <eblake@redhat.com>
19
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
5
---
23
include/block/block_int.h | 6 +++++-
6
block.c | 6 +++---
24
block.c | 21 +++++++++++++++++++--
7
1 file changed, 3 insertions(+), 3 deletions(-)
25
2 files changed, 24 insertions(+), 3 deletions(-)
26
8
27
diff --git a/include/block/block_int.h b/include/block/block_int.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block_int.h
30
+++ b/include/block/block_int.h
31
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
32
const char *format_name;
33
int instance_size;
34
35
- /* set to true if the BlockDriver is a block filter */
36
+ /* set to true if the BlockDriver is a block filter. Block filters pass
37
+ * certain callbacks that refer to data (see block.c) to their bs->file if
38
+ * the driver doesn't implement them. Drivers that do not wish to forward
39
+ * must implement them and return -ENOTSUP.
40
+ */
41
bool is_filter;
42
/* for snapshots block filter like Quorum can implement the
43
* following recursive callback.
44
diff --git a/block.c b/block.c
9
diff --git a/block.c b/block.c
45
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
46
--- a/block.c
11
--- a/block.c
47
+++ b/block.c
12
+++ b/block.c
48
@@ -XXX,XX +XXX,XX @@ int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
13
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
49
14
.help = "try to optimize zero writes (off, on, unmap)",
50
if (drv && drv->bdrv_probe_blocksizes) {
15
},
51
return drv->bdrv_probe_blocksizes(bs, bsz);
16
{
52
+ } else if (drv && drv->is_filter && bs->file) {
17
- .name = "discard",
53
+ return bdrv_probe_blocksizes(bs->file->bs, bsz);
18
+ .name = BDRV_OPT_DISCARD,
19
.type = QEMU_OPT_STRING,
20
.help = "discard operation (ignore/off, unmap/on)",
21
},
22
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
23
}
54
}
24
}
55
25
56
return -ENOTSUP;
26
- discard = qemu_opt_get(opts, "discard");
57
@@ -XXX,XX +XXX,XX @@ int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
27
+ discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
58
28
if (discard != NULL) {
59
if (drv && drv->bdrv_probe_geometry) {
29
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
60
return drv->bdrv_probe_geometry(bs, geo);
30
error_setg(errp, "Invalid discard option");
61
+ } else if (drv && drv->is_filter && bs->file) {
31
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
62
+ return bdrv_probe_geometry(bs->file->bs, geo);
32
63
}
33
update_flags_from_options(&reopen_state->flags, opts);
64
34
65
return -ENOTSUP;
35
- discard = qemu_opt_get_del(opts, "discard");
66
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
36
+ discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
67
37
if (discard != NULL) {
68
assert(child->perm & BLK_PERM_RESIZE);
38
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
69
39
error_setg(errp, "Invalid discard option");
70
+ /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
71
if (!drv) {
72
error_setg(errp, "No medium inserted");
73
return -ENOMEDIUM;
74
}
75
if (!drv->bdrv_truncate) {
76
+ if (bs->file && drv->is_filter) {
77
+ return bdrv_truncate(bs->file, offset, prealloc, errp);
78
+ }
79
error_setg(errp, "Image format driver does not support resize");
80
return -ENOTSUP;
81
}
82
@@ -XXX,XX +XXX,XX @@ int bdrv_has_zero_init(BlockDriverState *bs)
83
if (bs->drv->bdrv_has_zero_init) {
84
return bs->drv->bdrv_has_zero_init(bs);
85
}
86
+ if (bs->file && bs->drv->is_filter) {
87
+ return bdrv_has_zero_init(bs->file->bs);
88
+ }
89
90
/* safe default */
91
return 0;
92
@@ -XXX,XX +XXX,XX @@ void bdrv_get_backing_filename(BlockDriverState *bs,
93
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
94
{
95
BlockDriver *drv = bs->drv;
96
- if (!drv)
97
+ /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
98
+ if (!drv) {
99
return -ENOMEDIUM;
100
- if (!drv->bdrv_get_info)
101
+ }
102
+ if (!drv->bdrv_get_info) {
103
+ if (bs->file && drv->is_filter) {
104
+ return bdrv_get_info(bs->file->bs, bdi);
105
+ }
106
return -ENOTSUP;
107
+ }
108
memset(bdi, 0, sizeof(*bdi));
109
return drv->bdrv_get_info(bs, bdi);
110
}
111
--
40
--
112
2.13.5
41
2.19.1
113
42
114
43
diff view generated by jsdifflib
New patch
1
From: Stefan Weil <sw@weilnetz.de>
1
2
3
Use %zu instead of %zd for unsigned numbers.
4
5
This fixes two error messages from the LSTM static code analyzer:
6
7
This argument should be of type 'ssize_t' but is of type 'unsigned long'
8
9
Signed-off-by: Stefan Weil <sw@weilnetz.de>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
qemu-io-cmds.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/qemu-io-cmds.c
19
+++ b/qemu-io-cmds.c
20
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
21
memset(cmp_buf, pattern, qiov.size);
22
if (memcmp(buf, cmp_buf, qiov.size)) {
23
printf("Pattern verification failed at offset %"
24
- PRId64 ", %zd bytes\n", offset, qiov.size);
25
+ PRId64 ", %zu bytes\n", offset, qiov.size);
26
ret = -EINVAL;
27
}
28
g_free(cmp_buf);
29
@@ -XXX,XX +XXX,XX @@ static void aio_read_done(void *opaque, int ret)
30
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
31
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
32
printf("Pattern verification failed at offset %"
33
- PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
34
+ PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
35
}
36
g_free(cmp_buf);
37
}
38
--
39
2.19.1
40
41
diff view generated by jsdifflib
New patch
1
From: Peter Maydell <peter.maydell@linaro.org>
1
2
3
Taking the address of a field in a packed struct is a bad idea, because
4
it might not be actually aligned enough for that pointer type (and
5
thus cause a crash on dereference on some host architectures). Newer
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
9
There are a few places where the in-place swap function is
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
13
This patch was produced with the following spatch script
14
(and hand-editing to fold a few resulting overlength lines):
15
16
@@
17
expression E;
18
@@
19
-be16_to_cpus(&E);
20
+E = be16_to_cpu(E);
21
@@
22
expression E;
23
@@
24
-be32_to_cpus(&E);
25
+E = be32_to_cpu(E);
26
@@
27
expression E;
28
@@
29
-be64_to_cpus(&E);
30
+E = be64_to_cpu(E);
31
@@
32
expression E;
33
@@
34
-cpu_to_be16s(&E);
35
+E = cpu_to_be16(E);
36
@@
37
expression E;
38
@@
39
-cpu_to_be32s(&E);
40
+E = cpu_to_be32(E);
41
@@
42
expression E;
43
@@
44
-cpu_to_be64s(&E);
45
+E = cpu_to_be64(E);
46
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
49
Tested-by: John Snow <jsnow@redhat.com>
50
Reviewed-by: John Snow <jsnow@redhat.com>
51
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
52
---
53
block/qcow2.c | 64 +++++++++++++++++++++++++++------------------------
54
1 file changed, 34 insertions(+), 30 deletions(-)
55
56
diff --git a/block/qcow2.c b/block/qcow2.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block/qcow2.c
59
+++ b/block/qcow2.c
60
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
61
"pread fail from offset %" PRIu64, offset);
62
return 1;
63
}
64
- be32_to_cpus(&ext.magic);
65
- be32_to_cpus(&ext.len);
66
+ ext.magic = be32_to_cpu(ext.magic);
67
+ ext.len = be32_to_cpu(ext.len);
68
offset += sizeof(ext);
69
#ifdef DEBUG_EXT
70
printf("ext.magic = 0x%x\n", ext.magic);
71
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
72
"Unable to read CRYPTO header extension");
73
return ret;
74
}
75
- be64_to_cpus(&s->crypto_header.offset);
76
- be64_to_cpus(&s->crypto_header.length);
77
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
78
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
79
80
if ((s->crypto_header.offset % s->cluster_size) != 0) {
81
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
82
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
83
return -EINVAL;
84
}
85
86
- be32_to_cpus(&bitmaps_ext.nb_bitmaps);
87
- be64_to_cpus(&bitmaps_ext.bitmap_directory_size);
88
- be64_to_cpus(&bitmaps_ext.bitmap_directory_offset);
89
+ bitmaps_ext.nb_bitmaps = be32_to_cpu(bitmaps_ext.nb_bitmaps);
90
+ bitmaps_ext.bitmap_directory_size =
91
+ be64_to_cpu(bitmaps_ext.bitmap_directory_size);
92
+ bitmaps_ext.bitmap_directory_offset =
93
+ be64_to_cpu(bitmaps_ext.bitmap_directory_offset);
94
95
if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) {
96
error_setg(errp,
97
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
98
error_setg_errno(errp, -ret, "Could not read qcow2 header");
99
goto fail;
100
}
101
- be32_to_cpus(&header.magic);
102
- be32_to_cpus(&header.version);
103
- be64_to_cpus(&header.backing_file_offset);
104
- be32_to_cpus(&header.backing_file_size);
105
- be64_to_cpus(&header.size);
106
- be32_to_cpus(&header.cluster_bits);
107
- be32_to_cpus(&header.crypt_method);
108
- be64_to_cpus(&header.l1_table_offset);
109
- be32_to_cpus(&header.l1_size);
110
- be64_to_cpus(&header.refcount_table_offset);
111
- be32_to_cpus(&header.refcount_table_clusters);
112
- be64_to_cpus(&header.snapshots_offset);
113
- be32_to_cpus(&header.nb_snapshots);
114
+ header.magic = be32_to_cpu(header.magic);
115
+ header.version = be32_to_cpu(header.version);
116
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
117
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
118
+ header.size = be64_to_cpu(header.size);
119
+ header.cluster_bits = be32_to_cpu(header.cluster_bits);
120
+ header.crypt_method = be32_to_cpu(header.crypt_method);
121
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
122
+ header.l1_size = be32_to_cpu(header.l1_size);
123
+ header.refcount_table_offset = be64_to_cpu(header.refcount_table_offset);
124
+ header.refcount_table_clusters =
125
+ be32_to_cpu(header.refcount_table_clusters);
126
+ header.snapshots_offset = be64_to_cpu(header.snapshots_offset);
127
+ header.nb_snapshots = be32_to_cpu(header.nb_snapshots);
128
129
if (header.magic != QCOW_MAGIC) {
130
error_setg(errp, "Image is not in qcow2 format");
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
132
header.refcount_order = 4;
133
header.header_length = 72;
134
} else {
135
- be64_to_cpus(&header.incompatible_features);
136
- be64_to_cpus(&header.compatible_features);
137
- be64_to_cpus(&header.autoclear_features);
138
- be32_to_cpus(&header.refcount_order);
139
- be32_to_cpus(&header.header_length);
140
+ header.incompatible_features =
141
+ be64_to_cpu(header.incompatible_features);
142
+ header.compatible_features = be64_to_cpu(header.compatible_features);
143
+ header.autoclear_features = be64_to_cpu(header.autoclear_features);
144
+ header.refcount_order = be32_to_cpu(header.refcount_order);
145
+ header.header_length = be32_to_cpu(header.header_length);
146
147
if (header.header_length < 104) {
148
error_setg(errp, "qcow2 header too short");
149
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
150
goto fail;
151
}
152
for(i = 0;i < s->l1_size; i++) {
153
- be64_to_cpus(&s->l1_table[i]);
154
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
155
}
156
}
157
158
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
159
160
/* Full disk encryption header pointer extension */
161
if (s->crypto_header.offset != 0) {
162
- cpu_to_be64s(&s->crypto_header.offset);
163
- cpu_to_be64s(&s->crypto_header.length);
164
+ s->crypto_header.offset = cpu_to_be64(s->crypto_header.offset);
165
+ s->crypto_header.length = cpu_to_be64(s->crypto_header.length);
166
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
167
&s->crypto_header, sizeof(s->crypto_header),
168
buflen);
169
- be64_to_cpus(&s->crypto_header.offset);
170
- be64_to_cpus(&s->crypto_header.length);
171
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
172
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
173
if (ret < 0) {
174
goto fail;
175
}
176
--
177
2.19.1
178
179
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
Omitting the check for whether bdrv_getlength() and bdrv_truncate()
3
Taking the address of a field in a packed struct is a bad idea, because
4
failed meant that it was theoretically possible to return an
4
it might not be actually aligned enough for that pointer type (and
5
incorrect offset to the caller. More likely, conditions for either
5
thus cause a crash on dereference on some host architectures). Newer
6
of these functions to fail would also cause one of our other calls
6
versions of clang warn about this. Avoid the bug by not using the
7
(such as bdrv_pread() or bdrv_pwrite_sync()) to also fail, but
7
"modify in place" byte swapping functions.
8
auditing that we are safe is difficult compared to just patching
9
things to always forward on the error rather than ignoring it.
10
8
11
Use osdep.h macros instead of open-coded rounding while in the
9
There are a few places where the in-place swap function is
12
area.
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
13
12
14
Reported-by: Markus Armbruster <armbru@redhat.com>
13
This patch was produced with the following spatch script:
15
Signed-off-by: Eric Blake <eblake@redhat.com>
14
15
@@
16
expression E;
17
@@
18
-be16_to_cpus(&E);
19
+E = be16_to_cpu(E);
20
@@
21
expression E;
22
@@
23
-be32_to_cpus(&E);
24
+E = be32_to_cpu(E);
25
@@
26
expression E;
27
@@
28
-be64_to_cpus(&E);
29
+E = be64_to_cpu(E);
30
@@
31
expression E;
32
@@
33
-cpu_to_be16s(&E);
34
+E = cpu_to_be16(E);
35
@@
36
expression E;
37
@@
38
-cpu_to_be32s(&E);
39
+E = cpu_to_be32(E);
40
@@
41
expression E;
42
@@
43
-cpu_to_be64s(&E);
44
+E = cpu_to_be64(E);
45
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
48
Tested-by: John Snow <jsnow@redhat.com>
49
Reviewed-by: John Snow <jsnow@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
51
---
18
block/qcow.c | 30 ++++++++++++++++++++++--------
52
block/qcow.c | 18 +++++++++---------
19
1 file changed, 22 insertions(+), 8 deletions(-)
53
1 file changed, 9 insertions(+), 9 deletions(-)
20
54
21
diff --git a/block/qcow.c b/block/qcow.c
55
diff --git a/block/qcow.c b/block/qcow.c
22
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow.c
57
--- a/block/qcow.c
24
+++ b/block/qcow.c
58
+++ b/block/qcow.c
25
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
59
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
26
{
60
if (ret < 0) {
27
BDRVQcowState *s = bs->opaque;
61
goto fail;
28
int min_index, i, j, l1_index, l2_index, ret;
62
}
29
- uint64_t l2_offset, *l2_table, cluster_offset, tmp;
63
- be32_to_cpus(&header.magic);
30
+ int64_t l2_offset;
64
- be32_to_cpus(&header.version);
31
+ uint64_t *l2_table, cluster_offset, tmp;
65
- be64_to_cpus(&header.backing_file_offset);
32
uint32_t min_count;
66
- be32_to_cpus(&header.backing_file_size);
33
int new_l2_table;
67
- be32_to_cpus(&header.mtime);
34
68
- be64_to_cpus(&header.size);
35
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
69
- be32_to_cpus(&header.crypt_method);
36
return 0;
70
- be64_to_cpus(&header.l1_table_offset);
37
/* allocate a new l2 entry */
71
+ header.magic = be32_to_cpu(header.magic);
38
l2_offset = bdrv_getlength(bs->file->bs);
72
+ header.version = be32_to_cpu(header.version);
39
+ if (l2_offset < 0) {
73
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
40
+ return l2_offset;
74
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
41
+ }
75
+ header.mtime = be32_to_cpu(header.mtime);
42
/* round to cluster size */
76
+ header.size = be64_to_cpu(header.size);
43
- l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
77
+ header.crypt_method = be32_to_cpu(header.crypt_method);
44
+ l2_offset = QEMU_ALIGN_UP(l2_offset, s->cluster_size);
78
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
45
/* update the L1 entry */
79
46
s->l1_table[l1_index] = l2_offset;
80
if (header.magic != QCOW_MAGIC) {
47
tmp = cpu_to_be64(l2_offset);
81
error_setg(errp, "Image not in qcow format");
48
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
82
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
49
return -EIO;
83
}
50
}
84
51
cluster_offset = bdrv_getlength(bs->file->bs);
85
for(i = 0;i < s->l1_size; i++) {
52
- cluster_offset = (cluster_offset + s->cluster_size - 1) &
86
- be64_to_cpus(&s->l1_table[i]);
53
- ~(s->cluster_size - 1);
87
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
54
+ if ((int64_t) cluster_offset < 0) {
88
}
55
+ return cluster_offset;
89
56
+ }
90
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
57
+ cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
58
/* write the cluster content */
59
ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
60
s->cluster_size);
61
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
62
}
63
} else {
64
cluster_offset = bdrv_getlength(bs->file->bs);
65
+ if ((int64_t) cluster_offset < 0) {
66
+ return cluster_offset;
67
+ }
68
if (allocate == 1) {
69
/* round to cluster size */
70
- cluster_offset = (cluster_offset + s->cluster_size - 1) &
71
- ~(s->cluster_size - 1);
72
- bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
73
- PREALLOC_MODE_OFF, NULL);
74
+ cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
75
+ if (cluster_offset + s->cluster_size > INT64_MAX) {
76
+ return -E2BIG;
77
+ }
78
+ ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
79
+ PREALLOC_MODE_OFF, NULL);
80
+ if (ret < 0) {
81
+ return ret;
82
+ }
83
/* if encrypted, we must initialize the cluster
84
content which won't be written */
85
if (bs->encrypted &&
86
--
91
--
87
2.13.5
92
2.19.1
88
93
89
94
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
timer_cb() needs to know about the current Aio context of the throttle
3
Taking the address of a field in a packed struct is a bad idea, because
4
request that is woken up. In order to make ThrottleGroupMember backend
4
it might not be actually aligned enough for that pointer type (and
5
agnostic, this information is stored in an aio_context field instead of
5
thus cause a crash on dereference on some host architectures). Newer
6
accessing it from BlockBackend.
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
7
8
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
There are a few places where the in-place swap function is
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
used on something other than a packed struct field; we convert
10
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
11
those anyway, for consistency.
12
13
This patch was produced with the following spatch script:
14
15
@@
16
expression E;
17
@@
18
-be16_to_cpus(&E);
19
+E = be16_to_cpu(E);
20
@@
21
expression E;
22
@@
23
-be32_to_cpus(&E);
24
+E = be32_to_cpu(E);
25
@@
26
expression E;
27
@@
28
-be64_to_cpus(&E);
29
+E = be64_to_cpu(E);
30
@@
31
expression E;
32
@@
33
-cpu_to_be16s(&E);
34
+E = cpu_to_be16(E);
35
@@
36
expression E;
37
@@
38
-cpu_to_be32s(&E);
39
+E = cpu_to_be32(E);
40
@@
41
expression E;
42
@@
43
-cpu_to_be64s(&E);
44
+E = cpu_to_be64(E);
45
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
48
Tested-by: John Snow <jsnow@redhat.com>
49
Reviewed-by: John Snow <jsnow@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
51
---
13
include/block/throttle-groups.h | 7 ++++-
52
block/qcow2-bitmap.c | 24 ++++++++++++------------
14
block/block-backend.c | 15 ++++------
53
1 file changed, 12 insertions(+), 12 deletions(-)
15
block/throttle-groups.c | 38 ++++++++++++++++---------
16
tests/test-throttle.c | 63 +++++++++++++++++++++--------------------
17
4 files changed, 69 insertions(+), 54 deletions(-)
18
54
19
diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
55
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
20
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/throttle-groups.h
57
--- a/block/qcow2-bitmap.c
22
+++ b/include/block/throttle-groups.h
58
+++ b/block/qcow2-bitmap.c
23
@@ -XXX,XX +XXX,XX @@
59
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
24
*/
60
size_t i;
25
61
26
typedef struct ThrottleGroupMember {
62
for (i = 0; i < size; ++i) {
27
+ AioContext *aio_context;
63
- cpu_to_be64s(&bitmap_table[i]);
28
/* throttled_reqs_lock protects the CoQueues for throttled requests. */
64
+ bitmap_table[i] = cpu_to_be64(bitmap_table[i]);
29
CoMutex throttled_reqs_lock;
30
CoQueue throttled_reqs[2];
31
@@ -XXX,XX +XXX,XX @@ void throttle_group_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
32
void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
33
34
void throttle_group_register_tgm(ThrottleGroupMember *tgm,
35
- const char *groupname);
36
+ const char *groupname,
37
+ AioContext *ctx);
38
void throttle_group_unregister_tgm(ThrottleGroupMember *tgm);
39
void throttle_group_restart_tgm(ThrottleGroupMember *tgm);
40
41
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
42
unsigned int bytes,
43
bool is_write);
44
+void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
45
+ AioContext *new_context);
46
+void throttle_group_detach_aio_context(ThrottleGroupMember *tgm);
47
48
#endif
49
diff --git a/block/block-backend.c b/block/block-backend.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/block-backend.c
52
+++ b/block/block-backend.c
53
@@ -XXX,XX +XXX,XX @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
54
void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
55
{
56
BlockDriverState *bs = blk_bs(blk);
57
- ThrottleTimers *tt;
58
+ ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
59
60
if (bs) {
61
- if (blk->public.throttle_group_member.throttle_state) {
62
- tt = &blk->public.throttle_group_member.throttle_timers;
63
- throttle_timers_detach_aio_context(tt);
64
+ if (tgm->throttle_state) {
65
+ throttle_group_detach_aio_context(tgm);
66
+ throttle_group_attach_aio_context(tgm, new_context);
67
}
68
bdrv_set_aio_context(bs, new_context);
69
- if (blk->public.throttle_group_member.throttle_state) {
70
- tt = &blk->public.throttle_group_member.throttle_timers;
71
- throttle_timers_attach_aio_context(tt, new_context);
72
- }
73
}
65
}
74
}
66
}
75
67
76
@@ -XXX,XX +XXX,XX @@ void blk_io_limits_disable(BlockBackend *blk)
68
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
77
void blk_io_limits_enable(BlockBackend *blk, const char *group)
69
}
70
71
for (i = 0; i < tb->size; ++i) {
72
- be64_to_cpus(&table[i]);
73
+ table[i] = be64_to_cpu(table[i]);
74
ret = check_table_entry(table[i], s->cluster_size);
75
if (ret < 0) {
76
goto fail;
77
@@ -XXX,XX +XXX,XX @@ fail:
78
79
static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
78
{
80
{
79
assert(!blk->public.throttle_group_member.throttle_state);
81
- be64_to_cpus(&entry->bitmap_table_offset);
80
- throttle_group_register_tgm(&blk->public.throttle_group_member, group);
82
- be32_to_cpus(&entry->bitmap_table_size);
81
+ throttle_group_register_tgm(&blk->public.throttle_group_member,
83
- be32_to_cpus(&entry->flags);
82
+ group, blk_get_aio_context(blk));
84
- be16_to_cpus(&entry->name_size);
85
- be32_to_cpus(&entry->extra_data_size);
86
+ entry->bitmap_table_offset = be64_to_cpu(entry->bitmap_table_offset);
87
+ entry->bitmap_table_size = be32_to_cpu(entry->bitmap_table_size);
88
+ entry->flags = be32_to_cpu(entry->flags);
89
+ entry->name_size = be16_to_cpu(entry->name_size);
90
+ entry->extra_data_size = be32_to_cpu(entry->extra_data_size);
83
}
91
}
84
92
85
void blk_io_limits_update_group(BlockBackend *blk, const char *group)
93
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
86
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/throttle-groups.c
89
+++ b/block/throttle-groups.c
90
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn throttle_group_restart_queue_entry(void *opaque)
91
92
static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write)
93
{
94
{
94
- BlockBackendPublic *blkp = container_of(tgm, BlockBackendPublic,
95
- cpu_to_be64s(&entry->bitmap_table_offset);
95
- throttle_group_member);
96
- cpu_to_be32s(&entry->bitmap_table_size);
96
- BlockBackend *blk = blk_by_public(blkp);
97
- cpu_to_be32s(&entry->flags);
97
Coroutine *co;
98
- cpu_to_be16s(&entry->name_size);
98
RestartData rd = {
99
- cpu_to_be32s(&entry->extra_data_size);
99
.tgm = tgm,
100
+ entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
100
@@ -XXX,XX +XXX,XX @@ static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write
101
+ entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
101
};
102
+ entry->flags = cpu_to_be32(entry->flags);
102
103
+ entry->name_size = cpu_to_be16(entry->name_size);
103
co = qemu_coroutine_create(throttle_group_restart_queue_entry, &rd);
104
+ entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
104
- aio_co_enter(blk_get_aio_context(blk), co);
105
+ aio_co_enter(tgm->aio_context, co);
106
}
105
}
107
106
108
void throttle_group_restart_tgm(ThrottleGroupMember *tgm)
107
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
109
@@ -XXX,XX +XXX,XX @@ void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg)
110
/* ThrottleTimers callback. This wakes up a request that was waiting
111
* because it had been throttled.
112
*
113
- * @blk: the BlockBackend whose request had been throttled
114
+ * @tgm: the ThrottleGroupMember whose request had been throttled
115
* @is_write: the type of operation (read/write)
116
*/
117
-static void timer_cb(BlockBackend *blk, bool is_write)
118
+static void timer_cb(ThrottleGroupMember *tgm, bool is_write)
119
{
120
- BlockBackendPublic *blkp = blk_get_public(blk);
121
- ThrottleGroupMember *tgm = &blkp->throttle_group_member;
122
ThrottleState *ts = tgm->throttle_state;
123
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
124
125
@@ -XXX,XX +XXX,XX @@ static void write_timer_cb(void *opaque)
126
*
127
* @tgm: the ThrottleGroupMember to insert
128
* @groupname: the name of the group
129
+ * @ctx: the AioContext to use
130
*/
131
void throttle_group_register_tgm(ThrottleGroupMember *tgm,
132
- const char *groupname)
133
+ const char *groupname,
134
+ AioContext *ctx)
135
{
136
int i;
137
- BlockBackendPublic *blkp = container_of(tgm, BlockBackendPublic,
138
- throttle_group_member);
139
- BlockBackend *blk = blk_by_public(blkp);
140
ThrottleState *ts = throttle_group_incref(groupname);
141
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
142
143
tgm->throttle_state = ts;
144
+ tgm->aio_context = ctx;
145
146
qemu_mutex_lock(&tg->lock);
147
/* If the ThrottleGroup is new set this ThrottleGroupMember as the token */
148
@@ -XXX,XX +XXX,XX @@ void throttle_group_register_tgm(ThrottleGroupMember *tgm,
149
QLIST_INSERT_HEAD(&tg->head, tgm, round_robin);
150
151
throttle_timers_init(&tgm->throttle_timers,
152
- blk_get_aio_context(blk),
153
+ tgm->aio_context,
154
tg->clock_type,
155
read_timer_cb,
156
write_timer_cb,
157
- blk);
158
+ tgm);
159
160
qemu_mutex_unlock(&tg->lock);
161
}
162
@@ -XXX,XX +XXX,XX @@ void throttle_group_unregister_tgm(ThrottleGroupMember *tgm)
163
tgm->throttle_state = NULL;
164
}
165
166
+void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
167
+ AioContext *new_context)
168
+{
169
+ ThrottleTimers *tt = &tgm->throttle_timers;
170
+ throttle_timers_attach_aio_context(tt, new_context);
171
+ tgm->aio_context = new_context;
172
+}
173
+
174
+void throttle_group_detach_aio_context(ThrottleGroupMember *tgm)
175
+{
176
+ ThrottleTimers *tt = &tgm->throttle_timers;
177
+ throttle_timers_detach_aio_context(tt);
178
+ tgm->aio_context = NULL;
179
+}
180
+
181
static void throttle_groups_init(void)
182
{
183
qemu_mutex_init(&throttle_groups_lock);
184
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/tests/test-throttle.c
187
+++ b/tests/test-throttle.c
188
@@ -XXX,XX +XXX,XX @@
189
static AioContext *ctx;
190
static LeakyBucket bkt;
191
static ThrottleConfig cfg;
192
+static ThrottleGroupMember tgm;
193
static ThrottleState ts;
194
-static ThrottleTimers tt;
195
+static ThrottleTimers *tt;
196
197
/* useful function */
198
static bool double_cmp(double x, double y)
199
@@ -XXX,XX +XXX,XX @@ static void test_init(void)
200
{
201
int i;
202
203
+ tt = &tgm.throttle_timers;
204
+
205
/* fill the structures with crap */
206
memset(&ts, 1, sizeof(ts));
207
- memset(&tt, 1, sizeof(tt));
208
+ memset(tt, 1, sizeof(*tt));
209
210
/* init structures */
211
throttle_init(&ts);
212
- throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
213
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
214
read_timer_cb, write_timer_cb, &ts);
215
216
/* check initialized fields */
217
- g_assert(tt.clock_type == QEMU_CLOCK_VIRTUAL);
218
- g_assert(tt.timers[0]);
219
- g_assert(tt.timers[1]);
220
+ g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
221
+ g_assert(tt->timers[0]);
222
+ g_assert(tt->timers[1]);
223
224
/* check other fields where cleared */
225
g_assert(!ts.previous_leak);
226
@@ -XXX,XX +XXX,XX @@ static void test_init(void)
227
g_assert(!ts.cfg.buckets[i].level);
228
}
229
230
- throttle_timers_destroy(&tt);
231
+ throttle_timers_destroy(tt);
232
}
233
234
static void test_destroy(void)
235
{
236
int i;
237
throttle_init(&ts);
238
- throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
239
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
240
read_timer_cb, write_timer_cb, &ts);
241
- throttle_timers_destroy(&tt);
242
+ throttle_timers_destroy(tt);
243
for (i = 0; i < 2; i++) {
244
- g_assert(!tt.timers[i]);
245
+ g_assert(!tt->timers[i]);
246
}
247
}
248
249
@@ -XXX,XX +XXX,XX @@ static void test_config_functions(void)
250
orig_cfg.op_size = 1;
251
252
throttle_init(&ts);
253
- throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
254
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
255
read_timer_cb, write_timer_cb, &ts);
256
/* structure reset by throttle_init previous_leak should be null */
257
g_assert(!ts.previous_leak);
258
@@ -XXX,XX +XXX,XX @@ static void test_config_functions(void)
259
/* get back the fixed configuration */
260
throttle_get_config(&ts, &final_cfg);
261
262
- throttle_timers_destroy(&tt);
263
+ throttle_timers_destroy(tt);
264
265
g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153);
266
g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg == 56);
267
@@ -XXX,XX +XXX,XX @@ static void test_have_timer(void)
268
{
269
/* zero structures */
270
memset(&ts, 0, sizeof(ts));
271
- memset(&tt, 0, sizeof(tt));
272
+ memset(tt, 0, sizeof(*tt));
273
274
/* no timer set should return false */
275
- g_assert(!throttle_timers_are_initialized(&tt));
276
+ g_assert(!throttle_timers_are_initialized(tt));
277
278
/* init structures */
279
throttle_init(&ts);
280
- throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
281
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
282
read_timer_cb, write_timer_cb, &ts);
283
284
/* timer set by init should return true */
285
- g_assert(throttle_timers_are_initialized(&tt));
286
+ g_assert(throttle_timers_are_initialized(tt));
287
288
- throttle_timers_destroy(&tt);
289
+ throttle_timers_destroy(tt);
290
}
291
292
static void test_detach_attach(void)
293
{
294
/* zero structures */
295
memset(&ts, 0, sizeof(ts));
296
- memset(&tt, 0, sizeof(tt));
297
+ memset(tt, 0, sizeof(*tt));
298
299
/* init the structure */
300
throttle_init(&ts);
301
- throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
302
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
303
read_timer_cb, write_timer_cb, &ts);
304
305
/* timer set by init should return true */
306
- g_assert(throttle_timers_are_initialized(&tt));
307
+ g_assert(throttle_timers_are_initialized(tt));
308
309
/* timer should no longer exist after detaching */
310
- throttle_timers_detach_aio_context(&tt);
311
- g_assert(!throttle_timers_are_initialized(&tt));
312
+ throttle_timers_detach_aio_context(tt);
313
+ g_assert(!throttle_timers_are_initialized(tt));
314
315
/* timer should exist again after attaching */
316
- throttle_timers_attach_aio_context(&tt, ctx);
317
- g_assert(throttle_timers_are_initialized(&tt));
318
+ throttle_timers_attach_aio_context(tt, ctx);
319
+ g_assert(throttle_timers_are_initialized(tt));
320
321
- throttle_timers_destroy(&tt);
322
+ throttle_timers_destroy(tt);
323
}
324
325
static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
326
@@ -XXX,XX +XXX,XX @@ static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
327
cfg.op_size = op_size;
328
329
throttle_init(&ts);
330
- throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
331
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
332
read_timer_cb, write_timer_cb, &ts);
333
throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
334
335
@@ -XXX,XX +XXX,XX @@ static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
336
return false;
337
}
338
339
- throttle_timers_destroy(&tt);
340
+ throttle_timers_destroy(tt);
341
342
return true;
343
}
344
@@ -XXX,XX +XXX,XX @@ static void test_groups(void)
345
g_assert(tgm2->throttle_state == NULL);
346
g_assert(tgm3->throttle_state == NULL);
347
348
- throttle_group_register_tgm(tgm1, "bar");
349
- throttle_group_register_tgm(tgm2, "foo");
350
- throttle_group_register_tgm(tgm3, "bar");
351
+ throttle_group_register_tgm(tgm1, "bar", blk_get_aio_context(blk1));
352
+ throttle_group_register_tgm(tgm2, "foo", blk_get_aio_context(blk2));
353
+ throttle_group_register_tgm(tgm3, "bar", blk_get_aio_context(blk3));
354
355
g_assert(tgm1->throttle_state != NULL);
356
g_assert(tgm2->throttle_state != NULL);
357
--
108
--
358
2.13.5
109
2.19.1
359
110
360
111
diff view generated by jsdifflib
New patch
1
From: Daniel P. Berrangé <berrange@redhat.com>
1
2
3
The qcow2 block driver expects to see a valid sector size even when it
4
has opened the crypto layer with QCRYPTO_BLOCK_OPEN_NO_IO.
5
6
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
crypto/block-qcow.c | 2 ++
11
1 file changed, 2 insertions(+)
12
13
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/crypto/block-qcow.c
16
+++ b/crypto/block-qcow.c
17
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
18
Error **errp)
19
{
20
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
21
+ block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
22
+ block->payload_offset = 0;
23
return 0;
24
} else {
25
if (!options->u.qcow.key_secret) {
26
--
27
2.19.1
28
29
diff view generated by jsdifflib
1
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
After calling qcow2_inactivate(), all qcow2 caches must be flushed, but this
3
This doesn't have any practical effect at the moment because the
4
may not happen, because the last call qcow2_store_persistent_dirty_bitmaps()
4
values of BDRV_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE and
5
can lead to marking l2/refcont cache as dirty.
5
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE are all the same (512 bytes), but
6
future encryption methods could have different requirements.
6
7
7
Let's move qcow2_store_persistent_dirty_bitmaps() before the caсhe flushing
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
to fix it.
9
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
9
10
Cc: qemu-stable@nongnu.org
11
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
11
---
14
block/qcow2.c | 16 ++++++++--------
12
block/qcow2.c | 2 +-
15
1 file changed, 8 insertions(+), 8 deletions(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
16
14
17
diff --git a/block/qcow2.c b/block/qcow2.c
15
diff --git a/block/qcow2.c b/block/qcow2.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2.c
17
--- a/block/qcow2.c
20
+++ b/block/qcow2.c
18
+++ b/block/qcow2.c
21
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
19
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
22
int ret, result = 0;
20
23
Error *local_err = NULL;
21
if (bs->encrypted) {
24
22
/* Encryption works on a sector granularity */
25
+ qcow2_store_persistent_dirty_bitmaps(bs, &local_err);
23
- bs->bl.request_alignment = BDRV_SECTOR_SIZE;
26
+ if (local_err != NULL) {
24
+ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
27
+ result = -EINVAL;
28
+ error_report_err(local_err);
29
+ error_report("Persistent bitmaps are lost for node '%s'",
30
+ bdrv_get_device_or_node_name(bs));
31
+ }
32
+
33
ret = qcow2_cache_flush(bs, s->l2_table_cache);
34
if (ret) {
35
result = ret;
36
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
37
strerror(-ret));
38
}
25
}
39
26
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
40
- qcow2_store_persistent_dirty_bitmaps(bs, &local_err);
27
bs->bl.pdiscard_alignment = s->cluster_size;
41
- if (local_err != NULL) {
42
- result = -EINVAL;
43
- error_report_err(local_err);
44
- error_report("Persistent bitmaps are lost for node '%s'",
45
- bdrv_get_device_or_node_name(bs));
46
- }
47
-
48
if (result == 0) {
49
qcow2_mark_clean(bs);
50
}
51
--
28
--
52
2.13.5
29
2.19.1
53
30
54
31
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
From: Li Qiang <liq3ea@163.com>
2
2
3
This commit eliminates the 1:1 relationship between BlockBackend and
3
Signed-off-by: Li Qiang <liq3ea@163.com>
4
throttle group state. Users will be able to create multiple throttle
5
nodes, each with its own throttle group state, in the future. The
6
throttle group state cannot be per-BlockBackend anymore, it must be
7
per-throttle node. This is done by gathering ThrottleGroup membership
8
details from BlockBackendPublic into ThrottleGroupMember and refactoring
9
existing code to use the structure.
10
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
6
---
16
include/block/throttle-groups.h | 39 +++++-
7
include/sysemu/block-backend.h | 6 +++---
17
include/sysemu/block-backend.h | 20 +--
8
block/block-backend.c | 8 ++++----
18
block/block-backend.c | 66 +++++----
9
2 files changed, 7 insertions(+), 7 deletions(-)
19
block/qapi.c | 8 +-
20
block/throttle-groups.c | 288 ++++++++++++++++++++--------------------
21
blockdev.c | 4 +-
22
tests/test-throttle.c | 53 ++++----
23
7 files changed, 252 insertions(+), 226 deletions(-)
24
10
25
diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/throttle-groups.h
28
+++ b/include/block/throttle-groups.h
29
@@ -XXX,XX +XXX,XX @@
30
#include "qemu/throttle.h"
31
#include "block/block_int.h"
32
33
-const char *throttle_group_get_name(BlockBackend *blk);
34
+/* The ThrottleGroupMember structure indicates membership in a ThrottleGroup
35
+ * and holds related data.
36
+ */
37
+
38
+typedef struct ThrottleGroupMember {
39
+ /* throttled_reqs_lock protects the CoQueues for throttled requests. */
40
+ CoMutex throttled_reqs_lock;
41
+ CoQueue throttled_reqs[2];
42
+
43
+ /* Nonzero if the I/O limits are currently being ignored; generally
44
+ * it is zero. Accessed with atomic operations.
45
+ */
46
+ unsigned int io_limits_disabled;
47
+
48
+ /* The following fields are protected by the ThrottleGroup lock.
49
+ * See the ThrottleGroup documentation for details.
50
+ * throttle_state tells us if I/O limits are configured. */
51
+ ThrottleState *throttle_state;
52
+ ThrottleTimers throttle_timers;
53
+ unsigned pending_reqs[2];
54
+ QLIST_ENTRY(ThrottleGroupMember) round_robin;
55
+
56
+} ThrottleGroupMember;
57
+
58
+const char *throttle_group_get_name(ThrottleGroupMember *tgm);
59
60
ThrottleState *throttle_group_incref(const char *name);
61
void throttle_group_unref(ThrottleState *ts);
62
63
-void throttle_group_config(BlockBackend *blk, ThrottleConfig *cfg);
64
-void throttle_group_get_config(BlockBackend *blk, ThrottleConfig *cfg);
65
+void throttle_group_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
66
+void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
67
68
-void throttle_group_register_blk(BlockBackend *blk, const char *groupname);
69
-void throttle_group_unregister_blk(BlockBackend *blk);
70
-void throttle_group_restart_blk(BlockBackend *blk);
71
+void throttle_group_register_tgm(ThrottleGroupMember *tgm,
72
+ const char *groupname);
73
+void throttle_group_unregister_tgm(ThrottleGroupMember *tgm);
74
+void throttle_group_restart_tgm(ThrottleGroupMember *tgm);
75
76
-void coroutine_fn throttle_group_co_io_limits_intercept(BlockBackend *blk,
77
+void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
78
unsigned int bytes,
79
bool is_write);
80
81
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
82
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
83
--- a/include/sysemu/block-backend.h
13
--- a/include/sysemu/block-backend.h
84
+++ b/include/sysemu/block-backend.h
14
+++ b/include/sysemu/block-backend.h
85
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDevOps {
15
@@ -XXX,XX +XXX,XX @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
86
16
int error);
87
/* This struct is embedded in (the private) BlockBackend struct and contains
17
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
88
* fields that must be public. This is in particular for QLIST_ENTRY() and
18
bool is_read, int error);
89
- * friends so that BlockBackends can be kept in lists outside block-backend.c */
19
-int blk_is_read_only(BlockBackend *blk);
90
+ * friends so that BlockBackends can be kept in lists outside block-backend.c
20
-int blk_is_sg(BlockBackend *blk);
91
+ * */
21
-int blk_enable_write_cache(BlockBackend *blk);
92
typedef struct BlockBackendPublic {
22
+bool blk_is_read_only(BlockBackend *blk);
93
- /* throttled_reqs_lock protects the CoQueues for throttled requests. */
23
+bool blk_is_sg(BlockBackend *blk);
94
- CoMutex throttled_reqs_lock;
24
+bool blk_enable_write_cache(BlockBackend *blk);
95
- CoQueue throttled_reqs[2];
25
void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
96
-
26
void blk_invalidate_cache(BlockBackend *blk, Error **errp);
97
- /* Nonzero if the I/O limits are currently being ignored; generally
27
bool blk_is_inserted(BlockBackend *blk);
98
- * it is zero. Accessed with atomic operations.
99
- */
100
- unsigned int io_limits_disabled;
101
-
102
- /* The following fields are protected by the ThrottleGroup lock.
103
- * See the ThrottleGroup documentation for details.
104
- * throttle_state tells us if I/O limits are configured. */
105
- ThrottleState *throttle_state;
106
- ThrottleTimers throttle_timers;
107
- unsigned pending_reqs[2];
108
- QLIST_ENTRY(BlockBackendPublic) round_robin;
109
+ ThrottleGroupMember throttle_group_member;
110
} BlockBackendPublic;
111
112
BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm);
113
diff --git a/block/block-backend.c b/block/block-backend.c
28
diff --git a/block/block-backend.c b/block/block-backend.c
114
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
115
--- a/block/block-backend.c
30
--- a/block/block-backend.c
116
+++ b/block/block-backend.c
31
+++ b/block/block-backend.c
117
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
32
@@ -XXX,XX +XXX,XX @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
118
blk->shared_perm = shared_perm;
119
blk_set_enable_write_cache(blk, true);
120
121
- qemu_co_mutex_init(&blk->public.throttled_reqs_lock);
122
- qemu_co_queue_init(&blk->public.throttled_reqs[0]);
123
- qemu_co_queue_init(&blk->public.throttled_reqs[1]);
124
+ qemu_co_mutex_init(&blk->public.throttle_group_member.throttled_reqs_lock);
125
+ qemu_co_queue_init(&blk->public.throttle_group_member.throttled_reqs[0]);
126
+ qemu_co_queue_init(&blk->public.throttle_group_member.throttled_reqs[1]);
127
block_acct_init(&blk->stats);
128
129
notifier_list_init(&blk->remove_bs_notifiers);
130
@@ -XXX,XX +XXX,XX @@ static void blk_delete(BlockBackend *blk)
131
assert(!blk->refcnt);
132
assert(!blk->name);
133
assert(!blk->dev);
134
- if (blk->public.throttle_state) {
135
+ if (blk->public.throttle_group_member.throttle_state) {
136
blk_io_limits_disable(blk);
137
}
33
}
138
if (blk->root) {
34
}
139
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public)
35
140
*/
36
-int blk_is_read_only(BlockBackend *blk)
141
void blk_remove_bs(BlockBackend *blk)
37
+bool blk_is_read_only(BlockBackend *blk)
142
{
143
+ ThrottleTimers *tt;
144
+
145
notifier_list_notify(&blk->remove_bs_notifiers, blk);
146
- if (blk->public.throttle_state) {
147
- throttle_timers_detach_aio_context(&blk->public.throttle_timers);
148
+ if (blk->public.throttle_group_member.throttle_state) {
149
+ tt = &blk->public.throttle_group_member.throttle_timers;
150
+ throttle_timers_detach_aio_context(tt);
151
}
152
153
blk_update_root_state(blk);
154
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
155
bdrv_ref(bs);
156
157
notifier_list_notify(&blk->insert_bs_notifiers, blk);
158
- if (blk->public.throttle_state) {
159
+ if (blk->public.throttle_group_member.throttle_state) {
160
throttle_timers_attach_aio_context(
161
- &blk->public.throttle_timers, bdrv_get_aio_context(bs));
162
+ &blk->public.throttle_group_member.throttle_timers,
163
+ bdrv_get_aio_context(bs));
164
}
165
166
return 0;
167
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
168
bdrv_inc_in_flight(bs);
169
170
/* throttling disk I/O */
171
- if (blk->public.throttle_state) {
172
- throttle_group_co_io_limits_intercept(blk, bytes, false);
173
+ if (blk->public.throttle_group_member.throttle_state) {
174
+ throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
175
+ bytes, false);
176
}
177
178
ret = bdrv_co_preadv(blk->root, offset, bytes, qiov, flags);
179
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
180
}
181
182
bdrv_inc_in_flight(bs);
183
-
184
/* throttling disk I/O */
185
- if (blk->public.throttle_state) {
186
- throttle_group_co_io_limits_intercept(blk, bytes, true);
187
+ if (blk->public.throttle_group_member.throttle_state) {
188
+ throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
189
+ bytes, true);
190
}
191
192
if (!blk->enable_write_cache) {
193
@@ -XXX,XX +XXX,XX @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
194
void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
195
{
38
{
196
BlockDriverState *bs = blk_bs(blk);
39
BlockDriverState *bs = blk_bs(blk);
197
+ ThrottleTimers *tt;
40
198
41
@@ -XXX,XX +XXX,XX @@ int blk_is_read_only(BlockBackend *blk)
199
if (bs) {
200
- if (blk->public.throttle_state) {
201
- throttle_timers_detach_aio_context(&blk->public.throttle_timers);
202
+ if (blk->public.throttle_group_member.throttle_state) {
203
+ tt = &blk->public.throttle_group_member.throttle_timers;
204
+ throttle_timers_detach_aio_context(tt);
205
}
206
bdrv_set_aio_context(bs, new_context);
207
- if (blk->public.throttle_state) {
208
- throttle_timers_attach_aio_context(&blk->public.throttle_timers,
209
- new_context);
210
+ if (blk->public.throttle_group_member.throttle_state) {
211
+ tt = &blk->public.throttle_group_member.throttle_timers;
212
+ throttle_timers_attach_aio_context(tt, new_context);
213
}
214
}
42
}
215
}
43
}
216
@@ -XXX,XX +XXX,XX @@ int blk_commit_all(void)
44
217
/* throttling disk I/O limits */
45
-int blk_is_sg(BlockBackend *blk)
218
void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
46
+bool blk_is_sg(BlockBackend *blk)
219
{
47
{
220
- throttle_group_config(blk, cfg);
48
BlockDriverState *bs = blk_bs(blk);
221
+ throttle_group_config(&blk->public.throttle_group_member, cfg);
49
50
if (!bs) {
51
- return 0;
52
+ return false;
53
}
54
55
return bdrv_is_sg(bs);
222
}
56
}
223
57
224
void blk_io_limits_disable(BlockBackend *blk)
58
-int blk_enable_write_cache(BlockBackend *blk)
59
+bool blk_enable_write_cache(BlockBackend *blk)
225
{
60
{
226
- assert(blk->public.throttle_state);
61
return blk->enable_write_cache;
227
+ assert(blk->public.throttle_group_member.throttle_state);
228
bdrv_drained_begin(blk_bs(blk));
229
- throttle_group_unregister_blk(blk);
230
+ throttle_group_unregister_tgm(&blk->public.throttle_group_member);
231
bdrv_drained_end(blk_bs(blk));
232
}
62
}
233
234
/* should be called before blk_set_io_limits if a limit is set */
235
void blk_io_limits_enable(BlockBackend *blk, const char *group)
236
{
237
- assert(!blk->public.throttle_state);
238
- throttle_group_register_blk(blk, group);
239
+ assert(!blk->public.throttle_group_member.throttle_state);
240
+ throttle_group_register_tgm(&blk->public.throttle_group_member, group);
241
}
242
243
void blk_io_limits_update_group(BlockBackend *blk, const char *group)
244
{
245
/* this BB is not part of any group */
246
- if (!blk->public.throttle_state) {
247
+ if (!blk->public.throttle_group_member.throttle_state) {
248
return;
249
}
250
251
/* this BB is a part of the same group than the one we want */
252
- if (!g_strcmp0(throttle_group_get_name(blk), group)) {
253
+ if (!g_strcmp0(throttle_group_get_name(&blk->public.throttle_group_member),
254
+ group)) {
255
return;
256
}
257
258
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_begin(BdrvChild *child)
259
/* Note that blk->root may not be accessible here yet if we are just
260
* attaching to a BlockDriverState that is drained. Use child instead. */
261
262
- if (atomic_fetch_inc(&blk->public.io_limits_disabled) == 0) {
263
- throttle_group_restart_blk(blk);
264
+ if (atomic_fetch_inc(&blk->public.throttle_group_member.io_limits_disabled) == 0) {
265
+ throttle_group_restart_tgm(&blk->public.throttle_group_member);
266
}
267
}
268
269
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_end(BdrvChild *child)
270
BlockBackend *blk = child->opaque;
271
assert(blk->quiesce_counter);
272
273
- assert(blk->public.io_limits_disabled);
274
- atomic_dec(&blk->public.io_limits_disabled);
275
+ assert(blk->public.throttle_group_member.io_limits_disabled);
276
+ atomic_dec(&blk->public.throttle_group_member.io_limits_disabled);
277
278
if (--blk->quiesce_counter == 0) {
279
if (blk->dev_ops && blk->dev_ops->drained_end) {
280
diff --git a/block/qapi.c b/block/qapi.c
281
index XXXXXXX..XXXXXXX 100644
282
--- a/block/qapi.c
283
+++ b/block/qapi.c
284
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
285
286
info->detect_zeroes = bs->detect_zeroes;
287
288
- if (blk && blk_get_public(blk)->throttle_state) {
289
+ if (blk && blk_get_public(blk)->throttle_group_member.throttle_state) {
290
ThrottleConfig cfg;
291
+ BlockBackendPublic *blkp = blk_get_public(blk);
292
293
- throttle_group_get_config(blk, &cfg);
294
+ throttle_group_get_config(&blkp->throttle_group_member, &cfg);
295
296
info->bps = cfg.buckets[THROTTLE_BPS_TOTAL].avg;
297
info->bps_rd = cfg.buckets[THROTTLE_BPS_READ].avg;
298
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
299
info->iops_size = cfg.op_size;
300
301
info->has_group = true;
302
- info->group = g_strdup(throttle_group_get_name(blk));
303
+ info->group =
304
+ g_strdup(throttle_group_get_name(&blkp->throttle_group_member));
305
}
306
307
info->write_threshold = bdrv_write_threshold_get(bs);
308
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/block/throttle-groups.c
311
+++ b/block/throttle-groups.c
312
@@ -XXX,XX +XXX,XX @@
313
#include "sysemu/qtest.h"
314
315
/* The ThrottleGroup structure (with its ThrottleState) is shared
316
- * among different BlockBackends and it's independent from
317
+ * among different ThrottleGroupMembers and it's independent from
318
* AioContext, so in order to use it from different threads it needs
319
* its own locking.
320
*
321
@@ -XXX,XX +XXX,XX @@
322
* The whole ThrottleGroup structure is private and invisible to
323
* outside users, that only use it through its ThrottleState.
324
*
325
- * In addition to the ThrottleGroup structure, BlockBackendPublic has
326
+ * In addition to the ThrottleGroup structure, ThrottleGroupMember has
327
* fields that need to be accessed by other members of the group and
328
* therefore also need to be protected by this lock. Once a
329
- * BlockBackend is registered in a group those fields can be accessed
330
+ * ThrottleGroupMember is registered in a group those fields can be accessed
331
* by other threads any time.
332
*
333
* Again, all this is handled internally and is mostly transparent to
334
* the outside. The 'throttle_timers' field however has an additional
335
* constraint because it may be temporarily invalid (see for example
336
* blk_set_aio_context()). Therefore in this file a thread will
337
- * access some other BlockBackend's timers only after verifying that
338
- * that BlockBackend has throttled requests in the queue.
339
+ * access some other ThrottleGroupMember's timers only after verifying that
340
+ * that ThrottleGroupMember has throttled requests in the queue.
341
*/
342
typedef struct ThrottleGroup {
343
char *name; /* This is constant during the lifetime of the group */
344
345
QemuMutex lock; /* This lock protects the following four fields */
346
ThrottleState ts;
347
- QLIST_HEAD(, BlockBackendPublic) head;
348
- BlockBackend *tokens[2];
349
+ QLIST_HEAD(, ThrottleGroupMember) head;
350
+ ThrottleGroupMember *tokens[2];
351
bool any_timer_armed[2];
352
QEMUClockType clock_type;
353
354
@@ -XXX,XX +XXX,XX @@ void throttle_group_unref(ThrottleState *ts)
355
qemu_mutex_unlock(&throttle_groups_lock);
356
}
357
358
-/* Get the name from a BlockBackend's ThrottleGroup. The name (and the pointer)
359
+/* Get the name from a ThrottleGroupMember's group. The name (and the pointer)
360
* is guaranteed to remain constant during the lifetime of the group.
361
*
362
- * @blk: a BlockBackend that is member of a throttling group
363
+ * @tgm: a ThrottleGroupMember
364
* @ret: the name of the group.
365
*/
366
-const char *throttle_group_get_name(BlockBackend *blk)
367
+const char *throttle_group_get_name(ThrottleGroupMember *tgm)
368
{
369
- BlockBackendPublic *blkp = blk_get_public(blk);
370
- ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts);
371
+ ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
372
return tg->name;
373
}
374
375
-/* Return the next BlockBackend in the round-robin sequence, simulating a
376
- * circular list.
377
+/* Return the next ThrottleGroupMember in the round-robin sequence, simulating
378
+ * a circular list.
379
*
380
* This assumes that tg->lock is held.
381
*
382
- * @blk: the current BlockBackend
383
- * @ret: the next BlockBackend in the sequence
384
+ * @tgm: the current ThrottleGroupMember
385
+ * @ret: the next ThrottleGroupMember in the sequence
386
*/
387
-static BlockBackend *throttle_group_next_blk(BlockBackend *blk)
388
+static ThrottleGroupMember *throttle_group_next_tgm(ThrottleGroupMember *tgm)
389
{
390
- BlockBackendPublic *blkp = blk_get_public(blk);
391
- ThrottleState *ts = blkp->throttle_state;
392
+ ThrottleState *ts = tgm->throttle_state;
393
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
394
- BlockBackendPublic *next = QLIST_NEXT(blkp, round_robin);
395
+ ThrottleGroupMember *next = QLIST_NEXT(tgm, round_robin);
396
397
if (!next) {
398
next = QLIST_FIRST(&tg->head);
399
}
400
401
- return blk_by_public(next);
402
+ return next;
403
}
404
405
/*
406
- * Return whether a BlockBackend has pending requests.
407
+ * Return whether a ThrottleGroupMember has pending requests.
408
*
409
* This assumes that tg->lock is held.
410
*
411
- * @blk: the BlockBackend
412
- * @is_write: the type of operation (read/write)
413
- * @ret: whether the BlockBackend has pending requests.
414
+ * @tgm: the ThrottleGroupMember
415
+ * @is_write: the type of operation (read/write)
416
+ * @ret: whether the ThrottleGroupMember has pending requests.
417
*/
418
-static inline bool blk_has_pending_reqs(BlockBackend *blk,
419
+static inline bool tgm_has_pending_reqs(ThrottleGroupMember *tgm,
420
bool is_write)
421
{
422
- const BlockBackendPublic *blkp = blk_get_public(blk);
423
- return blkp->pending_reqs[is_write];
424
+ return tgm->pending_reqs[is_write];
425
}
426
427
-/* Return the next BlockBackend in the round-robin sequence with pending I/O
428
- * requests.
429
+/* Return the next ThrottleGroupMember in the round-robin sequence with pending
430
+ * I/O requests.
431
*
432
* This assumes that tg->lock is held.
433
*
434
- * @blk: the current BlockBackend
435
+ * @tgm: the current ThrottleGroupMember
436
* @is_write: the type of operation (read/write)
437
- * @ret: the next BlockBackend with pending requests, or blk if there is
438
- * none.
439
+ * @ret: the next ThrottleGroupMember with pending requests, or tgm if
440
+ * there is none.
441
*/
442
-static BlockBackend *next_throttle_token(BlockBackend *blk, bool is_write)
443
+static ThrottleGroupMember *next_throttle_token(ThrottleGroupMember *tgm,
444
+ bool is_write)
445
{
446
- BlockBackendPublic *blkp = blk_get_public(blk);
447
- ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts);
448
- BlockBackend *token, *start;
449
+ ThrottleState *ts = tgm->throttle_state;
450
+ ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
451
+ ThrottleGroupMember *token, *start;
452
453
start = token = tg->tokens[is_write];
454
455
/* get next bs round in round robin style */
456
- token = throttle_group_next_blk(token);
457
- while (token != start && !blk_has_pending_reqs(token, is_write)) {
458
- token = throttle_group_next_blk(token);
459
+ token = throttle_group_next_tgm(token);
460
+ while (token != start && !tgm_has_pending_reqs(token, is_write)) {
461
+ token = throttle_group_next_tgm(token);
462
}
463
464
/* If no IO are queued for scheduling on the next round robin token
465
- * then decide the token is the current bs because chances are
466
- * the current bs get the current request queued.
467
+ * then decide the token is the current tgm because chances are
468
+ * the current tgm got the current request queued.
469
*/
470
- if (token == start && !blk_has_pending_reqs(token, is_write)) {
471
- token = blk;
472
+ if (token == start && !tgm_has_pending_reqs(token, is_write)) {
473
+ token = tgm;
474
}
475
476
- /* Either we return the original BB, or one with pending requests */
477
- assert(token == blk || blk_has_pending_reqs(token, is_write));
478
+ /* Either we return the original TGM, or one with pending requests */
479
+ assert(token == tgm || tgm_has_pending_reqs(token, is_write));
480
481
return token;
482
}
483
484
-/* Check if the next I/O request for a BlockBackend needs to be throttled or
485
- * not. If there's no timer set in this group, set one and update the token
486
- * accordingly.
487
+/* Check if the next I/O request for a ThrottleGroupMember needs to be
488
+ * throttled or not. If there's no timer set in this group, set one and update
489
+ * the token accordingly.
490
*
491
* This assumes that tg->lock is held.
492
*
493
- * @blk: the current BlockBackend
494
+ * @tgm: the current ThrottleGroupMember
495
* @is_write: the type of operation (read/write)
496
* @ret: whether the I/O request needs to be throttled or not
497
*/
498
-static bool throttle_group_schedule_timer(BlockBackend *blk, bool is_write)
499
+static bool throttle_group_schedule_timer(ThrottleGroupMember *tgm,
500
+ bool is_write)
501
{
502
- BlockBackendPublic *blkp = blk_get_public(blk);
503
- ThrottleState *ts = blkp->throttle_state;
504
- ThrottleTimers *tt = &blkp->throttle_timers;
505
+ ThrottleState *ts = tgm->throttle_state;
506
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
507
+ ThrottleTimers *tt = &tgm->throttle_timers;
508
bool must_wait;
509
510
- if (atomic_read(&blkp->io_limits_disabled)) {
511
+ if (atomic_read(&tgm->io_limits_disabled)) {
512
return false;
513
}
514
515
@@ -XXX,XX +XXX,XX @@ static bool throttle_group_schedule_timer(BlockBackend *blk, bool is_write)
516
517
must_wait = throttle_schedule_timer(ts, tt, is_write);
518
519
- /* If a timer just got armed, set blk as the current token */
520
+ /* If a timer just got armed, set tgm as the current token */
521
if (must_wait) {
522
- tg->tokens[is_write] = blk;
523
+ tg->tokens[is_write] = tgm;
524
tg->any_timer_armed[is_write] = true;
525
}
526
527
return must_wait;
528
}
529
530
-/* Start the next pending I/O request for a BlockBackend. Return whether
531
+/* Start the next pending I/O request for a ThrottleGroupMember. Return whether
532
* any request was actually pending.
533
*
534
- * @blk: the current BlockBackend
535
+ * @tgm: the current ThrottleGroupMember
536
* @is_write: the type of operation (read/write)
537
*/
538
-static bool coroutine_fn throttle_group_co_restart_queue(BlockBackend *blk,
539
+static bool coroutine_fn throttle_group_co_restart_queue(ThrottleGroupMember *tgm,
540
bool is_write)
541
{
542
- BlockBackendPublic *blkp = blk_get_public(blk);
543
bool ret;
544
545
- qemu_co_mutex_lock(&blkp->throttled_reqs_lock);
546
- ret = qemu_co_queue_next(&blkp->throttled_reqs[is_write]);
547
- qemu_co_mutex_unlock(&blkp->throttled_reqs_lock);
548
+ qemu_co_mutex_lock(&tgm->throttled_reqs_lock);
549
+ ret = qemu_co_queue_next(&tgm->throttled_reqs[is_write]);
550
+ qemu_co_mutex_unlock(&tgm->throttled_reqs_lock);
551
552
return ret;
553
}
554
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn throttle_group_co_restart_queue(BlockBackend *blk,
555
*
556
* This assumes that tg->lock is held.
557
*
558
- * @blk: the current BlockBackend
559
+ * @tgm: the current ThrottleGroupMember
560
* @is_write: the type of operation (read/write)
561
*/
562
-static void schedule_next_request(BlockBackend *blk, bool is_write)
563
+static void schedule_next_request(ThrottleGroupMember *tgm, bool is_write)
564
{
565
- BlockBackendPublic *blkp = blk_get_public(blk);
566
- ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts);
567
+ ThrottleState *ts = tgm->throttle_state;
568
+ ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
569
bool must_wait;
570
- BlockBackend *token;
571
+ ThrottleGroupMember *token;
572
573
/* Check if there's any pending request to schedule next */
574
- token = next_throttle_token(blk, is_write);
575
- if (!blk_has_pending_reqs(token, is_write)) {
576
+ token = next_throttle_token(tgm, is_write);
577
+ if (!tgm_has_pending_reqs(token, is_write)) {
578
return;
579
}
580
581
@@ -XXX,XX +XXX,XX @@ static void schedule_next_request(BlockBackend *blk, bool is_write)
582
583
/* If it doesn't have to wait, queue it for immediate execution */
584
if (!must_wait) {
585
- /* Give preference to requests from the current blk */
586
+ /* Give preference to requests from the current tgm */
587
if (qemu_in_coroutine() &&
588
- throttle_group_co_restart_queue(blk, is_write)) {
589
- token = blk;
590
+ throttle_group_co_restart_queue(tgm, is_write)) {
591
+ token = tgm;
592
} else {
593
- ThrottleTimers *tt = &blk_get_public(token)->throttle_timers;
594
+ ThrottleTimers *tt = &token->throttle_timers;
595
int64_t now = qemu_clock_get_ns(tg->clock_type);
596
timer_mod(tt->timers[is_write], now);
597
tg->any_timer_armed[is_write] = true;
598
@@ -XXX,XX +XXX,XX @@ static void schedule_next_request(BlockBackend *blk, bool is_write)
599
* if necessary, and schedule the next request using a round robin
600
* algorithm.
601
*
602
- * @blk: the current BlockBackend
603
+ * @tgm: the current ThrottleGroupMember
604
* @bytes: the number of bytes for this I/O
605
* @is_write: the type of operation (read/write)
606
*/
607
-void coroutine_fn throttle_group_co_io_limits_intercept(BlockBackend *blk,
608
+void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
609
unsigned int bytes,
610
bool is_write)
611
{
612
bool must_wait;
613
- BlockBackend *token;
614
-
615
- BlockBackendPublic *blkp = blk_get_public(blk);
616
- ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts);
617
+ ThrottleGroupMember *token;
618
+ ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
619
qemu_mutex_lock(&tg->lock);
620
621
/* First we check if this I/O has to be throttled. */
622
- token = next_throttle_token(blk, is_write);
623
+ token = next_throttle_token(tgm, is_write);
624
must_wait = throttle_group_schedule_timer(token, is_write);
625
626
/* Wait if there's a timer set or queued requests of this type */
627
- if (must_wait || blkp->pending_reqs[is_write]) {
628
- blkp->pending_reqs[is_write]++;
629
+ if (must_wait || tgm->pending_reqs[is_write]) {
630
+ tgm->pending_reqs[is_write]++;
631
qemu_mutex_unlock(&tg->lock);
632
- qemu_co_mutex_lock(&blkp->throttled_reqs_lock);
633
- qemu_co_queue_wait(&blkp->throttled_reqs[is_write],
634
- &blkp->throttled_reqs_lock);
635
- qemu_co_mutex_unlock(&blkp->throttled_reqs_lock);
636
+ qemu_co_mutex_lock(&tgm->throttled_reqs_lock);
637
+ qemu_co_queue_wait(&tgm->throttled_reqs[is_write],
638
+ &tgm->throttled_reqs_lock);
639
+ qemu_co_mutex_unlock(&tgm->throttled_reqs_lock);
640
qemu_mutex_lock(&tg->lock);
641
- blkp->pending_reqs[is_write]--;
642
+ tgm->pending_reqs[is_write]--;
643
}
644
645
/* The I/O will be executed, so do the accounting */
646
- throttle_account(blkp->throttle_state, is_write, bytes);
647
+ throttle_account(tgm->throttle_state, is_write, bytes);
648
649
/* Schedule the next request */
650
- schedule_next_request(blk, is_write);
651
+ schedule_next_request(tgm, is_write);
652
653
qemu_mutex_unlock(&tg->lock);
654
}
655
656
typedef struct {
657
- BlockBackend *blk;
658
+ ThrottleGroupMember *tgm;
659
bool is_write;
660
} RestartData;
661
662
static void coroutine_fn throttle_group_restart_queue_entry(void *opaque)
663
{
664
RestartData *data = opaque;
665
- BlockBackend *blk = data->blk;
666
+ ThrottleGroupMember *tgm = data->tgm;
667
+ ThrottleState *ts = tgm->throttle_state;
668
+ ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
669
bool is_write = data->is_write;
670
- BlockBackendPublic *blkp = blk_get_public(blk);
671
- ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts);
672
bool empty_queue;
673
674
- empty_queue = !throttle_group_co_restart_queue(blk, is_write);
675
+ empty_queue = !throttle_group_co_restart_queue(tgm, is_write);
676
677
/* If the request queue was empty then we have to take care of
678
* scheduling the next one */
679
if (empty_queue) {
680
qemu_mutex_lock(&tg->lock);
681
- schedule_next_request(blk, is_write);
682
+ schedule_next_request(tgm, is_write);
683
qemu_mutex_unlock(&tg->lock);
684
}
685
}
686
687
-static void throttle_group_restart_queue(BlockBackend *blk, bool is_write)
688
+static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write)
689
{
690
+ BlockBackendPublic *blkp = container_of(tgm, BlockBackendPublic,
691
+ throttle_group_member);
692
+ BlockBackend *blk = blk_by_public(blkp);
693
Coroutine *co;
694
RestartData rd = {
695
- .blk = blk,
696
+ .tgm = tgm,
697
.is_write = is_write
698
};
699
700
@@ -XXX,XX +XXX,XX @@ static void throttle_group_restart_queue(BlockBackend *blk, bool is_write)
701
aio_co_enter(blk_get_aio_context(blk), co);
702
}
703
704
-void throttle_group_restart_blk(BlockBackend *blk)
705
+void throttle_group_restart_tgm(ThrottleGroupMember *tgm)
706
{
707
- BlockBackendPublic *blkp = blk_get_public(blk);
708
-
709
- if (blkp->throttle_state) {
710
- throttle_group_restart_queue(blk, 0);
711
- throttle_group_restart_queue(blk, 1);
712
+ if (tgm->throttle_state) {
713
+ throttle_group_restart_queue(tgm, 0);
714
+ throttle_group_restart_queue(tgm, 1);
715
}
716
}
717
718
@@ -XXX,XX +XXX,XX @@ void throttle_group_restart_blk(BlockBackend *blk)
719
* to throttle_config(), but guarantees atomicity within the
720
* throttling group.
721
*
722
- * @blk: a BlockBackend that is a member of the group
723
+ * @tgm: a ThrottleGroupMember that is a member of the group
724
* @cfg: the configuration to set
725
*/
726
-void throttle_group_config(BlockBackend *blk, ThrottleConfig *cfg)
727
+void throttle_group_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg)
728
{
729
- BlockBackendPublic *blkp = blk_get_public(blk);
730
- ThrottleState *ts = blkp->throttle_state;
731
+ ThrottleState *ts = tgm->throttle_state;
732
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
733
qemu_mutex_lock(&tg->lock);
734
throttle_config(ts, tg->clock_type, cfg);
735
qemu_mutex_unlock(&tg->lock);
736
737
- throttle_group_restart_blk(blk);
738
+ throttle_group_restart_tgm(tgm);
739
}
740
741
/* Get the throttle configuration from a particular group. Similar to
742
* throttle_get_config(), but guarantees atomicity within the
743
* throttling group.
744
*
745
- * @blk: a BlockBackend that is a member of the group
746
+ * @tgm: a ThrottleGroupMember that is a member of the group
747
* @cfg: the configuration will be written here
748
*/
749
-void throttle_group_get_config(BlockBackend *blk, ThrottleConfig *cfg)
750
+void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg)
751
{
752
- BlockBackendPublic *blkp = blk_get_public(blk);
753
- ThrottleState *ts = blkp->throttle_state;
754
+ ThrottleState *ts = tgm->throttle_state;
755
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
756
qemu_mutex_lock(&tg->lock);
757
throttle_get_config(ts, cfg);
758
@@ -XXX,XX +XXX,XX @@ void throttle_group_get_config(BlockBackend *blk, ThrottleConfig *cfg)
759
static void timer_cb(BlockBackend *blk, bool is_write)
760
{
761
BlockBackendPublic *blkp = blk_get_public(blk);
762
- ThrottleState *ts = blkp->throttle_state;
763
+ ThrottleGroupMember *tgm = &blkp->throttle_group_member;
764
+ ThrottleState *ts = tgm->throttle_state;
765
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
766
767
/* The timer has just been fired, so we can update the flag */
768
@@ -XXX,XX +XXX,XX @@ static void timer_cb(BlockBackend *blk, bool is_write)
769
qemu_mutex_unlock(&tg->lock);
770
771
/* Run the request that was waiting for this timer */
772
- throttle_group_restart_queue(blk, is_write);
773
+ throttle_group_restart_queue(tgm, is_write);
774
}
775
776
static void read_timer_cb(void *opaque)
777
@@ -XXX,XX +XXX,XX @@ static void write_timer_cb(void *opaque)
778
timer_cb(opaque, true);
779
}
780
781
-/* Register a BlockBackend in the throttling group, also initializing its
782
- * timers and updating its throttle_state pointer to point to it. If a
783
+/* Register a ThrottleGroupMember from the throttling group, also initializing
784
+ * its timers and updating its throttle_state pointer to point to it. If a
785
* throttling group with that name does not exist yet, it will be created.
786
*
787
- * @blk: the BlockBackend to insert
788
+ * @tgm: the ThrottleGroupMember to insert
789
* @groupname: the name of the group
790
*/
791
-void throttle_group_register_blk(BlockBackend *blk, const char *groupname)
792
+void throttle_group_register_tgm(ThrottleGroupMember *tgm,
793
+ const char *groupname)
794
{
795
int i;
796
- BlockBackendPublic *blkp = blk_get_public(blk);
797
+ BlockBackendPublic *blkp = container_of(tgm, BlockBackendPublic,
798
+ throttle_group_member);
799
+ BlockBackend *blk = blk_by_public(blkp);
800
ThrottleState *ts = throttle_group_incref(groupname);
801
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
802
- blkp->throttle_state = ts;
803
+
804
+ tgm->throttle_state = ts;
805
806
qemu_mutex_lock(&tg->lock);
807
- /* If the ThrottleGroup is new set this BlockBackend as the token */
808
+ /* If the ThrottleGroup is new set this ThrottleGroupMember as the token */
809
for (i = 0; i < 2; i++) {
810
if (!tg->tokens[i]) {
811
- tg->tokens[i] = blk;
812
+ tg->tokens[i] = tgm;
813
}
814
}
815
816
- QLIST_INSERT_HEAD(&tg->head, blkp, round_robin);
817
+ QLIST_INSERT_HEAD(&tg->head, tgm, round_robin);
818
819
- throttle_timers_init(&blkp->throttle_timers,
820
+ throttle_timers_init(&tgm->throttle_timers,
821
blk_get_aio_context(blk),
822
tg->clock_type,
823
read_timer_cb,
824
@@ -XXX,XX +XXX,XX @@ void throttle_group_register_blk(BlockBackend *blk, const char *groupname)
825
qemu_mutex_unlock(&tg->lock);
826
}
827
828
-/* Unregister a BlockBackend from its group, removing it from the list,
829
+/* Unregister a ThrottleGroupMember from its group, removing it from the list,
830
* destroying the timers and setting the throttle_state pointer to NULL.
831
*
832
- * The BlockBackend must not have pending throttled requests, so the caller has
833
- * to drain them first.
834
+ * The ThrottleGroupMember must not have pending throttled requests, so the
835
+ * caller has to drain them first.
836
*
837
* The group will be destroyed if it's empty after this operation.
838
*
839
- * @blk: the BlockBackend to remove
840
+ * @tgm the ThrottleGroupMember to remove
841
*/
842
-void throttle_group_unregister_blk(BlockBackend *blk)
843
+void throttle_group_unregister_tgm(ThrottleGroupMember *tgm)
844
{
845
- BlockBackendPublic *blkp = blk_get_public(blk);
846
- ThrottleGroup *tg = container_of(blkp->throttle_state, ThrottleGroup, ts);
847
+ ThrottleState *ts = tgm->throttle_state;
848
+ ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
849
+ ThrottleGroupMember *token;
850
int i;
851
852
- assert(blkp->pending_reqs[0] == 0 && blkp->pending_reqs[1] == 0);
853
- assert(qemu_co_queue_empty(&blkp->throttled_reqs[0]));
854
- assert(qemu_co_queue_empty(&blkp->throttled_reqs[1]));
855
+ assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0);
856
+ assert(qemu_co_queue_empty(&tgm->throttled_reqs[0]));
857
+ assert(qemu_co_queue_empty(&tgm->throttled_reqs[1]));
858
859
qemu_mutex_lock(&tg->lock);
860
for (i = 0; i < 2; i++) {
861
- if (tg->tokens[i] == blk) {
862
- BlockBackend *token = throttle_group_next_blk(blk);
863
- /* Take care of the case where this is the last blk in the group */
864
- if (token == blk) {
865
+ if (tg->tokens[i] == tgm) {
866
+ token = throttle_group_next_tgm(tgm);
867
+ /* Take care of the case where this is the last tgm in the group */
868
+ if (token == tgm) {
869
token = NULL;
870
}
871
tg->tokens[i] = token;
872
}
873
}
874
875
- /* remove the current blk from the list */
876
- QLIST_REMOVE(blkp, round_robin);
877
- throttle_timers_destroy(&blkp->throttle_timers);
878
+ /* remove the current tgm from the list */
879
+ QLIST_REMOVE(tgm, round_robin);
880
+ throttle_timers_destroy(&tgm->throttle_timers);
881
qemu_mutex_unlock(&tg->lock);
882
883
throttle_group_unref(&tg->ts);
884
- blkp->throttle_state = NULL;
885
+ tgm->throttle_state = NULL;
886
}
887
888
static void throttle_groups_init(void)
889
diff --git a/blockdev.c b/blockdev.c
890
index XXXXXXX..XXXXXXX 100644
891
--- a/blockdev.c
892
+++ b/blockdev.c
893
@@ -XXX,XX +XXX,XX @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp)
894
if (throttle_enabled(&cfg)) {
895
/* Enable I/O limits if they're not enabled yet, otherwise
896
* just update the throttling group. */
897
- if (!blk_get_public(blk)->throttle_state) {
898
+ if (!blk_get_public(blk)->throttle_group_member.throttle_state) {
899
blk_io_limits_enable(blk,
900
arg->has_group ? arg->group :
901
arg->has_device ? arg->device :
902
@@ -XXX,XX +XXX,XX @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp)
903
}
904
/* Set the new throttling configuration */
905
blk_set_io_limits(blk, &cfg);
906
- } else if (blk_get_public(blk)->throttle_state) {
907
+ } else if (blk_get_public(blk)->throttle_group_member.throttle_state) {
908
/* If all throttling settings are set to 0, disable I/O limits */
909
blk_io_limits_disable(blk);
910
}
911
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
912
index XXXXXXX..XXXXXXX 100644
913
--- a/tests/test-throttle.c
914
+++ b/tests/test-throttle.c
915
@@ -XXX,XX +XXX,XX @@ static void test_groups(void)
916
ThrottleConfig cfg1, cfg2;
917
BlockBackend *blk1, *blk2, *blk3;
918
BlockBackendPublic *blkp1, *blkp2, *blkp3;
919
+ ThrottleGroupMember *tgm1, *tgm2, *tgm3;
920
921
/* No actual I/O is performed on these devices */
922
blk1 = blk_new(0, BLK_PERM_ALL);
923
@@ -XXX,XX +XXX,XX @@ static void test_groups(void)
924
blkp2 = blk_get_public(blk2);
925
blkp3 = blk_get_public(blk3);
926
927
- g_assert(blkp1->throttle_state == NULL);
928
- g_assert(blkp2->throttle_state == NULL);
929
- g_assert(blkp3->throttle_state == NULL);
930
+ tgm1 = &blkp1->throttle_group_member;
931
+ tgm2 = &blkp2->throttle_group_member;
932
+ tgm3 = &blkp3->throttle_group_member;
933
934
- throttle_group_register_blk(blk1, "bar");
935
- throttle_group_register_blk(blk2, "foo");
936
- throttle_group_register_blk(blk3, "bar");
937
+ g_assert(tgm1->throttle_state == NULL);
938
+ g_assert(tgm2->throttle_state == NULL);
939
+ g_assert(tgm3->throttle_state == NULL);
940
941
- g_assert(blkp1->throttle_state != NULL);
942
- g_assert(blkp2->throttle_state != NULL);
943
- g_assert(blkp3->throttle_state != NULL);
944
+ throttle_group_register_tgm(tgm1, "bar");
945
+ throttle_group_register_tgm(tgm2, "foo");
946
+ throttle_group_register_tgm(tgm3, "bar");
947
948
- g_assert(!strcmp(throttle_group_get_name(blk1), "bar"));
949
- g_assert(!strcmp(throttle_group_get_name(blk2), "foo"));
950
- g_assert(blkp1->throttle_state == blkp3->throttle_state);
951
+ g_assert(tgm1->throttle_state != NULL);
952
+ g_assert(tgm2->throttle_state != NULL);
953
+ g_assert(tgm3->throttle_state != NULL);
954
+
955
+ g_assert(!strcmp(throttle_group_get_name(tgm1), "bar"));
956
+ g_assert(!strcmp(throttle_group_get_name(tgm2), "foo"));
957
+ g_assert(tgm1->throttle_state == tgm3->throttle_state);
958
959
/* Setting the config of a group member affects the whole group */
960
throttle_config_init(&cfg1);
961
@@ -XXX,XX +XXX,XX @@ static void test_groups(void)
962
cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
963
cfg1.buckets[THROTTLE_OPS_READ].avg = 20000;
964
cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
965
- throttle_group_config(blk1, &cfg1);
966
+ throttle_group_config(tgm1, &cfg1);
967
968
- throttle_group_get_config(blk1, &cfg1);
969
- throttle_group_get_config(blk3, &cfg2);
970
+ throttle_group_get_config(tgm1, &cfg1);
971
+ throttle_group_get_config(tgm3, &cfg2);
972
g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
973
974
cfg2.buckets[THROTTLE_BPS_READ].avg = 4547;
975
cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
976
cfg2.buckets[THROTTLE_OPS_READ].avg = 123;
977
cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
978
- throttle_group_config(blk3, &cfg1);
979
+ throttle_group_config(tgm3, &cfg1);
980
981
- throttle_group_get_config(blk1, &cfg1);
982
- throttle_group_get_config(blk3, &cfg2);
983
+ throttle_group_get_config(tgm1, &cfg1);
984
+ throttle_group_get_config(tgm3, &cfg2);
985
g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
986
987
- throttle_group_unregister_blk(blk1);
988
- throttle_group_unregister_blk(blk2);
989
- throttle_group_unregister_blk(blk3);
990
+ throttle_group_unregister_tgm(tgm1);
991
+ throttle_group_unregister_tgm(tgm2);
992
+ throttle_group_unregister_tgm(tgm3);
993
994
- g_assert(blkp1->throttle_state == NULL);
995
- g_assert(blkp2->throttle_state == NULL);
996
- g_assert(blkp3->throttle_state == NULL);
997
+ g_assert(tgm1->throttle_state == NULL);
998
+ g_assert(tgm2->throttle_state == NULL);
999
+ g_assert(tgm3->throttle_state == NULL);
1000
}
1001
1002
int main(int argc, char **argv)
1003
--
63
--
1004
2.13.5
64
2.19.1
1005
65
1006
66
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Cleber Rosa <crosa@redhat.com>
2
2
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
While testing the Python 3 changes which touch the 083 test, I noticed
4
Reviewed-by: Eric Blake <eblake@redhat.com>
4
that it would fail with qcow2. Expanding the testing, I noticed it
5
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
5
had nothing to do with the Python 3 changes, and in fact, it would not
6
pass on anything but raw:
7
8
raw: pass
9
bochs: not generic
10
cloop: not generic
11
parallels: fail
12
qcow: fail
13
qcow2: fail
14
qed: fail
15
vdi: fail
16
vhdx: fail
17
vmdk: fail
18
vpc: fail
19
luks: fail
20
21
The errors are a mixture I/O and "image not in xxx format", such as:
22
23
=== Check disconnect before data ===
24
25
Unexpected end-of-file before all bytes were read
26
-read failed: Input/output error
27
+can't open device nbd+tcp://127.0.0.1:PORT/foo: Could not open 'nbd://127.0.0.1:PORT/foo': Input/output error
28
29
=== Check disconnect after data ===
30
31
-read 512/512 bytes at offset 0
32
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
33
+can't open device nbd+tcp://127.0.0.1:PORT/foo: Image not in qcow format
34
35
I'm not aware if there's a quick fix, so, for the time being, it looks
36
like the honest approach is to make the test known to work on raw
37
only.
38
39
Signed-off-by: Cleber Rosa <crosa@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
41
---
8
include/block/block_int.h | 31 +++++++++++++++++++++++++++++++
42
tests/qemu-iotests/083 | 2 +-
9
1 file changed, 31 insertions(+)
43
1 file changed, 1 insertion(+), 1 deletion(-)
10
44
11
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
12
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100755
13
--- a/include/block/block_int.h
47
--- a/tests/qemu-iotests/083
14
+++ b/include/block/block_int.h
48
+++ b/tests/qemu-iotests/083
15
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
16
50
. ./common.rc
17
int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
51
. ./common.filter
18
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
52
19
+
53
-_supported_fmt generic
20
+ /**
54
+_supported_fmt raw
21
+ * @offset: position in bytes to read at
55
_supported_proto nbd
22
+ * @bytes: number of bytes to read
56
_supported_os Linux
23
+ * @qiov: the buffers to fill with read data
24
+ * @flags: currently unused, always 0
25
+ *
26
+ * @offset and @bytes will be a multiple of 'request_alignment',
27
+ * but the length of individual @qiov elements does not have to
28
+ * be a multiple.
29
+ *
30
+ * @bytes will always equal the total size of @qiov, and will be
31
+ * no larger than 'max_transfer'.
32
+ *
33
+ * The buffer in @qiov may point directly to guest memory.
34
+ */
35
int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs,
36
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags);
37
int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
38
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
39
int coroutine_fn (*bdrv_co_writev_flags)(BlockDriverState *bs,
40
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags);
41
+ /**
42
+ * @offset: position in bytes to write at
43
+ * @bytes: number of bytes to write
44
+ * @qiov: the buffers containing data to write
45
+ * @flags: zero or more bits allowed by 'supported_write_flags'
46
+ *
47
+ * @offset and @bytes will be a multiple of 'request_alignment',
48
+ * but the length of individual @qiov elements does not have to
49
+ * be a multiple.
50
+ *
51
+ * @bytes will always equal the total size of @qiov, and will be
52
+ * no larger than 'max_transfer'.
53
+ *
54
+ * The buffer in @qiov may point directly to guest memory.
55
+ */
56
int coroutine_fn (*bdrv_co_pwritev)(BlockDriverState *bs,
57
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags);
58
57
59
--
58
--
60
2.13.5
59
2.19.1
61
60
62
61
diff view generated by jsdifflib
New patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Alberto Garcia <berto@igalia.com>
3
---
4
block/vpc.c | 2 ++
5
1 file changed, 2 insertions(+)
1
6
7
diff --git a/block/vpc.c b/block/vpc.c
8
index XXXXXXX..XXXXXXX 100644
9
--- a/block/vpc.c
10
+++ b/block/vpc.c
11
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
12
}
13
14
qemu_co_mutex_init(&s->lock);
15
+ qemu_opts_del(opts);
16
17
return 0;
18
19
fail:
20
+ qemu_opts_del(opts);
21
qemu_vfree(s->pagetable);
22
#ifdef CACHE
23
g_free(s->pageentry_u8);
24
--
25
2.19.1
26
27
diff view generated by jsdifflib
New patch
1
1
From: Peter Maydell <peter.maydell@linaro.org>
2
3
Taking the address of a field in a packed struct is a bad idea, because
4
it might not be actually aligned enough for that pointer type (and
5
thus cause a crash on dereference on some host architectures). Newer
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
9
There are a few places where the in-place swap function is
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
block/vhdx.h | 12 ++---
20
block/vhdx-endian.c | 118 ++++++++++++++++++++++----------------------
21
block/vhdx-log.c | 4 +-
22
block/vhdx.c | 18 +++----
23
4 files changed, 76 insertions(+), 76 deletions(-)
24
25
diff --git a/block/vhdx.h b/block/vhdx.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/vhdx.h
28
+++ b/block/vhdx.h
29
@@ -XXX,XX +XXX,XX @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
30
31
static inline void leguid_to_cpus(MSGUID *guid)
32
{
33
- le32_to_cpus(&guid->data1);
34
- le16_to_cpus(&guid->data2);
35
- le16_to_cpus(&guid->data3);
36
+ guid->data1 = le32_to_cpu(guid->data1);
37
+ guid->data2 = le16_to_cpu(guid->data2);
38
+ guid->data3 = le16_to_cpu(guid->data3);
39
}
40
41
static inline void cpu_to_leguids(MSGUID *guid)
42
{
43
- cpu_to_le32s(&guid->data1);
44
- cpu_to_le16s(&guid->data2);
45
- cpu_to_le16s(&guid->data3);
46
+ guid->data1 = cpu_to_le32(guid->data1);
47
+ guid->data2 = cpu_to_le16(guid->data2);
48
+ guid->data3 = cpu_to_le16(guid->data3);
49
}
50
51
void vhdx_header_le_import(VHDXHeader *h);
52
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/block/vhdx-endian.c
55
+++ b/block/vhdx-endian.c
56
@@ -XXX,XX +XXX,XX @@ void vhdx_header_le_import(VHDXHeader *h)
57
{
58
assert(h != NULL);
59
60
- le32_to_cpus(&h->signature);
61
- le32_to_cpus(&h->checksum);
62
- le64_to_cpus(&h->sequence_number);
63
+ h->signature = le32_to_cpu(h->signature);
64
+ h->checksum = le32_to_cpu(h->checksum);
65
+ h->sequence_number = le64_to_cpu(h->sequence_number);
66
67
leguid_to_cpus(&h->file_write_guid);
68
leguid_to_cpus(&h->data_write_guid);
69
leguid_to_cpus(&h->log_guid);
70
71
- le16_to_cpus(&h->log_version);
72
- le16_to_cpus(&h->version);
73
- le32_to_cpus(&h->log_length);
74
- le64_to_cpus(&h->log_offset);
75
+ h->log_version = le16_to_cpu(h->log_version);
76
+ h->version = le16_to_cpu(h->version);
77
+ h->log_length = le32_to_cpu(h->log_length);
78
+ h->log_offset = le64_to_cpu(h->log_offset);
79
}
80
81
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
82
@@ -XXX,XX +XXX,XX @@ void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
83
{
84
assert(d != NULL);
85
86
- le32_to_cpus(&d->signature);
87
- le64_to_cpus(&d->file_offset);
88
- le64_to_cpus(&d->sequence_number);
89
+ d->signature = le32_to_cpu(d->signature);
90
+ d->file_offset = le64_to_cpu(d->file_offset);
91
+ d->sequence_number = le64_to_cpu(d->sequence_number);
92
}
93
94
void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
95
{
96
assert(d != NULL);
97
98
- cpu_to_le32s(&d->signature);
99
- cpu_to_le32s(&d->trailing_bytes);
100
- cpu_to_le64s(&d->leading_bytes);
101
- cpu_to_le64s(&d->file_offset);
102
- cpu_to_le64s(&d->sequence_number);
103
+ d->signature = cpu_to_le32(d->signature);
104
+ d->trailing_bytes = cpu_to_le32(d->trailing_bytes);
105
+ d->leading_bytes = cpu_to_le64(d->leading_bytes);
106
+ d->file_offset = cpu_to_le64(d->file_offset);
107
+ d->sequence_number = cpu_to_le64(d->sequence_number);
108
}
109
110
void vhdx_log_data_le_import(VHDXLogDataSector *d)
111
{
112
assert(d != NULL);
113
114
- le32_to_cpus(&d->data_signature);
115
- le32_to_cpus(&d->sequence_high);
116
- le32_to_cpus(&d->sequence_low);
117
+ d->data_signature = le32_to_cpu(d->data_signature);
118
+ d->sequence_high = le32_to_cpu(d->sequence_high);
119
+ d->sequence_low = le32_to_cpu(d->sequence_low);
120
}
121
122
void vhdx_log_data_le_export(VHDXLogDataSector *d)
123
{
124
assert(d != NULL);
125
126
- cpu_to_le32s(&d->data_signature);
127
- cpu_to_le32s(&d->sequence_high);
128
- cpu_to_le32s(&d->sequence_low);
129
+ d->data_signature = cpu_to_le32(d->data_signature);
130
+ d->sequence_high = cpu_to_le32(d->sequence_high);
131
+ d->sequence_low = cpu_to_le32(d->sequence_low);
132
}
133
134
void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr)
135
{
136
assert(hdr != NULL);
137
138
- le32_to_cpus(&hdr->signature);
139
- le32_to_cpus(&hdr->checksum);
140
- le32_to_cpus(&hdr->entry_length);
141
- le32_to_cpus(&hdr->tail);
142
- le64_to_cpus(&hdr->sequence_number);
143
- le32_to_cpus(&hdr->descriptor_count);
144
+ hdr->signature = le32_to_cpu(hdr->signature);
145
+ hdr->checksum = le32_to_cpu(hdr->checksum);
146
+ hdr->entry_length = le32_to_cpu(hdr->entry_length);
147
+ hdr->tail = le32_to_cpu(hdr->tail);
148
+ hdr->sequence_number = le64_to_cpu(hdr->sequence_number);
149
+ hdr->descriptor_count = le32_to_cpu(hdr->descriptor_count);
150
leguid_to_cpus(&hdr->log_guid);
151
- le64_to_cpus(&hdr->flushed_file_offset);
152
- le64_to_cpus(&hdr->last_file_offset);
153
+ hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset);
154
+ hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset);
155
}
156
157
void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr)
158
{
159
assert(hdr != NULL);
160
161
- cpu_to_le32s(&hdr->signature);
162
- cpu_to_le32s(&hdr->checksum);
163
- cpu_to_le32s(&hdr->entry_length);
164
- cpu_to_le32s(&hdr->tail);
165
- cpu_to_le64s(&hdr->sequence_number);
166
- cpu_to_le32s(&hdr->descriptor_count);
167
+ hdr->signature = cpu_to_le32(hdr->signature);
168
+ hdr->checksum = cpu_to_le32(hdr->checksum);
169
+ hdr->entry_length = cpu_to_le32(hdr->entry_length);
170
+ hdr->tail = cpu_to_le32(hdr->tail);
171
+ hdr->sequence_number = cpu_to_le64(hdr->sequence_number);
172
+ hdr->descriptor_count = cpu_to_le32(hdr->descriptor_count);
173
cpu_to_leguids(&hdr->log_guid);
174
- cpu_to_le64s(&hdr->flushed_file_offset);
175
- cpu_to_le64s(&hdr->last_file_offset);
176
+ hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset);
177
+ hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset);
178
}
179
180
181
@@ -XXX,XX +XXX,XX @@ void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr)
182
{
183
assert(hdr != NULL);
184
185
- le32_to_cpus(&hdr->signature);
186
- le32_to_cpus(&hdr->checksum);
187
- le32_to_cpus(&hdr->entry_count);
188
+ hdr->signature = le32_to_cpu(hdr->signature);
189
+ hdr->checksum = le32_to_cpu(hdr->checksum);
190
+ hdr->entry_count = le32_to_cpu(hdr->entry_count);
191
}
192
193
void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr)
194
{
195
assert(hdr != NULL);
196
197
- cpu_to_le32s(&hdr->signature);
198
- cpu_to_le32s(&hdr->checksum);
199
- cpu_to_le32s(&hdr->entry_count);
200
+ hdr->signature = cpu_to_le32(hdr->signature);
201
+ hdr->checksum = cpu_to_le32(hdr->checksum);
202
+ hdr->entry_count = cpu_to_le32(hdr->entry_count);
203
}
204
205
void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
206
@@ -XXX,XX +XXX,XX @@ void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
207
assert(e != NULL);
208
209
leguid_to_cpus(&e->guid);
210
- le64_to_cpus(&e->file_offset);
211
- le32_to_cpus(&e->length);
212
- le32_to_cpus(&e->data_bits);
213
+ e->file_offset = le64_to_cpu(e->file_offset);
214
+ e->length = le32_to_cpu(e->length);
215
+ e->data_bits = le32_to_cpu(e->data_bits);
216
}
217
218
void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
219
@@ -XXX,XX +XXX,XX @@ void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
220
assert(e != NULL);
221
222
cpu_to_leguids(&e->guid);
223
- cpu_to_le64s(&e->file_offset);
224
- cpu_to_le32s(&e->length);
225
- cpu_to_le32s(&e->data_bits);
226
+ e->file_offset = cpu_to_le64(e->file_offset);
227
+ e->length = cpu_to_le32(e->length);
228
+ e->data_bits = cpu_to_le32(e->data_bits);
229
}
230
231
232
@@ -XXX,XX +XXX,XX @@ void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr)
233
{
234
assert(hdr != NULL);
235
236
- le64_to_cpus(&hdr->signature);
237
- le16_to_cpus(&hdr->entry_count);
238
+ hdr->signature = le64_to_cpu(hdr->signature);
239
+ hdr->entry_count = le16_to_cpu(hdr->entry_count);
240
}
241
242
void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr)
243
{
244
assert(hdr != NULL);
245
246
- cpu_to_le64s(&hdr->signature);
247
- cpu_to_le16s(&hdr->entry_count);
248
+ hdr->signature = cpu_to_le64(hdr->signature);
249
+ hdr->entry_count = cpu_to_le16(hdr->entry_count);
250
}
251
252
void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
253
@@ -XXX,XX +XXX,XX @@ void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
254
assert(e != NULL);
255
256
leguid_to_cpus(&e->item_id);
257
- le32_to_cpus(&e->offset);
258
- le32_to_cpus(&e->length);
259
- le32_to_cpus(&e->data_bits);
260
+ e->offset = le32_to_cpu(e->offset);
261
+ e->length = le32_to_cpu(e->length);
262
+ e->data_bits = le32_to_cpu(e->data_bits);
263
}
264
void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e)
265
{
266
assert(e != NULL);
267
268
cpu_to_leguids(&e->item_id);
269
- cpu_to_le32s(&e->offset);
270
- cpu_to_le32s(&e->length);
271
- cpu_to_le32s(&e->data_bits);
272
+ e->offset = cpu_to_le32(e->offset);
273
+ e->length = cpu_to_le32(e->length);
274
+ e->data_bits = cpu_to_le32(e->data_bits);
275
}
276
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/block/vhdx-log.c
279
+++ b/block/vhdx-log.c
280
@@ -XXX,XX +XXX,XX @@ static void vhdx_log_raw_to_le_sector(VHDXLogDescriptor *desc,
281
/* 8 + 4084 + 4 = 4096, 1 log sector */
282
memcpy(&desc->leading_bytes, data, 8);
283
data += 8;
284
- cpu_to_le64s(&desc->leading_bytes);
285
+ desc->leading_bytes = cpu_to_le64(desc->leading_bytes);
286
memcpy(sector->data, data, 4084);
287
data += 4084;
288
memcpy(&desc->trailing_bytes, data, 4);
289
- cpu_to_le32s(&desc->trailing_bytes);
290
+ desc->trailing_bytes = cpu_to_le32(desc->trailing_bytes);
291
data += 4;
292
293
sector->sequence_high = (uint32_t) (seq >> 32);
294
diff --git a/block/vhdx.c b/block/vhdx.c
295
index XXXXXXX..XXXXXXX 100644
296
--- a/block/vhdx.c
297
+++ b/block/vhdx.c
298
@@ -XXX,XX +XXX,XX @@ uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset)
299
300
memset(buf + crc_offset, 0, sizeof(crc));
301
crc = crc32c(0xffffffff, buf, size);
302
- cpu_to_le32s(&crc);
303
+ crc = cpu_to_le32(crc);
304
memcpy(buf + crc_offset, &crc, sizeof(crc));
305
306
return crc;
307
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
308
goto exit;
309
}
310
311
- le32_to_cpus(&s->params.block_size);
312
- le32_to_cpus(&s->params.data_bits);
313
+ s->params.block_size = le32_to_cpu(s->params.block_size);
314
+ s->params.data_bits = le32_to_cpu(s->params.data_bits);
315
316
317
/* We now have the file parameters, so we can tell if this is a
318
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
319
goto exit;
320
}
321
322
- le64_to_cpus(&s->virtual_disk_size);
323
- le32_to_cpus(&s->logical_sector_size);
324
- le32_to_cpus(&s->physical_sector_size);
325
+ s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
326
+ s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
327
+ s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
328
329
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
330
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
331
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
332
/* endian convert, and verify populated BAT field file offsets against
333
* region table and log entries */
334
for (i = 0; i < s->bat_entries; i++) {
335
- le64_to_cpus(&s->bat[i]);
336
+ s->bat[i] = le64_to_cpu(s->bat[i]);
337
if (payblocks--) {
338
/* payload bat entries */
339
if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
340
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_new_metadata(BlockBackend *blk,
341
mt_file_params->block_size = cpu_to_le32(block_size);
342
if (type == VHDX_TYPE_FIXED) {
343
mt_file_params->data_bits |= VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED;
344
- cpu_to_le32s(&mt_file_params->data_bits);
345
+ mt_file_params->data_bits = cpu_to_le32(mt_file_params->data_bits);
346
}
347
348
vhdx_guid_generate(&mt_page83->page_83_data);
349
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
350
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
351
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
352
block_state);
353
- cpu_to_le64s(&s->bat[sinfo.bat_idx]);
354
+ s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
355
sector_num += s->sectors_per_block;
356
}
357
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
358
--
359
2.19.1
360
361
diff view generated by jsdifflib
New patch
1
From: Peter Maydell <peter.maydell@linaro.org>
1
2
3
Taking the address of a field in a packed struct is a bad idea, because
4
it might not be actually aligned enough for that pointer type (and
5
thus cause a crash on dereference on some host architectures). Newer
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
9
There are a few places where the in-place swap function is
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
14
15
There are other places where we take the address of a packed member
16
in this file for other purposes than passing it to a byteswap
17
function (all the calls to qemu_uuid_*()); we leave those for now.
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
block/vdi.c | 64 ++++++++++++++++++++++++++---------------------------
24
1 file changed, 32 insertions(+), 32 deletions(-)
25
26
diff --git a/block/vdi.c b/block/vdi.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/vdi.c
29
+++ b/block/vdi.c
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
32
static void vdi_header_to_cpu(VdiHeader *header)
33
{
34
- le32_to_cpus(&header->signature);
35
- le32_to_cpus(&header->version);
36
- le32_to_cpus(&header->header_size);
37
- le32_to_cpus(&header->image_type);
38
- le32_to_cpus(&header->image_flags);
39
- le32_to_cpus(&header->offset_bmap);
40
- le32_to_cpus(&header->offset_data);
41
- le32_to_cpus(&header->cylinders);
42
- le32_to_cpus(&header->heads);
43
- le32_to_cpus(&header->sectors);
44
- le32_to_cpus(&header->sector_size);
45
- le64_to_cpus(&header->disk_size);
46
- le32_to_cpus(&header->block_size);
47
- le32_to_cpus(&header->block_extra);
48
- le32_to_cpus(&header->blocks_in_image);
49
- le32_to_cpus(&header->blocks_allocated);
50
+ header->signature = le32_to_cpu(header->signature);
51
+ header->version = le32_to_cpu(header->version);
52
+ header->header_size = le32_to_cpu(header->header_size);
53
+ header->image_type = le32_to_cpu(header->image_type);
54
+ header->image_flags = le32_to_cpu(header->image_flags);
55
+ header->offset_bmap = le32_to_cpu(header->offset_bmap);
56
+ header->offset_data = le32_to_cpu(header->offset_data);
57
+ header->cylinders = le32_to_cpu(header->cylinders);
58
+ header->heads = le32_to_cpu(header->heads);
59
+ header->sectors = le32_to_cpu(header->sectors);
60
+ header->sector_size = le32_to_cpu(header->sector_size);
61
+ header->disk_size = le64_to_cpu(header->disk_size);
62
+ header->block_size = le32_to_cpu(header->block_size);
63
+ header->block_extra = le32_to_cpu(header->block_extra);
64
+ header->blocks_in_image = le32_to_cpu(header->blocks_in_image);
65
+ header->blocks_allocated = le32_to_cpu(header->blocks_allocated);
66
qemu_uuid_bswap(&header->uuid_image);
67
qemu_uuid_bswap(&header->uuid_last_snap);
68
qemu_uuid_bswap(&header->uuid_link);
69
@@ -XXX,XX +XXX,XX @@ static void vdi_header_to_cpu(VdiHeader *header)
70
71
static void vdi_header_to_le(VdiHeader *header)
72
{
73
- cpu_to_le32s(&header->signature);
74
- cpu_to_le32s(&header->version);
75
- cpu_to_le32s(&header->header_size);
76
- cpu_to_le32s(&header->image_type);
77
- cpu_to_le32s(&header->image_flags);
78
- cpu_to_le32s(&header->offset_bmap);
79
- cpu_to_le32s(&header->offset_data);
80
- cpu_to_le32s(&header->cylinders);
81
- cpu_to_le32s(&header->heads);
82
- cpu_to_le32s(&header->sectors);
83
- cpu_to_le32s(&header->sector_size);
84
- cpu_to_le64s(&header->disk_size);
85
- cpu_to_le32s(&header->block_size);
86
- cpu_to_le32s(&header->block_extra);
87
- cpu_to_le32s(&header->blocks_in_image);
88
- cpu_to_le32s(&header->blocks_allocated);
89
+ header->signature = cpu_to_le32(header->signature);
90
+ header->version = cpu_to_le32(header->version);
91
+ header->header_size = cpu_to_le32(header->header_size);
92
+ header->image_type = cpu_to_le32(header->image_type);
93
+ header->image_flags = cpu_to_le32(header->image_flags);
94
+ header->offset_bmap = cpu_to_le32(header->offset_bmap);
95
+ header->offset_data = cpu_to_le32(header->offset_data);
96
+ header->cylinders = cpu_to_le32(header->cylinders);
97
+ header->heads = cpu_to_le32(header->heads);
98
+ header->sectors = cpu_to_le32(header->sectors);
99
+ header->sector_size = cpu_to_le32(header->sector_size);
100
+ header->disk_size = cpu_to_le64(header->disk_size);
101
+ header->block_size = cpu_to_le32(header->block_size);
102
+ header->block_extra = cpu_to_le32(header->block_extra);
103
+ header->blocks_in_image = cpu_to_le32(header->blocks_in_image);
104
+ header->blocks_allocated = cpu_to_le32(header->blocks_allocated);
105
qemu_uuid_bswap(&header->uuid_image);
106
qemu_uuid_bswap(&header->uuid_last_snap);
107
qemu_uuid_bswap(&header->uuid_link);
108
--
109
2.19.1
110
111
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Now that bdrv_truncate is passed to bs->file by default, remove the
3
This is a static function with only one caller, so there's no need to
4
callback from block/blkdebug.c and set is_filter to true. is_filter also gives
4
keep it. Inlining the code in quorum_compare() makes it much simpler.
5
access to other callbacks that are forwarded automatically to bs->file for
6
filters.
7
5
8
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reported-by: Markus Armbruster <armbru@redhat.com>
10
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
block/blkdebug.c | 8 +-------
10
block/quorum.c | 24 +++++-------------------
14
1 file changed, 1 insertion(+), 7 deletions(-)
11
1 file changed, 5 insertions(+), 19 deletions(-)
15
12
16
diff --git a/block/blkdebug.c b/block/blkdebug.c
13
diff --git a/block/quorum.c b/block/quorum.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/block/blkdebug.c
15
--- a/block/quorum.c
19
+++ b/block/blkdebug.c
16
+++ b/block/quorum.c
20
@@ -XXX,XX +XXX,XX @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
17
@@ -XXX,XX +XXX,XX @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
21
return bdrv_getlength(bs->file->bs);
18
return true;
22
}
19
}
23
20
24
-static int blkdebug_truncate(BlockDriverState *bs, int64_t offset,
21
-static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
25
- PreallocMode prealloc, Error **errp)
22
- const char *fmt, ...)
26
-{
23
-{
27
- return bdrv_truncate(bs->file, offset, prealloc, errp);
24
- va_list ap;
25
-
26
- va_start(ap, fmt);
27
- fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
28
- acb->offset, acb->bytes);
29
- vfprintf(stderr, fmt, ap);
30
- fprintf(stderr, "\n");
31
- va_end(ap);
32
- exit(1);
28
-}
33
-}
29
-
34
-
30
static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
35
-static bool quorum_compare(QuorumAIOCB *acb,
36
- QEMUIOVector *a,
37
- QEMUIOVector *b)
38
+static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
31
{
39
{
32
BDRVBlkdebugState *s = bs->opaque;
40
BDRVQuorumState *s = acb->bs->opaque;
33
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
41
ssize_t offset;
34
.format_name = "blkdebug",
42
@@ -XXX,XX +XXX,XX @@ static bool quorum_compare(QuorumAIOCB *acb,
35
.protocol_name = "blkdebug",
43
if (s->is_blkverify) {
36
.instance_size = sizeof(BDRVBlkdebugState),
44
offset = qemu_iovec_compare(a, b);
37
+ .is_filter = true,
45
if (offset != -1) {
38
46
- quorum_err(acb, "contents mismatch at offset %" PRIu64,
39
.bdrv_parse_filename = blkdebug_parse_filename,
47
- acb->offset + offset);
40
.bdrv_file_open = blkdebug_open,
48
+ fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
41
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
49
+ " contents mismatch at offset %" PRIu64 "\n",
42
.bdrv_child_perm = bdrv_filter_default_perms,
50
+ acb->offset, acb->bytes, acb->offset + offset);
43
51
+ exit(1);
44
.bdrv_getlength = blkdebug_getlength,
52
}
45
- .bdrv_truncate = blkdebug_truncate,
53
return true;
46
.bdrv_refresh_filename = blkdebug_refresh_filename,
54
}
47
.bdrv_refresh_limits = blkdebug_refresh_limits,
48
49
--
55
--
50
2.13.5
56
2.19.1
51
57
52
58
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
The blkverify mode of Quorum can only be enabled if the number of
4
children is exactly two and the value of vote-threshold is also two.
5
6
If the user tries to enable it but the other settings are incorrect
7
then QEMU simply prints an error message to stderr and carries on
8
disabling the blkverify setting.
9
10
This patch makes quorum_open() fail and return an error in this case.
11
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Reported-by: Markus Armbruster <armbru@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/quorum.c | 13 ++++++-------
17
1 file changed, 6 insertions(+), 7 deletions(-)
18
19
diff --git a/block/quorum.c b/block/quorum.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/quorum.c
22
+++ b/block/quorum.c
23
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
24
s->read_pattern = ret;
25
26
if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) {
27
- /* is the driver in blkverify mode */
28
- if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
29
- s->num_children == 2 && s->threshold == 2) {
30
- s->is_blkverify = true;
31
- } else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
32
- fprintf(stderr, "blkverify mode is set by setting blkverify=on "
33
- "and using two files with vote_threshold=2\n");
34
+ s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false);
35
+ if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) {
36
+ error_setg(&local_err, "blkverify=on can only be set if there are "
37
+ "exactly two files and vote-threshold is 2");
38
+ ret = -EINVAL;
39
+ goto exit;
40
}
41
42
s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE,
43
--
44
2.19.1
45
46
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
tests/qemu-iotests/081 | 30 ++++++++++++++++++++++++++++++
7
tests/qemu-iotests/081.out | 16 ++++++++++++++++
8
2 files changed, 46 insertions(+)
9
10
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
11
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/081
13
+++ b/tests/qemu-iotests/081
14
@@ -XXX,XX +XXX,XX @@ echo "== checking that quorum is broken =="
15
16
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
17
18
+echo
19
+echo "== checking the blkverify mode with broken content =="
20
+
21
+quorum="driver=raw,file.driver=quorum,file.vote-threshold=2,file.blkverify=on"
22
+quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
23
+quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
24
+quorum="$quorum,file.children.0.driver=raw"
25
+quorum="$quorum,file.children.1.driver=raw"
26
+
27
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
28
+
29
+echo
30
+echo "== writing the same data to both files =="
31
+
32
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
33
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
34
+
35
+echo
36
+echo "== checking the blkverify mode with valid content =="
37
+
38
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
39
+
40
+echo
41
+echo "== checking the blkverify mode with invalid settings =="
42
+
43
+quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw"
44
+quorum="$quorum,file.children.2.driver=raw"
45
+
46
+$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
47
+
48
# success, all done
49
echo "*** done"
50
rm -f $seq.full
51
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/081.out
54
+++ b/tests/qemu-iotests/081.out
55
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 0
56
57
== checking that quorum is broken ==
58
read failed: Input/output error
59
+
60
+== checking the blkverify mode with broken content ==
61
+quorum: offset=0 bytes=10485760 contents mismatch at offset 0
62
+
63
+== writing the same data to both files ==
64
+wrote 10485760/10485760 bytes at offset 0
65
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
66
+wrote 10485760/10485760 bytes at offset 0
67
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
68
+
69
+== checking the blkverify mode with valid content ==
70
+read 10485760/10485760 bytes at offset 0
71
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
72
+
73
+== checking the blkverify mode with invalid settings ==
74
+can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
75
*** done
76
--
77
2.19.1
78
79
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
ThrottleGroup is converted to an object. This will allow the future
3
The blkverify mode of Quorum only works when the number of children is
4
throttle block filter drive easy creation and configuration of throttle
4
exactly two, so any attempt to add a new one must return an error.
5
groups in QMP and cli.
6
5
7
A new QAPI struct, ThrottleLimits, is introduced to provide a shared
6
quorum_del_child() on the other hand doesn't need any additional check
8
struct for all throttle configuration needs in QMP.
7
because decreasing the number of children would make it go under the
8
vote threshold.
9
9
10
ThrottleGroups can be created via CLI as
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
-object throttle-group,id=foo,x-iops-total=100,x-..
11
Reported-by: Kevin Wolf <kwolf@redhat.com>
12
where x-* are individual limit properties. Since we can't add non-scalar
13
properties in -object this interface must be used instead. However,
14
setting these properties must be disabled after initialization because
15
certain combinations of limits are forbidden and thus configuration
16
changes should be done in one transaction. The individual properties
17
will go away when support for non-scalar values in CLI is implemented
18
and thus are marked as experimental.
19
20
ThrottleGroup also has a `limits` property that uses the ThrottleLimits
21
struct. It can be used to create ThrottleGroups or set the
22
configuration in existing groups as follows:
23
24
{ "execute": "object-add",
25
"arguments": {
26
"qom-type": "throttle-group",
27
"id": "foo",
28
"props" : {
29
"limits": {
30
"iops-total": 100
31
}
32
}
33
}
34
}
35
{ "execute" : "qom-set",
36
"arguments" : {
37
"path" : "foo",
38
"property" : "limits",
39
"value" : {
40
"iops-total" : 99
41
}
42
}
43
}
44
45
This also means a group's configuration can be fetched with qom-get.
46
47
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
48
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
49
Reviewed-by: Alberto Garcia <berto@igalia.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
---
13
---
52
qapi/block-core.json | 48 +++++
14
block/quorum.c | 8 ++++++++
53
include/block/throttle-groups.h | 3 +
15
1 file changed, 8 insertions(+)
54
include/qemu/throttle-options.h | 59 ++++--
55
include/qemu/throttle.h | 3 +
56
block/throttle-groups.c | 424 ++++++++++++++++++++++++++++++++++++----
57
tests/test-throttle.c | 1 +
58
util/throttle.c | 151 ++++++++++++++
59
7 files changed, 628 insertions(+), 61 deletions(-)
60
16
61
diff --git a/qapi/block-core.json b/qapi/block-core.json
17
diff --git a/block/quorum.c b/block/quorum.c
62
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
63
--- a/qapi/block-core.json
19
--- a/block/quorum.c
64
+++ b/qapi/block-core.json
20
+++ b/block/quorum.c
65
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
66
'*iops_size': 'int', '*group': 'str' } }
22
char indexstr[32];
67
23
int ret;
68
##
24
69
+# @ThrottleLimits:
25
+ if (s->is_blkverify) {
70
+#
26
+ error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
71
+# Limit parameters for throttling.
72
+# Since some limit combinations are illegal, limits should always be set in one
73
+# transaction. All fields are optional. When setting limits, if a field is
74
+# missing the current value is not changed.
75
+#
76
+# @iops-total: limit total I/O operations per second
77
+# @iops-total-max: I/O operations burst
78
+# @iops-total-max-length: length of the iops-total-max burst period, in seconds
79
+# It must only be set if @iops-total-max is set as well.
80
+# @iops-read: limit read operations per second
81
+# @iops-read-max: I/O operations read burst
82
+# @iops-read-max-length: length of the iops-read-max burst period, in seconds
83
+# It must only be set if @iops-read-max is set as well.
84
+# @iops-write: limit write operations per second
85
+# @iops-write-max: I/O operations write burst
86
+# @iops-write-max-length: length of the iops-write-max burst period, in seconds
87
+# It must only be set if @iops-write-max is set as well.
88
+# @bps-total: limit total bytes per second
89
+# @bps-total-max: total bytes burst
90
+# @bps-total-max-length: length of the bps-total-max burst period, in seconds.
91
+# It must only be set if @bps-total-max is set as well.
92
+# @bps-read: limit read bytes per second
93
+# @bps-read-max: total bytes read burst
94
+# @bps-read-max-length: length of the bps-read-max burst period, in seconds
95
+# It must only be set if @bps-read-max is set as well.
96
+# @bps-write: limit write bytes per second
97
+# @bps-write-max: total bytes write burst
98
+# @bps-write-max-length: length of the bps-write-max burst period, in seconds
99
+# It must only be set if @bps-write-max is set as well.
100
+# @iops-size: when limiting by iops max size of an I/O in bytes
101
+#
102
+# Since: 2.11
103
+##
104
+{ 'struct': 'ThrottleLimits',
105
+ 'data': { '*iops-total' : 'int', '*iops-total-max' : 'int',
106
+ '*iops-total-max-length' : 'int', '*iops-read' : 'int',
107
+ '*iops-read-max' : 'int', '*iops-read-max-length' : 'int',
108
+ '*iops-write' : 'int', '*iops-write-max' : 'int',
109
+ '*iops-write-max-length' : 'int', '*bps-total' : 'int',
110
+ '*bps-total-max' : 'int', '*bps-total-max-length' : 'int',
111
+ '*bps-read' : 'int', '*bps-read-max' : 'int',
112
+ '*bps-read-max-length' : 'int', '*bps-write' : 'int',
113
+ '*bps-write-max' : 'int', '*bps-write-max-length' : 'int',
114
+ '*iops-size' : 'int' } }
115
+
116
+##
117
# @block-stream:
118
#
119
# Copy data from a backing file into a block device.
120
diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
121
index XXXXXXX..XXXXXXX 100644
122
--- a/include/block/throttle-groups.h
123
+++ b/include/block/throttle-groups.h
124
@@ -XXX,XX +XXX,XX @@ typedef struct ThrottleGroupMember {
125
126
} ThrottleGroupMember;
127
128
+#define TYPE_THROTTLE_GROUP "throttle-group"
129
+#define THROTTLE_GROUP(obj) OBJECT_CHECK(ThrottleGroup, (obj), TYPE_THROTTLE_GROUP)
130
+
131
const char *throttle_group_get_name(ThrottleGroupMember *tgm);
132
133
ThrottleState *throttle_group_incref(const char *name);
134
diff --git a/include/qemu/throttle-options.h b/include/qemu/throttle-options.h
135
index XXXXXXX..XXXXXXX 100644
136
--- a/include/qemu/throttle-options.h
137
+++ b/include/qemu/throttle-options.h
138
@@ -XXX,XX +XXX,XX @@
139
#ifndef THROTTLE_OPTIONS_H
140
#define THROTTLE_OPTIONS_H
141
142
+#define QEMU_OPT_IOPS_TOTAL "iops-total"
143
+#define QEMU_OPT_IOPS_TOTAL_MAX "iops-total-max"
144
+#define QEMU_OPT_IOPS_TOTAL_MAX_LENGTH "iops-total-max-length"
145
+#define QEMU_OPT_IOPS_READ "iops-read"
146
+#define QEMU_OPT_IOPS_READ_MAX "iops-read-max"
147
+#define QEMU_OPT_IOPS_READ_MAX_LENGTH "iops-read-max-length"
148
+#define QEMU_OPT_IOPS_WRITE "iops-write"
149
+#define QEMU_OPT_IOPS_WRITE_MAX "iops-write-max"
150
+#define QEMU_OPT_IOPS_WRITE_MAX_LENGTH "iops-write-max-length"
151
+#define QEMU_OPT_BPS_TOTAL "bps-total"
152
+#define QEMU_OPT_BPS_TOTAL_MAX "bps-total-max"
153
+#define QEMU_OPT_BPS_TOTAL_MAX_LENGTH "bps-total-max-length"
154
+#define QEMU_OPT_BPS_READ "bps-read"
155
+#define QEMU_OPT_BPS_READ_MAX "bps-read-max"
156
+#define QEMU_OPT_BPS_READ_MAX_LENGTH "bps-read-max-length"
157
+#define QEMU_OPT_BPS_WRITE "bps-write"
158
+#define QEMU_OPT_BPS_WRITE_MAX "bps-write-max"
159
+#define QEMU_OPT_BPS_WRITE_MAX_LENGTH "bps-write-max-length"
160
+#define QEMU_OPT_IOPS_SIZE "iops-size"
161
+
162
+#define THROTTLE_OPT_PREFIX "throttling."
163
#define THROTTLE_OPTS \
164
{ \
165
- .name = "throttling.iops-total",\
166
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL,\
167
.type = QEMU_OPT_NUMBER,\
168
.help = "limit total I/O operations per second",\
169
},{ \
170
- .name = "throttling.iops-read",\
171
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ,\
172
.type = QEMU_OPT_NUMBER,\
173
.help = "limit read operations per second",\
174
},{ \
175
- .name = "throttling.iops-write",\
176
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE,\
177
.type = QEMU_OPT_NUMBER,\
178
.help = "limit write operations per second",\
179
},{ \
180
- .name = "throttling.bps-total",\
181
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL,\
182
.type = QEMU_OPT_NUMBER,\
183
.help = "limit total bytes per second",\
184
},{ \
185
- .name = "throttling.bps-read",\
186
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ,\
187
.type = QEMU_OPT_NUMBER,\
188
.help = "limit read bytes per second",\
189
},{ \
190
- .name = "throttling.bps-write",\
191
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE,\
192
.type = QEMU_OPT_NUMBER,\
193
.help = "limit write bytes per second",\
194
},{ \
195
- .name = "throttling.iops-total-max",\
196
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX,\
197
.type = QEMU_OPT_NUMBER,\
198
.help = "I/O operations burst",\
199
},{ \
200
- .name = "throttling.iops-read-max",\
201
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX,\
202
.type = QEMU_OPT_NUMBER,\
203
.help = "I/O operations read burst",\
204
},{ \
205
- .name = "throttling.iops-write-max",\
206
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX,\
207
.type = QEMU_OPT_NUMBER,\
208
.help = "I/O operations write burst",\
209
},{ \
210
- .name = "throttling.bps-total-max",\
211
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX,\
212
.type = QEMU_OPT_NUMBER,\
213
.help = "total bytes burst",\
214
},{ \
215
- .name = "throttling.bps-read-max",\
216
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX,\
217
.type = QEMU_OPT_NUMBER,\
218
.help = "total bytes read burst",\
219
},{ \
220
- .name = "throttling.bps-write-max",\
221
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX,\
222
.type = QEMU_OPT_NUMBER,\
223
.help = "total bytes write burst",\
224
},{ \
225
- .name = "throttling.iops-total-max-length",\
226
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX_LENGTH,\
227
.type = QEMU_OPT_NUMBER,\
228
.help = "length of the iops-total-max burst period, in seconds",\
229
},{ \
230
- .name = "throttling.iops-read-max-length",\
231
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX_LENGTH,\
232
.type = QEMU_OPT_NUMBER,\
233
.help = "length of the iops-read-max burst period, in seconds",\
234
},{ \
235
- .name = "throttling.iops-write-max-length",\
236
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX_LENGTH,\
237
.type = QEMU_OPT_NUMBER,\
238
.help = "length of the iops-write-max burst period, in seconds",\
239
},{ \
240
- .name = "throttling.bps-total-max-length",\
241
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX_LENGTH,\
242
.type = QEMU_OPT_NUMBER,\
243
.help = "length of the bps-total-max burst period, in seconds",\
244
},{ \
245
- .name = "throttling.bps-read-max-length",\
246
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX_LENGTH,\
247
.type = QEMU_OPT_NUMBER,\
248
.help = "length of the bps-read-max burst period, in seconds",\
249
},{ \
250
- .name = "throttling.bps-write-max-length",\
251
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX_LENGTH,\
252
.type = QEMU_OPT_NUMBER,\
253
.help = "length of the bps-write-max burst period, in seconds",\
254
},{ \
255
- .name = "throttling.iops-size",\
256
+ .name = THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_SIZE,\
257
.type = QEMU_OPT_NUMBER,\
258
.help = "when limiting by iops max size of an I/O in bytes",\
259
}
260
diff --git a/include/qemu/throttle.h b/include/qemu/throttle.h
261
index XXXXXXX..XXXXXXX 100644
262
--- a/include/qemu/throttle.h
263
+++ b/include/qemu/throttle.h
264
@@ -XXX,XX +XXX,XX @@ bool throttle_schedule_timer(ThrottleState *ts,
265
bool is_write);
266
267
void throttle_account(ThrottleState *ts, bool is_write, uint64_t size);
268
+void throttle_limits_to_config(ThrottleLimits *arg, ThrottleConfig *cfg,
269
+ Error **errp);
270
+void throttle_config_to_limits(ThrottleConfig *cfg, ThrottleLimits *var);
271
272
#endif
273
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
274
index XXXXXXX..XXXXXXX 100644
275
--- a/block/throttle-groups.c
276
+++ b/block/throttle-groups.c
277
@@ -XXX,XX +XXX,XX @@
278
#include "qemu/osdep.h"
279
#include "sysemu/block-backend.h"
280
#include "block/throttle-groups.h"
281
+#include "qemu/throttle-options.h"
282
#include "qemu/queue.h"
283
#include "qemu/thread.h"
284
#include "sysemu/qtest.h"
285
+#include "qapi/error.h"
286
+#include "qapi-visit.h"
287
+#include "qom/object.h"
288
+#include "qom/object_interfaces.h"
289
+
290
+static void throttle_group_obj_init(Object *obj);
291
+static void throttle_group_obj_complete(UserCreatable *obj, Error **errp);
292
293
/* The ThrottleGroup structure (with its ThrottleState) is shared
294
* among different ThrottleGroupMembers and it's independent from
295
@@ -XXX,XX +XXX,XX @@
296
* that ThrottleGroupMember has throttled requests in the queue.
297
*/
298
typedef struct ThrottleGroup {
299
+ Object parent_obj;
300
+
301
+ /* refuse individual property change if initialization is complete */
302
+ bool is_initialized;
303
char *name; /* This is constant during the lifetime of the group */
304
305
QemuMutex lock; /* This lock protects the following four fields */
306
@@ -XXX,XX +XXX,XX @@ typedef struct ThrottleGroup {
307
bool any_timer_armed[2];
308
QEMUClockType clock_type;
309
310
- /* These two are protected by the global throttle_groups_lock */
311
- unsigned refcount;
312
+ /* This field is protected by the global QEMU mutex */
313
QTAILQ_ENTRY(ThrottleGroup) list;
314
} ThrottleGroup;
315
316
-static QemuMutex throttle_groups_lock;
317
+/* This is protected by the global QEMU mutex */
318
static QTAILQ_HEAD(, ThrottleGroup) throttle_groups =
319
QTAILQ_HEAD_INITIALIZER(throttle_groups);
320
321
+
322
+/* This function reads throttle_groups and must be called under the global
323
+ * mutex.
324
+ */
325
+static ThrottleGroup *throttle_group_by_name(const char *name)
326
+{
327
+ ThrottleGroup *iter;
328
+
329
+ /* Look for an existing group with that name */
330
+ QTAILQ_FOREACH(iter, &throttle_groups, list) {
331
+ if (!g_strcmp0(name, iter->name)) {
332
+ return iter;
333
+ }
334
+ }
335
+
336
+ return NULL;
337
+}
338
+
339
/* Increments the reference count of a ThrottleGroup given its name.
340
*
341
* If no ThrottleGroup is found with the given name a new one is
342
* created.
343
*
344
+ * This function edits throttle_groups and must be called under the global
345
+ * mutex.
346
+ *
347
* @name: the name of the ThrottleGroup
348
* @ret: the ThrottleState member of the ThrottleGroup
349
*/
350
ThrottleState *throttle_group_incref(const char *name)
351
{
352
ThrottleGroup *tg = NULL;
353
- ThrottleGroup *iter;
354
-
355
- qemu_mutex_lock(&throttle_groups_lock);
356
357
/* Look for an existing group with that name */
358
- QTAILQ_FOREACH(iter, &throttle_groups, list) {
359
- if (!strcmp(name, iter->name)) {
360
- tg = iter;
361
- break;
362
- }
363
- }
364
-
365
- /* Create a new one if not found */
366
- if (!tg) {
367
- tg = g_new0(ThrottleGroup, 1);
368
+ tg = throttle_group_by_name(name);
369
+
370
+ if (tg) {
371
+ object_ref(OBJECT(tg));
372
+ } else {
373
+ /* Create a new one if not found */
374
+ /* new ThrottleGroup obj will have a refcnt = 1 */
375
+ tg = THROTTLE_GROUP(object_new(TYPE_THROTTLE_GROUP));
376
tg->name = g_strdup(name);
377
- tg->clock_type = QEMU_CLOCK_REALTIME;
378
-
379
- if (qtest_enabled()) {
380
- /* For testing block IO throttling only */
381
- tg->clock_type = QEMU_CLOCK_VIRTUAL;
382
- }
383
- qemu_mutex_init(&tg->lock);
384
- throttle_init(&tg->ts);
385
- QLIST_INIT(&tg->head);
386
-
387
- QTAILQ_INSERT_TAIL(&throttle_groups, tg, list);
388
+ throttle_group_obj_complete(USER_CREATABLE(tg), &error_abort);
389
}
390
391
- tg->refcount++;
392
-
393
- qemu_mutex_unlock(&throttle_groups_lock);
394
-
395
return &tg->ts;
396
}
397
398
@@ -XXX,XX +XXX,XX @@ ThrottleState *throttle_group_incref(const char *name)
399
* When the reference count reaches zero the ThrottleGroup is
400
* destroyed.
401
*
402
+ * This function edits throttle_groups and must be called under the global
403
+ * mutex.
404
+ *
405
* @ts: The ThrottleGroup to unref, given by its ThrottleState member
406
*/
407
void throttle_group_unref(ThrottleState *ts)
408
{
409
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
410
-
411
- qemu_mutex_lock(&throttle_groups_lock);
412
- if (--tg->refcount == 0) {
413
- QTAILQ_REMOVE(&throttle_groups, tg, list);
414
- qemu_mutex_destroy(&tg->lock);
415
- g_free(tg->name);
416
- g_free(tg);
417
- }
418
- qemu_mutex_unlock(&throttle_groups_lock);
419
+ object_unref(OBJECT(tg));
420
}
421
422
/* Get the name from a ThrottleGroupMember's group. The name (and the pointer)
423
@@ -XXX,XX +XXX,XX @@ static void write_timer_cb(void *opaque)
424
* its timers and updating its throttle_state pointer to point to it. If a
425
* throttling group with that name does not exist yet, it will be created.
426
*
427
+ * This function edits throttle_groups and must be called under the global
428
+ * mutex.
429
+ *
430
* @tgm: the ThrottleGroupMember to insert
431
* @groupname: the name of the group
432
* @ctx: the AioContext to use
433
@@ -XXX,XX +XXX,XX @@ void throttle_group_detach_aio_context(ThrottleGroupMember *tgm)
434
tgm->aio_context = NULL;
435
}
436
437
+#undef THROTTLE_OPT_PREFIX
438
+#define THROTTLE_OPT_PREFIX "x-"
439
+
440
+/* Helper struct and array for QOM property setter/getter */
441
+typedef struct {
442
+ const char *name;
443
+ BucketType type;
444
+ enum {
445
+ AVG,
446
+ MAX,
447
+ BURST_LENGTH,
448
+ IOPS_SIZE,
449
+ } category;
450
+} ThrottleParamInfo;
451
+
452
+static ThrottleParamInfo properties[] = {
453
+ {
454
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL,
455
+ THROTTLE_OPS_TOTAL, AVG,
456
+ },
457
+ {
458
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX,
459
+ THROTTLE_OPS_TOTAL, MAX,
460
+ },
461
+ {
462
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX_LENGTH,
463
+ THROTTLE_OPS_TOTAL, BURST_LENGTH,
464
+ },
465
+ {
466
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ,
467
+ THROTTLE_OPS_READ, AVG,
468
+ },
469
+ {
470
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX,
471
+ THROTTLE_OPS_READ, MAX,
472
+ },
473
+ {
474
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX_LENGTH,
475
+ THROTTLE_OPS_READ, BURST_LENGTH,
476
+ },
477
+ {
478
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE,
479
+ THROTTLE_OPS_WRITE, AVG,
480
+ },
481
+ {
482
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX,
483
+ THROTTLE_OPS_WRITE, MAX,
484
+ },
485
+ {
486
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX_LENGTH,
487
+ THROTTLE_OPS_WRITE, BURST_LENGTH,
488
+ },
489
+ {
490
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL,
491
+ THROTTLE_BPS_TOTAL, AVG,
492
+ },
493
+ {
494
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX,
495
+ THROTTLE_BPS_TOTAL, MAX,
496
+ },
497
+ {
498
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX_LENGTH,
499
+ THROTTLE_BPS_TOTAL, BURST_LENGTH,
500
+ },
501
+ {
502
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ,
503
+ THROTTLE_BPS_READ, AVG,
504
+ },
505
+ {
506
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX,
507
+ THROTTLE_BPS_READ, MAX,
508
+ },
509
+ {
510
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX_LENGTH,
511
+ THROTTLE_BPS_READ, BURST_LENGTH,
512
+ },
513
+ {
514
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE,
515
+ THROTTLE_BPS_WRITE, AVG,
516
+ },
517
+ {
518
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX,
519
+ THROTTLE_BPS_WRITE, MAX,
520
+ },
521
+ {
522
+ THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX_LENGTH,
523
+ THROTTLE_BPS_WRITE, BURST_LENGTH,
524
+ },
525
+ {
526
+ THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_SIZE,
527
+ 0, IOPS_SIZE,
528
+ }
529
+};
530
+
531
+/* This function edits throttle_groups and must be called under the global
532
+ * mutex */
533
+static void throttle_group_obj_init(Object *obj)
534
+{
535
+ ThrottleGroup *tg = THROTTLE_GROUP(obj);
536
+
537
+ tg->clock_type = QEMU_CLOCK_REALTIME;
538
+ if (qtest_enabled()) {
539
+ /* For testing block IO throttling only */
540
+ tg->clock_type = QEMU_CLOCK_VIRTUAL;
541
+ }
542
+ tg->is_initialized = false;
543
+ qemu_mutex_init(&tg->lock);
544
+ throttle_init(&tg->ts);
545
+ QLIST_INIT(&tg->head);
546
+}
547
+
548
+/* This function edits throttle_groups and must be called under the global
549
+ * mutex */
550
+static void throttle_group_obj_complete(UserCreatable *obj, Error **errp)
551
+{
552
+ ThrottleGroup *tg = THROTTLE_GROUP(obj);
553
+ ThrottleConfig cfg;
554
+
555
+ /* set group name to object id if it exists */
556
+ if (!tg->name && tg->parent_obj.parent) {
557
+ tg->name = object_get_canonical_path_component(OBJECT(obj));
558
+ }
559
+ /* We must have a group name at this point */
560
+ assert(tg->name);
561
+
562
+ /* error if name is duplicate */
563
+ if (throttle_group_by_name(tg->name) != NULL) {
564
+ error_setg(errp, "A group with this name already exists");
565
+ return;
27
+ return;
566
+ }
28
+ }
567
+
29
+
568
+ /* check validity */
30
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
569
+ throttle_get_config(&tg->ts, &cfg);
31
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
570
+ if (!throttle_is_valid(&cfg, errp)) {
32
s->next_child_index == UINT_MAX) {
571
+ return;
33
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
572
+ }
34
return;
573
+ throttle_config(&tg->ts, tg->clock_type, &cfg);
35
}
574
+ QTAILQ_INSERT_TAIL(&throttle_groups, tg, list);
36
575
+ tg->is_initialized = true;
37
+ /* We know now that num_children > threshold, so blkverify must be false */
576
+}
38
+ assert(!s->is_blkverify);
577
+
39
+
578
+/* This function edits throttle_groups and must be called under the global
40
bdrv_drained_begin(bs);
579
+ * mutex */
41
580
+static void throttle_group_obj_finalize(Object *obj)
42
/* We can safely remove this child now */
581
+{
582
+ ThrottleGroup *tg = THROTTLE_GROUP(obj);
583
+ if (tg->is_initialized) {
584
+ QTAILQ_REMOVE(&throttle_groups, tg, list);
585
+ }
586
+ qemu_mutex_destroy(&tg->lock);
587
+ g_free(tg->name);
588
+}
589
+
590
+static void throttle_group_set(Object *obj, Visitor *v, const char * name,
591
+ void *opaque, Error **errp)
592
+
593
+{
594
+ ThrottleGroup *tg = THROTTLE_GROUP(obj);
595
+ ThrottleConfig *cfg;
596
+ ThrottleParamInfo *info = opaque;
597
+ Error *local_err = NULL;
598
+ int64_t value;
599
+
600
+ /* If we have finished initialization, don't accept individual property
601
+ * changes through QOM. Throttle configuration limits must be set in one
602
+ * transaction, as certain combinations are invalid.
603
+ */
604
+ if (tg->is_initialized) {
605
+ error_setg(&local_err, "Property cannot be set after initialization");
606
+ goto ret;
607
+ }
608
+
609
+ visit_type_int64(v, name, &value, &local_err);
610
+ if (local_err) {
611
+ goto ret;
612
+ }
613
+ if (value < 0) {
614
+ error_setg(&local_err, "Property values cannot be negative");
615
+ goto ret;
616
+ }
617
+
618
+ cfg = &tg->ts.cfg;
619
+ switch (info->category) {
620
+ case AVG:
621
+ cfg->buckets[info->type].avg = value;
622
+ break;
623
+ case MAX:
624
+ cfg->buckets[info->type].max = value;
625
+ break;
626
+ case BURST_LENGTH:
627
+ if (value > UINT_MAX) {
628
+ error_setg(&local_err, "%s value must be in the"
629
+ "range [0, %u]", info->name, UINT_MAX);
630
+ goto ret;
631
+ }
632
+ cfg->buckets[info->type].burst_length = value;
633
+ break;
634
+ case IOPS_SIZE:
635
+ cfg->op_size = value;
636
+ break;
637
+ }
638
+
639
+ret:
640
+ error_propagate(errp, local_err);
641
+ return;
642
+
643
+}
644
+
645
+static void throttle_group_get(Object *obj, Visitor *v, const char *name,
646
+ void *opaque, Error **errp)
647
+{
648
+ ThrottleGroup *tg = THROTTLE_GROUP(obj);
649
+ ThrottleConfig cfg;
650
+ ThrottleParamInfo *info = opaque;
651
+ int64_t value;
652
+
653
+ throttle_get_config(&tg->ts, &cfg);
654
+ switch (info->category) {
655
+ case AVG:
656
+ value = cfg.buckets[info->type].avg;
657
+ break;
658
+ case MAX:
659
+ value = cfg.buckets[info->type].max;
660
+ break;
661
+ case BURST_LENGTH:
662
+ value = cfg.buckets[info->type].burst_length;
663
+ break;
664
+ case IOPS_SIZE:
665
+ value = cfg.op_size;
666
+ break;
667
+ }
668
+
669
+ visit_type_int64(v, name, &value, errp);
670
+}
671
+
672
+static void throttle_group_set_limits(Object *obj, Visitor *v,
673
+ const char *name, void *opaque,
674
+ Error **errp)
675
+
676
+{
677
+ ThrottleGroup *tg = THROTTLE_GROUP(obj);
678
+ ThrottleConfig cfg;
679
+ ThrottleLimits arg = { 0 };
680
+ ThrottleLimits *argp = &arg;
681
+ Error *local_err = NULL;
682
+
683
+ visit_type_ThrottleLimits(v, name, &argp, &local_err);
684
+ if (local_err) {
685
+ goto ret;
686
+ }
687
+ qemu_mutex_lock(&tg->lock);
688
+ throttle_get_config(&tg->ts, &cfg);
689
+ throttle_limits_to_config(argp, &cfg, &local_err);
690
+ if (local_err) {
691
+ goto unlock;
692
+ }
693
+ throttle_config(&tg->ts, tg->clock_type, &cfg);
694
+
695
+unlock:
696
+ qemu_mutex_unlock(&tg->lock);
697
+ret:
698
+ error_propagate(errp, local_err);
699
+ return;
700
+}
701
+
702
+static void throttle_group_get_limits(Object *obj, Visitor *v,
703
+ const char *name, void *opaque,
704
+ Error **errp)
705
+{
706
+ ThrottleGroup *tg = THROTTLE_GROUP(obj);
707
+ ThrottleConfig cfg;
708
+ ThrottleLimits arg = { 0 };
709
+ ThrottleLimits *argp = &arg;
710
+
711
+ qemu_mutex_lock(&tg->lock);
712
+ throttle_get_config(&tg->ts, &cfg);
713
+ qemu_mutex_unlock(&tg->lock);
714
+
715
+ throttle_config_to_limits(&cfg, argp);
716
+
717
+ visit_type_ThrottleLimits(v, name, &argp, errp);
718
+}
719
+
720
+static bool throttle_group_can_be_deleted(UserCreatable *uc)
721
+{
722
+ return OBJECT(uc)->ref == 1;
723
+}
724
+
725
+static void throttle_group_obj_class_init(ObjectClass *klass, void *class_data)
726
+{
727
+ size_t i = 0;
728
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
729
+
730
+ ucc->complete = throttle_group_obj_complete;
731
+ ucc->can_be_deleted = throttle_group_can_be_deleted;
732
+
733
+ /* individual properties */
734
+ for (i = 0; i < sizeof(properties) / sizeof(ThrottleParamInfo); i++) {
735
+ object_class_property_add(klass,
736
+ properties[i].name,
737
+ "int",
738
+ throttle_group_get,
739
+ throttle_group_set,
740
+ NULL, &properties[i],
741
+ &error_abort);
742
+ }
743
+
744
+ /* ThrottleLimits */
745
+ object_class_property_add(klass,
746
+ "limits", "ThrottleLimits",
747
+ throttle_group_get_limits,
748
+ throttle_group_set_limits,
749
+ NULL, NULL,
750
+ &error_abort);
751
+}
752
+
753
+static const TypeInfo throttle_group_info = {
754
+ .name = TYPE_THROTTLE_GROUP,
755
+ .parent = TYPE_OBJECT,
756
+ .class_init = throttle_group_obj_class_init,
757
+ .instance_size = sizeof(ThrottleGroup),
758
+ .instance_init = throttle_group_obj_init,
759
+ .instance_finalize = throttle_group_obj_finalize,
760
+ .interfaces = (InterfaceInfo[]) {
761
+ { TYPE_USER_CREATABLE },
762
+ { }
763
+ },
764
+};
765
+
766
static void throttle_groups_init(void)
767
{
768
- qemu_mutex_init(&throttle_groups_lock);
769
+ type_register_static(&throttle_group_info);
770
}
771
772
-block_init(throttle_groups_init);
773
+type_init(throttle_groups_init);
774
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
775
index XXXXXXX..XXXXXXX 100644
776
--- a/tests/test-throttle.c
777
+++ b/tests/test-throttle.c
778
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
779
qemu_init_main_loop(&error_fatal);
780
ctx = qemu_get_aio_context();
781
bdrv_init();
782
+ module_call_init(MODULE_INIT_QOM);
783
784
do {} while (g_main_context_iteration(NULL, false));
785
786
diff --git a/util/throttle.c b/util/throttle.c
787
index XXXXXXX..XXXXXXX 100644
788
--- a/util/throttle.c
789
+++ b/util/throttle.c
790
@@ -XXX,XX +XXX,XX @@ void throttle_account(ThrottleState *ts, bool is_write, uint64_t size)
791
}
792
}
793
794
+/* return a ThrottleConfig based on the options in a ThrottleLimits
795
+ *
796
+ * @arg: the ThrottleLimits object to read from
797
+ * @cfg: the ThrottleConfig to edit
798
+ * @errp: error object
799
+ */
800
+void throttle_limits_to_config(ThrottleLimits *arg, ThrottleConfig *cfg,
801
+ Error **errp)
802
+{
803
+ if (arg->has_bps_total) {
804
+ cfg->buckets[THROTTLE_BPS_TOTAL].avg = arg->bps_total;
805
+ }
806
+ if (arg->has_bps_read) {
807
+ cfg->buckets[THROTTLE_BPS_READ].avg = arg->bps_read;
808
+ }
809
+ if (arg->has_bps_write) {
810
+ cfg->buckets[THROTTLE_BPS_WRITE].avg = arg->bps_write;
811
+ }
812
+
813
+ if (arg->has_iops_total) {
814
+ cfg->buckets[THROTTLE_OPS_TOTAL].avg = arg->iops_total;
815
+ }
816
+ if (arg->has_iops_read) {
817
+ cfg->buckets[THROTTLE_OPS_READ].avg = arg->iops_read;
818
+ }
819
+ if (arg->has_iops_write) {
820
+ cfg->buckets[THROTTLE_OPS_WRITE].avg = arg->iops_write;
821
+ }
822
+
823
+ if (arg->has_bps_total_max) {
824
+ cfg->buckets[THROTTLE_BPS_TOTAL].max = arg->bps_total_max;
825
+ }
826
+ if (arg->has_bps_read_max) {
827
+ cfg->buckets[THROTTLE_BPS_READ].max = arg->bps_read_max;
828
+ }
829
+ if (arg->has_bps_write_max) {
830
+ cfg->buckets[THROTTLE_BPS_WRITE].max = arg->bps_write_max;
831
+ }
832
+ if (arg->has_iops_total_max) {
833
+ cfg->buckets[THROTTLE_OPS_TOTAL].max = arg->iops_total_max;
834
+ }
835
+ if (arg->has_iops_read_max) {
836
+ cfg->buckets[THROTTLE_OPS_READ].max = arg->iops_read_max;
837
+ }
838
+ if (arg->has_iops_write_max) {
839
+ cfg->buckets[THROTTLE_OPS_WRITE].max = arg->iops_write_max;
840
+ }
841
+
842
+ if (arg->has_bps_total_max_length) {
843
+ if (arg->bps_total_max_length > UINT_MAX) {
844
+ error_setg(errp, "bps-total-max-length value must be in"
845
+ " the range [0, %u]", UINT_MAX);
846
+ return;
847
+ }
848
+ cfg->buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_total_max_length;
849
+ }
850
+ if (arg->has_bps_read_max_length) {
851
+ if (arg->bps_read_max_length > UINT_MAX) {
852
+ error_setg(errp, "bps-read-max-length value must be in"
853
+ " the range [0, %u]", UINT_MAX);
854
+ return;
855
+ }
856
+ cfg->buckets[THROTTLE_BPS_READ].burst_length = arg->bps_read_max_length;
857
+ }
858
+ if (arg->has_bps_write_max_length) {
859
+ if (arg->bps_write_max_length > UINT_MAX) {
860
+ error_setg(errp, "bps-write-max-length value must be in"
861
+ " the range [0, %u]", UINT_MAX);
862
+ return;
863
+ }
864
+ cfg->buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_write_max_length;
865
+ }
866
+ if (arg->has_iops_total_max_length) {
867
+ if (arg->iops_total_max_length > UINT_MAX) {
868
+ error_setg(errp, "iops-total-max-length value must be in"
869
+ " the range [0, %u]", UINT_MAX);
870
+ return;
871
+ }
872
+ cfg->buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_total_max_length;
873
+ }
874
+ if (arg->has_iops_read_max_length) {
875
+ if (arg->iops_read_max_length > UINT_MAX) {
876
+ error_setg(errp, "iops-read-max-length value must be in"
877
+ " the range [0, %u]", UINT_MAX);
878
+ return;
879
+ }
880
+ cfg->buckets[THROTTLE_OPS_READ].burst_length = arg->iops_read_max_length;
881
+ }
882
+ if (arg->has_iops_write_max_length) {
883
+ if (arg->iops_write_max_length > UINT_MAX) {
884
+ error_setg(errp, "iops-write-max-length value must be in"
885
+ " the range [0, %u]", UINT_MAX);
886
+ return;
887
+ }
888
+ cfg->buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_write_max_length;
889
+ }
890
+
891
+ if (arg->has_iops_size) {
892
+ cfg->op_size = arg->iops_size;
893
+ }
894
+
895
+ throttle_is_valid(cfg, errp);
896
+}
897
+
898
+/* write the options of a ThrottleConfig to a ThrottleLimits
899
+ *
900
+ * @cfg: the ThrottleConfig to read from
901
+ * @var: the ThrottleLimits to write to
902
+ */
903
+void throttle_config_to_limits(ThrottleConfig *cfg, ThrottleLimits *var)
904
+{
905
+ var->bps_total = cfg->buckets[THROTTLE_BPS_TOTAL].avg;
906
+ var->bps_read = cfg->buckets[THROTTLE_BPS_READ].avg;
907
+ var->bps_write = cfg->buckets[THROTTLE_BPS_WRITE].avg;
908
+ var->iops_total = cfg->buckets[THROTTLE_OPS_TOTAL].avg;
909
+ var->iops_read = cfg->buckets[THROTTLE_OPS_READ].avg;
910
+ var->iops_write = cfg->buckets[THROTTLE_OPS_WRITE].avg;
911
+ var->bps_total_max = cfg->buckets[THROTTLE_BPS_TOTAL].max;
912
+ var->bps_read_max = cfg->buckets[THROTTLE_BPS_READ].max;
913
+ var->bps_write_max = cfg->buckets[THROTTLE_BPS_WRITE].max;
914
+ var->iops_total_max = cfg->buckets[THROTTLE_OPS_TOTAL].max;
915
+ var->iops_read_max = cfg->buckets[THROTTLE_OPS_READ].max;
916
+ var->iops_write_max = cfg->buckets[THROTTLE_OPS_WRITE].max;
917
+ var->bps_total_max_length = cfg->buckets[THROTTLE_BPS_TOTAL].burst_length;
918
+ var->bps_read_max_length = cfg->buckets[THROTTLE_BPS_READ].burst_length;
919
+ var->bps_write_max_length = cfg->buckets[THROTTLE_BPS_WRITE].burst_length;
920
+ var->iops_total_max_length = cfg->buckets[THROTTLE_OPS_TOTAL].burst_length;
921
+ var->iops_read_max_length = cfg->buckets[THROTTLE_OPS_READ].burst_length;
922
+ var->iops_write_max_length = cfg->buckets[THROTTLE_OPS_WRITE].burst_length;
923
+ var->iops_size = cfg->op_size;
924
+
925
+ var->has_bps_total = true;
926
+ var->has_bps_read = true;
927
+ var->has_bps_write = true;
928
+ var->has_iops_total = true;
929
+ var->has_iops_read = true;
930
+ var->has_iops_write = true;
931
+ var->has_bps_total_max = true;
932
+ var->has_bps_read_max = true;
933
+ var->has_bps_write_max = true;
934
+ var->has_iops_total_max = true;
935
+ var->has_iops_read_max = true;
936
+ var->has_iops_write_max = true;
937
+ var->has_bps_read_max_length = true;
938
+ var->has_bps_total_max_length = true;
939
+ var->has_bps_write_max_length = true;
940
+ var->has_iops_total_max_length = true;
941
+ var->has_iops_read_max_length = true;
942
+ var->has_iops_write_max_length = true;
943
+ var->has_iops_size = true;
944
+}
945
--
43
--
946
2.13.5
44
2.19.1
947
45
948
46
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
This patch tests that you can add and remove drives from a Quorum
4
using the x-blockdev-change command.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
tests/qemu-iotests/081 | 86 ++++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/081.out | 54 ++++++++++++++++++++++++
11
2 files changed, 140 insertions(+)
12
13
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/081
16
+++ b/tests/qemu-iotests/081
17
@@ -XXX,XX +XXX,XX @@ quorum="$quorum,file.children.2.driver=raw"
18
19
$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
20
21
+echo
22
+echo "== dynamically adding a child to a quorum =="
23
+
24
+for verify in false true; do
25
+ run_qemu <<EOF
26
+ { "execute": "qmp_capabilities" }
27
+ { "execute": "blockdev-add",
28
+ "arguments": {
29
+ "driver": "quorum",
30
+ "node-name": "drive0-quorum",
31
+ "vote-threshold": 2,
32
+ "blkverify": ${verify},
33
+ "children": [
34
+ {
35
+ "driver": "$IMGFMT",
36
+ "file": {
37
+ "driver": "file",
38
+ "filename": "$TEST_DIR/1.raw"
39
+ }
40
+ },
41
+ {
42
+ "driver": "$IMGFMT",
43
+ "file": {
44
+ "driver": "file",
45
+ "filename": "$TEST_DIR/2.raw"
46
+ }
47
+ }
48
+ ]
49
+ }
50
+ }
51
+ { "execute": "blockdev-add",
52
+ "arguments": {
53
+ "node-name": "drive3",
54
+ "driver": "$IMGFMT",
55
+ "file": {
56
+ "driver": "file",
57
+ "filename": "$TEST_DIR/2.raw"
58
+ }
59
+ }
60
+ }
61
+ { "execute": "x-blockdev-change",
62
+ "arguments": { "parent": "drive0-quorum",
63
+ "node": "drive3" } }
64
+ { "execute": "quit" }
65
+EOF
66
+done
67
+
68
+echo
69
+echo "== dynamically removing a child from a quorum =="
70
+
71
+for verify in false true; do
72
+ for vote_threshold in 1 2; do
73
+ run_qemu <<EOF
74
+ { "execute": "qmp_capabilities" }
75
+ { "execute": "blockdev-add",
76
+ "arguments": {
77
+ "driver": "quorum",
78
+ "node-name": "drive0-quorum",
79
+ "vote-threshold": ${vote_threshold},
80
+ "blkverify": ${verify},
81
+ "children": [
82
+ {
83
+ "driver": "$IMGFMT",
84
+ "file": {
85
+ "driver": "file",
86
+ "filename": "$TEST_DIR/1.raw"
87
+ }
88
+ },
89
+ {
90
+ "driver": "$IMGFMT",
91
+ "file": {
92
+ "driver": "file",
93
+ "filename": "$TEST_DIR/2.raw"
94
+ }
95
+ }
96
+ ]
97
+ }
98
+ }
99
+ { "execute": "x-blockdev-change",
100
+ "arguments": { "parent": "drive0-quorum",
101
+ "child": "children.1" } }
102
+ { "execute": "quit" }
103
+EOF
104
+ done
105
+done
106
+
107
# success, all done
108
echo "*** done"
109
rm -f $seq.full
110
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
111
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qemu-iotests/081.out
113
+++ b/tests/qemu-iotests/081.out
114
@@ -XXX,XX +XXX,XX @@ read 10485760/10485760 bytes at offset 0
115
116
== checking the blkverify mode with invalid settings ==
117
can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
118
+
119
+== dynamically adding a child to a quorum ==
120
+Testing:
121
+QMP_VERSION
122
+{"return": {}}
123
+{"return": {}}
124
+{"return": {}}
125
+{"return": {}}
126
+{"return": {}}
127
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
128
+
129
+Testing:
130
+QMP_VERSION
131
+{"return": {}}
132
+{"return": {}}
133
+{"return": {}}
134
+{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
135
+{"return": {}}
136
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
137
+
138
+
139
+== dynamically removing a child from a quorum ==
140
+Testing:
141
+QMP_VERSION
142
+{"return": {}}
143
+{"return": {}}
144
+{"return": {}}
145
+{"return": {}}
146
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
147
+
148
+Testing:
149
+QMP_VERSION
150
+{"return": {}}
151
+{"return": {}}
152
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
153
+{"return": {}}
154
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
155
+
156
+Testing:
157
+QMP_VERSION
158
+{"return": {}}
159
+{"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
160
+{"error": {"class": "GenericError", "desc": "Cannot find device=drive0-quorum nor node_name=drive0-quorum"}}
161
+{"return": {}}
162
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
163
+
164
+Testing:
165
+QMP_VERSION
166
+{"return": {}}
167
+{"return": {}}
168
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
169
+{"return": {}}
170
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
171
+
172
*** done
173
--
174
2.19.1
175
176
diff view generated by jsdifflib
New patch
1
To fully change the read-only state of a node, we must not only change
2
bs->read_only, but also update bs->open_flags.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
---
8
block.c | 7 +++++++
9
1 file changed, 7 insertions(+)
10
11
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
14
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
16
}
17
18
bs->read_only = read_only;
19
+
20
+ if (read_only) {
21
+ bs->open_flags &= ~BDRV_O_RDWR;
22
+ } else {
23
+ bs->open_flags |= BDRV_O_RDWR;
24
+ }
25
+
26
return 0;
27
}
28
29
--
30
2.19.1
31
32
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
If a management application builds the block graph node by node, the
2
protocol layer doesn't inherit its read-only option from the format
3
layer any more, so it must be set explicitly.
2
4
3
block/throttle.c uses existing I/O throttle infrastructure inside a
5
Backing files should work on read-only storage, but at the same time, a
4
block filter driver. I/O operations are intercepted in the filter's
6
block job like commit should be able to reopen them read-write if they
5
read/write coroutines, and referred to block/throttle-groups.c
7
are on read-write storage. However, without option inheritance, reopen
8
only changes the read-only option for the root node (typically the
9
format layer), but not the protocol layer, so reopening fails (the
10
format layer wants to get write permissions, but the protocol layer is
11
still read-only).
6
12
7
The driver can be used with the syntax
13
A simple workaround for the problem in the management tool would be to
8
-drive driver=throttle,file.filename=foo.qcow2,throttle-group=bar
14
open the protocol layer always read-write and to make only the format
15
layer read-only for backing files. However, sometimes the file is
16
actually stored on read-only storage and we don't know whether the image
17
can be opened read-write (for example, for NBD it depends on the server
18
we're trying to connect to). This adds an option that makes QEMU try to
19
open the image read-write, but allows it to degrade to a read-only mode
20
without returning an error.
9
21
10
which registers the throttle filter node with the ThrottleGroup 'bar'. The
22
The documentation for this option is consciously phrased in a way that
11
given group must be created beforehand with object-add or -object.
23
allows QEMU to switch to a better model eventually: Instead of trying
24
when the image is first opened, making the read-only flag dynamic and
25
changing it automatically whenever the first BLK_PERM_WRITE user is
26
attached or the last one is detached would be much more useful
27
behaviour.
12
28
13
Reviewed-by: Alberto Garcia <berto@igalia.com>
29
Unfortunately, this more useful behaviour is also a lot harder to
14
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
30
implement, and libvirt needs a solution now before it can switch to
15
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
31
-blockdev, so let's start with this easier approach for now.
32
33
Instead of adding a new auto-read-only option, turning the existing
34
read-only into an enum (with a bool alternate for compatibility) was
35
considered, but it complicated the implementation to the point that it
36
didn't seem to be worth it.
37
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
Reviewed-by: Eric Blake <eblake@redhat.com>
17
---
40
---
18
qapi/block-core.json | 18 ++-
41
qapi/block-core.json | 7 +++++++
19
include/block/throttle-groups.h | 5 +
42
include/block/block.h | 2 ++
20
include/qemu/throttle-options.h | 1 +
43
block.c | 17 +++++++++++++++++
21
block/throttle-groups.c | 15 ++-
44
block/vvfat.c | 1 +
22
block/throttle.c | 237 ++++++++++++++++++++++++++++++++++++++++
45
blockdev.c | 2 +-
23
block/Makefile.objs | 1 +
46
5 files changed, 28 insertions(+), 1 deletion(-)
24
6 files changed, 275 insertions(+), 2 deletions(-)
25
create mode 100644 block/throttle.c
26
47
27
diff --git a/qapi/block-core.json b/qapi/block-core.json
48
diff --git a/qapi/block-core.json b/qapi/block-core.json
28
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
29
--- a/qapi/block-core.json
50
--- a/qapi/block-core.json
30
+++ b/qapi/block-core.json
51
+++ b/qapi/block-core.json
31
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
32
# Drivers that are supported in block device operations.
53
# either generally or in certain configurations. In this case,
33
#
54
# the default value does not work and the option must be
34
# @vxhs: Since 2.10
55
# specified explicitly.
35
+# @throttle: Since 2.11
56
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
36
#
57
+# decide not to open the image read-write as requested, but
37
# Since: 2.9
58
+# fall back to read-only instead (and switch between the modes
38
##
59
+# later), e.g. depending on whether the image file is writable
60
+# or whether a writing user is attached to the node
61
+# (default: false, since 3.1)
62
# @detect-zeroes: detect and optimize zero writes (Since 2.1)
63
# (default: off)
64
# @force-share: force share all permission on added nodes.
39
@@ -XXX,XX +XXX,XX @@
65
@@ -XXX,XX +XXX,XX @@
40
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
66
'*discard': 'BlockdevDiscardOptions',
41
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
67
'*cache': 'BlockdevCacheOptions',
42
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
68
'*read-only': 'bool',
43
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
69
+ '*auto-read-only': 'bool',
44
+ 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
70
'*force-share': 'bool',
45
71
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
46
##
72
'discriminator': 'driver',
47
# @BlockdevOptionsFile:
73
diff --git a/include/block/block.h b/include/block/block.h
48
@@ -XXX,XX +XXX,XX @@
49
'*tls-creds': 'str' } }
50
51
##
52
+# @BlockdevOptionsThrottle:
53
+#
54
+# Driver specific block device options for the throttle driver
55
+#
56
+# @throttle-group: the name of the throttle-group object to use. It
57
+# must already exist.
58
+# @file: reference to or definition of the data source block device
59
+# Since: 2.11
60
+##
61
+{ 'struct': 'BlockdevOptionsThrottle',
62
+ 'data': { 'throttle-group': 'str',
63
+ 'file' : 'BlockdevRef'
64
+ } }
65
+##
66
# @BlockdevOptions:
67
#
68
# Options for creating a block device. Many options are available for all
69
@@ -XXX,XX +XXX,XX @@
70
'replication':'BlockdevOptionsReplication',
71
'sheepdog': 'BlockdevOptionsSheepdog',
72
'ssh': 'BlockdevOptionsSsh',
73
+ 'throttle': 'BlockdevOptionsThrottle',
74
'vdi': 'BlockdevOptionsGenericFormat',
75
'vhdx': 'BlockdevOptionsGenericFormat',
76
'vmdk': 'BlockdevOptionsGenericCOWFormat',
77
diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
78
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
79
--- a/include/block/throttle-groups.h
75
--- a/include/block/block.h
80
+++ b/include/block/throttle-groups.h
76
+++ b/include/block/block.h
81
@@ -XXX,XX +XXX,XX @@ void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm
77
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
82
void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
78
select an appropriate protocol driver,
83
AioContext *new_context);
79
ignoring the format layer */
84
void throttle_group_detach_aio_context(ThrottleGroupMember *tgm);
80
#define BDRV_O_NO_IO 0x10000 /* don't initialize for I/O */
85
+/*
81
+#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening read-write fails */
86
+ * throttle_group_exists() must be called under the global
82
87
+ * mutex.
83
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
88
+ */
84
89
+bool throttle_group_exists(const char *name);
85
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
90
86
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
91
#endif
87
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
92
diff --git a/include/qemu/throttle-options.h b/include/qemu/throttle-options.h
88
#define BDRV_OPT_READ_ONLY "read-only"
89
+#define BDRV_OPT_AUTO_READ_ONLY "auto-read-only"
90
#define BDRV_OPT_DISCARD "discard"
91
#define BDRV_OPT_FORCE_SHARE "force-share"
92
93
diff --git a/block.c b/block.c
93
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
94
--- a/include/qemu/throttle-options.h
95
--- a/block.c
95
+++ b/include/qemu/throttle-options.h
96
+++ b/block.c
96
@@ -XXX,XX +XXX,XX @@
97
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
97
#define QEMU_OPT_BPS_WRITE_MAX "bps-write-max"
98
98
#define QEMU_OPT_BPS_WRITE_MAX_LENGTH "bps-write-max-length"
99
/* Inherit the read-only option from the parent if it's not set */
99
#define QEMU_OPT_IOPS_SIZE "iops-size"
100
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
100
+#define QEMU_OPT_THROTTLE_GROUP_NAME "throttle-group"
101
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
101
102
102
#define THROTTLE_OPT_PREFIX "throttling."
103
/* Our block drivers take care to send flushes and respect unmap policy,
103
#define THROTTLE_OPTS \
104
* so we can default to enable both on lower layers regardless of the
104
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
105
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
106
107
/* backing files always opened read-only */
108
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
109
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
110
flags &= ~BDRV_O_COPY_ON_READ;
111
112
/* snapshot=on is handled on the top layer */
113
@@ -XXX,XX +XXX,XX @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
114
*flags |= BDRV_O_RDWR;
115
}
116
117
+ assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
118
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
119
+ *flags |= BDRV_O_AUTO_RDONLY;
120
+ }
121
}
122
123
static void update_options_from_flags(QDict *options, int flags)
124
@@ -XXX,XX +XXX,XX @@ static void update_options_from_flags(QDict *options, int flags)
125
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
126
qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
127
}
128
+ if (!qdict_haskey(options, BDRV_OPT_AUTO_READ_ONLY)) {
129
+ qdict_put_bool(options, BDRV_OPT_AUTO_READ_ONLY,
130
+ flags & BDRV_O_AUTO_RDONLY);
131
+ }
132
}
133
134
static void bdrv_assign_node_name(BlockDriverState *bs,
135
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
136
.type = QEMU_OPT_BOOL,
137
.help = "Node is opened in read-only mode",
138
},
139
+ {
140
+ .name = BDRV_OPT_AUTO_READ_ONLY,
141
+ .type = QEMU_OPT_BOOL,
142
+ .help = "Node can become read-only if opening read-write fails",
143
+ },
144
{
145
.name = "detect-zeroes",
146
.type = QEMU_OPT_STRING,
147
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
148
qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
149
qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
150
qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
151
+ qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
152
+
153
}
154
155
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
156
diff --git a/block/vvfat.c b/block/vvfat.c
105
index XXXXXXX..XXXXXXX 100644
157
index XXXXXXX..XXXXXXX 100644
106
--- a/block/throttle-groups.c
158
--- a/block/vvfat.c
107
+++ b/block/throttle-groups.c
159
+++ b/block/vvfat.c
108
@@ -XXX,XX +XXX,XX @@ static ThrottleGroup *throttle_group_by_name(const char *name)
160
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
109
return NULL;
161
int parent_flags, QDict *parent_options)
162
{
163
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
164
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
165
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
110
}
166
}
111
167
112
+/* This function reads throttle_groups and must be called under the global
168
diff --git a/blockdev.c b/blockdev.c
113
+ * mutex.
114
+ */
115
+bool throttle_group_exists(const char *name)
116
+{
117
+ return throttle_group_by_name(name) != NULL;
118
+}
119
+
120
/* Increments the reference count of a ThrottleGroup given its name.
121
*
122
* If no ThrottleGroup is found with the given name a new one is
123
@@ -XXX,XX +XXX,XX @@ void throttle_group_unregister_tgm(ThrottleGroupMember *tgm)
124
ThrottleGroupMember *token;
125
int i;
126
127
+ if (!ts) {
128
+ /* Discard already unregistered tgm */
129
+ return;
130
+ }
131
+
132
assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0);
133
assert(qemu_co_queue_empty(&tgm->throttled_reqs[0]));
134
assert(qemu_co_queue_empty(&tgm->throttled_reqs[1]));
135
@@ -XXX,XX +XXX,XX @@ static void throttle_group_obj_complete(UserCreatable *obj, Error **errp)
136
assert(tg->name);
137
138
/* error if name is duplicate */
139
- if (throttle_group_by_name(tg->name) != NULL) {
140
+ if (throttle_group_exists(tg->name)) {
141
error_setg(errp, "A group with this name already exists");
142
return;
143
}
144
diff --git a/block/throttle.c b/block/throttle.c
145
new file mode 100644
146
index XXXXXXX..XXXXXXX
147
--- /dev/null
148
+++ b/block/throttle.c
149
@@ -XXX,XX +XXX,XX @@
150
+/*
151
+ * QEMU block throttling filter driver infrastructure
152
+ *
153
+ * Copyright (c) 2017 Manos Pitsidianakis
154
+ *
155
+ * This program is free software; you can redistribute it and/or
156
+ * modify it under the terms of the GNU General Public License as
157
+ * published by the Free Software Foundation; either version 2 or
158
+ * (at your option) version 3 of the License.
159
+ *
160
+ * This program is distributed in the hope that it will be useful,
161
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
162
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163
+ * GNU General Public License for more details.
164
+ *
165
+ * You should have received a copy of the GNU General Public License
166
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
167
+ */
168
+
169
+#include "qemu/osdep.h"
170
+#include "block/throttle-groups.h"
171
+#include "qemu/throttle-options.h"
172
+#include "qapi/error.h"
173
+
174
+static QemuOptsList throttle_opts = {
175
+ .name = "throttle",
176
+ .head = QTAILQ_HEAD_INITIALIZER(throttle_opts.head),
177
+ .desc = {
178
+ {
179
+ .name = QEMU_OPT_THROTTLE_GROUP_NAME,
180
+ .type = QEMU_OPT_STRING,
181
+ .help = "Name of the throttle group",
182
+ },
183
+ { /* end of list */ }
184
+ },
185
+};
186
+
187
+static int throttle_configure_tgm(BlockDriverState *bs,
188
+ ThrottleGroupMember *tgm,
189
+ QDict *options, Error **errp)
190
+{
191
+ int ret;
192
+ const char *group_name;
193
+ Error *local_err = NULL;
194
+ QemuOpts *opts = qemu_opts_create(&throttle_opts, NULL, 0, &error_abort);
195
+
196
+ qemu_opts_absorb_qdict(opts, options, &local_err);
197
+ if (local_err) {
198
+ error_propagate(errp, local_err);
199
+ ret = -EINVAL;
200
+ goto fin;
201
+ }
202
+
203
+ group_name = qemu_opt_get(opts, QEMU_OPT_THROTTLE_GROUP_NAME);
204
+ if (!group_name) {
205
+ error_setg(errp, "Please specify a throttle group");
206
+ ret = -EINVAL;
207
+ goto fin;
208
+ } else if (!throttle_group_exists(group_name)) {
209
+ error_setg(errp, "Throttle group '%s' does not exist", group_name);
210
+ ret = -EINVAL;
211
+ goto fin;
212
+ }
213
+
214
+ /* Register membership to group with name group_name */
215
+ throttle_group_register_tgm(tgm, group_name, bdrv_get_aio_context(bs));
216
+ ret = 0;
217
+fin:
218
+ qemu_opts_del(opts);
219
+ return ret;
220
+}
221
+
222
+static int throttle_open(BlockDriverState *bs, QDict *options,
223
+ int flags, Error **errp)
224
+{
225
+ ThrottleGroupMember *tgm = bs->opaque;
226
+
227
+ bs->file = bdrv_open_child(NULL, options, "file", bs,
228
+ &child_file, false, errp);
229
+ if (!bs->file) {
230
+ return -EINVAL;
231
+ }
232
+ bs->supported_write_flags = bs->file->bs->supported_write_flags;
233
+ bs->supported_zero_flags = bs->file->bs->supported_zero_flags;
234
+
235
+ return throttle_configure_tgm(bs, tgm, options, errp);
236
+}
237
+
238
+static void throttle_close(BlockDriverState *bs)
239
+{
240
+ ThrottleGroupMember *tgm = bs->opaque;
241
+ throttle_group_unregister_tgm(tgm);
242
+}
243
+
244
+
245
+static int64_t throttle_getlength(BlockDriverState *bs)
246
+{
247
+ return bdrv_getlength(bs->file->bs);
248
+}
249
+
250
+static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
251
+ uint64_t offset, uint64_t bytes,
252
+ QEMUIOVector *qiov, int flags)
253
+{
254
+
255
+ ThrottleGroupMember *tgm = bs->opaque;
256
+ throttle_group_co_io_limits_intercept(tgm, bytes, false);
257
+
258
+ return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
259
+}
260
+
261
+static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
262
+ uint64_t offset, uint64_t bytes,
263
+ QEMUIOVector *qiov, int flags)
264
+{
265
+ ThrottleGroupMember *tgm = bs->opaque;
266
+ throttle_group_co_io_limits_intercept(tgm, bytes, true);
267
+
268
+ return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
269
+}
270
+
271
+static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
272
+ int64_t offset, int bytes,
273
+ BdrvRequestFlags flags)
274
+{
275
+ ThrottleGroupMember *tgm = bs->opaque;
276
+ throttle_group_co_io_limits_intercept(tgm, bytes, true);
277
+
278
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
279
+}
280
+
281
+static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
282
+ int64_t offset, int bytes)
283
+{
284
+ ThrottleGroupMember *tgm = bs->opaque;
285
+ throttle_group_co_io_limits_intercept(tgm, bytes, true);
286
+
287
+ return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
288
+}
289
+
290
+static int throttle_co_flush(BlockDriverState *bs)
291
+{
292
+ return bdrv_co_flush(bs->file->bs);
293
+}
294
+
295
+static void throttle_detach_aio_context(BlockDriverState *bs)
296
+{
297
+ ThrottleGroupMember *tgm = bs->opaque;
298
+ throttle_group_detach_aio_context(tgm);
299
+}
300
+
301
+static void throttle_attach_aio_context(BlockDriverState *bs,
302
+ AioContext *new_context)
303
+{
304
+ ThrottleGroupMember *tgm = bs->opaque;
305
+ throttle_group_attach_aio_context(tgm, new_context);
306
+}
307
+
308
+static int throttle_reopen_prepare(BDRVReopenState *reopen_state,
309
+ BlockReopenQueue *queue, Error **errp)
310
+{
311
+ ThrottleGroupMember *tgm;
312
+
313
+ assert(reopen_state != NULL);
314
+ assert(reopen_state->bs != NULL);
315
+
316
+ reopen_state->opaque = g_new0(ThrottleGroupMember, 1);
317
+ tgm = reopen_state->opaque;
318
+
319
+ return throttle_configure_tgm(reopen_state->bs, tgm, reopen_state->options,
320
+ errp);
321
+}
322
+
323
+static void throttle_reopen_commit(BDRVReopenState *reopen_state)
324
+{
325
+ ThrottleGroupMember *old_tgm = reopen_state->bs->opaque;
326
+ ThrottleGroupMember *new_tgm = reopen_state->opaque;
327
+
328
+ throttle_group_unregister_tgm(old_tgm);
329
+ g_free(old_tgm);
330
+ reopen_state->bs->opaque = new_tgm;
331
+ reopen_state->opaque = NULL;
332
+}
333
+
334
+static void throttle_reopen_abort(BDRVReopenState *reopen_state)
335
+{
336
+ ThrottleGroupMember *tgm = reopen_state->opaque;
337
+
338
+ throttle_group_unregister_tgm(tgm);
339
+ g_free(tgm);
340
+ reopen_state->opaque = NULL;
341
+}
342
+
343
+static bool throttle_recurse_is_first_non_filter(BlockDriverState *bs,
344
+ BlockDriverState *candidate)
345
+{
346
+ return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
347
+}
348
+
349
+static BlockDriver bdrv_throttle = {
350
+ .format_name = "throttle",
351
+ .protocol_name = "throttle",
352
+ .instance_size = sizeof(ThrottleGroupMember),
353
+
354
+ .bdrv_file_open = throttle_open,
355
+ .bdrv_close = throttle_close,
356
+ .bdrv_co_flush = throttle_co_flush,
357
+
358
+ .bdrv_child_perm = bdrv_filter_default_perms,
359
+
360
+ .bdrv_getlength = throttle_getlength,
361
+
362
+ .bdrv_co_preadv = throttle_co_preadv,
363
+ .bdrv_co_pwritev = throttle_co_pwritev,
364
+
365
+ .bdrv_co_pwrite_zeroes = throttle_co_pwrite_zeroes,
366
+ .bdrv_co_pdiscard = throttle_co_pdiscard,
367
+
368
+ .bdrv_recurse_is_first_non_filter = throttle_recurse_is_first_non_filter,
369
+
370
+ .bdrv_attach_aio_context = throttle_attach_aio_context,
371
+ .bdrv_detach_aio_context = throttle_detach_aio_context,
372
+
373
+ .bdrv_reopen_prepare = throttle_reopen_prepare,
374
+ .bdrv_reopen_commit = throttle_reopen_commit,
375
+ .bdrv_reopen_abort = throttle_reopen_abort,
376
+ .bdrv_co_get_block_status = bdrv_co_get_block_status_from_file,
377
+
378
+ .is_filter = true,
379
+};
380
+
381
+static void bdrv_throttle_init(void)
382
+{
383
+ bdrv_register(&bdrv_throttle);
384
+}
385
+
386
+block_init(bdrv_throttle_init);
387
diff --git a/block/Makefile.objs b/block/Makefile.objs
388
index XXXXXXX..XXXXXXX 100644
169
index XXXXXXX..XXXXXXX 100644
389
--- a/block/Makefile.objs
170
--- a/blockdev.c
390
+++ b/block/Makefile.objs
171
+++ b/blockdev.c
391
@@ -XXX,XX +XXX,XX @@ block-obj-y += accounting.o dirty-bitmap.o
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
392
block-obj-y += write-threshold.o
173
393
block-obj-y += backup.o
174
bdrv_flags = blk_get_open_flags_from_root_state(blk);
394
block-obj-$(CONFIG_REPLICATION) += replication.o
175
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
395
+block-obj-y += throttle.o
176
- BDRV_O_PROTOCOL);
396
177
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
397
block-obj-y += crypto.o
178
398
179
if (!has_read_only) {
180
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
399
--
181
--
400
2.13.5
182
2.19.1
401
183
402
184
diff view generated by jsdifflib
New patch
1
Commit e2b8247a322 introduced an error path in qemu_rbd_open() after
2
calling rbd_open(), but neglected to close the image again in this error
3
path. The error path should contain everything that the regular close
4
function qemu_rbd_close() contains.
1
5
6
This adds the missing rbd_close() call.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
---
11
block/rbd.c | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/block/rbd.c b/block/rbd.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
17
+++ b/block/rbd.c
18
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
19
"automatically marking the image read-only.");
20
r = bdrv_set_read_only(bs, true, &local_err);
21
if (r < 0) {
22
+ rbd_close(s->image);
23
error_propagate(errp, local_err);
24
goto failed_open;
25
}
26
--
27
2.19.1
28
29
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
Some block drivers have traditionally changed their node to read-only
2
2
mode without asking the user. This behaviour has been marked deprecated
3
This function is not used anywhere, so remove it.
3
since 2.11, expecting users to provide an explicit read-only=on option.
4
4
5
Markus Armbruster adds:
5
Now that we have auto-read-only=on, enable these drivers to make use of
6
The i82078 floppy device model used to call bdrv_media_changed() to
6
the option.
7
implement its media change bit when backed by a host floppy. This
7
8
went away in 21fcf36 "fdc: simplify media change handling".
8
This is the only use of bdrv_set_read_only(), so we can make it a bit
9
Probably broke host floppy media change. Host floppy pass-through
9
more specific and turn it into a bdrv_apply_auto_read_only() that is
10
was dropped in commit f709623. bdrv_media_changed() has never been
10
more convenient for drivers to use.
11
used for anything else. Remove it.
11
12
(Source is Message-ID: <87y3ruaypm.fsf@dusky.pond.sub.org>)
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
14
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
14
---
19
include/block/block.h | 1 -
15
include/block/block.h | 3 ++-
20
include/block/block_int.h | 1 -
16
block.c | 42 +++++++++++++++++++++++++++---------------
21
block.c | 14 --------------
17
block/bochs.c | 17 ++++++-----------
22
block/raw-format.c | 6 ------
18
block/cloop.c | 16 +++++-----------
23
4 files changed, 22 deletions(-)
19
block/dmg.c | 16 +++++-----------
20
block/rbd.c | 15 ++++-----------
21
block/vvfat.c | 10 ++--------
22
7 files changed, 51 insertions(+), 68 deletions(-)
24
23
25
diff --git a/include/block/block.h b/include/block/block.h
24
diff --git a/include/block/block.h b/include/block/block.h
26
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block.h
26
--- a/include/block/block.h
28
+++ b/include/block/block.h
27
+++ b/include/block/block.h
29
@@ -XXX,XX +XXX,XX @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
28
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
30
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
29
bool bdrv_is_read_only(BlockDriverState *bs);
30
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
31
bool ignore_allow_rdw, Error **errp);
32
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
33
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
34
+ Error **errp);
35
bool bdrv_is_writable(BlockDriverState *bs);
31
bool bdrv_is_sg(BlockDriverState *bs);
36
bool bdrv_is_sg(BlockDriverState *bs);
32
bool bdrv_is_inserted(BlockDriverState *bs);
37
bool bdrv_is_inserted(BlockDriverState *bs);
33
-int bdrv_media_changed(BlockDriverState *bs);
34
void bdrv_lock_medium(BlockDriverState *bs, bool locked);
35
void bdrv_eject(BlockDriverState *bs, bool eject_flag);
36
const char *bdrv_get_format_name(BlockDriverState *bs);
37
diff --git a/include/block/block_int.h b/include/block/block_int.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block_int.h
40
+++ b/include/block/block_int.h
41
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
42
43
/* removable device specific */
44
bool (*bdrv_is_inserted)(BlockDriverState *bs);
45
- int (*bdrv_media_changed)(BlockDriverState *bs);
46
void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag);
47
void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
48
49
diff --git a/block.c b/block.c
38
diff --git a/block.c b/block.c
50
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
51
--- a/block.c
40
--- a/block.c
52
+++ b/block.c
41
+++ b/block.c
53
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_inserted(BlockDriverState *bs)
42
@@ -XXX,XX +XXX,XX @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
43
return 0;
54
}
44
}
55
45
56
/**
46
-/* TODO Remove (deprecated since 2.11)
57
- * Return whether the media changed since the last call to this
47
- * Block drivers are not supposed to automatically change bs->read_only.
58
- * function, or -ENOTSUP if we don't know. Most drivers don't know.
48
- * Instead, they should just check whether they can provide what the user
59
- */
49
- * explicitly requested and error out if read-write is requested, but they can
60
-int bdrv_media_changed(BlockDriverState *bs)
50
- * only provide read-only access. */
61
-{
51
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
62
- BlockDriver *drv = bs->drv;
52
+/*
63
-
53
+ * Called by a driver that can only provide a read-only image.
64
- if (drv && drv->bdrv_media_changed) {
54
+ *
65
- return drv->bdrv_media_changed(bs);
55
+ * Returns 0 if the node is already read-only or it could switch the node to
56
+ * read-only because BDRV_O_AUTO_RDONLY is set.
57
+ *
58
+ * Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
59
+ * or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
60
+ * is not NULL, it is used as the error message for the Error object.
61
+ */
62
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
63
+ Error **errp)
64
{
65
int ret = 0;
66
67
- ret = bdrv_can_set_read_only(bs, read_only, false, errp);
68
- if (ret < 0) {
69
- return ret;
70
+ if (!(bs->open_flags & BDRV_O_RDWR)) {
71
+ return 0;
72
+ }
73
+ if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
74
+ goto fail;
75
}
76
77
- bs->read_only = read_only;
78
-
79
- if (read_only) {
80
- bs->open_flags &= ~BDRV_O_RDWR;
81
- } else {
82
- bs->open_flags |= BDRV_O_RDWR;
83
+ ret = bdrv_can_set_read_only(bs, true, false, NULL);
84
+ if (ret < 0) {
85
+ goto fail;
86
}
87
88
+ bs->read_only = true;
89
+ bs->open_flags &= ~BDRV_O_RDWR;
90
+
91
return 0;
92
+
93
+fail:
94
+ error_setg(errp, "%s", errmsg ?: "Image is read-only");
95
+ return -EACCES;
96
}
97
98
void bdrv_get_full_backing_filename_from_filename(const char *backed,
99
diff --git a/block/bochs.c b/block/bochs.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/bochs.c
102
+++ b/block/bochs.c
103
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
104
struct bochs_header bochs;
105
int ret;
106
107
+ /* No write support yet */
108
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
109
+ if (ret < 0) {
110
+ return ret;
111
+ }
112
+
113
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
114
false, errp);
115
if (!bs->file) {
116
return -EINVAL;
117
}
118
119
- if (!bdrv_is_read_only(bs)) {
120
- error_report("Opening bochs images without an explicit read-only=on "
121
- "option is deprecated. Future versions will refuse to "
122
- "open the image instead of automatically marking the "
123
- "image read-only.");
124
- ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
125
- if (ret < 0) {
126
- return ret;
127
- }
66
- }
128
- }
67
- return -ENOTSUP;
129
-
68
-}
130
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
69
-
131
if (ret < 0) {
70
-/**
132
return ret;
71
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
133
diff --git a/block/cloop.c b/block/cloop.c
72
*/
134
index XXXXXXX..XXXXXXX 100644
73
void bdrv_eject(BlockDriverState *bs, bool eject_flag)
135
--- a/block/cloop.c
74
diff --git a/block/raw-format.c b/block/raw-format.c
136
+++ b/block/cloop.c
75
index XXXXXXX..XXXXXXX 100644
137
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
76
--- a/block/raw-format.c
138
uint32_t offsets_size, max_compressed_block_size = 1, i;
77
+++ b/block/raw-format.c
139
int ret;
78
@@ -XXX,XX +XXX,XX @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
140
79
return bdrv_truncate(bs->file, offset, prealloc, errp);
141
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
80
}
142
+ if (ret < 0) {
81
143
+ return ret;
82
-static int raw_media_changed(BlockDriverState *bs)
144
+ }
83
-{
145
+
84
- return bdrv_media_changed(bs->file->bs);
146
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
85
-}
147
false, errp);
86
-
148
if (!bs->file) {
87
static void raw_eject(BlockDriverState *bs, bool eject_flag)
149
return -EINVAL;
88
{
150
}
89
bdrv_eject(bs->file->bs, eject_flag);
151
90
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
152
- if (!bdrv_is_read_only(bs)) {
91
.bdrv_refresh_limits = &raw_refresh_limits,
153
- error_report("Opening cloop images without an explicit read-only=on "
92
.bdrv_probe_blocksizes = &raw_probe_blocksizes,
154
- "option is deprecated. Future versions will refuse to "
93
.bdrv_probe_geometry = &raw_probe_geometry,
155
- "open the image instead of automatically marking the "
94
- .bdrv_media_changed = &raw_media_changed,
156
- "image read-only.");
95
.bdrv_eject = &raw_eject,
157
- ret = bdrv_set_read_only(bs, true, errp);
96
.bdrv_lock_medium = &raw_lock_medium,
158
- if (ret < 0) {
97
.bdrv_co_ioctl = &raw_co_ioctl,
159
- return ret;
160
- }
161
- }
162
-
163
/* read header */
164
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
165
if (ret < 0) {
166
diff --git a/block/dmg.c b/block/dmg.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/block/dmg.c
169
+++ b/block/dmg.c
170
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
171
int64_t offset;
172
int ret;
173
174
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
175
+ if (ret < 0) {
176
+ return ret;
177
+ }
178
+
179
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
180
false, errp);
181
if (!bs->file) {
182
return -EINVAL;
183
}
184
185
- if (!bdrv_is_read_only(bs)) {
186
- error_report("Opening dmg images without an explicit read-only=on "
187
- "option is deprecated. Future versions will refuse to "
188
- "open the image instead of automatically marking the "
189
- "image read-only.");
190
- ret = bdrv_set_read_only(bs, true, errp);
191
- if (ret < 0) {
192
- return ret;
193
- }
194
- }
195
-
196
block_module_load_one("dmg-bz2");
197
198
s->n_chunks = 0;
199
diff --git a/block/rbd.c b/block/rbd.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/block/rbd.c
202
+++ b/block/rbd.c
203
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
204
/* If we are using an rbd snapshot, we must be r/o, otherwise
205
* leave as-is */
206
if (s->snap != NULL) {
207
- if (!bdrv_is_read_only(bs)) {
208
- error_report("Opening rbd snapshots without an explicit "
209
- "read-only=on option is deprecated. Future versions "
210
- "will refuse to open the image instead of "
211
- "automatically marking the image read-only.");
212
- r = bdrv_set_read_only(bs, true, &local_err);
213
- if (r < 0) {
214
- rbd_close(s->image);
215
- error_propagate(errp, local_err);
216
- goto failed_open;
217
- }
218
+ r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
219
+ if (r < 0) {
220
+ rbd_close(s->image);
221
+ goto failed_open;
222
}
223
}
224
225
diff --git a/block/vvfat.c b/block/vvfat.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/block/vvfat.c
228
+++ b/block/vvfat.c
229
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
230
"Unable to set VVFAT to 'rw' when drive is read-only");
231
goto fail;
232
}
233
- } else if (!bdrv_is_read_only(bs)) {
234
- error_report("Opening non-rw vvfat images without an explicit "
235
- "read-only=on option is deprecated. Future versions "
236
- "will refuse to open the image instead of "
237
- "automatically marking the image read-only.");
238
- /* read only is the default for safety */
239
- ret = bdrv_set_read_only(bs, true, &local_err);
240
+ } else {
241
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
242
if (ret < 0) {
243
- error_propagate(errp, local_err);
244
goto fail;
245
}
246
}
98
--
247
--
99
2.13.5
248
2.19.1
100
249
101
250
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
If read-only=off, but auto-read-only=on is given, open a read-write NBD
2
connection if the server provides a read-write export, but instead of
3
erroring out for read-only exports, just degrade to read-only.
2
4
3
The old signature has an ambiguous meaning for a return of 0:
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
either no allocation was requested or necessary, or an error
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
occurred (but any errno associated with the error is lost to
7
---
6
the caller, which then has to assume EIO).
8
block/nbd-client.c | 10 +++++-----
9
1 file changed, 5 insertions(+), 5 deletions(-)
7
10
8
Better is to follow the example of qcow2, by changing the
11
diff --git a/block/nbd-client.c b/block/nbd-client.c
9
signature to have a separate return value that cleanly
10
distinguishes between failure and success, along with a
11
parameter that cleanly holds a 64-bit value. Then update all
12
callers.
13
14
While auditing that all return paths return a negative errno
15
(rather than -1), I also simplified places where we can pass
16
NULL rather than a local Error that just gets thrown away.
17
18
Suggested-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Eric Blake <eblake@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
22
block/qcow.c | 123 +++++++++++++++++++++++++++++++++++------------------------
23
1 file changed, 73 insertions(+), 50 deletions(-)
24
25
diff --git a/block/qcow.c b/block/qcow.c
26
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow.c
13
--- a/block/nbd-client.c
28
+++ b/block/qcow.c
14
+++ b/block/nbd-client.c
29
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
15
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
30
* 'compressed_size'. 'compressed_size' must be > 0 and <
16
logout("Failed to negotiate with the NBD server\n");
31
* cluster_size
17
return ret;
32
*
33
- * return 0 if not allocated.
34
+ * return 0 if not allocated, 1 if *result is assigned, and negative
35
+ * errno on failure.
36
*/
37
-static uint64_t get_cluster_offset(BlockDriverState *bs,
38
- uint64_t offset, int allocate,
39
- int compressed_size,
40
- int n_start, int n_end)
41
+static int get_cluster_offset(BlockDriverState *bs,
42
+ uint64_t offset, int allocate,
43
+ int compressed_size,
44
+ int n_start, int n_end, uint64_t *result)
45
{
46
BDRVQcowState *s = bs->opaque;
47
- int min_index, i, j, l1_index, l2_index;
48
+ int min_index, i, j, l1_index, l2_index, ret;
49
uint64_t l2_offset, *l2_table, cluster_offset, tmp;
50
uint32_t min_count;
51
int new_l2_table;
52
53
+ *result = 0;
54
l1_index = offset >> (s->l2_bits + s->cluster_bits);
55
l2_offset = s->l1_table[l1_index];
56
new_l2_table = 0;
57
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
58
/* update the L1 entry */
59
s->l1_table[l1_index] = l2_offset;
60
tmp = cpu_to_be64(l2_offset);
61
- if (bdrv_pwrite_sync(bs->file,
62
- s->l1_table_offset + l1_index * sizeof(tmp),
63
- &tmp, sizeof(tmp)) < 0)
64
- return 0;
65
+ ret = bdrv_pwrite_sync(bs->file,
66
+ s->l1_table_offset + l1_index * sizeof(tmp),
67
+ &tmp, sizeof(tmp));
68
+ if (ret < 0) {
69
+ return ret;
70
+ }
71
new_l2_table = 1;
72
}
18
}
73
for(i = 0; i < L2_CACHE_SIZE; i++) {
19
- if (client->info.flags & NBD_FLAG_READ_ONLY &&
74
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
20
- !bdrv_is_read_only(bs)) {
75
l2_table = s->l2_cache + (min_index << s->l2_bits);
21
- error_setg(errp,
76
if (new_l2_table) {
22
- "request for write access conflicts with read-only export");
77
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
23
- return -EACCES;
78
- if (bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
24
+ if (client->info.flags & NBD_FLAG_READ_ONLY) {
79
- s->l2_size * sizeof(uint64_t)) < 0)
25
+ ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
80
- return 0;
81
+ ret = bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
82
+ s->l2_size * sizeof(uint64_t));
83
+ if (ret < 0) {
84
+ return ret;
85
+ }
86
} else {
87
- if (bdrv_pread(bs->file, l2_offset, l2_table,
88
- s->l2_size * sizeof(uint64_t)) !=
89
- s->l2_size * sizeof(uint64_t))
90
- return 0;
91
+ ret = bdrv_pread(bs->file, l2_offset, l2_table,
92
+ s->l2_size * sizeof(uint64_t));
93
+ if (ret < 0) {
26
+ if (ret < 0) {
94
+ return ret;
27
+ return ret;
95
+ }
28
+ }
96
}
29
}
97
s->l2_cache_offsets[min_index] = l2_offset;
30
if (client->info.flags & NBD_FLAG_SEND_FUA) {
98
s->l2_cache_counts[min_index] = 1;
31
bs->supported_write_flags = BDRV_REQ_FUA;
99
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
100
/* if the cluster is already compressed, we must
101
decompress it in the case it is not completely
102
overwritten */
103
- if (decompress_cluster(bs, cluster_offset) < 0)
104
- return 0;
105
+ if (decompress_cluster(bs, cluster_offset) < 0) {
106
+ return -EIO;
107
+ }
108
cluster_offset = bdrv_getlength(bs->file->bs);
109
cluster_offset = (cluster_offset + s->cluster_size - 1) &
110
~(s->cluster_size - 1);
111
/* write the cluster content */
112
- if (bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
113
- s->cluster_size) !=
114
- s->cluster_size)
115
- return -1;
116
+ ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
117
+ s->cluster_size);
118
+ if (ret < 0) {
119
+ return ret;
120
+ }
121
} else {
122
cluster_offset = bdrv_getlength(bs->file->bs);
123
if (allocate == 1) {
124
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
125
s->cluster_data,
126
BDRV_SECTOR_SIZE,
127
NULL) < 0) {
128
- errno = EIO;
129
- return -1;
130
+ return -EIO;
131
+ }
132
+ ret = bdrv_pwrite(bs->file,
133
+ cluster_offset + i * 512,
134
+ s->cluster_data, 512);
135
+ if (ret < 0) {
136
+ return ret;
137
}
138
- if (bdrv_pwrite(bs->file,
139
- cluster_offset + i * 512,
140
- s->cluster_data, 512) != 512)
141
- return -1;
142
}
143
}
144
}
145
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
146
/* update L2 table */
147
tmp = cpu_to_be64(cluster_offset);
148
l2_table[l2_index] = tmp;
149
- if (bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
150
- &tmp, sizeof(tmp)) < 0)
151
- return 0;
152
+ ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
153
+ &tmp, sizeof(tmp));
154
+ if (ret < 0) {
155
+ return ret;
156
+ }
157
}
158
- return cluster_offset;
159
+ *result = cluster_offset;
160
+ return 1;
161
}
162
163
static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
164
int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
165
{
166
BDRVQcowState *s = bs->opaque;
167
- int index_in_cluster, n;
168
+ int index_in_cluster, n, ret;
169
uint64_t cluster_offset;
170
171
qemu_co_mutex_lock(&s->lock);
172
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
173
+ ret = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0, &cluster_offset);
174
qemu_co_mutex_unlock(&s->lock);
175
+ if (ret < 0) {
176
+ return ret;
177
+ }
178
index_in_cluster = sector_num & (s->cluster_sectors - 1);
179
n = s->cluster_sectors - index_in_cluster;
180
if (n > nb_sectors)
181
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
182
183
while (nb_sectors != 0) {
184
/* prepare next request */
185
- cluster_offset = get_cluster_offset(bs, sector_num << 9,
186
- 0, 0, 0, 0);
187
+ ret = get_cluster_offset(bs, sector_num << 9,
188
+ 0, 0, 0, 0, &cluster_offset);
189
+ if (ret < 0) {
190
+ break;
191
+ }
192
index_in_cluster = sector_num & (s->cluster_sectors - 1);
193
n = s->cluster_sectors - index_in_cluster;
194
if (n > nb_sectors) {
195
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
196
ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
197
qemu_co_mutex_lock(&s->lock);
198
if (ret < 0) {
199
- goto fail;
200
+ break;
201
}
202
} else {
203
/* Note: in this case, no need to wait */
204
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
205
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
206
/* add AIO support for compressed blocks ? */
207
if (decompress_cluster(bs, cluster_offset) < 0) {
208
- goto fail;
209
+ ret = -EIO;
210
+ break;
211
}
212
memcpy(buf,
213
s->cluster_cache + index_in_cluster * 512, 512 * n);
214
} else {
215
if ((cluster_offset & 511) != 0) {
216
- goto fail;
217
+ ret = -EIO;
218
+ break;
219
}
220
hd_iov.iov_base = (void *)buf;
221
hd_iov.iov_len = n * 512;
222
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
223
assert(s->crypto);
224
if (qcrypto_block_decrypt(s->crypto, sector_num, buf,
225
n * BDRV_SECTOR_SIZE, NULL) < 0) {
226
- goto fail;
227
+ ret = -EIO;
228
+ break;
229
}
230
}
231
}
232
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
233
buf += n * 512;
234
}
235
236
-done:
237
qemu_co_mutex_unlock(&s->lock);
238
239
if (qiov->niov > 1) {
240
@@ -XXX,XX +XXX,XX @@ done:
241
}
242
243
return ret;
244
-
245
-fail:
246
- ret = -EIO;
247
- goto done;
248
}
249
250
static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
251
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
252
if (n > nb_sectors) {
253
n = nb_sectors;
254
}
255
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
256
- index_in_cluster,
257
- index_in_cluster + n);
258
+ ret = get_cluster_offset(bs, sector_num << 9, 1, 0,
259
+ index_in_cluster,
260
+ index_in_cluster + n, &cluster_offset);
261
+ if (ret < 0) {
262
+ break;
263
+ }
264
if (!cluster_offset || (cluster_offset & 511) != 0) {
265
ret = -EIO;
266
break;
267
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
268
goto success;
269
}
270
qemu_co_mutex_lock(&s->lock);
271
- cluster_offset = get_cluster_offset(bs, offset, 2, out_len, 0, 0);
272
+ ret = get_cluster_offset(bs, offset, 2, out_len, 0, 0, &cluster_offset);
273
qemu_co_mutex_unlock(&s->lock);
274
+ if (ret < 0) {
275
+ goto fail;
276
+ }
277
if (cluster_offset == 0) {
278
ret = -EIO;
279
goto fail;
280
--
32
--
281
2.13.5
33
2.19.1
282
34
283
35
diff view generated by jsdifflib
New patch
1
If read-only=off, but auto-read-only=on is given, open the file
2
read-write if we have the permissions, but instead of erroring out for
3
read-only files, just degrade to read-only.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
block/file-posix.c | 19 ++++++++++++++++---
9
1 file changed, 16 insertions(+), 3 deletions(-)
10
11
diff --git a/block/file-posix.c b/block/file-posix.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-posix.c
14
+++ b/block/file-posix.c
15
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
16
17
s->fd = -1;
18
fd = qemu_open(filename, s->open_flags, 0644);
19
- if (fd < 0) {
20
- ret = -errno;
21
- error_setg_errno(errp, errno, "Could not open '%s'", filename);
22
+ ret = fd < 0 ? -errno : 0;
23
+
24
+ if (ret == -EACCES || ret == -EROFS) {
25
+ /* Try to degrade to read-only, but if it doesn't work, still use the
26
+ * normal error message. */
27
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
28
+ bdrv_flags &= ~BDRV_O_RDWR;
29
+ raw_parse_flags(bdrv_flags, &s->open_flags);
30
+ assert(!(s->open_flags & O_CREAT));
31
+ fd = qemu_open(filename, s->open_flags);
32
+ ret = fd < 0 ? -errno : 0;
33
+ }
34
+ }
35
+
36
+ if (ret < 0) {
37
+ error_setg_errno(errp, -ret, "Could not open '%s'", filename);
38
if (ret == -EROFS) {
39
ret = -EACCES;
40
}
41
--
42
2.19.1
43
44
diff view generated by jsdifflib
New patch
1
If read-only=off, but auto-read-only=on is given, just degrade to
2
read-only.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
---
7
block/curl.c | 8 ++++----
8
1 file changed, 4 insertions(+), 4 deletions(-)
9
10
diff --git a/block/curl.c b/block/curl.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/curl.c
13
+++ b/block/curl.c
14
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
15
const char *protocol_delimiter;
16
int ret;
17
18
-
19
- if (flags & BDRV_O_RDWR) {
20
- error_setg(errp, "curl block device does not support writes");
21
- return -EROFS;
22
+ ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
23
+ errp);
24
+ if (ret < 0) {
25
+ return ret;
26
}
27
28
if (!libcurl_initialized) {
29
--
30
2.19.1
31
32
diff view generated by jsdifflib
New patch
1
If read-only=off, but auto-read-only=on is given, open the file
2
read-write if we have the permissions, but instead of erroring out for
3
read-only files, just degrade to read-only.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Niels de Vos <ndevos@redhat.com>
7
---
8
block/gluster.c | 12 ++++++++++--
9
1 file changed, 10 insertions(+), 2 deletions(-)
10
11
diff --git a/block/gluster.c b/block/gluster.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/gluster.c
14
+++ b/block/gluster.c
15
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
16
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
17
18
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
19
- if (!s->fd) {
20
- ret = -errno;
21
+ ret = s->fd ? 0 : -errno;
22
+
23
+ if (ret == -EACCES || ret == -EROFS) {
24
+ /* Try to degrade to read-only, but if it doesn't work, still use the
25
+ * normal error message. */
26
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
27
+ open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
28
+ s->fd = glfs_open(s->glfs, gconf->path, open_flags);
29
+ ret = s->fd ? 0 : -errno;
30
+ }
31
}
32
33
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
34
--
35
2.19.1
36
37
diff view generated by jsdifflib
New patch
1
If read-only=off, but auto-read-only=on is given, open the volume
2
read-write if we have the permissions, but instead of erroring out for
3
read-only volumes, just degrade to read-only.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
block/iscsi.c | 8 +++++---
9
1 file changed, 5 insertions(+), 3 deletions(-)
10
11
diff --git a/block/iscsi.c b/block/iscsi.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/iscsi.c
14
+++ b/block/iscsi.c
15
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
16
/* Check the write protect flag of the LUN if we want to write */
17
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
18
iscsilun->write_protected) {
19
- error_setg(errp, "Cannot open a write protected LUN as read-write");
20
- ret = -EACCES;
21
- goto out;
22
+ ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
23
+ if (ret < 0) {
24
+ goto out;
25
+ }
26
+ flags &= ~BDRV_O_RDWR;
27
}
28
29
iscsi_readcapacity_sync(iscsilun, &local_err);
30
--
31
2.19.1
32
33
diff view generated by jsdifflib
New patch
1
While we want machine interfaces like -blockdev and QMP blockdev-add to
2
add as little auto-detection as possible so that management tools are
3
explicit about their needs, -drive is a convenience option for human
4
users. Enabling auto-read-only=on by default there enables users to use
5
read-only images for read-only guest devices without having to specify
6
read-only=on explicitly. If they try to attach the image to a read-write
7
device, they will still get an error message.
1
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
---
12
blockdev.c | 1 +
13
1 file changed, 1 insertion(+)
14
15
diff --git a/blockdev.c b/blockdev.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/blockdev.c
18
+++ b/blockdev.c
19
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
20
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
21
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
22
read_only ? "on" : "off");
23
+ qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
24
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
25
26
if (runstate_check(RUN_STATE_INMIGRATE)) {
27
--
28
2.19.1
29
30
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
4
tests/qemu-iotests/232 | 147 +++++++++++++++++++++++++++++++++++++
5
tests/qemu-iotests/232.out | 59 +++++++++++++++
6
tests/qemu-iotests/group | 1 +
7
3 files changed, 207 insertions(+)
8
create mode 100755 tests/qemu-iotests/232
9
create mode 100644 tests/qemu-iotests/232.out
2
10
3
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
4
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
tests/qemu-iotests/184 | 205 ++++++++++++++++++++++++++++++
9
tests/qemu-iotests/184.out | 302 +++++++++++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/group | 1 +
11
3 files changed, 508 insertions(+)
12
create mode 100755 tests/qemu-iotests/184
13
create mode 100644 tests/qemu-iotests/184.out
14
15
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
16
new file mode 100755
12
new file mode 100755
17
index XXXXXXX..XXXXXXX
13
index XXXXXXX..XXXXXXX
18
--- /dev/null
14
--- /dev/null
19
+++ b/tests/qemu-iotests/184
15
+++ b/tests/qemu-iotests/232
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
21
+#!/bin/bash
17
+#!/bin/bash
22
+#
18
+#
23
+# Test I/O throttle block filter driver interface
19
+# Test for auto-read-only
24
+#
20
+#
25
+# Copyright (C) 2017 Manos Pitsidianakis
21
+# Copyright (C) 2018 Red Hat, Inc.
26
+#
22
+#
27
+# This program is free software; you can redistribute it and/or modify
23
+# This program is free software; you can redistribute it and/or modify
28
+# it under the terms of the GNU General Public License as published by
24
+# it under the terms of the GNU General Public License as published by
29
+# the Free Software Foundation; either version 2 of the License, or
25
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
26
+# (at your option) any later version.
...
...
37
+# You should have received a copy of the GNU General Public License
33
+# You should have received a copy of the GNU General Public License
38
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
34
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+#
35
+#
40
+
36
+
41
+# creator
37
+# creator
42
+owner="Manos Pitsidianakis"
38
+owner=kwolf@redhat.com
43
+
39
+
44
+seq=`basename $0`
40
+seq=`basename $0`
45
+echo "QA output created by $seq"
41
+echo "QA output created by $seq"
46
+
42
+
47
+here=`pwd`
43
+here=`pwd`
48
+status=1    # failure is the default!
44
+status=1    # failure is the default!
49
+
45
+
50
+_cleanup()
46
+_cleanup()
51
+{
47
+{
52
+ _cleanup_test_img
48
+ _cleanup_test_img
49
+ rm -f $TEST_IMG.snap
53
+}
50
+}
54
+trap "_cleanup; exit \$status" 0 1 2 3 15
51
+trap "_cleanup; exit \$status" 0 1 2 3 15
55
+
52
+
56
+# get standard environment, filters and checks
53
+# get standard environment, filters and checks
57
+. ./common.rc
54
+. ./common.rc
58
+. ./common.filter
55
+. ./common.filter
59
+
56
+
60
+_supported_fmt qcow2
57
+_supported_fmt generic
61
+_supported_proto file
58
+_supported_proto file
62
+_supported_os Linux
59
+_supported_os Linux
63
+
60
+
64
+function do_run_qemu()
61
+function do_run_qemu()
65
+{
62
+{
66
+ echo Testing: "$@" | _filter_imgfmt
63
+ echo Testing: "$@"
67
+ $QEMU -nographic -qmp-pretty stdio -serial none "$@"
64
+ (
65
+ if ! test -t 0; then
66
+ while read cmd; do
67
+ echo $cmd
68
+ done
69
+ fi
70
+ echo quit
71
+ ) | $QEMU -nographic -monitor stdio -nodefaults "$@"
68
+ echo
72
+ echo
69
+}
73
+}
70
+
74
+
71
+function run_qemu()
75
+function run_qemu()
72
+{
76
+{
73
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
77
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp |
74
+ | _filter_qemu_io | _filter_generated_node_ids
78
+ _filter_generated_node_ids | _filter_imgfmt
75
+}
79
+}
76
+
80
+
77
+_make_test_img 64M
81
+function run_qemu_info_block()
78
+test_throttle=$($QEMU_IMG --help|grep throttle)
82
+{
79
+[ "$test_throttle" = "" ] && _supported_fmt throttle
83
+ echo "info block -n" | run_qemu "$@" | grep -e "(file" -e "QEMU_PROG"
80
+
84
+}
81
+echo
85
+
82
+echo "== checking interface =="
86
+size=128M
83
+
87
+
84
+run_qemu <<EOF
88
+_make_test_img $size
85
+{ "execute": "qmp_capabilities" }
89
+
86
+{ "execute": "blockdev-add",
90
+echo
87
+ "arguments": {
91
+echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
88
+ "driver": "$IMGFMT",
92
+echo
89
+ "node-name": "disk0",
93
+
90
+ "file": {
94
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
91
+ "driver": "file",
95
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
92
+ "filename": "$TEST_IMG"
96
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
93
+ }
97
+echo
94
+ }
98
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
95
+}
99
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
96
+{ "execute": "object-add",
100
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
97
+ "arguments": {
101
+echo
98
+ "qom-type": "throttle-group",
102
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
99
+ "id": "group0",
103
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
100
+ "props": {
104
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
101
+ "limits" : {
105
+
102
+ "iops-total": 1000
106
+echo
103
+ }
107
+echo "=== -drive with read-only image: read-only/auto-read-only combinations ==="
104
+ }
108
+echo
105
+ }
109
+
106
+}
110
+chmod a-w $TEST_IMG
107
+{ "execute": "blockdev-add",
111
+
108
+ "arguments": {
112
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
109
+ "driver": "throttle",
113
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
110
+ "node-name": "throttle0",
114
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
111
+ "throttle-group": "group0",
115
+echo
112
+ "file": "disk0"
116
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
113
+ }
117
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
114
+}
118
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
115
+{ "execute": "query-named-block-nodes" }
119
+echo
116
+{ "execute": "query-block" }
120
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
117
+{ "execute": "quit" }
121
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
118
+EOF
122
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
119
+
123
+
120
+echo
124
+echo
121
+echo "== property changes in ThrottleGroup =="
125
+echo "=== -blockdev with read-write image: read-only/auto-read-only combinations ==="
122
+
126
+echo
123
+run_qemu <<EOF
127
+
124
+{ "execute": "qmp_capabilities" }
128
+chmod a+w $TEST_IMG
125
+{ "execute": "object-add",
129
+
126
+ "arguments": {
130
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
127
+ "qom-type": "throttle-group",
131
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
128
+ "id": "group0",
132
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
129
+ "props" : {
133
+echo
130
+ "limits": {
134
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
131
+ "iops-total": 1000
135
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
132
+ }
136
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
133
+ }
137
+echo
134
+ }
138
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
135
+}
139
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
136
+{ "execute" : "qom-get",
140
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
137
+ "arguments" : {
141
+
138
+ "path" : "group0",
142
+echo
139
+ "property" : "limits"
143
+echo "=== -blockdev with read-only image: read-only/auto-read-only combinations ==="
140
+ }
144
+echo
141
+}
145
+
142
+{ "execute" : "qom-set",
146
+chmod a-w $TEST_IMG
143
+ "arguments" : {
147
+
144
+ "path" : "group0",
148
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
145
+ "property" : "limits",
149
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
146
+ "value" : {
150
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
147
+ "iops-total" : 0
151
+echo
148
+ }
152
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
149
+ }
153
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
150
+}
154
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
151
+{ "execute" : "qom-get",
155
+echo
152
+ "arguments" : {
156
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
153
+ "path" : "group0",
157
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
154
+ "property" : "limits"
158
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
155
+ }
159
+
156
+}
157
+{ "execute": "quit" }
158
+EOF
159
+
160
+echo
161
+echo "== object creation/set errors =="
162
+
163
+run_qemu <<EOF
164
+{ "execute": "qmp_capabilities" }
165
+{ "execute": "object-add",
166
+ "arguments": {
167
+ "qom-type": "throttle-group",
168
+ "id": "group0",
169
+ "props" : {
170
+ "limits": {
171
+ "iops-total": 1000
172
+ }
173
+ }
174
+ }
175
+}
176
+{ "execute" : "qom-set",
177
+ "arguments" : {
178
+ "path" : "group0",
179
+ "property" : "x-iops-total",
180
+ "value" : 0
181
+ }
182
+}
183
+{ "execute" : "qom-set",
184
+ "arguments" : {
185
+ "path" : "group0",
186
+ "property" : "limits",
187
+ "value" : {
188
+ "iops-total" : 10,
189
+ "iops-read" : 10
190
+ }
191
+ }
192
+}
193
+{ "execute": "quit" }
194
+EOF
195
+
196
+echo
197
+echo "== don't specify group =="
198
+
199
+run_qemu <<EOF
200
+{ "execute": "qmp_capabilities" }
201
+{ "execute": "blockdev-add",
202
+ "arguments": {
203
+ "driver": "$IMGFMT",
204
+ "node-name": "disk0",
205
+ "file": {
206
+ "driver": "file",
207
+ "filename": "$TEST_IMG"
208
+ }
209
+ }
210
+}
211
+{ "execute": "blockdev-add",
212
+ "arguments": {
213
+ "driver": "throttle",
214
+ "node-name": "throttle0",
215
+ "file": "disk0"
216
+ }
217
+}
218
+{ "execute": "quit" }
219
+EOF
220
+
221
+echo
222
+# success, all done
160
+# success, all done
223
+echo "*** done"
161
+echo "*** done"
224
+rm -f $seq.full
162
+rm -f $seq.full
225
+status=0
163
+status=0
226
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
164
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
227
new file mode 100644
165
new file mode 100644
228
index XXXXXXX..XXXXXXX
166
index XXXXXXX..XXXXXXX
229
--- /dev/null
167
--- /dev/null
230
+++ b/tests/qemu-iotests/184.out
168
+++ b/tests/qemu-iotests/232.out
231
@@ -XXX,XX +XXX,XX @@
169
@@ -XXX,XX +XXX,XX @@
232
+QA output created by 184
170
+QA output created by 232
233
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
171
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
234
+
172
+
235
+== checking interface ==
173
+=== -drive with read-write image: read-only/auto-read-only combinations ===
236
+Testing:
174
+
237
+{
175
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
238
+ QMP_VERSION
176
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
239
+}
177
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
240
+{
178
+
241
+ "return": {
179
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
242
+ }
180
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
243
+}
181
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
244
+{
182
+
245
+ "return": {
183
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
246
+ }
184
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
247
+}
185
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
248
+{
186
+
249
+ "return": {
187
+=== -drive with read-only image: read-only/auto-read-only combinations ===
250
+ }
188
+
251
+}
189
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
252
+{
190
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
253
+ "return": {
191
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
254
+ }
192
+
255
+}
193
+QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
256
+{
194
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
257
+ "return": [
195
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
258
+ {
196
+
259
+ "iops_rd": 0,
197
+QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
260
+ "detect_zeroes": "off",
198
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
261
+ "image": {
199
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
262
+ "virtual-size": 67108864,
200
+
263
+ "filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"qcow2\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/t.qcow2\"}}}",
201
+=== -blockdev with read-write image: read-only/auto-read-only combinations ===
264
+ "cluster-size": 65536,
202
+
265
+ "format": "throttle",
203
+node0: TEST_DIR/t.IMGFMT (file, read-only)
266
+ "actual-size": 200704,
204
+node0: TEST_DIR/t.IMGFMT (file, read-only)
267
+ "dirty-flag": false
205
+node0: TEST_DIR/t.IMGFMT (file, read-only)
268
+ },
206
+
269
+ "iops_wr": 0,
207
+node0: TEST_DIR/t.IMGFMT (file)
270
+ "ro": false,
208
+node0: TEST_DIR/t.IMGFMT (file)
271
+ "node-name": "throttle0",
209
+node0: TEST_DIR/t.IMGFMT (file)
272
+ "backing_file_depth": 0,
210
+
273
+ "drv": "throttle",
211
+node0: TEST_DIR/t.IMGFMT (file)
274
+ "iops": 0,
212
+node0: TEST_DIR/t.IMGFMT (file)
275
+ "bps_wr": 0,
213
+node0: TEST_DIR/t.IMGFMT (file)
276
+ "write_threshold": 0,
214
+
277
+ "encrypted": false,
215
+=== -blockdev with read-only image: read-only/auto-read-only combinations ===
278
+ "bps": 0,
216
+
279
+ "bps_rd": 0,
217
+node0: TEST_DIR/t.IMGFMT (file, read-only)
280
+ "cache": {
218
+node0: TEST_DIR/t.IMGFMT (file, read-only)
281
+ "no-flush": false,
219
+node0: TEST_DIR/t.IMGFMT (file, read-only)
282
+ "direct": false,
220
+
283
+ "writeback": true
221
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
284
+ },
222
+node0: TEST_DIR/t.IMGFMT (file, read-only)
285
+ "file": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"qcow2\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/t.qcow2\"}}}",
223
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
286
+ "encryption_key_missing": false
224
+
287
+ },
225
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
288
+ {
226
+node0: TEST_DIR/t.IMGFMT (file, read-only)
289
+ "iops_rd": 0,
227
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
290
+ "detect_zeroes": "off",
291
+ "image": {
292
+ "virtual-size": 67108864,
293
+ "filename": "TEST_DIR/t.qcow2",
294
+ "cluster-size": 65536,
295
+ "format": "qcow2",
296
+ "actual-size": 200704,
297
+ "format-specific": {
298
+ "type": "qcow2",
299
+ "data": {
300
+ "compat": "1.1",
301
+ "lazy-refcounts": false,
302
+ "refcount-bits": 16,
303
+ "corrupt": false
304
+ }
305
+ },
306
+ "dirty-flag": false
307
+ },
308
+ "iops_wr": 0,
309
+ "ro": false,
310
+ "node-name": "disk0",
311
+ "backing_file_depth": 0,
312
+ "drv": "qcow2",
313
+ "iops": 0,
314
+ "bps_wr": 0,
315
+ "write_threshold": 0,
316
+ "encrypted": false,
317
+ "bps": 0,
318
+ "bps_rd": 0,
319
+ "cache": {
320
+ "no-flush": false,
321
+ "direct": false,
322
+ "writeback": true
323
+ },
324
+ "file": "TEST_DIR/t.qcow2",
325
+ "encryption_key_missing": false
326
+ },
327
+ {
328
+ "iops_rd": 0,
329
+ "detect_zeroes": "off",
330
+ "image": {
331
+ "virtual-size": 197120,
332
+ "filename": "TEST_DIR/t.qcow2",
333
+ "format": "file",
334
+ "actual-size": 200704,
335
+ "dirty-flag": false
336
+ },
337
+ "iops_wr": 0,
338
+ "ro": false,
339
+ "node-name": "NODE_NAME",
340
+ "backing_file_depth": 0,
341
+ "drv": "file",
342
+ "iops": 0,
343
+ "bps_wr": 0,
344
+ "write_threshold": 0,
345
+ "encrypted": false,
346
+ "bps": 0,
347
+ "bps_rd": 0,
348
+ "cache": {
349
+ "no-flush": false,
350
+ "direct": false,
351
+ "writeback": true
352
+ },
353
+ "file": "TEST_DIR/t.qcow2",
354
+ "encryption_key_missing": false
355
+ }
356
+ ]
357
+}
358
+{
359
+ "return": [
360
+ ]
361
+}
362
+{
363
+ "return": {
364
+ }
365
+}
366
+{
367
+ "timestamp": {
368
+ "seconds": TIMESTAMP,
369
+ "microseconds": TIMESTAMP
370
+ },
371
+ "event": "SHUTDOWN",
372
+ "data": {
373
+ "guest": false
374
+ }
375
+}
376
+
377
+
378
+== property changes in ThrottleGroup ==
379
+Testing:
380
+{
381
+ QMP_VERSION
382
+}
383
+{
384
+ "return": {
385
+ }
386
+}
387
+{
388
+ "return": {
389
+ }
390
+}
391
+{
392
+ "return": {
393
+ "bps-read-max-length": 1,
394
+ "iops-read-max-length": 1,
395
+ "bps-read-max": 0,
396
+ "bps-total": 0,
397
+ "iops-total-max-length": 1,
398
+ "iops-total": 1000,
399
+ "iops-write-max": 0,
400
+ "bps-write": 0,
401
+ "bps-total-max": 0,
402
+ "bps-write-max": 0,
403
+ "iops-size": 0,
404
+ "iops-read": 0,
405
+ "iops-write-max-length": 1,
406
+ "iops-write": 0,
407
+ "bps-total-max-length": 1,
408
+ "iops-read-max": 0,
409
+ "bps-read": 0,
410
+ "bps-write-max-length": 1,
411
+ "iops-total-max": 0
412
+ }
413
+}
414
+{
415
+ "return": {
416
+ }
417
+}
418
+{
419
+ "return": {
420
+ "bps-read-max-length": 1,
421
+ "iops-read-max-length": 1,
422
+ "bps-read-max": 0,
423
+ "bps-total": 0,
424
+ "iops-total-max-length": 1,
425
+ "iops-total": 0,
426
+ "iops-write-max": 0,
427
+ "bps-write": 0,
428
+ "bps-total-max": 0,
429
+ "bps-write-max": 0,
430
+ "iops-size": 0,
431
+ "iops-read": 0,
432
+ "iops-write-max-length": 1,
433
+ "iops-write": 0,
434
+ "bps-total-max-length": 1,
435
+ "iops-read-max": 0,
436
+ "bps-read": 0,
437
+ "bps-write-max-length": 1,
438
+ "iops-total-max": 0
439
+ }
440
+}
441
+{
442
+ "return": {
443
+ }
444
+}
445
+{
446
+ "timestamp": {
447
+ "seconds": TIMESTAMP,
448
+ "microseconds": TIMESTAMP
449
+ },
450
+ "event": "SHUTDOWN",
451
+ "data": {
452
+ "guest": false
453
+ }
454
+}
455
+
456
+
457
+== object creation/set errors ==
458
+Testing:
459
+{
460
+ QMP_VERSION
461
+}
462
+{
463
+ "return": {
464
+ }
465
+}
466
+{
467
+ "return": {
468
+ }
469
+}
470
+{
471
+ "error": {
472
+ "class": "GenericError",
473
+ "desc": "Property cannot be set after initialization"
474
+ }
475
+}
476
+{
477
+ "error": {
478
+ "class": "GenericError",
479
+ "desc": "bps/iops/max total values and read/write values cannot be used at the same time"
480
+ }
481
+}
482
+{
483
+ "return": {
484
+ }
485
+}
486
+{
487
+ "timestamp": {
488
+ "seconds": TIMESTAMP,
489
+ "microseconds": TIMESTAMP
490
+ },
491
+ "event": "SHUTDOWN",
492
+ "data": {
493
+ "guest": false
494
+ }
495
+}
496
+
497
+
498
+== don't specify group ==
499
+Testing:
500
+{
501
+ QMP_VERSION
502
+}
503
+{
504
+ "return": {
505
+ }
506
+}
507
+{
508
+ "return": {
509
+ }
510
+}
511
+{
512
+ "error": {
513
+ "class": "GenericError",
514
+ "desc": "Parameter 'throttle-group' is missing"
515
+ }
516
+}
517
+{
518
+ "return": {
519
+ }
520
+}
521
+{
522
+ "timestamp": {
523
+ "seconds": TIMESTAMP,
524
+ "microseconds": TIMESTAMP
525
+ },
526
+ "event": "SHUTDOWN",
527
+ "data": {
528
+ "guest": false
529
+ }
530
+}
531
+
532
+
533
+*** done
228
+*** done
534
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
229
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
535
index XXXXXXX..XXXXXXX 100644
230
index XXXXXXX..XXXXXXX 100644
536
--- a/tests/qemu-iotests/group
231
--- a/tests/qemu-iotests/group
537
+++ b/tests/qemu-iotests/group
232
+++ b/tests/qemu-iotests/group
538
@@ -XXX,XX +XXX,XX @@
233
@@ -XXX,XX +XXX,XX @@
539
181 rw auto migration
234
227 auto quick
540
182 rw auto quick
235
229 auto quick
541
183 rw auto migration
236
231 auto quick
542
+184 rw auto quick
237
+232 auto quick
543
185 rw auto
544
186 rw auto
545
187 rw auto
546
--
238
--
547
2.13.5
239
2.19.1
548
240
549
241
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
This adds some whitespace into the option help (including indentation)
4
and puts angle brackets around the type names. Furthermore, the list
5
name is no longer printed as part of every line, but only once in
6
advance, and only if the caller did not print a caption already.
7
8
This patch also restores the description alignment we had before commit
9
9cbef9d68ee1d8d0, just at 24 instead of 16 characters like we used to.
10
This increase is because now we have the type and two spaces of
11
indentation before the description, and with a usual type name length of
12
three chracters, this sums up to eight additional characters -- which
13
means that we now need 24 characters to get the same amount of padding
14
for most options. Also, 24 is a third of 80, which makes it kind of a
15
round number in terminal terms.
16
17
Finally, this patch amends the reference output of iotest 082 to match
18
the changes (and thus makes it pass again).
19
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
24
include/qemu/option.h | 2 +-
25
qemu-img.c | 4 +-
26
util/qemu-option.c | 32 +-
27
tests/qemu-iotests/082.out | 956 ++++++++++++++++++-------------------
28
4 files changed, 507 insertions(+), 487 deletions(-)
29
30
diff --git a/include/qemu/option.h b/include/qemu/option.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/qemu/option.h
33
+++ b/include/qemu/option.h
34
@@ -XXX,XX +XXX,XX @@ typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp);
35
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
36
void *opaque, Error **errp);
37
void qemu_opts_print(QemuOpts *opts, const char *sep);
38
-void qemu_opts_print_help(QemuOptsList *list);
39
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
40
void qemu_opts_free(QemuOptsList *list);
41
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
42
43
diff --git a/qemu-img.c b/qemu-img.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/qemu-img.c
46
+++ b/qemu-img.c
47
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
48
}
49
50
printf("Supported options:\n");
51
- qemu_opts_print_help(create_opts);
52
+ qemu_opts_print_help(create_opts, false);
53
qemu_opts_free(create_opts);
54
return 0;
55
}
56
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
57
assert(drv->create_opts);
58
59
printf("Creation options for '%s':\n", format);
60
- qemu_opts_print_help(drv->create_opts);
61
+ qemu_opts_print_help(drv->create_opts, false);
62
printf("\nNote that not all of these options may be amendable.\n");
63
return 0;
64
}
65
diff --git a/util/qemu-option.c b/util/qemu-option.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/util/qemu-option.c
68
+++ b/util/qemu-option.c
69
@@ -XXX,XX +XXX,XX @@ static const char *opt_type_to_string(enum QemuOptType type)
70
g_assert_not_reached();
71
}
72
73
-void qemu_opts_print_help(QemuOptsList *list)
74
+/**
75
+ * Print the list of options available in the given list. If
76
+ * @print_caption is true, a caption (including the list name, if it
77
+ * exists) is printed. The options itself will be indented, so
78
+ * @print_caption should only be set to false if the caller prints its
79
+ * own custom caption (so that the indentation makes sense).
80
+ */
81
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
82
{
83
QemuOptDesc *desc;
84
int i;
85
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
86
desc = list->desc;
87
while (desc && desc->name) {
88
GString *str = g_string_new(NULL);
89
- if (list->name) {
90
- g_string_append_printf(str, "%s.", list->name);
91
- }
92
- g_string_append_printf(str, "%s=%s", desc->name,
93
+ g_string_append_printf(str, " %s=<%s>", desc->name,
94
opt_type_to_string(desc->type));
95
if (desc->help) {
96
+ if (str->len < 24) {
97
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
98
+ }
99
g_string_append_printf(str, " - %s", desc->help);
100
}
101
g_ptr_array_add(array, g_string_free(str, false));
102
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
103
}
104
105
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
106
+ if (print_caption && array->len > 0) {
107
+ if (list->name) {
108
+ printf("%s options:\n", list->name);
109
+ } else {
110
+ printf("Options:\n");
111
+ }
112
+ } else if (array->len == 0) {
113
+ if (list->name) {
114
+ printf("There are no options for %s.\n", list->name);
115
+ } else {
116
+ printf("No options available.\n");
117
+ }
118
+ }
119
for (i = 0; i < array->len; i++) {
120
printf("%s\n", (char *)array->pdata[i]);
121
}
122
@@ -XXX,XX +XXX,XX @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
123
opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
124
if (err) {
125
if (invalidp && has_help_option(params)) {
126
- qemu_opts_print_help(list);
127
+ qemu_opts_print_help(list, true);
128
error_free(err);
129
} else {
130
error_report_err(err);
131
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
132
index XXXXXXX..XXXXXXX 100644
133
--- a/tests/qemu-iotests/082.out
134
+++ b/tests/qemu-iotests/082.out
135
@@ -XXX,XX +XXX,XX @@ cluster_size: 8192
136
137
Testing: create -f qcow2 -o help TEST_DIR/t.qcow2 128M
138
Supported options:
139
-size Virtual disk size
140
-compat Compatibility level (0.10 or 1.1)
141
-backing_file File name of a base image
142
-backing_fmt Image format of the base image
143
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
144
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
145
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
146
-encrypt.cipher-alg Name of encryption cipher algorithm
147
-encrypt.cipher-mode Name of encryption cipher mode
148
-encrypt.ivgen-alg Name of IV generator algorithm
149
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
150
-encrypt.hash-alg Name of encryption hash algorithm
151
-encrypt.iter-time Time to spend in PBKDF in milliseconds
152
-cluster_size qcow2 cluster size
153
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
154
-lazy_refcounts Postpone refcount updates
155
-refcount_bits Width of a reference count entry in bits
156
-nocow Turn off copy-on-write (valid only on btrfs)
157
+ backing_file=<str> - File name of a base image
158
+ backing_fmt=<str> - Image format of the base image
159
+ cluster_size=<size> - qcow2 cluster size
160
+ compat=<str> - Compatibility level (0.10 or 1.1)
161
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
162
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
163
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
164
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
165
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
166
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
167
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
168
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
169
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
170
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
171
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
172
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
173
+ refcount_bits=<num> - Width of a reference count entry in bits
174
+ size=<size> - Virtual disk size
175
176
Testing: create -f qcow2 -o ? TEST_DIR/t.qcow2 128M
177
Supported options:
178
-size Virtual disk size
179
-compat Compatibility level (0.10 or 1.1)
180
-backing_file File name of a base image
181
-backing_fmt Image format of the base image
182
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
183
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
184
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
185
-encrypt.cipher-alg Name of encryption cipher algorithm
186
-encrypt.cipher-mode Name of encryption cipher mode
187
-encrypt.ivgen-alg Name of IV generator algorithm
188
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
189
-encrypt.hash-alg Name of encryption hash algorithm
190
-encrypt.iter-time Time to spend in PBKDF in milliseconds
191
-cluster_size qcow2 cluster size
192
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
193
-lazy_refcounts Postpone refcount updates
194
-refcount_bits Width of a reference count entry in bits
195
-nocow Turn off copy-on-write (valid only on btrfs)
196
+ backing_file=<str> - File name of a base image
197
+ backing_fmt=<str> - Image format of the base image
198
+ cluster_size=<size> - qcow2 cluster size
199
+ compat=<str> - Compatibility level (0.10 or 1.1)
200
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
201
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
202
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
203
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
204
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
205
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
206
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
207
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
208
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
209
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
210
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
211
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
212
+ refcount_bits=<num> - Width of a reference count entry in bits
213
+ size=<size> - Virtual disk size
214
215
Testing: create -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 128M
216
Supported options:
217
-size Virtual disk size
218
-compat Compatibility level (0.10 or 1.1)
219
-backing_file File name of a base image
220
-backing_fmt Image format of the base image
221
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
222
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
223
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
224
-encrypt.cipher-alg Name of encryption cipher algorithm
225
-encrypt.cipher-mode Name of encryption cipher mode
226
-encrypt.ivgen-alg Name of IV generator algorithm
227
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
228
-encrypt.hash-alg Name of encryption hash algorithm
229
-encrypt.iter-time Time to spend in PBKDF in milliseconds
230
-cluster_size qcow2 cluster size
231
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
232
-lazy_refcounts Postpone refcount updates
233
-refcount_bits Width of a reference count entry in bits
234
-nocow Turn off copy-on-write (valid only on btrfs)
235
+ backing_file=<str> - File name of a base image
236
+ backing_fmt=<str> - Image format of the base image
237
+ cluster_size=<size> - qcow2 cluster size
238
+ compat=<str> - Compatibility level (0.10 or 1.1)
239
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
240
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
241
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
242
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
243
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
244
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
245
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
246
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
247
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
248
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
249
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
250
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
251
+ refcount_bits=<num> - Width of a reference count entry in bits
252
+ size=<size> - Virtual disk size
253
254
Testing: create -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 128M
255
Supported options:
256
-size Virtual disk size
257
-compat Compatibility level (0.10 or 1.1)
258
-backing_file File name of a base image
259
-backing_fmt Image format of the base image
260
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
261
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
262
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
263
-encrypt.cipher-alg Name of encryption cipher algorithm
264
-encrypt.cipher-mode Name of encryption cipher mode
265
-encrypt.ivgen-alg Name of IV generator algorithm
266
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
267
-encrypt.hash-alg Name of encryption hash algorithm
268
-encrypt.iter-time Time to spend in PBKDF in milliseconds
269
-cluster_size qcow2 cluster size
270
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
271
-lazy_refcounts Postpone refcount updates
272
-refcount_bits Width of a reference count entry in bits
273
-nocow Turn off copy-on-write (valid only on btrfs)
274
+ backing_file=<str> - File name of a base image
275
+ backing_fmt=<str> - Image format of the base image
276
+ cluster_size=<size> - qcow2 cluster size
277
+ compat=<str> - Compatibility level (0.10 or 1.1)
278
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
279
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
280
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
281
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
282
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
283
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
284
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
285
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
286
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
287
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
288
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
289
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
290
+ refcount_bits=<num> - Width of a reference count entry in bits
291
+ size=<size> - Virtual disk size
292
293
Testing: create -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 128M
294
Supported options:
295
-size Virtual disk size
296
-compat Compatibility level (0.10 or 1.1)
297
-backing_file File name of a base image
298
-backing_fmt Image format of the base image
299
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
300
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
301
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
302
-encrypt.cipher-alg Name of encryption cipher algorithm
303
-encrypt.cipher-mode Name of encryption cipher mode
304
-encrypt.ivgen-alg Name of IV generator algorithm
305
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
306
-encrypt.hash-alg Name of encryption hash algorithm
307
-encrypt.iter-time Time to spend in PBKDF in milliseconds
308
-cluster_size qcow2 cluster size
309
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
310
-lazy_refcounts Postpone refcount updates
311
-refcount_bits Width of a reference count entry in bits
312
-nocow Turn off copy-on-write (valid only on btrfs)
313
+ backing_file=<str> - File name of a base image
314
+ backing_fmt=<str> - Image format of the base image
315
+ cluster_size=<size> - qcow2 cluster size
316
+ compat=<str> - Compatibility level (0.10 or 1.1)
317
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
318
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
319
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
320
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
321
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
322
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
323
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
324
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
325
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
326
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
327
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
328
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
329
+ refcount_bits=<num> - Width of a reference count entry in bits
330
+ size=<size> - Virtual disk size
331
332
Testing: create -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 128M
333
Supported options:
334
-size Virtual disk size
335
-compat Compatibility level (0.10 or 1.1)
336
-backing_file File name of a base image
337
-backing_fmt Image format of the base image
338
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
339
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
340
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
341
-encrypt.cipher-alg Name of encryption cipher algorithm
342
-encrypt.cipher-mode Name of encryption cipher mode
343
-encrypt.ivgen-alg Name of IV generator algorithm
344
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
345
-encrypt.hash-alg Name of encryption hash algorithm
346
-encrypt.iter-time Time to spend in PBKDF in milliseconds
347
-cluster_size qcow2 cluster size
348
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
349
-lazy_refcounts Postpone refcount updates
350
-refcount_bits Width of a reference count entry in bits
351
-nocow Turn off copy-on-write (valid only on btrfs)
352
+ backing_file=<str> - File name of a base image
353
+ backing_fmt=<str> - Image format of the base image
354
+ cluster_size=<size> - qcow2 cluster size
355
+ compat=<str> - Compatibility level (0.10 or 1.1)
356
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
357
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
358
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
359
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
360
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
361
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
362
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
363
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
364
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
365
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
366
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
367
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
368
+ refcount_bits=<num> - Width of a reference count entry in bits
369
+ size=<size> - Virtual disk size
370
371
Testing: create -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 128M
372
Supported options:
373
-size Virtual disk size
374
-compat Compatibility level (0.10 or 1.1)
375
-backing_file File name of a base image
376
-backing_fmt Image format of the base image
377
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
378
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
379
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
380
-encrypt.cipher-alg Name of encryption cipher algorithm
381
-encrypt.cipher-mode Name of encryption cipher mode
382
-encrypt.ivgen-alg Name of IV generator algorithm
383
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
384
-encrypt.hash-alg Name of encryption hash algorithm
385
-encrypt.iter-time Time to spend in PBKDF in milliseconds
386
-cluster_size qcow2 cluster size
387
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
388
-lazy_refcounts Postpone refcount updates
389
-refcount_bits Width of a reference count entry in bits
390
-nocow Turn off copy-on-write (valid only on btrfs)
391
+ backing_file=<str> - File name of a base image
392
+ backing_fmt=<str> - Image format of the base image
393
+ cluster_size=<size> - qcow2 cluster size
394
+ compat=<str> - Compatibility level (0.10 or 1.1)
395
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
396
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
397
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
398
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
399
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
400
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
401
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
402
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
403
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
404
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
405
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
406
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
407
+ refcount_bits=<num> - Width of a reference count entry in bits
408
+ size=<size> - Virtual disk size
409
410
Testing: create -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 128M
411
Supported options:
412
-size Virtual disk size
413
-compat Compatibility level (0.10 or 1.1)
414
-backing_file File name of a base image
415
-backing_fmt Image format of the base image
416
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
417
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
418
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
419
-encrypt.cipher-alg Name of encryption cipher algorithm
420
-encrypt.cipher-mode Name of encryption cipher mode
421
-encrypt.ivgen-alg Name of IV generator algorithm
422
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
423
-encrypt.hash-alg Name of encryption hash algorithm
424
-encrypt.iter-time Time to spend in PBKDF in milliseconds
425
-cluster_size qcow2 cluster size
426
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
427
-lazy_refcounts Postpone refcount updates
428
-refcount_bits Width of a reference count entry in bits
429
-nocow Turn off copy-on-write (valid only on btrfs)
430
+ backing_file=<str> - File name of a base image
431
+ backing_fmt=<str> - Image format of the base image
432
+ cluster_size=<size> - qcow2 cluster size
433
+ compat=<str> - Compatibility level (0.10 or 1.1)
434
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
435
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
436
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
437
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
438
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
439
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
440
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
441
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
442
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
443
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
444
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
445
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
446
+ refcount_bits=<num> - Width of a reference count entry in bits
447
+ size=<size> - Virtual disk size
448
449
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
450
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16
451
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
452
453
Testing: create -f qcow2 -o help
454
Supported options:
455
-size Virtual disk size
456
-compat Compatibility level (0.10 or 1.1)
457
-backing_file File name of a base image
458
-backing_fmt Image format of the base image
459
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
460
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
461
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
462
-encrypt.cipher-alg Name of encryption cipher algorithm
463
-encrypt.cipher-mode Name of encryption cipher mode
464
-encrypt.ivgen-alg Name of IV generator algorithm
465
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
466
-encrypt.hash-alg Name of encryption hash algorithm
467
-encrypt.iter-time Time to spend in PBKDF in milliseconds
468
-cluster_size qcow2 cluster size
469
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
470
-lazy_refcounts Postpone refcount updates
471
-refcount_bits Width of a reference count entry in bits
472
+ backing_file=<str> - File name of a base image
473
+ backing_fmt=<str> - Image format of the base image
474
+ cluster_size=<size> - qcow2 cluster size
475
+ compat=<str> - Compatibility level (0.10 or 1.1)
476
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
477
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
478
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
479
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
480
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
481
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
482
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
483
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
484
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
485
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
486
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
487
+ refcount_bits=<num> - Width of a reference count entry in bits
488
+ size=<size> - Virtual disk size
489
490
Testing: create -o help
491
Supported options:
492
-size Virtual disk size
493
+ size=<size> - Virtual disk size
494
495
Testing: create -f bochs -o help
496
qemu-img: Format driver 'bochs' does not support image creation
497
@@ -XXX,XX +XXX,XX @@ cluster_size: 8192
498
499
Testing: convert -O qcow2 -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
500
Supported options:
501
-size Virtual disk size
502
-compat Compatibility level (0.10 or 1.1)
503
-backing_file File name of a base image
504
-backing_fmt Image format of the base image
505
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
506
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
507
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
508
-encrypt.cipher-alg Name of encryption cipher algorithm
509
-encrypt.cipher-mode Name of encryption cipher mode
510
-encrypt.ivgen-alg Name of IV generator algorithm
511
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
512
-encrypt.hash-alg Name of encryption hash algorithm
513
-encrypt.iter-time Time to spend in PBKDF in milliseconds
514
-cluster_size qcow2 cluster size
515
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
516
-lazy_refcounts Postpone refcount updates
517
-refcount_bits Width of a reference count entry in bits
518
-nocow Turn off copy-on-write (valid only on btrfs)
519
+ backing_file=<str> - File name of a base image
520
+ backing_fmt=<str> - Image format of the base image
521
+ cluster_size=<size> - qcow2 cluster size
522
+ compat=<str> - Compatibility level (0.10 or 1.1)
523
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
524
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
525
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
526
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
527
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
528
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
529
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
530
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
531
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
532
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
533
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
534
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
535
+ refcount_bits=<num> - Width of a reference count entry in bits
536
+ size=<size> - Virtual disk size
537
538
Testing: convert -O qcow2 -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
539
Supported options:
540
-size Virtual disk size
541
-compat Compatibility level (0.10 or 1.1)
542
-backing_file File name of a base image
543
-backing_fmt Image format of the base image
544
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
545
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
546
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
547
-encrypt.cipher-alg Name of encryption cipher algorithm
548
-encrypt.cipher-mode Name of encryption cipher mode
549
-encrypt.ivgen-alg Name of IV generator algorithm
550
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
551
-encrypt.hash-alg Name of encryption hash algorithm
552
-encrypt.iter-time Time to spend in PBKDF in milliseconds
553
-cluster_size qcow2 cluster size
554
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
555
-lazy_refcounts Postpone refcount updates
556
-refcount_bits Width of a reference count entry in bits
557
-nocow Turn off copy-on-write (valid only on btrfs)
558
+ backing_file=<str> - File name of a base image
559
+ backing_fmt=<str> - Image format of the base image
560
+ cluster_size=<size> - qcow2 cluster size
561
+ compat=<str> - Compatibility level (0.10 or 1.1)
562
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
563
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
564
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
565
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
566
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
567
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
568
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
569
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
570
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
571
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
572
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
573
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
574
+ refcount_bits=<num> - Width of a reference count entry in bits
575
+ size=<size> - Virtual disk size
576
577
Testing: convert -O qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
578
Supported options:
579
-size Virtual disk size
580
-compat Compatibility level (0.10 or 1.1)
581
-backing_file File name of a base image
582
-backing_fmt Image format of the base image
583
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
584
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
585
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
586
-encrypt.cipher-alg Name of encryption cipher algorithm
587
-encrypt.cipher-mode Name of encryption cipher mode
588
-encrypt.ivgen-alg Name of IV generator algorithm
589
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
590
-encrypt.hash-alg Name of encryption hash algorithm
591
-encrypt.iter-time Time to spend in PBKDF in milliseconds
592
-cluster_size qcow2 cluster size
593
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
594
-lazy_refcounts Postpone refcount updates
595
-refcount_bits Width of a reference count entry in bits
596
-nocow Turn off copy-on-write (valid only on btrfs)
597
+ backing_file=<str> - File name of a base image
598
+ backing_fmt=<str> - Image format of the base image
599
+ cluster_size=<size> - qcow2 cluster size
600
+ compat=<str> - Compatibility level (0.10 or 1.1)
601
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
602
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
603
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
604
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
605
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
606
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
607
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
608
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
609
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
610
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
611
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
612
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
613
+ refcount_bits=<num> - Width of a reference count entry in bits
614
+ size=<size> - Virtual disk size
615
616
Testing: convert -O qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
617
Supported options:
618
-size Virtual disk size
619
-compat Compatibility level (0.10 or 1.1)
620
-backing_file File name of a base image
621
-backing_fmt Image format of the base image
622
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
623
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
624
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
625
-encrypt.cipher-alg Name of encryption cipher algorithm
626
-encrypt.cipher-mode Name of encryption cipher mode
627
-encrypt.ivgen-alg Name of IV generator algorithm
628
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
629
-encrypt.hash-alg Name of encryption hash algorithm
630
-encrypt.iter-time Time to spend in PBKDF in milliseconds
631
-cluster_size qcow2 cluster size
632
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
633
-lazy_refcounts Postpone refcount updates
634
-refcount_bits Width of a reference count entry in bits
635
-nocow Turn off copy-on-write (valid only on btrfs)
636
+ backing_file=<str> - File name of a base image
637
+ backing_fmt=<str> - Image format of the base image
638
+ cluster_size=<size> - qcow2 cluster size
639
+ compat=<str> - Compatibility level (0.10 or 1.1)
640
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
641
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
642
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
643
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
644
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
645
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
646
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
647
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
648
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
649
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
650
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
651
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
652
+ refcount_bits=<num> - Width of a reference count entry in bits
653
+ size=<size> - Virtual disk size
654
655
Testing: convert -O qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
656
Supported options:
657
-size Virtual disk size
658
-compat Compatibility level (0.10 or 1.1)
659
-backing_file File name of a base image
660
-backing_fmt Image format of the base image
661
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
662
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
663
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
664
-encrypt.cipher-alg Name of encryption cipher algorithm
665
-encrypt.cipher-mode Name of encryption cipher mode
666
-encrypt.ivgen-alg Name of IV generator algorithm
667
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
668
-encrypt.hash-alg Name of encryption hash algorithm
669
-encrypt.iter-time Time to spend in PBKDF in milliseconds
670
-cluster_size qcow2 cluster size
671
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
672
-lazy_refcounts Postpone refcount updates
673
-refcount_bits Width of a reference count entry in bits
674
-nocow Turn off copy-on-write (valid only on btrfs)
675
+ backing_file=<str> - File name of a base image
676
+ backing_fmt=<str> - Image format of the base image
677
+ cluster_size=<size> - qcow2 cluster size
678
+ compat=<str> - Compatibility level (0.10 or 1.1)
679
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
680
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
681
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
682
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
683
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
684
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
685
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
686
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
687
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
688
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
689
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
690
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
691
+ refcount_bits=<num> - Width of a reference count entry in bits
692
+ size=<size> - Virtual disk size
693
694
Testing: convert -O qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
695
Supported options:
696
-size Virtual disk size
697
-compat Compatibility level (0.10 or 1.1)
698
-backing_file File name of a base image
699
-backing_fmt Image format of the base image
700
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
701
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
702
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
703
-encrypt.cipher-alg Name of encryption cipher algorithm
704
-encrypt.cipher-mode Name of encryption cipher mode
705
-encrypt.ivgen-alg Name of IV generator algorithm
706
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
707
-encrypt.hash-alg Name of encryption hash algorithm
708
-encrypt.iter-time Time to spend in PBKDF in milliseconds
709
-cluster_size qcow2 cluster size
710
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
711
-lazy_refcounts Postpone refcount updates
712
-refcount_bits Width of a reference count entry in bits
713
-nocow Turn off copy-on-write (valid only on btrfs)
714
+ backing_file=<str> - File name of a base image
715
+ backing_fmt=<str> - Image format of the base image
716
+ cluster_size=<size> - qcow2 cluster size
717
+ compat=<str> - Compatibility level (0.10 or 1.1)
718
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
719
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
720
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
721
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
722
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
723
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
724
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
725
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
726
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
727
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
728
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
729
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
730
+ refcount_bits=<num> - Width of a reference count entry in bits
731
+ size=<size> - Virtual disk size
732
733
Testing: convert -O qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
734
Supported options:
735
-size Virtual disk size
736
-compat Compatibility level (0.10 or 1.1)
737
-backing_file File name of a base image
738
-backing_fmt Image format of the base image
739
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
740
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
741
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
742
-encrypt.cipher-alg Name of encryption cipher algorithm
743
-encrypt.cipher-mode Name of encryption cipher mode
744
-encrypt.ivgen-alg Name of IV generator algorithm
745
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
746
-encrypt.hash-alg Name of encryption hash algorithm
747
-encrypt.iter-time Time to spend in PBKDF in milliseconds
748
-cluster_size qcow2 cluster size
749
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
750
-lazy_refcounts Postpone refcount updates
751
-refcount_bits Width of a reference count entry in bits
752
-nocow Turn off copy-on-write (valid only on btrfs)
753
+ backing_file=<str> - File name of a base image
754
+ backing_fmt=<str> - Image format of the base image
755
+ cluster_size=<size> - qcow2 cluster size
756
+ compat=<str> - Compatibility level (0.10 or 1.1)
757
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
758
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
759
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
760
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
761
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
762
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
763
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
764
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
765
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
766
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
767
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
768
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
769
+ refcount_bits=<num> - Width of a reference count entry in bits
770
+ size=<size> - Virtual disk size
771
772
Testing: convert -O qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
773
Supported options:
774
-size Virtual disk size
775
-compat Compatibility level (0.10 or 1.1)
776
-backing_file File name of a base image
777
-backing_fmt Image format of the base image
778
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
779
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
780
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
781
-encrypt.cipher-alg Name of encryption cipher algorithm
782
-encrypt.cipher-mode Name of encryption cipher mode
783
-encrypt.ivgen-alg Name of IV generator algorithm
784
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
785
-encrypt.hash-alg Name of encryption hash algorithm
786
-encrypt.iter-time Time to spend in PBKDF in milliseconds
787
-cluster_size qcow2 cluster size
788
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
789
-lazy_refcounts Postpone refcount updates
790
-refcount_bits Width of a reference count entry in bits
791
-nocow Turn off copy-on-write (valid only on btrfs)
792
+ backing_file=<str> - File name of a base image
793
+ backing_fmt=<str> - Image format of the base image
794
+ cluster_size=<size> - qcow2 cluster size
795
+ compat=<str> - Compatibility level (0.10 or 1.1)
796
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
797
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
798
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
799
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
800
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
801
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
802
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
803
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
804
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
805
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
806
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
807
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
808
+ refcount_bits=<num> - Width of a reference count entry in bits
809
+ size=<size> - Virtual disk size
810
811
Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
812
qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,help': No such file or directory
813
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
814
815
Testing: convert -O qcow2 -o help
816
Supported options:
817
-size Virtual disk size
818
-compat Compatibility level (0.10 or 1.1)
819
-backing_file File name of a base image
820
-backing_fmt Image format of the base image
821
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
822
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
823
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
824
-encrypt.cipher-alg Name of encryption cipher algorithm
825
-encrypt.cipher-mode Name of encryption cipher mode
826
-encrypt.ivgen-alg Name of IV generator algorithm
827
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
828
-encrypt.hash-alg Name of encryption hash algorithm
829
-encrypt.iter-time Time to spend in PBKDF in milliseconds
830
-cluster_size qcow2 cluster size
831
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
832
-lazy_refcounts Postpone refcount updates
833
-refcount_bits Width of a reference count entry in bits
834
+ backing_file=<str> - File name of a base image
835
+ backing_fmt=<str> - Image format of the base image
836
+ cluster_size=<size> - qcow2 cluster size
837
+ compat=<str> - Compatibility level (0.10 or 1.1)
838
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
839
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
840
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
841
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
842
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
843
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
844
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
845
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
846
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
847
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
848
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
849
+ refcount_bits=<num> - Width of a reference count entry in bits
850
+ size=<size> - Virtual disk size
851
852
Testing: convert -o help
853
Supported options:
854
-size Virtual disk size
855
+ size=<size> - Virtual disk size
856
857
Testing: convert -O bochs -o help
858
qemu-img: Format driver 'bochs' does not support image creation
859
@@ -XXX,XX +XXX,XX @@ cluster_size: 65536
860
861
Testing: amend -f qcow2 -o help TEST_DIR/t.qcow2
862
Creation options for 'qcow2':
863
-size Virtual disk size
864
-compat Compatibility level (0.10 or 1.1)
865
-backing_file File name of a base image
866
-backing_fmt Image format of the base image
867
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
868
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
869
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
870
-encrypt.cipher-alg Name of encryption cipher algorithm
871
-encrypt.cipher-mode Name of encryption cipher mode
872
-encrypt.ivgen-alg Name of IV generator algorithm
873
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
874
-encrypt.hash-alg Name of encryption hash algorithm
875
-encrypt.iter-time Time to spend in PBKDF in milliseconds
876
-cluster_size qcow2 cluster size
877
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
878
-lazy_refcounts Postpone refcount updates
879
-refcount_bits Width of a reference count entry in bits
880
+ backing_file=<str> - File name of a base image
881
+ backing_fmt=<str> - Image format of the base image
882
+ cluster_size=<size> - qcow2 cluster size
883
+ compat=<str> - Compatibility level (0.10 or 1.1)
884
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
885
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
886
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
887
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
888
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
889
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
890
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
891
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
892
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
893
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
894
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
895
+ refcount_bits=<num> - Width of a reference count entry in bits
896
+ size=<size> - Virtual disk size
897
898
Note that not all of these options may be amendable.
899
900
Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
901
Creation options for 'qcow2':
902
-size Virtual disk size
903
-compat Compatibility level (0.10 or 1.1)
904
-backing_file File name of a base image
905
-backing_fmt Image format of the base image
906
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
907
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
908
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
909
-encrypt.cipher-alg Name of encryption cipher algorithm
910
-encrypt.cipher-mode Name of encryption cipher mode
911
-encrypt.ivgen-alg Name of IV generator algorithm
912
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
913
-encrypt.hash-alg Name of encryption hash algorithm
914
-encrypt.iter-time Time to spend in PBKDF in milliseconds
915
-cluster_size qcow2 cluster size
916
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
917
-lazy_refcounts Postpone refcount updates
918
-refcount_bits Width of a reference count entry in bits
919
+ backing_file=<str> - File name of a base image
920
+ backing_fmt=<str> - Image format of the base image
921
+ cluster_size=<size> - qcow2 cluster size
922
+ compat=<str> - Compatibility level (0.10 or 1.1)
923
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
924
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
925
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
926
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
927
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
928
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
929
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
930
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
931
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
932
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
933
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
934
+ refcount_bits=<num> - Width of a reference count entry in bits
935
+ size=<size> - Virtual disk size
936
937
Note that not all of these options may be amendable.
938
939
Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
940
Creation options for 'qcow2':
941
-size Virtual disk size
942
-compat Compatibility level (0.10 or 1.1)
943
-backing_file File name of a base image
944
-backing_fmt Image format of the base image
945
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
946
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
947
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
948
-encrypt.cipher-alg Name of encryption cipher algorithm
949
-encrypt.cipher-mode Name of encryption cipher mode
950
-encrypt.ivgen-alg Name of IV generator algorithm
951
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
952
-encrypt.hash-alg Name of encryption hash algorithm
953
-encrypt.iter-time Time to spend in PBKDF in milliseconds
954
-cluster_size qcow2 cluster size
955
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
956
-lazy_refcounts Postpone refcount updates
957
-refcount_bits Width of a reference count entry in bits
958
+ backing_file=<str> - File name of a base image
959
+ backing_fmt=<str> - Image format of the base image
960
+ cluster_size=<size> - qcow2 cluster size
961
+ compat=<str> - Compatibility level (0.10 or 1.1)
962
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
963
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
964
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
965
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
966
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
967
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
968
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
969
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
970
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
971
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
972
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
973
+ refcount_bits=<num> - Width of a reference count entry in bits
974
+ size=<size> - Virtual disk size
975
976
Note that not all of these options may be amendable.
977
978
Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
979
Creation options for 'qcow2':
980
-size Virtual disk size
981
-compat Compatibility level (0.10 or 1.1)
982
-backing_file File name of a base image
983
-backing_fmt Image format of the base image
984
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
985
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
986
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
987
-encrypt.cipher-alg Name of encryption cipher algorithm
988
-encrypt.cipher-mode Name of encryption cipher mode
989
-encrypt.ivgen-alg Name of IV generator algorithm
990
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
991
-encrypt.hash-alg Name of encryption hash algorithm
992
-encrypt.iter-time Time to spend in PBKDF in milliseconds
993
-cluster_size qcow2 cluster size
994
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
995
-lazy_refcounts Postpone refcount updates
996
-refcount_bits Width of a reference count entry in bits
997
+ backing_file=<str> - File name of a base image
998
+ backing_fmt=<str> - Image format of the base image
999
+ cluster_size=<size> - qcow2 cluster size
1000
+ compat=<str> - Compatibility level (0.10 or 1.1)
1001
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1002
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1003
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1004
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1005
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1006
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1007
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1008
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1009
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1010
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1011
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1012
+ refcount_bits=<num> - Width of a reference count entry in bits
1013
+ size=<size> - Virtual disk size
1014
1015
Note that not all of these options may be amendable.
1016
1017
Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
1018
Creation options for 'qcow2':
1019
-size Virtual disk size
1020
-compat Compatibility level (0.10 or 1.1)
1021
-backing_file File name of a base image
1022
-backing_fmt Image format of the base image
1023
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1024
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1025
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1026
-encrypt.cipher-alg Name of encryption cipher algorithm
1027
-encrypt.cipher-mode Name of encryption cipher mode
1028
-encrypt.ivgen-alg Name of IV generator algorithm
1029
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1030
-encrypt.hash-alg Name of encryption hash algorithm
1031
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1032
-cluster_size qcow2 cluster size
1033
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1034
-lazy_refcounts Postpone refcount updates
1035
-refcount_bits Width of a reference count entry in bits
1036
+ backing_file=<str> - File name of a base image
1037
+ backing_fmt=<str> - Image format of the base image
1038
+ cluster_size=<size> - qcow2 cluster size
1039
+ compat=<str> - Compatibility level (0.10 or 1.1)
1040
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1041
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1042
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1043
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1044
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1045
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1046
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1047
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1048
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1049
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1050
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1051
+ refcount_bits=<num> - Width of a reference count entry in bits
1052
+ size=<size> - Virtual disk size
1053
1054
Note that not all of these options may be amendable.
1055
1056
Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
1057
Creation options for 'qcow2':
1058
-size Virtual disk size
1059
-compat Compatibility level (0.10 or 1.1)
1060
-backing_file File name of a base image
1061
-backing_fmt Image format of the base image
1062
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1063
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1064
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1065
-encrypt.cipher-alg Name of encryption cipher algorithm
1066
-encrypt.cipher-mode Name of encryption cipher mode
1067
-encrypt.ivgen-alg Name of IV generator algorithm
1068
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1069
-encrypt.hash-alg Name of encryption hash algorithm
1070
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1071
-cluster_size qcow2 cluster size
1072
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1073
-lazy_refcounts Postpone refcount updates
1074
-refcount_bits Width of a reference count entry in bits
1075
+ backing_file=<str> - File name of a base image
1076
+ backing_fmt=<str> - Image format of the base image
1077
+ cluster_size=<size> - qcow2 cluster size
1078
+ compat=<str> - Compatibility level (0.10 or 1.1)
1079
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1080
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1081
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1082
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1083
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1084
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1085
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1086
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1087
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1088
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1089
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1090
+ refcount_bits=<num> - Width of a reference count entry in bits
1091
+ size=<size> - Virtual disk size
1092
1093
Note that not all of these options may be amendable.
1094
1095
Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
1096
Creation options for 'qcow2':
1097
-size Virtual disk size
1098
-compat Compatibility level (0.10 or 1.1)
1099
-backing_file File name of a base image
1100
-backing_fmt Image format of the base image
1101
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1102
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1103
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1104
-encrypt.cipher-alg Name of encryption cipher algorithm
1105
-encrypt.cipher-mode Name of encryption cipher mode
1106
-encrypt.ivgen-alg Name of IV generator algorithm
1107
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1108
-encrypt.hash-alg Name of encryption hash algorithm
1109
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1110
-cluster_size qcow2 cluster size
1111
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1112
-lazy_refcounts Postpone refcount updates
1113
-refcount_bits Width of a reference count entry in bits
1114
+ backing_file=<str> - File name of a base image
1115
+ backing_fmt=<str> - Image format of the base image
1116
+ cluster_size=<size> - qcow2 cluster size
1117
+ compat=<str> - Compatibility level (0.10 or 1.1)
1118
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1119
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1120
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1121
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1122
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1123
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1124
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1125
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1126
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1127
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1128
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1129
+ refcount_bits=<num> - Width of a reference count entry in bits
1130
+ size=<size> - Virtual disk size
1131
1132
Note that not all of these options may be amendable.
1133
1134
Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
1135
Creation options for 'qcow2':
1136
-size Virtual disk size
1137
-compat Compatibility level (0.10 or 1.1)
1138
-backing_file File name of a base image
1139
-backing_fmt Image format of the base image
1140
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1141
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1142
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1143
-encrypt.cipher-alg Name of encryption cipher algorithm
1144
-encrypt.cipher-mode Name of encryption cipher mode
1145
-encrypt.ivgen-alg Name of IV generator algorithm
1146
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1147
-encrypt.hash-alg Name of encryption hash algorithm
1148
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1149
-cluster_size qcow2 cluster size
1150
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1151
-lazy_refcounts Postpone refcount updates
1152
-refcount_bits Width of a reference count entry in bits
1153
+ backing_file=<str> - File name of a base image
1154
+ backing_fmt=<str> - Image format of the base image
1155
+ cluster_size=<size> - qcow2 cluster size
1156
+ compat=<str> - Compatibility level (0.10 or 1.1)
1157
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1158
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1159
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1160
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1161
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1162
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1163
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1164
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1165
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1166
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1167
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1168
+ refcount_bits=<num> - Width of a reference count entry in bits
1169
+ size=<size> - Virtual disk size
1170
1171
Note that not all of these options may be amendable.
1172
1173
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
1174
1175
Testing: amend -f qcow2 -o help
1176
Creation options for 'qcow2':
1177
-size Virtual disk size
1178
-compat Compatibility level (0.10 or 1.1)
1179
-backing_file File name of a base image
1180
-backing_fmt Image format of the base image
1181
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1182
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1183
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1184
-encrypt.cipher-alg Name of encryption cipher algorithm
1185
-encrypt.cipher-mode Name of encryption cipher mode
1186
-encrypt.ivgen-alg Name of IV generator algorithm
1187
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1188
-encrypt.hash-alg Name of encryption hash algorithm
1189
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1190
-cluster_size qcow2 cluster size
1191
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1192
-lazy_refcounts Postpone refcount updates
1193
-refcount_bits Width of a reference count entry in bits
1194
+ backing_file=<str> - File name of a base image
1195
+ backing_fmt=<str> - Image format of the base image
1196
+ cluster_size=<size> - qcow2 cluster size
1197
+ compat=<str> - Compatibility level (0.10 or 1.1)
1198
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1199
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1200
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1201
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1202
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1203
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1204
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1205
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1206
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1207
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1208
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1209
+ refcount_bits=<num> - Width of a reference count entry in bits
1210
+ size=<size> - Virtual disk size
1211
1212
Note that not all of these options may be amendable.
1213
1214
Testing: convert -o help
1215
Supported options:
1216
-size Virtual disk size
1217
+ size=<size> - Virtual disk size
1218
1219
Testing: amend -f bochs -o help
1220
qemu-img: Format driver 'bochs' does not support option amendment
1221
--
1222
2.19.1
1223
1224
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Following the example of qemu_opts_print_help(), indent all entries in
4
the list of character devices.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
chardev/char.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/chardev/char.c b/chardev/char.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/chardev/char.c
16
+++ b/chardev/char.c
17
@@ -XXX,XX +XXX,XX @@ help_string_append(const char *name, void *opaque)
18
{
19
GString *str = opaque;
20
21
- g_string_append_printf(str, "\n%s", name);
22
+ g_string_append_printf(str, "\n %s", name);
23
}
24
25
static const char *chardev_alias_translate(const char *name)
26
--
27
2.19.1
28
29
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Just like in qemu_opts_print_help(), print the device name as a caption
4
instead of on every single line, indent all options, add angle brackets
5
around types, and align the descriptions after 24 characters. Also,
6
separate the descriptions with " - " instead of putting them in
7
parentheses, because that is what we do everywhere else. This does look
8
a bit funny here because basically all bits have the description
9
"on/off", but funny does not mean it is less readable.
10
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
qdev-monitor.c | 13 +++++++++++--
16
1 file changed, 11 insertions(+), 2 deletions(-)
17
18
diff --git a/qdev-monitor.c b/qdev-monitor.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/qdev-monitor.c
21
+++ b/qdev-monitor.c
22
@@ -XXX,XX +XXX,XX @@ int qdev_device_help(QemuOpts *opts)
23
goto error;
24
}
25
26
+ if (prop_list) {
27
+ out_printf("%s options:\n", driver);
28
+ } else {
29
+ out_printf("There are no options for %s.\n", driver);
30
+ }
31
for (prop = prop_list; prop; prop = prop->next) {
32
- out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
33
+ int len;
34
+ out_printf(" %s=<%s>%n", prop->value->name, prop->value->type, &len);
35
if (prop->value->has_description) {
36
- out_printf(" (%s)\n", prop->value->description);
37
+ if (len < 24) {
38
+ out_printf("%*s", 24 - len, "");
39
+ }
40
+ out_printf(" - %s\n", prop->value->description);
41
} else {
42
out_printf("\n");
43
}
44
--
45
2.19.1
46
47
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Just like in qemu_opts_print_help(), print the object name as a caption
4
instead of on every single line, indent all options, add angle brackets
5
around types, and align the descriptions after 24 characters.
6
7
Also, indent every object name in the list of available objects.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
vl.c | 13 ++++++++++---
14
1 file changed, 10 insertions(+), 3 deletions(-)
15
16
diff --git a/vl.c b/vl.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/vl.c
19
+++ b/vl.c
20
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
21
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
22
for (l = list; l != NULL; l = l->next) {
23
ObjectClass *oc = OBJECT_CLASS(l->data);
24
- printf("%s\n", object_class_get_name(oc));
25
+ printf(" %s\n", object_class_get_name(oc));
26
}
27
g_slist_free(list);
28
exit(0);
29
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
30
}
31
32
str = g_string_new(NULL);
33
- g_string_append_printf(str, "%s.%s=%s", type,
34
- prop->name, prop->type);
35
+ g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
36
if (prop->description) {
37
+ if (str->len < 24) {
38
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
39
+ }
40
g_string_append_printf(str, " - %s", prop->description);
41
}
42
g_ptr_array_add(array, g_string_free(str, false));
43
}
44
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
45
+ if (array->len > 0) {
46
+ printf("%s options:\n", type);
47
+ } else {
48
+ printf("There are no options for %s.\n", type);
49
+ }
50
for (i = 0; i < array->len; i++) {
51
printf("%s\n", (char *)array->pdata[i]);
52
}
53
--
54
2.19.1
55
56
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
There is no good reason why there should be a newline in this
4
description, so remove it.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
vl.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/vl.c b/vl.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/vl.c
17
+++ b/vl.c
18
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_fw_cfg_opts = {
19
}, {
20
.name = "file",
21
.type = QEMU_OPT_STRING,
22
- .help = "Sets the name of the file from which\n"
23
+ .help = "Sets the name of the file from which "
24
"the fw_cfg blob will be loaded",
25
}, {
26
.name = "string",
27
--
28
2.19.1
29
30
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
Move the CoMutex and CoQueue inits inside throttle_group_register_tgm()
3
If an expression is used to define DEFAULT_CLUSTER_SIZE, when compiled,
4
which is called whenever a ThrottleGroupMember is initialized. There's
4
it will be embedded as a literal expression in the binary (as the
5
no need for them to be separate.
5
default value) because it is stringified to mark the size of the default
6
value. Now this is fixed by using a defined number to define this value.
6
7
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Stefan Weil <sw@weilnetz.de>
9
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
11
---
12
block/block-backend.c | 3 ---
12
block/vdi.c | 4 ++--
13
block/throttle-groups.c | 3 +++
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
2 files changed, 3 insertions(+), 3 deletions(-)
15
14
16
diff --git a/block/block-backend.c b/block/block-backend.c
15
diff --git a/block/vdi.c b/block/vdi.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/block/block-backend.c
17
--- a/block/vdi.c
19
+++ b/block/block-backend.c
18
+++ b/block/vdi.c
20
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
19
@@ -XXX,XX +XXX,XX @@
21
blk->shared_perm = shared_perm;
20
#define BLOCK_OPT_STATIC "static"
22
blk_set_enable_write_cache(blk, true);
21
23
22
#define SECTOR_SIZE 512
24
- qemu_co_mutex_init(&blk->public.throttle_group_member.throttled_reqs_lock);
23
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
25
- qemu_co_queue_init(&blk->public.throttle_group_member.throttled_reqs[0]);
24
+#define DEFAULT_CLUSTER_SIZE S_1MiB
26
- qemu_co_queue_init(&blk->public.throttle_group_member.throttled_reqs[1]);
25
27
block_acct_init(&blk->stats);
26
#if defined(CONFIG_VDI_DEBUG)
28
27
#define VDI_DEBUG 1
29
notifier_list_init(&blk->remove_bs_notifiers);
28
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
30
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
29
goto fail;
31
index XXXXXXX..XXXXXXX 100644
30
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
32
--- a/block/throttle-groups.c
31
error_setg(errp, "unsupported VDI image (block size %" PRIu32
33
+++ b/block/throttle-groups.c
32
- " is not %" PRIu64 ")",
34
@@ -XXX,XX +XXX,XX @@ void throttle_group_register_tgm(ThrottleGroupMember *tgm,
33
+ " is not %" PRIu32 ")",
35
read_timer_cb,
34
header.block_size, DEFAULT_CLUSTER_SIZE);
36
write_timer_cb,
35
ret = -ENOTSUP;
37
tgm);
36
goto fail;
38
+ qemu_co_mutex_init(&tgm->throttled_reqs_lock);
39
+ qemu_co_queue_init(&tgm->throttled_reqs[0]);
40
+ qemu_co_queue_init(&tgm->throttled_reqs[1]);
41
42
qemu_mutex_unlock(&tg->lock);
43
}
44
--
37
--
45
2.13.5
38
2.19.1
46
39
47
40
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
bdrv_co_get_block_status_from_file() and
3
The lookup table for power-of-two sizes was added in commit 540b8492618eb
4
bdrv_co_get_block_status_from_backing() set *file to bs->file and
4
for the purpose of having convenient shortcuts for these sizes in cases
5
bs->backing respectively, so that bdrv_co_get_block_status() can recurse
5
when the literal number has to be present at compile time, and
6
to them. Future block drivers won't have to duplicate code to implement
6
expressions as '(1 * KiB)' can not be used. One such case is the
7
this.
7
stringification of sizes. Beyond that, it is convenient to use these
8
shortcuts for all power-of-two sizes, even if they don't have to be
9
literal numbers.
8
10
9
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Despite its convenience, this table introduced 55 lines of "dumb" code,
10
Reviewed-by: Eric Blake <eblake@redhat.com>
12
the purpose and origin of which are obscure without reading the message
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
of the commit which introduced it. This patch fixes that by adding a
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
comment to the code itself with a brief explanation for the reasoning
13
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
15
behind this table. This comment includes the short AWK script that
16
generated the table, so that anyone who's interested could make sure
17
that the values in it are correct (otherwise these values look as if
18
they were typed manually).
19
20
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
22
---
16
include/block/block_int.h | 18 ++++++++++++++++++
23
include/qemu/units.h | 18 ++++++++++++++++++
17
block/blkdebug.c | 12 +-----------
24
1 file changed, 18 insertions(+)
18
block/commit.c | 12 +-----------
19
block/io.c | 26 ++++++++++++++++++++++++++
20
block/mirror.c | 12 +-----------
21
5 files changed, 47 insertions(+), 33 deletions(-)
22
25
23
diff --git a/include/block/block_int.h b/include/block/block_int.h
26
diff --git a/include/qemu/units.h b/include/qemu/units.h
24
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block_int.h
28
--- a/include/qemu/units.h
26
+++ b/include/block/block_int.h
29
+++ b/include/qemu/units.h
27
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
30
@@ -XXX,XX +XXX,XX @@
28
uint64_t perm, uint64_t shared,
31
#define PiB (INT64_C(1) << 50)
29
uint64_t *nperm, uint64_t *nshared);
32
#define EiB (INT64_C(1) << 60)
30
33
31
+/*
34
+/*
32
+ * Default implementation for drivers to pass bdrv_co_get_block_status() to
35
+ * The following lookup table is intended to be used when a literal string of
33
+ * their file.
36
+ * the number of bytes is required (for example if it needs to be stringified).
37
+ * It can also be used for generic shortcuts of power-of-two sizes.
38
+ * This table is generated using the AWK script below:
39
+ *
40
+ * BEGIN {
41
+ * suffix="KMGTPE";
42
+ * for(i=10; i<64; i++) {
43
+ * val=2**i;
44
+ * s=substr(suffix, int(i/10), 1);
45
+ * n=2**(i%10);
46
+ * pad=21-int(log(n)/log(10));
47
+ * printf("#define S_%d%siB %*d\n", n, s, pad, val);
48
+ * }
49
+ * }
34
+ */
50
+ */
35
+int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
36
+ int64_t sector_num,
37
+ int nb_sectors,
38
+ int *pnum,
39
+ BlockDriverState **file);
40
+/*
41
+ * Default implementation for drivers to pass bdrv_co_get_block_status() to
42
+ * their backing file.
43
+ */
44
+int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
45
+ int64_t sector_num,
46
+ int nb_sectors,
47
+ int *pnum,
48
+ BlockDriverState **file);
49
const char *bdrv_get_parent_name(const BlockDriverState *bs);
50
void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp);
51
bool blk_dev_has_removable_media(BlockBackend *blk);
52
diff --git a/block/blkdebug.c b/block/blkdebug.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/block/blkdebug.c
55
+++ b/block/blkdebug.c
56
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
57
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
58
}
59
60
-static int64_t coroutine_fn blkdebug_co_get_block_status(
61
- BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
62
- BlockDriverState **file)
63
-{
64
- *pnum = nb_sectors;
65
- *file = bs->file->bs;
66
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
67
- (sector_num << BDRV_SECTOR_BITS);
68
-}
69
-
70
static void blkdebug_close(BlockDriverState *bs)
71
{
72
BDRVBlkdebugState *s = bs->opaque;
73
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
74
.bdrv_co_flush_to_disk = blkdebug_co_flush,
75
.bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
76
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
77
- .bdrv_co_get_block_status = blkdebug_co_get_block_status,
78
+ .bdrv_co_get_block_status = bdrv_co_get_block_status_from_file,
79
80
.bdrv_debug_event = blkdebug_debug_event,
81
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
82
diff --git a/block/commit.c b/block/commit.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/block/commit.c
85
+++ b/block/commit.c
86
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
87
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
88
}
89
90
-static int64_t coroutine_fn bdrv_commit_top_get_block_status(
91
- BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
92
- BlockDriverState **file)
93
-{
94
- *pnum = nb_sectors;
95
- *file = bs->backing->bs;
96
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
97
- (sector_num << BDRV_SECTOR_BITS);
98
-}
99
-
100
static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
101
{
102
bdrv_refresh_filename(bs->backing->bs);
103
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
104
static BlockDriver bdrv_commit_top = {
105
.format_name = "commit_top",
106
.bdrv_co_preadv = bdrv_commit_top_preadv,
107
- .bdrv_co_get_block_status = bdrv_commit_top_get_block_status,
108
+ .bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
109
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
110
.bdrv_close = bdrv_commit_top_close,
111
.bdrv_child_perm = bdrv_commit_top_child_perm,
112
diff --git a/block/io.c b/block/io.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/block/io.c
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvCoGetBlockStatusData {
117
bool done;
118
} BdrvCoGetBlockStatusData;
119
120
+int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
121
+ int64_t sector_num,
122
+ int nb_sectors,
123
+ int *pnum,
124
+ BlockDriverState **file)
125
+{
126
+ assert(bs->file && bs->file->bs);
127
+ *pnum = nb_sectors;
128
+ *file = bs->file->bs;
129
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
130
+ (sector_num << BDRV_SECTOR_BITS);
131
+}
132
+
51
+
133
+int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
52
#define S_1KiB 1024
134
+ int64_t sector_num,
53
#define S_2KiB 2048
135
+ int nb_sectors,
54
#define S_4KiB 4096
136
+ int *pnum,
137
+ BlockDriverState **file)
138
+{
139
+ assert(bs->backing && bs->backing->bs);
140
+ *pnum = nb_sectors;
141
+ *file = bs->backing->bs;
142
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
143
+ (sector_num << BDRV_SECTOR_BITS);
144
+}
145
+
146
/*
147
* Returns the allocation status of the specified sectors.
148
* Drivers not implementing the functionality are assumed to not support
149
diff --git a/block/mirror.c b/block/mirror.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/block/mirror.c
152
+++ b/block/mirror.c
153
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs)
154
return bdrv_co_flush(bs->backing->bs);
155
}
156
157
-static int64_t coroutine_fn bdrv_mirror_top_get_block_status(
158
- BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
159
- BlockDriverState **file)
160
-{
161
- *pnum = nb_sectors;
162
- *file = bs->backing->bs;
163
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
164
- (sector_num << BDRV_SECTOR_BITS);
165
-}
166
-
167
static int coroutine_fn bdrv_mirror_top_pwrite_zeroes(BlockDriverState *bs,
168
int64_t offset, int bytes, BdrvRequestFlags flags)
169
{
170
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
171
.bdrv_co_pwrite_zeroes = bdrv_mirror_top_pwrite_zeroes,
172
.bdrv_co_pdiscard = bdrv_mirror_top_pdiscard,
173
.bdrv_co_flush = bdrv_mirror_top_flush,
174
- .bdrv_co_get_block_status = bdrv_mirror_top_get_block_status,
175
+ .bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
176
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
177
.bdrv_close = bdrv_mirror_top_close,
178
.bdrv_child_perm = bdrv_mirror_top_child_perm,
179
--
55
--
180
2.13.5
56
2.19.1
181
57
182
58
diff view generated by jsdifflib