1
The following changes since commit b2f7a038bb4c4fc5ce6b8486e8513dfd97665e2a:
1
The following changes since commit 6972ef1440a9d685482d78672620a7482f2bd09a:
2
2
3
Merge remote-tracking branch 'remotes/rth/tags/pull-softfloat-20181104' into staging (2018-11-05 10:32:49 +0000)
3
Merge tag 'pull-tcg-20230516-3' of https://gitlab.com/rth7680/qemu into staging (2023-05-16 21:30:27 -0700)
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
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 1240ac558d348f6c7a5752b1a57c1da58e4efe3e:
9
for you to fetch changes up to 75b2591bbce5dc9f3da89f140b7bdc00e92fa8ec:
10
10
11
include: Add a comment to explain the origin of sizes' lookup table (2018-11-05 15:29:59 +0100)
11
tested: add test for nested aio_poll() in poll handlers (2023-05-17 18:01:22 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- auto-read-only option to fix commit job when used with -blockdev
16
- qcow2 spec: Rename "zlib" compression to "deflate"
17
- Fix help text related qemu-iotests failure (by improving the help text
17
- Honour graph read lock even in the main thread + prerequisite fixes
18
and updating the reference output)
18
- aio-posix: do not nest poll handlers (fixes infinite recursion)
19
- quorum: Add missing checks when adding/removing child nodes
19
- Refactor QMP blockdev transactions
20
- Don't take address of fields in packed structs
20
- iotests/245: Check if 'compress' driver is available
21
- vvfat: Fix crash when reporting error about too many files in directory
22
21
23
----------------------------------------------------------------
22
----------------------------------------------------------------
24
Alberto Garcia (7):
23
Akihiro Suda (1):
25
block: replace "discard" literal with BDRV_OPT_DISCARD macro
24
docs/interop/qcow2.txt: fix description about "zlib" clusters
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
32
25
33
Cleber Rosa (1):
26
Kevin Wolf (9):
34
iotests: make 083 specific to raw
27
block: Call .bdrv_co_create(_opts) unlocked
28
block/export: Fix null pointer dereference in error path
29
qcow2: Unlock the graph in qcow2_do_open() where necessary
30
qemu-img: Take graph lock more selectively
31
test-bdrv-drain: Take graph lock more selectively
32
test-bdrv-drain: Call bdrv_co_unref() in coroutine context
33
blockjob: Adhere to rate limit even when reentered early
34
graph-lock: Honour read locks even in the main thread
35
iotests/245: Check if 'compress' driver is available
35
36
36
Daniel P. Berrangé (1):
37
Stefan Hajnoczi (2):
37
crypto: initialize sector size even when opening with no IO flag
38
aio-posix: do not nest poll handlers
39
tested: add test for nested aio_poll() in poll handlers
38
40
39
Kevin Wolf (12):
41
Vladimir Sementsov-Ogievskiy (6):
40
vpc: Don't leak opts in vpc_open()
42
blockdev: refactor transaction to use Transaction API
41
block: Update flags in bdrv_set_read_only()
43
blockdev: transactions: rename some things
42
block: Add auto-read-only option
44
blockdev: qmp_transaction: refactor loop to classic for
43
rbd: Close image in qemu_rbd_open() error path
45
blockdev: transaction: refactor handling transaction properties
44
block: Require auto-read-only for existing fallbacks
46
blockdev: use state.bitmap in block-dirty-bitmap-add action
45
nbd: Support auto-read-only option
47
blockdev: qmp_transaction: drop extra generic layer
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
52
48
53
Leonid Bloch (2):
49
docs/interop/qcow2.txt | 10 +-
54
vdi: Use a literal number of bytes for DEFAULT_CLUSTER_SIZE
50
include/block/block-global-state.h | 8 +-
55
include: Add a comment to explain the origin of sizes' lookup table
51
include/block/block_int-common.h | 4 +-
56
52
include/block/blockjob_int.h | 14 +-
57
Li Qiang (1):
53
block.c | 1 -
58
block: change some function return type to bool
54
block/commit.c | 7 +-
59
55
block/create.c | 1 -
60
Max Reitz (5):
56
block/crypto.c | 25 +-
61
option: Make option help nicer to read
57
block/export/export.c | 6 +-
62
chardev: Indent list of chardevs
58
block/graph-lock.c | 10 -
63
qdev-monitor: Make device options help nicer
59
block/mirror.c | 23 +-
64
object: Make option help nicer to read
60
block/parallels.c | 6 +-
65
fw_cfg: Drop newline in @file description
61
block/qcow.c | 6 +-
66
62
block/qcow2.c | 43 ++-
67
Peter Maydell (5):
63
block/qed.c | 6 +-
68
block/qcow2: Don't take address of fields in packed structs
64
block/raw-format.c | 2 +-
69
block/qcow: Don't take address of fields in packed structs
65
block/stream.c | 7 +-
70
block/qcow2-bitmap: Don't take address of fields in packed structs
66
block/vdi.c | 11 +-
71
block/vhdx: Don't take address of fields in packed structs
67
block/vhdx.c | 8 +-
72
block/vdi: Don't take address of fields in packed structs
68
block/vmdk.c | 27 +-
73
69
block/vpc.c | 6 +-
74
Stefan Weil (1):
70
blockdev.c | 606 +++++++++++++++----------------------
75
qemu-io-cmds: Fix two format strings
71
blockjob.c | 22 +-
76
72
qemu-img.c | 5 +-
77
Thomas Huth (1):
73
tests/unit/test-bdrv-drain.c | 6 +-
78
block/vvfat: Fix crash when reporting error about too many files in directory
74
tests/unit/test-nested-aio-poll.c | 130 ++++++++
79
75
util/aio-posix.c | 11 +
80
qapi/block-core.json | 7 +
76
tests/qemu-iotests/245 | 7 +-
81
block/vhdx.h | 12 +-
77
tests/qemu-iotests/245.out | 9 +-
82
include/block/block.h | 5 +-
78
tests/unit/meson.build | 1 +
83
include/qemu/option.h | 2 +-
79
30 files changed, 541 insertions(+), 487 deletions(-)
84
include/qemu/units.h | 18 +
80
create mode 100644 tests/unit/test-nested-aio-poll.c
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
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
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
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
block.c | 6 +++---
7
1 file changed, 3 insertions(+), 3 deletions(-)
8
9
diff --git a/block.c b/block.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
12
+++ b/block.c
13
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
14
.help = "try to optimize zero writes (off, on, unmap)",
15
},
16
{
17
- .name = "discard",
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
}
24
}
25
26
- discard = qemu_opt_get(opts, "discard");
27
+ discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
28
if (discard != NULL) {
29
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
30
error_setg(errp, "Invalid discard option");
31
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
32
33
update_flags_from_options(&reopen_state->flags, opts);
34
35
- discard = qemu_opt_get_del(opts, "discard");
36
+ discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
37
if (discard != NULL) {
38
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
39
error_setg(errp, "Invalid discard option");
40
--
41
2.19.1
42
43
diff view generated by jsdifflib
1
Some block drivers have traditionally changed their node to read-only
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
mode without asking the user. This behaviour has been marked deprecated
3
since 2.11, expecting users to provide an explicit read-only=on option.
4
2
5
Now that we have auto-read-only=on, enable these drivers to make use of
3
We are going to add more block-graph modifying transaction actions,
6
the option.
4
and block-graph modifying functions are already based on Transaction
5
API.
7
6
8
This is the only use of bdrv_set_read_only(), so we can make it a bit
7
Next, we'll need to separately update permissions after several
9
more specific and turn it into a bdrv_apply_auto_read_only() that is
8
graph-modifying actions, and this would be simple with help of
10
more convenient for drivers to use.
9
Transaction API.
11
10
11
So, now let's just transform what we have into new-style transaction
12
actions.
13
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
15
Message-Id: <20230510150624.310640-2-vsementsov@yandex-team.ru>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
---
18
---
15
include/block/block.h | 3 ++-
19
blockdev.c | 309 ++++++++++++++++++++++++++++++-----------------------
16
block.c | 42 +++++++++++++++++++++++++++---------------
20
1 file changed, 178 insertions(+), 131 deletions(-)
17
block/bochs.c | 17 ++++++-----------
18
block/cloop.c | 16 +++++-----------
19
block/dmg.c | 16 +++++-----------
20
block/rbd.c | 15 ++++-----------
21
block/vvfat.c | 10 ++--------
22
7 files changed, 51 insertions(+), 68 deletions(-)
23
21
24
diff --git a/include/block/block.h b/include/block/block.h
22
diff --git a/blockdev.c b/blockdev.c
25
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
24
--- a/blockdev.c
27
+++ b/include/block/block.h
25
+++ b/blockdev.c
28
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
26
@@ -XXX,XX +XXX,XX @@ typedef struct BlkActionState BlkActionState;
29
bool bdrv_is_read_only(BlockDriverState *bs);
27
*/
30
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
28
typedef struct BlkActionOps {
31
bool ignore_allow_rdw, Error **errp);
29
size_t instance_size;
32
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
30
- void (*prepare)(BlkActionState *common, Error **errp);
33
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
31
- void (*commit)(BlkActionState *common);
34
+ Error **errp);
32
- void (*abort)(BlkActionState *common);
35
bool bdrv_is_writable(BlockDriverState *bs);
33
- void (*clean)(BlkActionState *common);
36
bool bdrv_is_sg(BlockDriverState *bs);
34
+ void (*action)(BlkActionState *common, Transaction *tran, Error **errp);
37
bool bdrv_is_inserted(BlockDriverState *bs);
35
} BlkActionOps;
38
diff --git a/block.c b/block.c
36
39
index XXXXXXX..XXXXXXX 100644
37
/**
40
--- a/block.c
38
@@ -XXX,XX +XXX,XX @@ typedef struct InternalSnapshotState {
41
+++ b/block.c
39
bool created;
42
@@ -XXX,XX +XXX,XX @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
40
} InternalSnapshotState;
41
42
+static void internal_snapshot_abort(void *opaque);
43
+static void internal_snapshot_clean(void *opaque);
44
+TransactionActionDrv internal_snapshot_drv = {
45
+ .abort = internal_snapshot_abort,
46
+ .clean = internal_snapshot_clean,
47
+};
48
49
static int action_check_completion_mode(BlkActionState *s, Error **errp)
50
{
51
@@ -XXX,XX +XXX,XX @@ static int action_check_completion_mode(BlkActionState *s, Error **errp)
43
return 0;
52
return 0;
44
}
53
}
45
54
46
-/* TODO Remove (deprecated since 2.11)
55
-static void internal_snapshot_prepare(BlkActionState *common,
47
- * Block drivers are not supposed to automatically change bs->read_only.
56
- Error **errp)
48
- * Instead, they should just check whether they can provide what the user
57
+static void internal_snapshot_action(BlkActionState *common,
49
- * explicitly requested and error out if read-write is requested, but they can
58
+ Transaction *tran, Error **errp)
50
- * only provide read-only access. */
59
{
51
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
60
Error *local_err = NULL;
52
+/*
61
const char *device;
53
+ * Called by a driver that can only provide a read-only image.
62
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
54
+ *
63
internal = common->action->u.blockdev_snapshot_internal_sync.data;
55
+ * Returns 0 if the node is already read-only or it could switch the node to
64
state = DO_UPCAST(InternalSnapshotState, common, common);
56
+ * read-only because BDRV_O_AUTO_RDONLY is set.
65
57
+ *
66
+ tran_add(tran, &internal_snapshot_drv, state);
58
+ * Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
67
+
59
+ * or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
68
/* 1. parse input */
60
+ * is not NULL, it is used as the error message for the Error object.
69
device = internal->device;
61
+ */
70
name = internal->name;
62
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
71
@@ -XXX,XX +XXX,XX @@ out:
63
+ Error **errp)
72
aio_context_release(aio_context);
64
{
73
}
65
int ret = 0;
74
66
75
-static void internal_snapshot_abort(BlkActionState *common)
67
- ret = bdrv_can_set_read_only(bs, read_only, false, errp);
76
+static void internal_snapshot_abort(void *opaque)
68
- if (ret < 0) {
77
{
69
- return ret;
78
- InternalSnapshotState *state =
70
+ if (!(bs->open_flags & BDRV_O_RDWR)) {
79
- DO_UPCAST(InternalSnapshotState, common, common);
71
+ return 0;
80
+ InternalSnapshotState *state = opaque;
72
+ }
81
BlockDriverState *bs = state->bs;
73
+ if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
82
QEMUSnapshotInfo *sn = &state->sn;
74
+ goto fail;
83
AioContext *aio_context;
75
}
84
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(BlkActionState *common)
76
85
aio_context_release(aio_context);
77
- bs->read_only = read_only;
86
}
87
88
-static void internal_snapshot_clean(BlkActionState *common)
89
+static void internal_snapshot_clean(void *opaque)
90
{
91
- InternalSnapshotState *state = DO_UPCAST(InternalSnapshotState,
92
- common, common);
93
+ g_autofree InternalSnapshotState *state = opaque;
94
AioContext *aio_context;
95
96
if (!state->bs) {
97
@@ -XXX,XX +XXX,XX @@ typedef struct ExternalSnapshotState {
98
bool overlay_appended;
99
} ExternalSnapshotState;
100
101
-static void external_snapshot_prepare(BlkActionState *common,
102
- Error **errp)
103
+static void external_snapshot_commit(void *opaque);
104
+static void external_snapshot_abort(void *opaque);
105
+static void external_snapshot_clean(void *opaque);
106
+TransactionActionDrv external_snapshot_drv = {
107
+ .commit = external_snapshot_commit,
108
+ .abort = external_snapshot_abort,
109
+ .clean = external_snapshot_clean,
110
+};
111
+
112
+static void external_snapshot_action(BlkActionState *common, Transaction *tran,
113
+ Error **errp)
114
{
115
int ret;
116
int flags = 0;
117
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
118
AioContext *aio_context;
119
uint64_t perm, shared;
120
121
+ tran_add(tran, &external_snapshot_drv, state);
122
+
123
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
124
* purpose but a different set of parameters */
125
switch (action->type) {
126
@@ -XXX,XX +XXX,XX @@ out:
127
aio_context_release(aio_context);
128
}
129
130
-static void external_snapshot_commit(BlkActionState *common)
131
+static void external_snapshot_commit(void *opaque)
132
{
133
- ExternalSnapshotState *state =
134
- DO_UPCAST(ExternalSnapshotState, common, common);
135
+ ExternalSnapshotState *state = opaque;
136
AioContext *aio_context;
137
138
aio_context = bdrv_get_aio_context(state->old_bs);
139
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_commit(BlkActionState *common)
140
aio_context_release(aio_context);
141
}
142
143
-static void external_snapshot_abort(BlkActionState *common)
144
+static void external_snapshot_abort(void *opaque)
145
{
146
- ExternalSnapshotState *state =
147
- DO_UPCAST(ExternalSnapshotState, common, common);
148
+ ExternalSnapshotState *state = opaque;
149
if (state->new_bs) {
150
if (state->overlay_appended) {
151
AioContext *aio_context;
152
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
153
}
154
}
155
156
-static void external_snapshot_clean(BlkActionState *common)
157
+static void external_snapshot_clean(void *opaque)
158
{
159
- ExternalSnapshotState *state =
160
- DO_UPCAST(ExternalSnapshotState, common, common);
161
+ g_autofree ExternalSnapshotState *state = opaque;
162
AioContext *aio_context;
163
164
if (!state->old_bs) {
165
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
166
AioContext *aio_context,
167
JobTxn *txn, Error **errp);
168
169
-static void drive_backup_prepare(BlkActionState *common, Error **errp)
170
+static void drive_backup_commit(void *opaque);
171
+static void drive_backup_abort(void *opaque);
172
+static void drive_backup_clean(void *opaque);
173
+TransactionActionDrv drive_backup_drv = {
174
+ .commit = drive_backup_commit,
175
+ .abort = drive_backup_abort,
176
+ .clean = drive_backup_clean,
177
+};
178
+
179
+static void drive_backup_action(BlkActionState *common, Transaction *tran,
180
+ Error **errp)
181
{
182
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
183
DriveBackup *backup;
184
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
185
bool set_backing_hd = false;
186
int ret;
187
188
+ tran_add(tran, &drive_backup_drv, state);
189
+
190
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
191
backup = common->action->u.drive_backup.data;
192
193
@@ -XXX,XX +XXX,XX @@ out:
194
aio_context_release(aio_context);
195
}
196
197
-static void drive_backup_commit(BlkActionState *common)
198
+static void drive_backup_commit(void *opaque)
199
{
200
- DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
201
+ DriveBackupState *state = opaque;
202
AioContext *aio_context;
203
204
aio_context = bdrv_get_aio_context(state->bs);
205
@@ -XXX,XX +XXX,XX @@ static void drive_backup_commit(BlkActionState *common)
206
aio_context_release(aio_context);
207
}
208
209
-static void drive_backup_abort(BlkActionState *common)
210
+static void drive_backup_abort(void *opaque)
211
{
212
- DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
213
+ DriveBackupState *state = opaque;
214
215
if (state->job) {
216
job_cancel_sync(&state->job->job, true);
217
}
218
}
219
220
-static void drive_backup_clean(BlkActionState *common)
221
+static void drive_backup_clean(void *opaque)
222
{
223
- DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
224
+ g_autofree DriveBackupState *state = opaque;
225
AioContext *aio_context;
226
227
if (!state->bs) {
228
@@ -XXX,XX +XXX,XX @@ typedef struct BlockdevBackupState {
229
BlockJob *job;
230
} BlockdevBackupState;
231
232
-static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
233
+static void blockdev_backup_commit(void *opaque);
234
+static void blockdev_backup_abort(void *opaque);
235
+static void blockdev_backup_clean(void *opaque);
236
+TransactionActionDrv blockdev_backup_drv = {
237
+ .commit = blockdev_backup_commit,
238
+ .abort = blockdev_backup_abort,
239
+ .clean = blockdev_backup_clean,
240
+};
241
+
242
+static void blockdev_backup_action(BlkActionState *common, Transaction *tran,
243
+ Error **errp)
244
{
245
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
246
BlockdevBackup *backup;
247
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
248
AioContext *old_context;
249
int ret;
250
251
+ tran_add(tran, &blockdev_backup_drv, state);
252
+
253
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
254
backup = common->action->u.blockdev_backup.data;
255
256
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
257
aio_context_release(aio_context);
258
}
259
260
-static void blockdev_backup_commit(BlkActionState *common)
261
+static void blockdev_backup_commit(void *opaque)
262
{
263
- BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
264
+ BlockdevBackupState *state = opaque;
265
AioContext *aio_context;
266
267
aio_context = bdrv_get_aio_context(state->bs);
268
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_commit(BlkActionState *common)
269
aio_context_release(aio_context);
270
}
271
272
-static void blockdev_backup_abort(BlkActionState *common)
273
+static void blockdev_backup_abort(void *opaque)
274
{
275
- BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
276
+ BlockdevBackupState *state = opaque;
277
278
if (state->job) {
279
job_cancel_sync(&state->job->job, true);
280
}
281
}
282
283
-static void blockdev_backup_clean(BlkActionState *common)
284
+static void blockdev_backup_clean(void *opaque)
285
{
286
- BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
287
+ g_autofree BlockdevBackupState *state = opaque;
288
AioContext *aio_context;
289
290
if (!state->bs) {
291
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDirtyBitmapState {
292
bool was_enabled;
293
} BlockDirtyBitmapState;
294
295
-static void block_dirty_bitmap_add_prepare(BlkActionState *common,
296
- Error **errp)
297
+static void block_dirty_bitmap_add_abort(void *opaque);
298
+TransactionActionDrv block_dirty_bitmap_add_drv = {
299
+ .abort = block_dirty_bitmap_add_abort,
300
+ .clean = g_free,
301
+};
302
+
303
+static void block_dirty_bitmap_add_action(BlkActionState *common,
304
+ Transaction *tran, Error **errp)
305
{
306
Error *local_err = NULL;
307
BlockDirtyBitmapAdd *action;
308
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
309
common, common);
310
311
+ tran_add(tran, &block_dirty_bitmap_add_drv, state);
312
+
313
if (action_check_completion_mode(common, errp) < 0) {
314
return;
315
}
316
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common,
317
}
318
}
319
320
-static void block_dirty_bitmap_add_abort(BlkActionState *common)
321
+static void block_dirty_bitmap_add_abort(void *opaque)
322
{
323
BlockDirtyBitmapAdd *action;
324
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
325
- common, common);
326
+ BlockDirtyBitmapState *state = opaque;
327
328
- action = common->action->u.block_dirty_bitmap_add.data;
329
+ action = state->common.action->u.block_dirty_bitmap_add.data;
330
/* Should not be able to fail: IF the bitmap was added via .prepare(),
331
* then the node reference and bitmap name must have been valid.
332
*/
333
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_add_abort(BlkActionState *common)
334
}
335
}
336
337
-static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
338
- Error **errp)
339
+static void block_dirty_bitmap_restore(void *opaque);
340
+static void block_dirty_bitmap_free_backup(void *opaque);
341
+TransactionActionDrv block_dirty_bitmap_clear_drv = {
342
+ .abort = block_dirty_bitmap_restore,
343
+ .commit = block_dirty_bitmap_free_backup,
344
+ .clean = g_free,
345
+};
346
+
347
+static void block_dirty_bitmap_clear_action(BlkActionState *common,
348
+ Transaction *tran, Error **errp)
349
{
350
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
351
common, common);
352
BlockDirtyBitmap *action;
353
354
+ tran_add(tran, &block_dirty_bitmap_clear_drv, state);
355
+
356
if (action_check_completion_mode(common, errp) < 0) {
357
return;
358
}
359
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
360
bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
361
}
362
363
-static void block_dirty_bitmap_restore(BlkActionState *common)
364
+static void block_dirty_bitmap_restore(void *opaque)
365
{
366
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
367
- common, common);
368
+ BlockDirtyBitmapState *state = opaque;
369
370
if (state->backup) {
371
bdrv_restore_dirty_bitmap(state->bitmap, state->backup);
372
}
373
}
374
375
-static void block_dirty_bitmap_free_backup(BlkActionState *common)
376
+static void block_dirty_bitmap_free_backup(void *opaque)
377
{
378
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
379
- common, common);
380
+ BlockDirtyBitmapState *state = opaque;
381
382
hbitmap_free(state->backup);
383
}
384
385
-static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
386
- Error **errp)
387
+static void block_dirty_bitmap_enable_abort(void *opaque);
388
+TransactionActionDrv block_dirty_bitmap_enable_drv = {
389
+ .abort = block_dirty_bitmap_enable_abort,
390
+ .clean = g_free,
391
+};
392
+
393
+static void block_dirty_bitmap_enable_action(BlkActionState *common,
394
+ Transaction *tran, Error **errp)
395
{
396
BlockDirtyBitmap *action;
397
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
398
common, common);
399
400
+ tran_add(tran, &block_dirty_bitmap_enable_drv, state);
401
+
402
if (action_check_completion_mode(common, errp) < 0) {
403
return;
404
}
405
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
406
bdrv_enable_dirty_bitmap(state->bitmap);
407
}
408
409
-static void block_dirty_bitmap_enable_abort(BlkActionState *common)
410
+static void block_dirty_bitmap_enable_abort(void *opaque)
411
{
412
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
413
- common, common);
414
+ BlockDirtyBitmapState *state = opaque;
415
416
if (!state->was_enabled) {
417
bdrv_disable_dirty_bitmap(state->bitmap);
418
}
419
}
420
421
-static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
422
- Error **errp)
423
+static void block_dirty_bitmap_disable_abort(void *opaque);
424
+TransactionActionDrv block_dirty_bitmap_disable_drv = {
425
+ .abort = block_dirty_bitmap_disable_abort,
426
+ .clean = g_free,
427
+};
428
+
429
+static void block_dirty_bitmap_disable_action(BlkActionState *common,
430
+ Transaction *tran, Error **errp)
431
{
432
BlockDirtyBitmap *action;
433
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
434
common, common);
435
436
+ tran_add(tran, &block_dirty_bitmap_disable_drv, state);
437
+
438
if (action_check_completion_mode(common, errp) < 0) {
439
return;
440
}
441
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
442
bdrv_disable_dirty_bitmap(state->bitmap);
443
}
444
445
-static void block_dirty_bitmap_disable_abort(BlkActionState *common)
446
+static void block_dirty_bitmap_disable_abort(void *opaque)
447
{
448
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
449
- common, common);
450
+ BlockDirtyBitmapState *state = opaque;
451
452
if (state->was_enabled) {
453
bdrv_enable_dirty_bitmap(state->bitmap);
454
}
455
}
456
457
-static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
458
- Error **errp)
459
+TransactionActionDrv block_dirty_bitmap_merge_drv = {
460
+ .commit = block_dirty_bitmap_free_backup,
461
+ .abort = block_dirty_bitmap_restore,
462
+ .clean = g_free,
463
+};
464
+
465
+static void block_dirty_bitmap_merge_action(BlkActionState *common,
466
+ Transaction *tran, Error **errp)
467
{
468
BlockDirtyBitmapMerge *action;
469
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
470
common, common);
471
472
+ tran_add(tran, &block_dirty_bitmap_merge_drv, state);
473
+
474
if (action_check_completion_mode(common, errp) < 0) {
475
return;
476
}
477
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
478
errp);
479
}
480
481
-static void block_dirty_bitmap_remove_prepare(BlkActionState *common,
482
- Error **errp)
483
+static void block_dirty_bitmap_remove_commit(void *opaque);
484
+static void block_dirty_bitmap_remove_abort(void *opaque);
485
+TransactionActionDrv block_dirty_bitmap_remove_drv = {
486
+ .commit = block_dirty_bitmap_remove_commit,
487
+ .abort = block_dirty_bitmap_remove_abort,
488
+ .clean = g_free,
489
+};
490
+
491
+static void block_dirty_bitmap_remove_action(BlkActionState *common,
492
+ Transaction *tran, Error **errp)
493
{
494
BlockDirtyBitmap *action;
495
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
496
common, common);
497
498
+ tran_add(tran, &block_dirty_bitmap_remove_drv, state);
499
+
500
if (action_check_completion_mode(common, errp) < 0) {
501
return;
502
}
503
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_remove_prepare(BlkActionState *common,
504
}
505
}
506
507
-static void block_dirty_bitmap_remove_abort(BlkActionState *common)
508
+static void block_dirty_bitmap_remove_abort(void *opaque)
509
{
510
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
511
- common, common);
512
+ BlockDirtyBitmapState *state = opaque;
513
514
if (state->bitmap) {
515
bdrv_dirty_bitmap_skip_store(state->bitmap, false);
516
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_remove_abort(BlkActionState *common)
517
}
518
}
519
520
-static void block_dirty_bitmap_remove_commit(BlkActionState *common)
521
+static void block_dirty_bitmap_remove_commit(void *opaque)
522
{
523
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
524
- common, common);
525
+ BlockDirtyBitmapState *state = opaque;
526
527
bdrv_dirty_bitmap_set_busy(state->bitmap, false);
528
bdrv_release_dirty_bitmap(state->bitmap);
529
}
530
531
-static void abort_prepare(BlkActionState *common, Error **errp)
532
+static void abort_commit(void *opaque);
533
+TransactionActionDrv abort_drv = {
534
+ .commit = abort_commit,
535
+ .clean = g_free,
536
+};
537
+
538
+static void abort_action(BlkActionState *common, Transaction *tran,
539
+ Error **errp)
540
{
541
+ tran_add(tran, &abort_drv, common);
542
error_setg(errp, "Transaction aborted using Abort action");
543
}
544
545
-static void abort_commit(BlkActionState *common)
546
+static void abort_commit(void *opaque)
547
{
548
g_assert_not_reached(); /* this action never succeeds */
549
}
550
@@ -XXX,XX +XXX,XX @@ static void abort_commit(BlkActionState *common)
551
static const BlkActionOps actions[] = {
552
[TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = {
553
.instance_size = sizeof(ExternalSnapshotState),
554
- .prepare = external_snapshot_prepare,
555
- .commit = external_snapshot_commit,
556
- .abort = external_snapshot_abort,
557
- .clean = external_snapshot_clean,
558
+ .action = external_snapshot_action,
559
},
560
[TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] = {
561
.instance_size = sizeof(ExternalSnapshotState),
562
- .prepare = external_snapshot_prepare,
563
- .commit = external_snapshot_commit,
564
- .abort = external_snapshot_abort,
565
- .clean = external_snapshot_clean,
566
+ .action = external_snapshot_action,
567
},
568
[TRANSACTION_ACTION_KIND_DRIVE_BACKUP] = {
569
.instance_size = sizeof(DriveBackupState),
570
- .prepare = drive_backup_prepare,
571
- .commit = drive_backup_commit,
572
- .abort = drive_backup_abort,
573
- .clean = drive_backup_clean,
574
+ .action = drive_backup_action,
575
},
576
[TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP] = {
577
.instance_size = sizeof(BlockdevBackupState),
578
- .prepare = blockdev_backup_prepare,
579
- .commit = blockdev_backup_commit,
580
- .abort = blockdev_backup_abort,
581
- .clean = blockdev_backup_clean,
582
+ .action = blockdev_backup_action,
583
},
584
[TRANSACTION_ACTION_KIND_ABORT] = {
585
.instance_size = sizeof(BlkActionState),
586
- .prepare = abort_prepare,
587
- .commit = abort_commit,
588
+ .action = abort_action,
589
},
590
[TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC] = {
591
.instance_size = sizeof(InternalSnapshotState),
592
- .prepare = internal_snapshot_prepare,
593
- .abort = internal_snapshot_abort,
594
- .clean = internal_snapshot_clean,
595
+ .action = internal_snapshot_action,
596
},
597
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD] = {
598
.instance_size = sizeof(BlockDirtyBitmapState),
599
- .prepare = block_dirty_bitmap_add_prepare,
600
- .abort = block_dirty_bitmap_add_abort,
601
+ .action = block_dirty_bitmap_add_action,
602
},
603
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR] = {
604
.instance_size = sizeof(BlockDirtyBitmapState),
605
- .prepare = block_dirty_bitmap_clear_prepare,
606
- .commit = block_dirty_bitmap_free_backup,
607
- .abort = block_dirty_bitmap_restore,
608
+ .action = block_dirty_bitmap_clear_action,
609
},
610
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ENABLE] = {
611
.instance_size = sizeof(BlockDirtyBitmapState),
612
- .prepare = block_dirty_bitmap_enable_prepare,
613
- .abort = block_dirty_bitmap_enable_abort,
614
+ .action = block_dirty_bitmap_enable_action,
615
},
616
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_DISABLE] = {
617
.instance_size = sizeof(BlockDirtyBitmapState),
618
- .prepare = block_dirty_bitmap_disable_prepare,
619
- .abort = block_dirty_bitmap_disable_abort,
620
+ .action = block_dirty_bitmap_disable_action,
621
},
622
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_MERGE] = {
623
.instance_size = sizeof(BlockDirtyBitmapState),
624
- .prepare = block_dirty_bitmap_merge_prepare,
625
- .commit = block_dirty_bitmap_free_backup,
626
- .abort = block_dirty_bitmap_restore,
627
+ .action = block_dirty_bitmap_merge_action,
628
},
629
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_REMOVE] = {
630
.instance_size = sizeof(BlockDirtyBitmapState),
631
- .prepare = block_dirty_bitmap_remove_prepare,
632
- .commit = block_dirty_bitmap_remove_commit,
633
- .abort = block_dirty_bitmap_remove_abort,
634
+ .action = block_dirty_bitmap_remove_action,
635
},
636
/* Where are transactions for MIRROR, COMMIT and STREAM?
637
* Although these blockjobs use transaction callbacks like the backup job,
638
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *dev_list,
639
TransactionActionList *dev_entry = dev_list;
640
bool has_props = !!props;
641
JobTxn *block_job_txn = NULL;
642
- BlkActionState *state, *next;
643
Error *local_err = NULL;
644
+ Transaction *tran = tran_new();
645
646
GLOBAL_STATE_CODE();
647
648
- QTAILQ_HEAD(, BlkActionState) snap_bdrv_states;
649
- QTAILQ_INIT(&snap_bdrv_states);
78
-
650
-
79
- if (read_only) {
651
/* Does this transaction get canceled as a group on failure?
80
- bs->open_flags &= ~BDRV_O_RDWR;
652
* If not, we don't really need to make a JobTxn.
81
- } else {
653
*/
82
- bs->open_flags |= BDRV_O_RDWR;
654
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *dev_list,
83
+ ret = bdrv_can_set_read_only(bs, true, false, NULL);
655
while (NULL != dev_entry) {
84
+ if (ret < 0) {
656
TransactionAction *dev_info = NULL;
85
+ goto fail;
657
const BlkActionOps *ops;
86
}
658
+ BlkActionState *state;
87
659
88
+ bs->read_only = true;
660
dev_info = dev_entry->value;
89
+ bs->open_flags &= ~BDRV_O_RDWR;
661
dev_entry = dev_entry->next;
90
+
662
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *dev_list,
91
return 0;
663
state->action = dev_info;
92
+
664
state->block_job_txn = block_job_txn;
93
+fail:
665
state->txn_props = props;
94
+ error_setg(errp, "%s", errmsg ?: "Image is read-only");
666
- QTAILQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
95
+ return -EACCES;
667
96
}
668
- state->ops->prepare(state, &local_err);
97
669
+ state->ops->action(state, tran, &local_err);
98
void bdrv_get_full_backing_filename_from_filename(const char *backed,
670
if (local_err) {
99
diff --git a/block/bochs.c b/block/bochs.c
671
error_propagate(errp, local_err);
100
index XXXXXXX..XXXXXXX 100644
672
goto delete_and_fail;
101
--- a/block/bochs.c
673
}
102
+++ b/block/bochs.c
674
}
103
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
675
104
struct bochs_header bochs;
676
- QTAILQ_FOREACH(state, &snap_bdrv_states, entry) {
105
int ret;
677
- if (state->ops->commit) {
106
678
- state->ops->commit(state);
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
- }
679
- }
128
- }
680
- }
129
-
681
+ tran_commit(tran);
130
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
682
131
if (ret < 0) {
683
/* success */
132
return ret;
684
goto exit;
133
diff --git a/block/cloop.c b/block/cloop.c
685
134
index XXXXXXX..XXXXXXX 100644
686
delete_and_fail:
135
--- a/block/cloop.c
687
/* failure, and it is all-or-none; roll back all operations */
136
+++ b/block/cloop.c
688
- QTAILQ_FOREACH_REVERSE(state, &snap_bdrv_states, entry) {
137
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
689
- if (state->ops->abort) {
138
uint32_t offsets_size, max_compressed_block_size = 1, i;
690
- state->ops->abort(state);
139
int ret;
140
141
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
142
+ if (ret < 0) {
143
+ return ret;
144
+ }
145
+
146
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
147
false, errp);
148
if (!bs->file) {
149
return -EINVAL;
150
}
151
152
- if (!bdrv_is_read_only(bs)) {
153
- error_report("Opening cloop images without an explicit read-only=on "
154
- "option is deprecated. Future versions will refuse to "
155
- "open the image instead of automatically marking the "
156
- "image read-only.");
157
- ret = bdrv_set_read_only(bs, true, errp);
158
- if (ret < 0) {
159
- return ret;
160
- }
691
- }
161
- }
692
- }
162
-
693
+ tran_abort(tran);
163
/* read header */
694
exit:
164
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
695
- QTAILQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
165
if (ret < 0) {
696
- if (state->ops->clean) {
166
diff --git a/block/dmg.c b/block/dmg.c
697
- state->ops->clean(state);
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
- }
698
- }
699
- g_free(state);
194
- }
700
- }
195
-
701
if (!has_props) {
196
block_module_load_one("dmg-bz2");
702
qapi_free_TransactionProperties(props);
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
}
703
}
247
--
704
--
248
2.19.1
705
2.40.1
249
250
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Just like in qemu_opts_print_help(), print the device name as a caption
3
Look at qmp_transaction(): dev_list is not obvious name for list of
4
instead of on every single line, indent all options, add angle brackets
4
actions. Let's look at qapi spec, this argument is "actions". Let's
5
around types, and align the descriptions after 24 characters. Also,
5
follow the common practice of using same argument names in qapi scheme
6
separate the descriptions with " - " instead of putting them in
6
and code.
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
7
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
To be honest, rename props to properties for same reason.
12
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
10
Next, we have to rename global map of actions, to not conflict with new
11
name for function argument.
12
13
Rename also dev_entry loop variable accordingly to new name of the
14
list.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
Message-Id: <20230510150624.310640-3-vsementsov@yandex-team.ru>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
20
---
15
qdev-monitor.c | 13 +++++++++++--
21
blockdev.c | 30 +++++++++++++++---------------
16
1 file changed, 11 insertions(+), 2 deletions(-)
22
1 file changed, 15 insertions(+), 15 deletions(-)
17
23
18
diff --git a/qdev-monitor.c b/qdev-monitor.c
24
diff --git a/blockdev.c b/blockdev.c
19
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
20
--- a/qdev-monitor.c
26
--- a/blockdev.c
21
+++ b/qdev-monitor.c
27
+++ b/blockdev.c
22
@@ -XXX,XX +XXX,XX @@ int qdev_device_help(QemuOpts *opts)
28
@@ -XXX,XX +XXX,XX @@ static void abort_commit(void *opaque)
23
goto error;
29
g_assert_not_reached(); /* this action never succeeds */
30
}
31
32
-static const BlkActionOps actions[] = {
33
+static const BlkActionOps actions_map[] = {
34
[TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = {
35
.instance_size = sizeof(ExternalSnapshotState),
36
.action = external_snapshot_action,
37
@@ -XXX,XX +XXX,XX @@ static TransactionProperties *get_transaction_properties(
38
*
39
* Always run under BQL.
40
*/
41
-void qmp_transaction(TransactionActionList *dev_list,
42
- struct TransactionProperties *props,
43
+void qmp_transaction(TransactionActionList *actions,
44
+ struct TransactionProperties *properties,
45
Error **errp)
46
{
47
- TransactionActionList *dev_entry = dev_list;
48
- bool has_props = !!props;
49
+ TransactionActionList *act = actions;
50
+ bool has_properties = !!properties;
51
JobTxn *block_job_txn = NULL;
52
Error *local_err = NULL;
53
Transaction *tran = tran_new();
54
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *dev_list,
55
/* Does this transaction get canceled as a group on failure?
56
* If not, we don't really need to make a JobTxn.
57
*/
58
- props = get_transaction_properties(props);
59
- if (props->completion_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
60
+ properties = get_transaction_properties(properties);
61
+ if (properties->completion_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
62
block_job_txn = job_txn_new();
24
}
63
}
25
64
26
+ if (prop_list) {
65
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *dev_list,
27
+ out_printf("%s options:\n", driver);
66
bdrv_drain_all();
28
+ } else {
67
29
+ out_printf("There are no options for %s.\n", driver);
68
/* We don't do anything in this loop that commits us to the operations */
30
+ }
69
- while (NULL != dev_entry) {
31
for (prop = prop_list; prop; prop = prop->next) {
70
+ while (NULL != act) {
32
- out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
71
TransactionAction *dev_info = NULL;
33
+ int len;
72
const BlkActionOps *ops;
34
+ out_printf(" %s=<%s>%n", prop->value->name, prop->value->type, &len);
73
BlkActionState *state;
35
if (prop->value->has_description) {
74
36
- out_printf(" (%s)\n", prop->value->description);
75
- dev_info = dev_entry->value;
37
+ if (len < 24) {
76
- dev_entry = dev_entry->next;
38
+ out_printf("%*s", 24 - len, "");
77
+ dev_info = act->value;
39
+ }
78
+ act = act->next;
40
+ out_printf(" - %s\n", prop->value->description);
79
41
} else {
80
- assert(dev_info->type < ARRAY_SIZE(actions));
42
out_printf("\n");
81
+ assert(dev_info->type < ARRAY_SIZE(actions_map));
43
}
82
83
- ops = &actions[dev_info->type];
84
+ ops = &actions_map[dev_info->type];
85
assert(ops->instance_size > 0);
86
87
state = g_malloc0(ops->instance_size);
88
state->ops = ops;
89
state->action = dev_info;
90
state->block_job_txn = block_job_txn;
91
- state->txn_props = props;
92
+ state->txn_props = properties;
93
94
state->ops->action(state, tran, &local_err);
95
if (local_err) {
96
@@ -XXX,XX +XXX,XX @@ delete_and_fail:
97
/* failure, and it is all-or-none; roll back all operations */
98
tran_abort(tran);
99
exit:
100
- if (!has_props) {
101
- qapi_free_TransactionProperties(props);
102
+ if (!has_properties) {
103
+ qapi_free_TransactionProperties(properties);
104
}
105
job_txn_unref(block_job_txn);
106
}
44
--
107
--
45
2.19.1
108
2.40.1
46
47
diff view generated by jsdifflib
1
While we want machine interfaces like -blockdev and QMP blockdev-add to
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
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.
8
2
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
4
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20230510150624.310640-4-vsementsov@yandex-team.ru>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
---
7
---
12
blockdev.c | 1 +
8
blockdev.c | 9 +++------
13
1 file changed, 1 insertion(+)
9
1 file changed, 3 insertions(+), 6 deletions(-)
14
10
15
diff --git a/blockdev.c b/blockdev.c
11
diff --git a/blockdev.c b/blockdev.c
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/blockdev.c
13
--- a/blockdev.c
18
+++ b/blockdev.c
14
+++ b/blockdev.c
19
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
15
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *actions,
20
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
16
struct TransactionProperties *properties,
21
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
17
Error **errp)
22
read_only ? "on" : "off");
18
{
23
+ qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
19
- TransactionActionList *act = actions;
24
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
20
+ TransactionActionList *act;
25
21
bool has_properties = !!properties;
26
if (runstate_check(RUN_STATE_INMIGRATE)) {
22
JobTxn *block_job_txn = NULL;
23
Error *local_err = NULL;
24
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *actions,
25
bdrv_drain_all();
26
27
/* We don't do anything in this loop that commits us to the operations */
28
- while (NULL != act) {
29
- TransactionAction *dev_info = NULL;
30
+ for (act = actions; act; act = act->next) {
31
+ TransactionAction *dev_info = act->value;
32
const BlkActionOps *ops;
33
BlkActionState *state;
34
35
- dev_info = act->value;
36
- act = act->next;
37
-
38
assert(dev_info->type < ARRAY_SIZE(actions_map));
39
40
ops = &actions_map[dev_info->type];
27
--
41
--
28
2.19.1
42
2.40.1
29
30
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Following the example of qemu_opts_print_help(), indent all entries in
3
Only backup supports GROUPED mode. Make this logic more clear. And
4
the list of character devices.
4
avoid passing extra thing to each action.
5
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
7
Message-Id: <20230510150624.310640-5-vsementsov@yandex-team.ru>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
chardev/char.c | 2 +-
11
blockdev.c | 96 +++++++++++++-----------------------------------------
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 22 insertions(+), 74 deletions(-)
12
13
13
diff --git a/chardev/char.c b/chardev/char.c
14
diff --git a/blockdev.c b/blockdev.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/chardev/char.c
16
--- a/blockdev.c
16
+++ b/chardev/char.c
17
+++ b/blockdev.c
17
@@ -XXX,XX +XXX,XX @@ help_string_append(const char *name, void *opaque)
18
@@ -XXX,XX +XXX,XX @@ struct BlkActionState {
19
TransactionAction *action;
20
const BlkActionOps *ops;
21
JobTxn *block_job_txn;
22
- TransactionProperties *txn_props;
23
QTAILQ_ENTRY(BlkActionState) entry;
24
};
25
26
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv internal_snapshot_drv = {
27
.clean = internal_snapshot_clean,
28
};
29
30
-static int action_check_completion_mode(BlkActionState *s, Error **errp)
31
-{
32
- if (s->txn_props->completion_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
33
- error_setg(errp,
34
- "Action '%s' does not support Transaction property "
35
- "completion-mode = %s",
36
- TransactionActionKind_str(s->action->type),
37
- ActionCompletionMode_str(s->txn_props->completion_mode));
38
- return -1;
39
- }
40
- return 0;
41
-}
42
-
43
static void internal_snapshot_action(BlkActionState *common,
44
Transaction *tran, Error **errp)
18
{
45
{
19
GString *str = opaque;
46
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_action(BlkActionState *common,
20
47
21
- g_string_append_printf(str, "\n%s", name);
48
tran_add(tran, &internal_snapshot_drv, state);
22
+ g_string_append_printf(str, "\n %s", name);
49
50
- /* 1. parse input */
51
device = internal->device;
52
name = internal->name;
53
54
- /* 2. check for validation */
55
- if (action_check_completion_mode(common, errp) < 0) {
56
- return;
57
- }
58
-
59
bs = qmp_get_root_bs(device, errp);
60
if (!bs) {
61
return;
62
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_action(BlkActionState *common, Transaction *tran,
63
}
64
65
/* start processing */
66
- if (action_check_completion_mode(common, errp) < 0) {
67
- return;
68
- }
69
70
state->old_bs = bdrv_lookup_bs(device, node_name, errp);
71
if (!state->old_bs) {
72
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_add_action(BlkActionState *common,
73
74
tran_add(tran, &block_dirty_bitmap_add_drv, state);
75
76
- if (action_check_completion_mode(common, errp) < 0) {
77
- return;
78
- }
79
-
80
action = common->action->u.block_dirty_bitmap_add.data;
81
/* AIO context taken and released within qmp_block_dirty_bitmap_add */
82
qmp_block_dirty_bitmap_add(action->node, action->name,
83
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_action(BlkActionState *common,
84
85
tran_add(tran, &block_dirty_bitmap_clear_drv, state);
86
87
- if (action_check_completion_mode(common, errp) < 0) {
88
- return;
89
- }
90
-
91
action = common->action->u.block_dirty_bitmap_clear.data;
92
state->bitmap = block_dirty_bitmap_lookup(action->node,
93
action->name,
94
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_enable_action(BlkActionState *common,
95
96
tran_add(tran, &block_dirty_bitmap_enable_drv, state);
97
98
- if (action_check_completion_mode(common, errp) < 0) {
99
- return;
100
- }
101
-
102
action = common->action->u.block_dirty_bitmap_enable.data;
103
state->bitmap = block_dirty_bitmap_lookup(action->node,
104
action->name,
105
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_disable_action(BlkActionState *common,
106
107
tran_add(tran, &block_dirty_bitmap_disable_drv, state);
108
109
- if (action_check_completion_mode(common, errp) < 0) {
110
- return;
111
- }
112
-
113
action = common->action->u.block_dirty_bitmap_disable.data;
114
state->bitmap = block_dirty_bitmap_lookup(action->node,
115
action->name,
116
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_merge_action(BlkActionState *common,
117
118
tran_add(tran, &block_dirty_bitmap_merge_drv, state);
119
120
- if (action_check_completion_mode(common, errp) < 0) {
121
- return;
122
- }
123
-
124
action = common->action->u.block_dirty_bitmap_merge.data;
125
126
state->bitmap = block_dirty_bitmap_merge(action->node, action->target,
127
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_remove_action(BlkActionState *common,
128
129
tran_add(tran, &block_dirty_bitmap_remove_drv, state);
130
131
- if (action_check_completion_mode(common, errp) < 0) {
132
- return;
133
- }
134
-
135
action = common->action->u.block_dirty_bitmap_remove.data;
136
137
state->bitmap = block_dirty_bitmap_remove(action->node, action->name,
138
@@ -XXX,XX +XXX,XX @@ static const BlkActionOps actions_map[] = {
139
*/
140
};
141
142
-/**
143
- * Allocate a TransactionProperties structure if necessary, and fill
144
- * that structure with desired defaults if they are unset.
145
- */
146
-static TransactionProperties *get_transaction_properties(
147
- TransactionProperties *props)
148
-{
149
- if (!props) {
150
- props = g_new0(TransactionProperties, 1);
151
- }
152
-
153
- if (!props->has_completion_mode) {
154
- props->has_completion_mode = true;
155
- props->completion_mode = ACTION_COMPLETION_MODE_INDIVIDUAL;
156
- }
157
-
158
- return props;
159
-}
160
-
161
/*
162
* 'Atomic' group operations. The operations are performed as a set, and if
163
* any fail then we roll back all operations in the group.
164
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *actions,
165
Error **errp)
166
{
167
TransactionActionList *act;
168
- bool has_properties = !!properties;
169
JobTxn *block_job_txn = NULL;
170
Error *local_err = NULL;
171
- Transaction *tran = tran_new();
172
+ Transaction *tran;
173
+ ActionCompletionMode comp_mode =
174
+ properties ? properties->completion_mode :
175
+ ACTION_COMPLETION_MODE_INDIVIDUAL;
176
177
GLOBAL_STATE_CODE();
178
179
/* Does this transaction get canceled as a group on failure?
180
* If not, we don't really need to make a JobTxn.
181
*/
182
- properties = get_transaction_properties(properties);
183
- if (properties->completion_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
184
+ if (comp_mode != ACTION_COMPLETION_MODE_INDIVIDUAL) {
185
+ for (act = actions; act; act = act->next) {
186
+ TransactionActionKind type = act->value->type;
187
+
188
+ if (type != TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP &&
189
+ type != TRANSACTION_ACTION_KIND_DRIVE_BACKUP)
190
+ {
191
+ error_setg(errp,
192
+ "Action '%s' does not support transaction property "
193
+ "completion-mode = %s",
194
+ TransactionActionKind_str(type),
195
+ ActionCompletionMode_str(comp_mode));
196
+ return;
197
+ }
198
+ }
199
+
200
block_job_txn = job_txn_new();
201
}
202
203
/* drain all i/o before any operations */
204
bdrv_drain_all();
205
206
+ tran = tran_new();
207
+
208
/* We don't do anything in this loop that commits us to the operations */
209
for (act = actions; act; act = act->next) {
210
TransactionAction *dev_info = act->value;
211
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *actions,
212
state->ops = ops;
213
state->action = dev_info;
214
state->block_job_txn = block_job_txn;
215
- state->txn_props = properties;
216
217
state->ops->action(state, tran, &local_err);
218
if (local_err) {
219
@@ -XXX,XX +XXX,XX @@ delete_and_fail:
220
/* failure, and it is all-or-none; roll back all operations */
221
tran_abort(tran);
222
exit:
223
- if (!has_properties) {
224
- qapi_free_TransactionProperties(properties);
225
- }
226
job_txn_unref(block_job_txn);
23
}
227
}
24
228
25
static const char *chardev_alias_translate(const char *name)
26
--
229
--
27
2.19.1
230
2.40.1
28
29
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Taking the address of a field in a packed struct is a bad idea, because
3
Other bitmap related actions use the .bitmap pointer in .abort action,
4
it might not be actually aligned enough for that pointer type (and
4
let's do same here:
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
5
9
There are a few places where the in-place swap function is
6
1. It helps further refactoring, as bitmap-add is the only bitmap
10
used on something other than a packed struct field; we convert
7
action that uses state.action in .abort
11
those anyway, for consistency.
12
8
13
This patch was produced with the following spatch script:
9
2. It must be safe: transaction actions rely on the fact that on
10
.abort() the state is the same as at the end of .prepare(), so that
11
in .abort() we could precisely rollback the changes done by
12
.prepare().
13
The only way to remove the bitmap during transaction should be
14
block-dirty-bitmap-remove action, but it postpones actual removal to
15
.commit(), so we are OK on any rollback path. (Note also that
16
bitmap-remove is the only bitmap action that has .commit() phase,
17
except for simple g_free the state on .clean())
14
18
15
@@
19
3. Again, other bitmap actions behave this way: keep the bitmap pointer
16
expression E;
20
during the transaction.
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
21
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-Id: <20230510150624.310640-6-vsementsov@yandex-team.ru>
48
Tested-by: John Snow <jsnow@redhat.com>
24
[kwolf: Also remove the now unused BlockDirtyBitmapState.prepared]
49
Reviewed-by: John Snow <jsnow@redhat.com>
25
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
---
27
---
52
block/qcow2-bitmap.c | 24 ++++++++++++------------
28
blockdev.c | 13 ++++---------
53
1 file changed, 12 insertions(+), 12 deletions(-)
29
1 file changed, 4 insertions(+), 9 deletions(-)
54
30
55
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
31
diff --git a/blockdev.c b/blockdev.c
56
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qcow2-bitmap.c
33
--- a/blockdev.c
58
+++ b/block/qcow2-bitmap.c
34
+++ b/blockdev.c
59
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
35
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDirtyBitmapState {
60
size_t i;
36
BdrvDirtyBitmap *bitmap;
61
37
BlockDriverState *bs;
62
for (i = 0; i < size; ++i) {
38
HBitmap *backup;
63
- cpu_to_be64s(&bitmap_table[i]);
39
- bool prepared;
64
+ bitmap_table[i] = cpu_to_be64(bitmap_table[i]);
40
bool was_enabled;
41
} BlockDirtyBitmapState;
42
43
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_add_action(BlkActionState *common,
44
&local_err);
45
46
if (!local_err) {
47
- state->prepared = true;
48
+ state->bitmap = block_dirty_bitmap_lookup(action->node, action->name,
49
+ NULL, &error_abort);
50
} else {
51
error_propagate(errp, local_err);
52
}
53
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_add_action(BlkActionState *common,
54
55
static void block_dirty_bitmap_add_abort(void *opaque)
56
{
57
- BlockDirtyBitmapAdd *action;
58
BlockDirtyBitmapState *state = opaque;
59
60
- action = state->common.action->u.block_dirty_bitmap_add.data;
61
- /* Should not be able to fail: IF the bitmap was added via .prepare(),
62
- * then the node reference and bitmap name must have been valid.
63
- */
64
- if (state->prepared) {
65
- qmp_block_dirty_bitmap_remove(action->node, action->name, &error_abort);
66
+ if (state->bitmap) {
67
+ bdrv_release_dirty_bitmap(state->bitmap);
65
}
68
}
66
}
69
}
67
70
68
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
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)
80
{
81
- be64_to_cpus(&entry->bitmap_table_offset);
82
- be32_to_cpus(&entry->bitmap_table_size);
83
- be32_to_cpus(&entry->flags);
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);
91
}
92
93
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
94
{
95
- cpu_to_be64s(&entry->bitmap_table_offset);
96
- cpu_to_be32s(&entry->bitmap_table_size);
97
- cpu_to_be32s(&entry->flags);
98
- cpu_to_be16s(&entry->name_size);
99
- cpu_to_be32s(&entry->extra_data_size);
100
+ entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
101
+ entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
102
+ entry->flags = cpu_to_be32(entry->flags);
103
+ entry->name_size = cpu_to_be16(entry->name_size);
104
+ entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
105
}
106
107
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
108
--
71
--
109
2.19.1
72
2.40.1
110
111
diff view generated by jsdifflib
1
If a management application builds the block graph node by node, the
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
protocol layer doesn't inherit its read-only option from the format
2
3
layer any more, so it must be set explicitly.
3
Let's simplify things:
4
4
5
Backing files should work on read-only storage, but at the same time, a
5
First, actions generally don't need access to common BlkActionState
6
block job like commit should be able to reopen them read-write if they
6
structure. The only exclusion are backup actions that need
7
are on read-write storage. However, without option inheritance, reopen
7
block_job_txn.
8
only changes the read-only option for the root node (typically the
8
9
format layer), but not the protocol layer, so reopening fails (the
9
Next, for transaction actions of Transaction API is more native to
10
format layer wants to get write permissions, but the protocol layer is
10
allocated state structure in the action itself.
11
still read-only).
11
12
12
So, do the following transformation:
13
A simple workaround for the problem in the management tool would be to
13
14
open the protocol layer always read-write and to make only the format
14
1. Let all actions be represented by a function with corresponding
15
layer read-only for backing files. However, sometimes the file is
15
structure as arguments.
16
actually stored on read-only storage and we don't know whether the image
16
17
can be opened read-write (for example, for NBD it depends on the server
17
2. Instead of array-map marshaller, let's make a function, that calls
18
we're trying to connect to). This adds an option that makes QEMU try to
18
corresponding action directly.
19
open the image read-write, but allows it to degrade to a read-only mode
19
20
without returning an error.
20
3. BlkActionOps and BlkActionState structures become unused
21
21
22
The documentation for this option is consciously phrased in a way that
22
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
23
allows QEMU to switch to a better model eventually: Instead of trying
23
Message-Id: <20230510150624.310640-7-vsementsov@yandex-team.ru>
24
when the image is first opened, making the read-only flag dynamic and
24
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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.
28
29
Unfortunately, this more useful behaviour is also a lot harder to
30
implement, and libvirt needs a solution now before it can switch to
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
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
Reviewed-by: Eric Blake <eblake@redhat.com>
40
---
26
---
41
qapi/block-core.json | 7 +++++++
27
blockdev.c | 265 +++++++++++++++++------------------------------------
42
include/block/block.h | 2 ++
28
1 file changed, 85 insertions(+), 180 deletions(-)
43
block.c | 17 +++++++++++++++++
29
44
block/vvfat.c | 1 +
45
blockdev.c | 2 +-
46
5 files changed, 28 insertions(+), 1 deletion(-)
47
48
diff --git a/qapi/block-core.json b/qapi/block-core.json
49
index XXXXXXX..XXXXXXX 100644
50
--- a/qapi/block-core.json
51
+++ b/qapi/block-core.json
52
@@ -XXX,XX +XXX,XX @@
53
# either generally or in certain configurations. In this case,
54
# the default value does not work and the option must be
55
# specified explicitly.
56
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
57
+# decide not to open the image read-write as requested, but
58
+# fall back to read-only instead (and switch between the modes
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.
65
@@ -XXX,XX +XXX,XX @@
66
'*discard': 'BlockdevDiscardOptions',
67
'*cache': 'BlockdevCacheOptions',
68
'*read-only': 'bool',
69
+ '*auto-read-only': 'bool',
70
'*force-share': 'bool',
71
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
72
'discriminator': 'driver',
73
diff --git a/include/block/block.h b/include/block/block.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/include/block/block.h
76
+++ b/include/block/block.h
77
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
78
select an appropriate protocol driver,
79
ignoring the format layer */
80
#define BDRV_O_NO_IO 0x10000 /* don't initialize for I/O */
81
+#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening read-write fails */
82
83
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
84
85
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
86
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
87
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
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
94
index XXXXXXX..XXXXXXX 100644
95
--- a/block.c
96
+++ b/block.c
97
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
98
99
/* Inherit the read-only option from the parent if it's not set */
100
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
101
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
102
103
/* Our block drivers take care to send flushes and respect unmap policy,
104
* so we can default to enable both on lower layers regardless of the
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
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/vvfat.c
159
+++ b/block/vvfat.c
160
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
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");
166
}
167
168
diff --git a/blockdev.c b/blockdev.c
30
diff --git a/blockdev.c b/blockdev.c
169
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
170
--- a/blockdev.c
32
--- a/blockdev.c
171
+++ b/blockdev.c
33
+++ b/blockdev.c
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
34
@@ -XXX,XX +XXX,XX @@ out_aio_context:
173
35
return NULL;
174
bdrv_flags = blk_get_open_flags_from_root_state(blk);
36
}
175
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
37
176
- BDRV_O_PROTOCOL);
38
-/* New and old BlockDriverState structs for atomic group operations */
177
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
39
-
178
40
-typedef struct BlkActionState BlkActionState;
179
if (!has_read_only) {
41
-
180
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
42
-/**
43
- * BlkActionOps:
44
- * Table of operations that define an Action.
45
- *
46
- * @instance_size: Size of state struct, in bytes.
47
- * @prepare: Prepare the work, must NOT be NULL.
48
- * @commit: Commit the changes, can be NULL.
49
- * @abort: Abort the changes on fail, can be NULL.
50
- * @clean: Clean up resources after all transaction actions have called
51
- * commit() or abort(). Can be NULL.
52
- *
53
- * Only prepare() may fail. In a single transaction, only one of commit() or
54
- * abort() will be called. clean() will always be called if it is present.
55
- *
56
- * Always run under BQL.
57
- */
58
-typedef struct BlkActionOps {
59
- size_t instance_size;
60
- void (*action)(BlkActionState *common, Transaction *tran, Error **errp);
61
-} BlkActionOps;
62
-
63
-/**
64
- * BlkActionState:
65
- * Describes one Action's state within a Transaction.
66
- *
67
- * @action: QAPI-defined enum identifying which Action to perform.
68
- * @ops: Table of ActionOps this Action can perform.
69
- * @block_job_txn: Transaction which this action belongs to.
70
- * @entry: List membership for all Actions in this Transaction.
71
- *
72
- * This structure must be arranged as first member in a subclassed type,
73
- * assuming that the compiler will also arrange it to the same offsets as the
74
- * base class.
75
- */
76
-struct BlkActionState {
77
- TransactionAction *action;
78
- const BlkActionOps *ops;
79
- JobTxn *block_job_txn;
80
- QTAILQ_ENTRY(BlkActionState) entry;
81
-};
82
-
83
/* internal snapshot private data */
84
typedef struct InternalSnapshotState {
85
- BlkActionState common;
86
BlockDriverState *bs;
87
QEMUSnapshotInfo sn;
88
bool created;
89
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv internal_snapshot_drv = {
90
.clean = internal_snapshot_clean,
91
};
92
93
-static void internal_snapshot_action(BlkActionState *common,
94
+static void internal_snapshot_action(BlockdevSnapshotInternal *internal,
95
Transaction *tran, Error **errp)
96
{
97
Error *local_err = NULL;
98
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_action(BlkActionState *common,
99
QEMUSnapshotInfo old_sn, *sn;
100
bool ret;
101
int64_t rt;
102
- BlockdevSnapshotInternal *internal;
103
- InternalSnapshotState *state;
104
+ InternalSnapshotState *state = g_new0(InternalSnapshotState, 1);
105
AioContext *aio_context;
106
int ret1;
107
108
- g_assert(common->action->type ==
109
- TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
110
- internal = common->action->u.blockdev_snapshot_internal_sync.data;
111
- state = DO_UPCAST(InternalSnapshotState, common, common);
112
-
113
tran_add(tran, &internal_snapshot_drv, state);
114
115
device = internal->device;
116
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_clean(void *opaque)
117
118
/* external snapshot private data */
119
typedef struct ExternalSnapshotState {
120
- BlkActionState common;
121
BlockDriverState *old_bs;
122
BlockDriverState *new_bs;
123
bool overlay_appended;
124
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv external_snapshot_drv = {
125
.clean = external_snapshot_clean,
126
};
127
128
-static void external_snapshot_action(BlkActionState *common, Transaction *tran,
129
- Error **errp)
130
+static void external_snapshot_action(TransactionAction *action,
131
+ Transaction *tran, Error **errp)
132
{
133
int ret;
134
int flags = 0;
135
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_action(BlkActionState *common, Transaction *tran,
136
const char *snapshot_ref;
137
/* File name of the new image (for 'blockdev-snapshot-sync') */
138
const char *new_image_file;
139
- ExternalSnapshotState *state =
140
- DO_UPCAST(ExternalSnapshotState, common, common);
141
- TransactionAction *action = common->action;
142
+ ExternalSnapshotState *state = g_new0(ExternalSnapshotState, 1);
143
AioContext *aio_context;
144
uint64_t perm, shared;
145
146
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(void *opaque)
147
}
148
149
typedef struct DriveBackupState {
150
- BlkActionState common;
151
BlockDriverState *bs;
152
BlockJob *job;
153
} DriveBackupState;
154
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv drive_backup_drv = {
155
.clean = drive_backup_clean,
156
};
157
158
-static void drive_backup_action(BlkActionState *common, Transaction *tran,
159
- Error **errp)
160
+static void drive_backup_action(DriveBackup *backup,
161
+ JobTxn *block_job_txn,
162
+ Transaction *tran, Error **errp)
163
{
164
- DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
165
- DriveBackup *backup;
166
+ DriveBackupState *state = g_new0(DriveBackupState, 1);
167
BlockDriverState *bs;
168
BlockDriverState *target_bs;
169
BlockDriverState *source = NULL;
170
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(BlkActionState *common, Transaction *tran,
171
172
tran_add(tran, &drive_backup_drv, state);
173
174
- assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
175
- backup = common->action->u.drive_backup.data;
176
-
177
if (!backup->has_mode) {
178
backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
179
}
180
@@ -XXX,XX +XXX,XX @@ static void drive_backup_action(BlkActionState *common, Transaction *tran,
181
182
state->job = do_backup_common(qapi_DriveBackup_base(backup),
183
bs, target_bs, aio_context,
184
- common->block_job_txn, errp);
185
+ block_job_txn, errp);
186
187
unref:
188
bdrv_unref(target_bs);
189
@@ -XXX,XX +XXX,XX @@ static void drive_backup_clean(void *opaque)
190
}
191
192
typedef struct BlockdevBackupState {
193
- BlkActionState common;
194
BlockDriverState *bs;
195
BlockJob *job;
196
} BlockdevBackupState;
197
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv blockdev_backup_drv = {
198
.clean = blockdev_backup_clean,
199
};
200
201
-static void blockdev_backup_action(BlkActionState *common, Transaction *tran,
202
- Error **errp)
203
+static void blockdev_backup_action(BlockdevBackup *backup,
204
+ JobTxn *block_job_txn,
205
+ Transaction *tran, Error **errp)
206
{
207
- BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
208
- BlockdevBackup *backup;
209
+ BlockdevBackupState *state = g_new0(BlockdevBackupState, 1);
210
BlockDriverState *bs;
211
BlockDriverState *target_bs;
212
AioContext *aio_context;
213
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_action(BlkActionState *common, Transaction *tran,
214
215
tran_add(tran, &blockdev_backup_drv, state);
216
217
- assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
218
- backup = common->action->u.blockdev_backup.data;
219
-
220
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
221
if (!bs) {
222
return;
223
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_action(BlkActionState *common, Transaction *tran,
224
225
state->job = do_backup_common(qapi_BlockdevBackup_base(backup),
226
bs, target_bs, aio_context,
227
- common->block_job_txn, errp);
228
+ block_job_txn, errp);
229
230
aio_context_release(aio_context);
231
}
232
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_clean(void *opaque)
233
}
234
235
typedef struct BlockDirtyBitmapState {
236
- BlkActionState common;
237
BdrvDirtyBitmap *bitmap;
238
BlockDriverState *bs;
239
HBitmap *backup;
240
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv block_dirty_bitmap_add_drv = {
241
.clean = g_free,
242
};
243
244
-static void block_dirty_bitmap_add_action(BlkActionState *common,
245
+static void block_dirty_bitmap_add_action(BlockDirtyBitmapAdd *action,
246
Transaction *tran, Error **errp)
247
{
248
Error *local_err = NULL;
249
- BlockDirtyBitmapAdd *action;
250
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
251
- common, common);
252
+ BlockDirtyBitmapState *state = g_new0(BlockDirtyBitmapState, 1);
253
254
tran_add(tran, &block_dirty_bitmap_add_drv, state);
255
256
- action = common->action->u.block_dirty_bitmap_add.data;
257
/* AIO context taken and released within qmp_block_dirty_bitmap_add */
258
qmp_block_dirty_bitmap_add(action->node, action->name,
259
action->has_granularity, action->granularity,
260
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv block_dirty_bitmap_clear_drv = {
261
.clean = g_free,
262
};
263
264
-static void block_dirty_bitmap_clear_action(BlkActionState *common,
265
+static void block_dirty_bitmap_clear_action(BlockDirtyBitmap *action,
266
Transaction *tran, Error **errp)
267
{
268
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
269
- common, common);
270
- BlockDirtyBitmap *action;
271
+ BlockDirtyBitmapState *state = g_new0(BlockDirtyBitmapState, 1);
272
273
tran_add(tran, &block_dirty_bitmap_clear_drv, state);
274
275
- action = common->action->u.block_dirty_bitmap_clear.data;
276
state->bitmap = block_dirty_bitmap_lookup(action->node,
277
action->name,
278
&state->bs,
279
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv block_dirty_bitmap_enable_drv = {
280
.clean = g_free,
281
};
282
283
-static void block_dirty_bitmap_enable_action(BlkActionState *common,
284
+static void block_dirty_bitmap_enable_action(BlockDirtyBitmap *action,
285
Transaction *tran, Error **errp)
286
{
287
- BlockDirtyBitmap *action;
288
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
289
- common, common);
290
+ BlockDirtyBitmapState *state = g_new0(BlockDirtyBitmapState, 1);
291
292
tran_add(tran, &block_dirty_bitmap_enable_drv, state);
293
294
- action = common->action->u.block_dirty_bitmap_enable.data;
295
state->bitmap = block_dirty_bitmap_lookup(action->node,
296
action->name,
297
NULL,
298
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv block_dirty_bitmap_disable_drv = {
299
.clean = g_free,
300
};
301
302
-static void block_dirty_bitmap_disable_action(BlkActionState *common,
303
+static void block_dirty_bitmap_disable_action(BlockDirtyBitmap *action,
304
Transaction *tran, Error **errp)
305
{
306
- BlockDirtyBitmap *action;
307
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
308
- common, common);
309
+ BlockDirtyBitmapState *state = g_new0(BlockDirtyBitmapState, 1);
310
311
tran_add(tran, &block_dirty_bitmap_disable_drv, state);
312
313
- action = common->action->u.block_dirty_bitmap_disable.data;
314
state->bitmap = block_dirty_bitmap_lookup(action->node,
315
action->name,
316
NULL,
317
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv block_dirty_bitmap_merge_drv = {
318
.clean = g_free,
319
};
320
321
-static void block_dirty_bitmap_merge_action(BlkActionState *common,
322
+static void block_dirty_bitmap_merge_action(BlockDirtyBitmapMerge *action,
323
Transaction *tran, Error **errp)
324
{
325
- BlockDirtyBitmapMerge *action;
326
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
327
- common, common);
328
+ BlockDirtyBitmapState *state = g_new0(BlockDirtyBitmapState, 1);
329
330
tran_add(tran, &block_dirty_bitmap_merge_drv, state);
331
332
- action = common->action->u.block_dirty_bitmap_merge.data;
333
-
334
state->bitmap = block_dirty_bitmap_merge(action->node, action->target,
335
action->bitmaps, &state->backup,
336
errp);
337
@@ -XXX,XX +XXX,XX @@ TransactionActionDrv block_dirty_bitmap_remove_drv = {
338
.clean = g_free,
339
};
340
341
-static void block_dirty_bitmap_remove_action(BlkActionState *common,
342
+static void block_dirty_bitmap_remove_action(BlockDirtyBitmap *action,
343
Transaction *tran, Error **errp)
344
{
345
- BlockDirtyBitmap *action;
346
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
347
- common, common);
348
+ BlockDirtyBitmapState *state = g_new0(BlockDirtyBitmapState, 1);
349
350
tran_add(tran, &block_dirty_bitmap_remove_drv, state);
351
352
- action = common->action->u.block_dirty_bitmap_remove.data;
353
354
state->bitmap = block_dirty_bitmap_remove(action->node, action->name,
355
false, &state->bs, errp);
356
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_remove_commit(void *opaque)
357
static void abort_commit(void *opaque);
358
TransactionActionDrv abort_drv = {
359
.commit = abort_commit,
360
- .clean = g_free,
361
};
362
363
-static void abort_action(BlkActionState *common, Transaction *tran,
364
- Error **errp)
365
+static void abort_action(Transaction *tran, Error **errp)
366
{
367
- tran_add(tran, &abort_drv, common);
368
+ tran_add(tran, &abort_drv, NULL);
369
error_setg(errp, "Transaction aborted using Abort action");
370
}
371
372
@@ -XXX,XX +XXX,XX @@ static void abort_commit(void *opaque)
373
g_assert_not_reached(); /* this action never succeeds */
374
}
375
376
-static const BlkActionOps actions_map[] = {
377
- [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = {
378
- .instance_size = sizeof(ExternalSnapshotState),
379
- .action = external_snapshot_action,
380
- },
381
- [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] = {
382
- .instance_size = sizeof(ExternalSnapshotState),
383
- .action = external_snapshot_action,
384
- },
385
- [TRANSACTION_ACTION_KIND_DRIVE_BACKUP] = {
386
- .instance_size = sizeof(DriveBackupState),
387
- .action = drive_backup_action,
388
- },
389
- [TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP] = {
390
- .instance_size = sizeof(BlockdevBackupState),
391
- .action = blockdev_backup_action,
392
- },
393
- [TRANSACTION_ACTION_KIND_ABORT] = {
394
- .instance_size = sizeof(BlkActionState),
395
- .action = abort_action,
396
- },
397
- [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC] = {
398
- .instance_size = sizeof(InternalSnapshotState),
399
- .action = internal_snapshot_action,
400
- },
401
- [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD] = {
402
- .instance_size = sizeof(BlockDirtyBitmapState),
403
- .action = block_dirty_bitmap_add_action,
404
- },
405
- [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR] = {
406
- .instance_size = sizeof(BlockDirtyBitmapState),
407
- .action = block_dirty_bitmap_clear_action,
408
- },
409
- [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ENABLE] = {
410
- .instance_size = sizeof(BlockDirtyBitmapState),
411
- .action = block_dirty_bitmap_enable_action,
412
- },
413
- [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_DISABLE] = {
414
- .instance_size = sizeof(BlockDirtyBitmapState),
415
- .action = block_dirty_bitmap_disable_action,
416
- },
417
- [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_MERGE] = {
418
- .instance_size = sizeof(BlockDirtyBitmapState),
419
- .action = block_dirty_bitmap_merge_action,
420
- },
421
- [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_REMOVE] = {
422
- .instance_size = sizeof(BlockDirtyBitmapState),
423
- .action = block_dirty_bitmap_remove_action,
424
- },
425
- /* Where are transactions for MIRROR, COMMIT and STREAM?
426
+static void transaction_action(TransactionAction *act, JobTxn *block_job_txn,
427
+ Transaction *tran, Error **errp)
428
+{
429
+ switch (act->type) {
430
+ case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:
431
+ case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
432
+ external_snapshot_action(act, tran, errp);
433
+ return;
434
+ case TRANSACTION_ACTION_KIND_DRIVE_BACKUP:
435
+ drive_backup_action(act->u.drive_backup.data,
436
+ block_job_txn, tran, errp);
437
+ return;
438
+ case TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP:
439
+ blockdev_backup_action(act->u.blockdev_backup.data,
440
+ block_job_txn, tran, errp);
441
+ return;
442
+ case TRANSACTION_ACTION_KIND_ABORT:
443
+ abort_action(tran, errp);
444
+ return;
445
+ case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC:
446
+ internal_snapshot_action(act->u.blockdev_snapshot_internal_sync.data,
447
+ tran, errp);
448
+ return;
449
+ case TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD:
450
+ block_dirty_bitmap_add_action(act->u.block_dirty_bitmap_add.data,
451
+ tran, errp);
452
+ return;
453
+ case TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR:
454
+ block_dirty_bitmap_clear_action(act->u.block_dirty_bitmap_clear.data,
455
+ tran, errp);
456
+ return;
457
+ case TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ENABLE:
458
+ block_dirty_bitmap_enable_action(act->u.block_dirty_bitmap_enable.data,
459
+ tran, errp);
460
+ return;
461
+ case TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_DISABLE:
462
+ block_dirty_bitmap_disable_action(
463
+ act->u.block_dirty_bitmap_disable.data, tran, errp);
464
+ return;
465
+ case TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_MERGE:
466
+ block_dirty_bitmap_merge_action(act->u.block_dirty_bitmap_merge.data,
467
+ tran, errp);
468
+ return;
469
+ case TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_REMOVE:
470
+ block_dirty_bitmap_remove_action(act->u.block_dirty_bitmap_remove.data,
471
+ tran, errp);
472
+ return;
473
+ /*
474
+ * Where are transactions for MIRROR, COMMIT and STREAM?
475
* Although these blockjobs use transaction callbacks like the backup job,
476
* these jobs do not necessarily adhere to transaction semantics.
477
* These jobs may not fully undo all of their actions on abort, nor do they
478
* necessarily work in transactions with more than one job in them.
479
*/
480
-};
481
+ case TRANSACTION_ACTION_KIND__MAX:
482
+ default:
483
+ g_assert_not_reached();
484
+ };
485
+}
486
+
487
488
/*
489
* 'Atomic' group operations. The operations are performed as a set, and if
490
@@ -XXX,XX +XXX,XX @@ void qmp_transaction(TransactionActionList *actions,
491
492
/* We don't do anything in this loop that commits us to the operations */
493
for (act = actions; act; act = act->next) {
494
- TransactionAction *dev_info = act->value;
495
- const BlkActionOps *ops;
496
- BlkActionState *state;
497
-
498
- assert(dev_info->type < ARRAY_SIZE(actions_map));
499
-
500
- ops = &actions_map[dev_info->type];
501
- assert(ops->instance_size > 0);
502
-
503
- state = g_malloc0(ops->instance_size);
504
- state->ops = ops;
505
- state->action = dev_info;
506
- state->block_job_txn = block_job_txn;
507
-
508
- state->ops->action(state, tran, &local_err);
509
+ transaction_action(act->value, block_job_txn, tran, &local_err);
510
if (local_err) {
511
error_propagate(errp, local_err);
512
goto delete_and_fail;
181
--
513
--
182
2.19.1
514
2.40.1
183
184
diff view generated by jsdifflib
1
From: Leonid Bloch <lbloch@janustech.com>
1
From: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2
2
3
The lookup table for power-of-two sizes was added in commit 540b8492618eb
3
"zlib" clusters are actually raw deflate (RFC1951) clusters without
4
for the purpose of having convenient shortcuts for these sizes in cases
4
zlib headers.
5
when the literal number has to be present at compile time, and
6
expressions as '(1 * KiB)' can not be used. One such case is the
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.
10
5
11
Despite its convenience, this table introduced 55 lines of "dumb" code,
6
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
12
the purpose and origin of which are obscure without reading the message
7
Message-Id: <168424874322.11954.1340942046351859521-0@git.sr.ht>
13
of the commit which introduced it. This patch fixes that by adding a
8
Reviewed-by: Eric Blake <eblake@redhat.com>
14
comment to the code itself with a brief explanation for the reasoning
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
11
---
23
include/qemu/units.h | 18 ++++++++++++++++++
12
docs/interop/qcow2.txt | 10 +++++++---
24
1 file changed, 18 insertions(+)
13
1 file changed, 7 insertions(+), 3 deletions(-)
25
14
26
diff --git a/include/qemu/units.h b/include/qemu/units.h
15
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
27
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
28
--- a/include/qemu/units.h
17
--- a/docs/interop/qcow2.txt
29
+++ b/include/qemu/units.h
18
+++ b/docs/interop/qcow2.txt
30
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ version 2.
31
#define PiB (INT64_C(1) << 50)
20
type.
32
#define EiB (INT64_C(1) << 60)
21
33
22
If the incompatible bit "Compression type" is set: the field
34
+/*
23
- must be present and non-zero (which means non-zlib
35
+ * The following lookup table is intended to be used when a literal string of
24
+ must be present and non-zero (which means non-deflate
36
+ * the number of bytes is required (for example if it needs to be stringified).
25
compression type). Otherwise, this field must not be present
37
+ * It can also be used for generic shortcuts of power-of-two sizes.
26
- or must be zero (which means zlib).
38
+ * This table is generated using the AWK script below:
27
+ or must be zero (which means deflate).
39
+ *
28
40
+ * BEGIN {
29
Available compression type values:
41
+ * suffix="KMGTPE";
30
- 0: zlib <https://www.zlib.net/>
42
+ * for(i=10; i<64; i++) {
31
+ 0: deflate <https://www.ietf.org/rfc/rfc1951.txt>
43
+ * val=2**i;
32
1: zstd <http://github.com/facebook/zstd>
44
+ * s=substr(suffix, int(i/10), 1);
33
45
+ * n=2**(i%10);
34
+ The deflate compression type is called "zlib"
46
+ * pad=21-int(log(n)/log(10));
35
+ <https://www.zlib.net/> in QEMU. However, clusters with the
47
+ * printf("#define S_%d%siB %*d\n", n, s, pad, val);
36
+ deflate compression type do not have zlib headers.
48
+ * }
49
+ * }
50
+ */
51
+
37
+
52
#define S_1KiB 1024
38
53
#define S_2KiB 2048
39
=== Header padding ===
54
#define S_4KiB 4096
40
55
--
41
--
56
2.19.1
42
2.40.1
57
58
diff view generated by jsdifflib
1
To fully change the read-only state of a node, we must not only change
1
These are functions that modify the graph, so they must be able to take
2
bs->read_only, but also update bs->open_flags.
2
a writer lock. This is impossible if they already hold the reader lock.
3
If they need a reader lock for some of their operations, they should
4
take it internally.
5
6
Many of them go through blk_*(), which will always take the lock itself.
7
Direct calls of bdrv_*() need to take the reader lock. Note that while
8
locking for bdrv_co_*() calls is checked by TSA, this is not the case
9
for the mixed_coroutine_fns bdrv_*(). Holding the lock is still required
10
when they are called from coroutine context like here!
11
12
This effectively reverts 4ec8df0183, but adds some internal locking
13
instead.
3
14
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Message-Id: <20230510203601.418015-2-kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
19
---
8
block.c | 7 +++++++
20
include/block/block-global-state.h | 8 +++----
9
1 file changed, 7 insertions(+)
21
include/block/block_int-common.h | 4 ++--
22
block.c | 1 -
23
block/create.c | 1 -
24
block/crypto.c | 25 ++++++++++----------
25
block/parallels.c | 6 ++---
26
block/qcow.c | 6 ++---
27
block/qcow2.c | 37 +++++++++++++++++++-----------
28
block/qed.c | 6 ++---
29
block/raw-format.c | 2 +-
30
block/vdi.c | 11 +++++----
31
block/vhdx.c | 8 ++++---
32
block/vmdk.c | 27 ++++++++++------------
33
block/vpc.c | 6 ++---
34
14 files changed, 78 insertions(+), 70 deletions(-)
10
35
36
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/block-global-state.h
39
+++ b/include/block/block-global-state.h
40
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_find_protocol(const char *filename,
41
Error **errp);
42
BlockDriver *bdrv_find_format(const char *format_name);
43
44
-int coroutine_fn GRAPH_RDLOCK
45
+int coroutine_fn GRAPH_UNLOCKED
46
bdrv_co_create(BlockDriver *drv, const char *filename, QemuOpts *opts,
47
Error **errp);
48
49
-int co_wrapper_bdrv_rdlock bdrv_create(BlockDriver *drv, const char *filename,
50
- QemuOpts *opts, Error **errp);
51
+int co_wrapper bdrv_create(BlockDriver *drv, const char *filename,
52
+ QemuOpts *opts, Error **errp);
53
54
-int coroutine_fn GRAPH_RDLOCK
55
+int coroutine_fn GRAPH_UNLOCKED
56
bdrv_co_create_file(const char *filename, QemuOpts *opts, Error **errp);
57
58
BlockDriverState *bdrv_new(void);
59
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
60
index XXXXXXX..XXXXXXX 100644
61
--- a/include/block/block_int-common.h
62
+++ b/include/block/block_int-common.h
63
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
64
BlockDriverState *bs, QDict *options, int flags, Error **errp);
65
void (*bdrv_close)(BlockDriverState *bs);
66
67
- int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create)(
68
+ int coroutine_fn GRAPH_UNLOCKED_PTR (*bdrv_co_create)(
69
BlockdevCreateOptions *opts, Error **errp);
70
71
- int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create_opts)(
72
+ int coroutine_fn GRAPH_UNLOCKED_PTR (*bdrv_co_create_opts)(
73
BlockDriver *drv, const char *filename, QemuOpts *opts, Error **errp);
74
75
int (*bdrv_amend_options)(BlockDriverState *bs,
11
diff --git a/block.c b/block.c
76
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
77
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
78
--- a/block.c
14
+++ b/block.c
79
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
80
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
81
int ret;
82
GLOBAL_STATE_CODE();
83
ERRP_GUARD();
84
- assert_bdrv_graph_readable();
85
86
if (!drv->bdrv_co_create_opts) {
87
error_setg(errp, "Driver '%s' does not support image creation",
88
diff --git a/block/create.c b/block/create.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/create.c
91
+++ b/block/create.c
92
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
93
int ret;
94
95
GLOBAL_STATE_CODE();
96
- GRAPH_RDLOCK_GUARD();
97
98
job_progress_set_remaining(&s->common, 1);
99
ret = s->drv->bdrv_co_create(s->opts, errp);
100
diff --git a/block/crypto.c b/block/crypto.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/crypto.c
103
+++ b/block/crypto.c
104
@@ -XXX,XX +XXX,XX @@ struct BlockCryptoCreateData {
105
};
106
107
108
-static int block_crypto_create_write_func(QCryptoBlock *block,
109
- size_t offset,
110
- const uint8_t *buf,
111
- size_t buflen,
112
- void *opaque,
113
- Error **errp)
114
+static int coroutine_fn GRAPH_UNLOCKED
115
+block_crypto_create_write_func(QCryptoBlock *block, size_t offset,
116
+ const uint8_t *buf, size_t buflen, void *opaque,
117
+ Error **errp)
118
{
119
struct BlockCryptoCreateData *data = opaque;
120
ssize_t ret;
121
@@ -XXX,XX +XXX,XX @@ static int block_crypto_create_write_func(QCryptoBlock *block,
122
return 0;
123
}
124
125
-static int block_crypto_create_init_func(QCryptoBlock *block,
126
- size_t headerlen,
127
- void *opaque,
128
- Error **errp)
129
+static int coroutine_fn GRAPH_UNLOCKED
130
+block_crypto_create_init_func(QCryptoBlock *block, size_t headerlen,
131
+ void *opaque, Error **errp)
132
{
133
struct BlockCryptoCreateData *data = opaque;
134
Error *local_error = NULL;
135
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
136
}
137
138
139
-static int coroutine_fn
140
+static int coroutine_fn GRAPH_UNLOCKED
141
block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
142
QCryptoBlockCreateOptions *opts,
143
PreallocMode prealloc, Error **errp)
144
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_luks(BlockDriverState *bs,
145
bs, options, flags, errp);
146
}
147
148
-static int coroutine_fn
149
+static int coroutine_fn GRAPH_UNLOCKED
150
block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
151
{
152
BlockdevCreateOptionsLUKS *luks_opts;
153
@@ -XXX,XX +XXX,XX @@ fail:
154
return ret;
155
}
156
157
-static int coroutine_fn GRAPH_RDLOCK
158
+static int coroutine_fn GRAPH_UNLOCKED
159
block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
160
QemuOpts *opts, Error **errp)
161
{
162
@@ -XXX,XX +XXX,XX @@ fail:
163
* beforehand, it has been truncated and corrupted in the process.
164
*/
165
if (ret) {
166
+ bdrv_graph_co_rdlock();
167
bdrv_co_delete_file_noerr(bs);
168
+ bdrv_graph_co_rdunlock();
16
}
169
}
17
170
18
bs->read_only = read_only;
171
bdrv_co_unref(bs);
172
diff --git a/block/parallels.c b/block/parallels.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/parallels.c
175
+++ b/block/parallels.c
176
@@ -XXX,XX +XXX,XX @@ out:
177
}
178
179
180
-static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
181
- Error **errp)
182
+static int coroutine_fn GRAPH_UNLOCKED
183
+parallels_co_create(BlockdevCreateOptions* opts, Error **errp)
184
{
185
BlockdevCreateOptionsParallels *parallels_opts;
186
BlockDriverState *bs;
187
@@ -XXX,XX +XXX,XX @@ exit:
188
goto out;
189
}
190
191
-static int coroutine_fn GRAPH_RDLOCK
192
+static int coroutine_fn GRAPH_UNLOCKED
193
parallels_co_create_opts(BlockDriver *drv, const char *filename,
194
QemuOpts *opts, Error **errp)
195
{
196
diff --git a/block/qcow.c b/block/qcow.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/block/qcow.c
199
+++ b/block/qcow.c
200
@@ -XXX,XX +XXX,XX @@ static void qcow_close(BlockDriverState *bs)
201
error_free(s->migration_blocker);
202
}
203
204
-static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
205
- Error **errp)
206
+static int coroutine_fn GRAPH_UNLOCKED
207
+qcow_co_create(BlockdevCreateOptions *opts, Error **errp)
208
{
209
BlockdevCreateOptionsQcow *qcow_opts;
210
int header_size, backing_filename_len, l1_size, shift, i;
211
@@ -XXX,XX +XXX,XX @@ exit:
212
return ret;
213
}
214
215
-static int coroutine_fn GRAPH_RDLOCK
216
+static int coroutine_fn GRAPH_UNLOCKED
217
qcow_co_create_opts(BlockDriver *drv, const char *filename,
218
QemuOpts *opts, Error **errp)
219
{
220
diff --git a/block/qcow2.c b/block/qcow2.c
221
index XXXXXXX..XXXXXXX 100644
222
--- a/block/qcow2.c
223
+++ b/block/qcow2.c
224
@@ -XXX,XX +XXX,XX @@ static int qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
225
}
226
227
228
-static int qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
229
- void *opaque, Error **errp)
230
+static int coroutine_fn GRAPH_RDLOCK
231
+qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen, void *opaque,
232
+ Error **errp)
233
{
234
BlockDriverState *bs = opaque;
235
BDRVQcow2State *s = bs->opaque;
236
@@ -XXX,XX +XXX,XX @@ static int qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
237
*/
238
clusterlen = size_to_clusters(s, headerlen) * s->cluster_size;
239
assert(qcow2_pre_write_overlap_check(bs, 0, ret, clusterlen, false) == 0);
240
- ret = bdrv_pwrite_zeroes(bs->file,
241
- ret,
242
- clusterlen, 0);
243
+ ret = bdrv_co_pwrite_zeroes(bs->file, ret, clusterlen, 0);
244
if (ret < 0) {
245
error_setg_errno(errp, -ret, "Could not zero fill encryption header");
246
return -1;
247
@@ -XXX,XX +XXX,XX @@ static int qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
248
}
249
250
251
-static int qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
252
- const uint8_t *buf, size_t buflen,
253
- void *opaque, Error **errp)
254
+/* The graph lock must be held when called in coroutine context */
255
+static int coroutine_mixed_fn
256
+qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
257
+ const uint8_t *buf, size_t buflen,
258
+ void *opaque, Error **errp)
259
{
260
BlockDriverState *bs = opaque;
261
BDRVQcow2State *s = bs->opaque;
262
@@ -XXX,XX +XXX,XX @@ static int qcow2_change_backing_file(BlockDriverState *bs,
263
return qcow2_update_header(bs);
264
}
265
266
-static int qcow2_set_up_encryption(BlockDriverState *bs,
267
- QCryptoBlockCreateOptions *cryptoopts,
268
- Error **errp)
269
+static int coroutine_fn GRAPH_RDLOCK
270
+qcow2_set_up_encryption(BlockDriverState *bs,
271
+ QCryptoBlockCreateOptions *cryptoopts,
272
+ Error **errp)
273
{
274
BDRVQcow2State *s = bs->opaque;
275
QCryptoBlock *crypto = NULL;
276
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
277
return refcount_bits;
278
}
279
280
-static int coroutine_fn
281
+static int coroutine_fn GRAPH_UNLOCKED
282
qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
283
{
284
BlockdevCreateOptionsQcow2 *qcow2_opts;
285
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
286
goto out;
287
}
288
289
+ bdrv_graph_co_rdlock();
290
ret = qcow2_alloc_clusters(blk_bs(blk), 3 * cluster_size);
291
if (ret < 0) {
292
+ bdrv_graph_co_rdunlock();
293
error_setg_errno(errp, -ret, "Could not allocate clusters for qcow2 "
294
"header and refcount table");
295
goto out;
296
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
297
298
/* Create a full header (including things like feature table) */
299
ret = qcow2_update_header(blk_bs(blk));
300
+ bdrv_graph_co_rdunlock();
19
+
301
+
20
+ if (read_only) {
302
if (ret < 0) {
21
+ bs->open_flags &= ~BDRV_O_RDWR;
303
error_setg_errno(errp, -ret, "Could not update qcow2 header");
22
+ } else {
304
goto out;
23
+ bs->open_flags |= BDRV_O_RDWR;
305
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
24
+ }
306
307
/* Want encryption? There you go. */
308
if (qcow2_opts->encrypt) {
309
+ bdrv_graph_co_rdlock();
310
ret = qcow2_set_up_encryption(blk_bs(blk), qcow2_opts->encrypt, errp);
311
+ bdrv_graph_co_rdunlock();
25
+
312
+
313
if (ret < 0) {
314
goto out;
315
}
316
@@ -XXX,XX +XXX,XX @@ out:
317
return ret;
318
}
319
320
-static int coroutine_fn GRAPH_RDLOCK
321
+static int coroutine_fn GRAPH_UNLOCKED
322
qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts,
323
Error **errp)
324
{
325
@@ -XXX,XX +XXX,XX @@ qcow2_co_create_opts(BlockDriver *drv, const char *filename, QemuOpts *opts,
326
ret = qcow2_co_create(create_options, errp);
327
finish:
328
if (ret < 0) {
329
+ bdrv_graph_co_rdlock();
330
bdrv_co_delete_file_noerr(bs);
331
bdrv_co_delete_file_noerr(data_bs);
332
+ bdrv_graph_co_rdunlock();
333
} else {
334
ret = 0;
335
}
336
diff --git a/block/qed.c b/block/qed.c
337
index XXXXXXX..XXXXXXX 100644
338
--- a/block/qed.c
339
+++ b/block/qed.c
340
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_close(BlockDriverState *bs)
341
qemu_vfree(s->l1_table);
342
}
343
344
-static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
345
- Error **errp)
346
+static int coroutine_fn GRAPH_UNLOCKED
347
+bdrv_qed_co_create(BlockdevCreateOptions *opts, Error **errp)
348
{
349
BlockdevCreateOptionsQed *qed_opts;
350
BlockBackend *blk = NULL;
351
@@ -XXX,XX +XXX,XX @@ out:
352
return ret;
353
}
354
355
-static int coroutine_fn GRAPH_RDLOCK
356
+static int coroutine_fn GRAPH_UNLOCKED
357
bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
358
QemuOpts *opts, Error **errp)
359
{
360
diff --git a/block/raw-format.c b/block/raw-format.c
361
index XXXXXXX..XXXXXXX 100644
362
--- a/block/raw-format.c
363
+++ b/block/raw-format.c
364
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
365
return bdrv_has_zero_init(bs->file->bs);
366
}
367
368
-static int coroutine_fn GRAPH_RDLOCK
369
+static int coroutine_fn GRAPH_UNLOCKED
370
raw_co_create_opts(BlockDriver *drv, const char *filename,
371
QemuOpts *opts, Error **errp)
372
{
373
diff --git a/block/vdi.c b/block/vdi.c
374
index XXXXXXX..XXXXXXX 100644
375
--- a/block/vdi.c
376
+++ b/block/vdi.c
377
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
378
return ret;
379
}
380
381
-static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
382
- size_t block_size, Error **errp)
383
+static int coroutine_fn GRAPH_UNLOCKED
384
+vdi_co_do_create(BlockdevCreateOptions *create_options, size_t block_size,
385
+ Error **errp)
386
{
387
BlockdevCreateOptionsVdi *vdi_opts;
388
int ret = 0;
389
@@ -XXX,XX +XXX,XX @@ exit:
390
return ret;
391
}
392
393
-static int coroutine_fn vdi_co_create(BlockdevCreateOptions *create_options,
394
- Error **errp)
395
+static int coroutine_fn GRAPH_UNLOCKED
396
+vdi_co_create(BlockdevCreateOptions *create_options, Error **errp)
397
{
398
return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp);
399
}
400
401
-static int coroutine_fn GRAPH_RDLOCK
402
+static int coroutine_fn GRAPH_UNLOCKED
403
vdi_co_create_opts(BlockDriver *drv, const char *filename,
404
QemuOpts *opts, Error **errp)
405
{
406
diff --git a/block/vhdx.c b/block/vhdx.c
407
index XXXXXXX..XXXXXXX 100644
408
--- a/block/vhdx.c
409
+++ b/block/vhdx.c
410
@@ -XXX,XX +XXX,XX @@ exit:
411
* There are 2 headers, and the highest sequence number will represent
412
* the active header
413
*/
414
-static int coroutine_fn GRAPH_RDLOCK
415
+static int coroutine_fn GRAPH_UNLOCKED
416
vhdx_create_new_headers(BlockBackend *blk, uint64_t image_size,
417
uint32_t log_size)
418
{
419
@@ -XXX,XX +XXX,XX @@ vhdx_create_new_headers(BlockBackend *blk, uint64_t image_size,
420
int ret = 0;
421
VHDXHeader *hdr = NULL;
422
423
+ GRAPH_RDLOCK_GUARD();
424
+
425
hdr = g_new0(VHDXHeader, 1);
426
427
hdr->signature = VHDX_HEADER_SIGNATURE;
428
@@ -XXX,XX +XXX,XX @@ exit:
429
* .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
430
* 1MB
431
*/
432
-static int coroutine_fn GRAPH_RDLOCK
433
+static int coroutine_fn GRAPH_UNLOCKED
434
vhdx_co_create(BlockdevCreateOptions *opts, Error **errp)
435
{
436
BlockdevCreateOptionsVhdx *vhdx_opts;
437
@@ -XXX,XX +XXX,XX @@ delete_and_exit:
438
return ret;
439
}
440
441
-static int coroutine_fn GRAPH_RDLOCK
442
+static int coroutine_fn GRAPH_UNLOCKED
443
vhdx_co_create_opts(BlockDriver *drv, const char *filename,
444
QemuOpts *opts, Error **errp)
445
{
446
diff --git a/block/vmdk.c b/block/vmdk.c
447
index XXXXXXX..XXXXXXX 100644
448
--- a/block/vmdk.c
449
+++ b/block/vmdk.c
450
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
451
return ret;
452
}
453
454
-static int vmdk_init_extent(BlockBackend *blk,
455
- int64_t filesize, bool flat,
456
- bool compress, bool zeroed_grain,
457
- Error **errp)
458
+static int GRAPH_UNLOCKED
459
+vmdk_init_extent(BlockBackend *blk, int64_t filesize, bool flat, bool compress,
460
+ bool zeroed_grain, Error **errp)
461
{
462
int ret, i;
463
VMDK4Header header;
464
@@ -XXX,XX +XXX,XX @@ exit:
465
return ret;
466
}
467
468
-static int coroutine_fn GRAPH_RDLOCK
469
+static int coroutine_fn GRAPH_UNLOCKED
470
vmdk_create_extent(const char *filename, int64_t filesize, bool flat,
471
bool compress, bool zeroed_grain, BlockBackend **pbb,
472
QemuOpts *opts, Error **errp)
473
@@ -XXX,XX +XXX,XX @@ static int filename_decompose(const char *filename, char *path, char *prefix,
474
* non-split format.
475
* idx >= 1: get the n-th extent if in a split subformat
476
*/
477
-typedef BlockBackend * coroutine_fn /* GRAPH_RDLOCK */
478
+typedef BlockBackend * coroutine_fn GRAPH_UNLOCKED_PTR
479
(*vmdk_create_extent_fn)(int64_t size, int idx, bool flat, bool split,
480
bool compress, bool zeroed_grain, void *opaque,
481
Error **errp);
482
@@ -XXX,XX +XXX,XX @@ static void vmdk_desc_add_extent(GString *desc,
483
g_free(basename);
484
}
485
486
-static int coroutine_fn GRAPH_RDLOCK
487
+static int coroutine_fn GRAPH_UNLOCKED
488
vmdk_co_do_create(int64_t size,
489
BlockdevVmdkSubformat subformat,
490
BlockdevVmdkAdapterType adapter_type,
491
@@ -XXX,XX +XXX,XX @@ typedef struct {
492
QemuOpts *opts;
493
} VMDKCreateOptsData;
494
495
-static BlockBackend * coroutine_fn GRAPH_RDLOCK
496
+static BlockBackend * coroutine_fn GRAPH_UNLOCKED
497
vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split,
498
bool compress, bool zeroed_grain, void *opaque,
499
Error **errp)
500
@@ -XXX,XX +XXX,XX @@ exit:
501
return blk;
502
}
503
504
-static int coroutine_fn GRAPH_RDLOCK
505
+static int coroutine_fn GRAPH_UNLOCKED
506
vmdk_co_create_opts(BlockDriver *drv, const char *filename,
507
QemuOpts *opts, Error **errp)
508
{
509
@@ -XXX,XX +XXX,XX @@ exit:
510
return ret;
511
}
512
513
-static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
514
- bool flat, bool split,
515
- bool compress,
516
- bool zeroed_grain,
517
- void *opaque, Error **errp)
518
+static BlockBackend * coroutine_fn GRAPH_UNLOCKED
519
+vmdk_co_create_cb(int64_t size, int idx, bool flat, bool split, bool compress,
520
+ bool zeroed_grain, void *opaque, Error **errp)
521
{
522
int ret;
523
BlockDriverState *bs;
524
@@ -XXX,XX +XXX,XX @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
525
return blk;
526
}
527
528
-static int coroutine_fn GRAPH_RDLOCK
529
+static int coroutine_fn GRAPH_UNLOCKED
530
vmdk_co_create(BlockdevCreateOptions *create_options, Error **errp)
531
{
532
BlockdevCreateOptionsVmdk *opts;
533
diff --git a/block/vpc.c b/block/vpc.c
534
index XXXXXXX..XXXXXXX 100644
535
--- a/block/vpc.c
536
+++ b/block/vpc.c
537
@@ -XXX,XX +XXX,XX @@ static int calculate_rounded_image_size(BlockdevCreateOptionsVpc *vpc_opts,
26
return 0;
538
return 0;
27
}
539
}
28
540
541
-static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
542
- Error **errp)
543
+static int coroutine_fn GRAPH_UNLOCKED
544
+vpc_co_create(BlockdevCreateOptions *opts, Error **errp)
545
{
546
BlockdevCreateOptionsVpc *vpc_opts;
547
BlockBackend *blk = NULL;
548
@@ -XXX,XX +XXX,XX @@ out:
549
return ret;
550
}
551
552
-static int coroutine_fn GRAPH_RDLOCK
553
+static int coroutine_fn GRAPH_UNLOCKED
554
vpc_co_create_opts(BlockDriver *drv, const char *filename,
555
QemuOpts *opts, Error **errp)
556
{
29
--
557
--
30
2.19.1
558
2.40.1
31
32
diff view generated by jsdifflib
1
From: Leonid Bloch <lbloch@janustech.com>
1
There are some error paths in blk_exp_add() that jump to 'fail:' before
2
'exp' is even created. So we can't just unconditionally access exp->blk.
2
3
3
If an expression is used to define DEFAULT_CLUSTER_SIZE, when compiled,
4
Add a NULL check, and switch from exp->blk to blk, which is available
4
it will be embedded as a literal expression in the binary (as the
5
earlier, just to be extra sure that we really cover all cases where
5
default value) because it is stringified to mark the size of the default
6
BlockDevOps could have been set for it (in practice, this only happens
6
value. Now this is fixed by using a defined number to define this value.
7
in drv->create() today, so this part of the change isn't strictly
8
necessary).
7
9
8
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
10
Fixes: Coverity CID 1509238
9
Reviewed-by: Stefan Weil <sw@weilnetz.de>
11
Fixes: de79b52604e43fdeba6cee4f5af600b62169f2d2
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230510203601.418015-3-kwolf@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Tested-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
17
---
12
block/vdi.c | 4 ++--
18
block/export/export.c | 6 ++++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
19
1 file changed, 4 insertions(+), 2 deletions(-)
14
20
15
diff --git a/block/vdi.c b/block/vdi.c
21
diff --git a/block/export/export.c b/block/export/export.c
16
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
17
--- a/block/vdi.c
23
--- a/block/export/export.c
18
+++ b/block/vdi.c
24
+++ b/block/export/export.c
19
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
20
#define BLOCK_OPT_STATIC "static"
26
return exp;
21
27
22
#define SECTOR_SIZE 512
28
fail:
23
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
29
- blk_set_dev_ops(exp->blk, NULL, NULL);
24
+#define DEFAULT_CLUSTER_SIZE S_1MiB
30
- blk_unref(blk);
25
31
+ if (blk) {
26
#if defined(CONFIG_VDI_DEBUG)
32
+ blk_set_dev_ops(blk, NULL, NULL);
27
#define VDI_DEBUG 1
33
+ blk_unref(blk);
28
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
34
+ }
29
goto fail;
35
aio_context_release(ctx);
30
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
36
if (exp) {
31
error_setg(errp, "unsupported VDI image (block size %" PRIu32
37
g_free(exp->id);
32
- " is not %" PRIu64 ")",
33
+ " is not %" PRIu32 ")",
34
header.block_size, DEFAULT_CLUSTER_SIZE);
35
ret = -ENOTSUP;
36
goto fail;
37
--
38
--
38
2.19.1
39
2.40.1
39
40
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
qcow2_do_open() calls a few no_co_wrappers that wrap functions taking
2
the graph lock internally as a writer. Therefore, it can't hold the
3
reader lock across these calls, it causes deadlocks. Drop the lock
4
temporarily around the calls.
2
5
3
This doesn't have any practical effect at the moment because the
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
values of BDRV_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE and
7
Message-Id: <20230510203601.418015-4-kwolf@redhat.com>
5
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE are all the same (512 bytes), but
8
Reviewed-by: Eric Blake <eblake@redhat.com>
6
future encryption methods could have different requirements.
7
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
10
---
12
block/qcow2.c | 2 +-
11
block/qcow2.c | 6 ++++++
13
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 6 insertions(+)
14
13
15
diff --git a/block/qcow2.c b/block/qcow2.c
14
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
16
--- a/block/qcow2.c
18
+++ b/block/qcow2.c
17
+++ b/block/qcow2.c
19
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
18
@@ -XXX,XX +XXX,XX @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
20
19
21
if (bs->encrypted) {
20
if (open_data_file) {
22
/* Encryption works on a sector granularity */
21
/* Open external data file */
23
- bs->bl.request_alignment = BDRV_SECTOR_SIZE;
22
+ bdrv_graph_co_rdunlock();
24
+ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
23
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,
24
&child_of_bds, BDRV_CHILD_DATA,
25
true, errp);
26
+ bdrv_graph_co_rdlock();
27
if (*errp) {
28
ret = -EINVAL;
29
goto fail;
30
@@ -XXX,XX +XXX,XX @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
31
32
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
33
if (!s->data_file && s->image_data_file) {
34
+ bdrv_graph_co_rdunlock();
35
s->data_file = bdrv_co_open_child(s->image_data_file, options,
36
"data-file", bs,
37
&child_of_bds,
38
BDRV_CHILD_DATA, false, errp);
39
+ bdrv_graph_co_rdlock();
40
if (!s->data_file) {
41
ret = -EINVAL;
42
goto fail;
43
@@ -XXX,XX +XXX,XX @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
44
fail:
45
g_free(s->image_data_file);
46
if (open_data_file && has_data_file(bs)) {
47
+ bdrv_graph_co_rdunlock();
48
bdrv_unref_child(bs, s->data_file);
49
+ bdrv_graph_co_rdlock();
50
s->data_file = NULL;
25
}
51
}
26
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
52
g_free(s->unknown_header_fields);
27
bs->bl.pdiscard_alignment = s->cluster_size;
28
--
53
--
29
2.19.1
54
2.40.1
30
31
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
If we take a reader lock, we can't call any functions that take a writer
2
lock internally without causing deadlocks once the reader lock is
3
actually enforced in the main thread, too. Take the reader lock only
4
where it is actually needed.
2
5
3
This adds some whitespace into the option help (including indentation)
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
and puts angle brackets around the type names. Furthermore, the list
7
Message-Id: <20230510203601.418015-5-kwolf@redhat.com>
5
name is no longer printed as part of every line, but only once in
8
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
10
---
24
include/qemu/option.h | 2 +-
11
qemu-img.c | 5 +++--
25
qemu-img.c | 4 +-
12
1 file changed, 3 insertions(+), 2 deletions(-)
26
util/qemu-option.c | 32 +-
27
tests/qemu-iotests/082.out | 956 ++++++++++++++++++-------------------
28
4 files changed, 507 insertions(+), 487 deletions(-)
29
13
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
14
diff --git a/qemu-img.c b/qemu-img.c
44
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
45
--- a/qemu-img.c
16
--- a/qemu-img.c
46
+++ b/qemu-img.c
17
+++ b/qemu-img.c
47
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
18
@@ -XXX,XX +XXX,XX @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
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
}
19
}
101
g_ptr_array_add(array, g_string_free(str, false));
20
bs = blk_bs(blk);
102
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
21
103
}
22
- GRAPH_RDLOCK_GUARD_MAINLOOP();
104
23
-
105
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
24
/*
106
+ if (print_caption && array->len > 0) {
25
* Note that the returned BlockGraphInfo object will not have
107
+ if (list->name) {
26
* information about this image's backing node, because we have opened
108
+ printf("%s options:\n", list->name);
27
@@ -XXX,XX +XXX,XX @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
109
+ } else {
28
* duplicate the backing chain information that we obtain by walking
110
+ printf("Options:\n");
29
* the chain manually here.
111
+ }
30
*/
112
+ } else if (array->len == 0) {
31
+ bdrv_graph_rdlock_main_loop();
113
+ if (list->name) {
32
bdrv_query_block_graph_info(bs, &info, &err);
114
+ printf("There are no options for %s.\n", list->name);
33
+ bdrv_graph_rdunlock_main_loop();
115
+ } else {
34
+
116
+ printf("No options available.\n");
35
if (err) {
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);
36
error_report_err(err);
131
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
37
blk_unref(blk);
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
--
38
--
1222
2.19.1
39
2.40.1
1223
1224
diff view generated by jsdifflib
1
From: Stefan Weil <sw@weilnetz.de>
1
If we take a reader lock, we can't call any functions that take a writer
2
lock internally without causing deadlocks once the reader lock is
3
actually enforced in the main thread, too. Take the reader lock only
4
where it is actually needed.
2
5
3
Use %zu instead of %zd for unsigned numbers.
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
7
Message-Id: <20230510203601.418015-6-kwolf@redhat.com>
5
This fixes two error messages from the LSTM static code analyzer:
8
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
10
---
13
qemu-io-cmds.c | 4 ++--
11
tests/unit/test-bdrv-drain.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 2 insertions(+), 2 deletions(-)
15
13
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
14
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/qemu-io-cmds.c
16
--- a/tests/unit/test-bdrv-drain.c
19
+++ b/qemu-io-cmds.c
17
+++ b/tests/unit/test-bdrv-drain.c
20
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
18
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
21
memset(cmp_buf, pattern, qiov.size);
19
void *buffer = g_malloc(65536);
22
if (memcmp(buf, cmp_buf, qiov.size)) {
20
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buffer, 65536);
23
printf("Pattern verification failed at offset %"
21
24
- PRId64 ", %zd bytes\n", offset, qiov.size);
22
- GRAPH_RDLOCK_GUARD();
25
+ PRId64 ", %zu bytes\n", offset, qiov.size);
23
-
26
ret = -EINVAL;
24
/* Pretend some internal write operation from parent to child.
27
}
25
* Important: We have to read from the child, not from the parent!
28
g_free(cmp_buf);
26
* Draining works by first propagating it all up the tree to the
29
@@ -XXX,XX +XXX,XX @@ static void aio_read_done(void *opaque, int ret)
27
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
30
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
28
* everything will be drained before we go back down the tree, but
31
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
29
* we do not want that. We want to be in the middle of draining
32
printf("Pattern verification failed at offset %"
30
* when this following requests returns. */
33
- PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
31
+ bdrv_graph_co_rdlock();
34
+ PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
32
bdrv_co_preadv(tts->wait_child, 0, 65536, &qiov, 0);
35
}
33
+ bdrv_graph_co_rdunlock();
36
g_free(cmp_buf);
34
37
}
35
g_assert_cmpint(bs->refcnt, ==, 1);
36
38
--
37
--
39
2.19.1
38
2.40.1
40
41
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
bdrv_unref() is a no_coroutine_fn, so calling it from coroutine context
2
is invalid. Use bdrv_co_unref() instead.
2
3
3
There is no good reason why there should be a newline in this
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
description, so remove it.
5
Message-Id: <20230510203601.418015-7-kwolf@redhat.com>
5
6
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
8
---
11
vl.c | 2 +-
9
tests/unit/test-bdrv-drain.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
13
11
14
diff --git a/vl.c b/vl.c
12
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/vl.c
14
--- a/tests/unit/test-bdrv-drain.c
17
+++ b/vl.c
15
+++ b/tests/unit/test-bdrv-drain.c
18
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_fw_cfg_opts = {
16
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
19
}, {
17
g_assert_cmpint(bs->refcnt, ==, 1);
20
.name = "file",
18
21
.type = QEMU_OPT_STRING,
19
if (!dbdd->detach_instead_of_delete) {
22
- .help = "Sets the name of the file from which\n"
20
- blk_unref(blk);
23
+ .help = "Sets the name of the file from which "
21
+ blk_co_unref(blk);
24
"the fw_cfg blob will be loaded",
22
} else {
25
}, {
23
BdrvChild *c, *next_c;
26
.name = "string",
24
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
27
--
25
--
28
2.19.1
26
2.40.1
29
30
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
When jobs are sleeping, for example to enforce a given rate limit, they
2
2
can be reentered early, in particular in order to get paused, to update
3
Just like in qemu_opts_print_help(), print the object name as a caption
3
the rate limit or to get cancelled.
4
instead of on every single line, indent all options, add angle brackets
4
5
around types, and align the descriptions after 24 characters.
5
Before this patch, they behave in this case as if they had fully
6
6
completed their rate limiting delay. This means that requests are sped
7
Also, indent every object name in the list of available objects.
7
up beyond their limit, violating the constraints that the user gave us.
8
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Change the block jobs to sleep in a loop until the necessary delay is
10
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
10
completed, while still allowing cancelling them immediately as well
11
pausing (handled by the pause point in job_sleep_ns()) and updating the
12
rate limit.
13
14
This change is also motivated by iotests cases being prone to fail
15
because drain operations pause and unpause them so often that block jobs
16
complete earlier than they are supposed to. In particular, the next
17
commit would fail iotests 030 without this change.
18
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Message-Id: <20230510203601.418015-8-kwolf@redhat.com>
21
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
23
---
13
vl.c | 13 ++++++++++---
24
include/block/blockjob_int.h | 14 ++++++++++----
14
1 file changed, 10 insertions(+), 3 deletions(-)
25
block/commit.c | 7 ++-----
15
26
block/mirror.c | 23 ++++++++++-------------
16
diff --git a/vl.c b/vl.c
27
block/stream.c | 7 ++-----
17
index XXXXXXX..XXXXXXX 100644
28
blockjob.c | 22 ++++++++++++++++++++--
18
--- a/vl.c
29
5 files changed, 44 insertions(+), 29 deletions(-)
19
+++ b/vl.c
30
20
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
31
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
21
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
32
index XXXXXXX..XXXXXXX 100644
22
for (l = list; l != NULL; l = l->next) {
33
--- a/include/block/blockjob_int.h
23
ObjectClass *oc = OBJECT_CLASS(l->data);
34
+++ b/include/block/blockjob_int.h
24
- printf("%s\n", object_class_get_name(oc));
35
@@ -XXX,XX +XXX,XX @@ void block_job_user_resume(Job *job);
25
+ printf(" %s\n", object_class_get_name(oc));
36
*/
26
}
37
27
g_slist_free(list);
38
/**
28
exit(0);
39
- * block_job_ratelimit_get_delay:
29
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
40
+ * block_job_ratelimit_processed_bytes:
41
*
42
- * Calculate and return delay for the next request in ns. See the documentation
43
- * of ratelimit_calculate_delay() for details.
44
+ * To be called after some work has been done. Adjusts the delay for the next
45
+ * request. See the documentation of ratelimit_calculate_delay() for details.
46
*/
47
-int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n);
48
+void block_job_ratelimit_processed_bytes(BlockJob *job, uint64_t n);
49
+
50
+/**
51
+ * Put the job to sleep (assuming that it wasn't canceled) to throttle it to the
52
+ * right speed according to its rate limiting.
53
+ */
54
+void block_job_ratelimit_sleep(BlockJob *job);
55
56
/**
57
* block_job_error_action:
58
diff --git a/block/commit.c b/block/commit.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/block/commit.c
61
+++ b/block/commit.c
62
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
63
{
64
CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
65
int64_t offset;
66
- uint64_t delay_ns = 0;
67
int ret = 0;
68
int64_t n = 0; /* bytes */
69
QEMU_AUTO_VFREE void *buf = NULL;
70
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
71
/* Note that even when no rate limit is applied we need to yield
72
* with no pending I/O here so that bdrv_drain_all() returns.
73
*/
74
- job_sleep_ns(&s->common.job, delay_ns);
75
+ block_job_ratelimit_sleep(&s->common);
76
if (job_is_cancelled(&s->common.job)) {
77
break;
78
}
79
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
80
job_progress_update(&s->common.job, n);
81
82
if (copy) {
83
- delay_ns = block_job_ratelimit_get_delay(&s->common, n);
84
- } else {
85
- delay_ns = 0;
86
+ block_job_ratelimit_processed_bytes(&s->common, n);
87
}
88
}
89
90
diff --git a/block/mirror.c b/block/mirror.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/block/mirror.c
93
+++ b/block/mirror.c
94
@@ -XXX,XX +XXX,XX @@ static unsigned mirror_perform(MirrorBlockJob *s, int64_t offset,
95
return bytes_handled;
96
}
97
98
-static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
99
+static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
100
{
101
BlockDriverState *source = s->mirror_top_bs->backing->bs;
102
MirrorOp *pseudo_op;
103
int64_t offset;
104
- uint64_t delay_ns = 0, ret = 0;
105
/* At least the first dirty chunk is mirrored in one iteration. */
106
int nb_chunks = 1;
107
bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target));
108
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
109
assert(io_bytes);
110
offset += io_bytes;
111
nb_chunks -= DIV_ROUND_UP(io_bytes, s->granularity);
112
- delay_ns = block_job_ratelimit_get_delay(&s->common, io_bytes_acct);
113
+ block_job_ratelimit_processed_bytes(&s->common, io_bytes_acct);
114
}
115
116
- ret = delay_ns;
117
fail:
118
QTAILQ_REMOVE(&s->ops_in_flight, pseudo_op, next);
119
qemu_co_queue_restart_all(&pseudo_op->waiting_requests);
120
g_free(pseudo_op);
121
-
122
- return ret;
123
}
124
125
static void mirror_free_init(MirrorBlockJob *s)
126
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
127
assert(!s->dbi);
128
s->dbi = bdrv_dirty_iter_new(s->dirty_bitmap);
129
for (;;) {
130
- uint64_t delay_ns = 0;
131
int64_t cnt, delta;
132
bool should_complete;
133
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
135
mirror_wait_for_free_in_flight_slot(s);
136
continue;
137
} else if (cnt != 0) {
138
- delay_ns = mirror_iteration(s);
139
+ mirror_iteration(s);
30
}
140
}
31
141
}
32
str = g_string_new(NULL);
142
33
- g_string_append_printf(str, "%s.%s=%s", type,
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
34
- prop->name, prop->type);
144
}
35
+ g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
145
36
if (prop->description) {
146
if (job_is_ready(&s->common.job) && !should_complete) {
37
+ if (str->len < 24) {
147
- delay_ns = (s->in_flight == 0 &&
38
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
148
- cnt == 0 ? BLOCK_JOB_SLICE_TIME : 0);
39
+ }
149
+ if (s->in_flight == 0 && cnt == 0) {
40
g_string_append_printf(str, " - %s", prop->description);
150
+ trace_mirror_before_sleep(s, cnt, job_is_ready(&s->common.job),
41
}
151
+ BLOCK_JOB_SLICE_TIME);
42
g_ptr_array_add(array, g_string_free(str, false));
152
+ job_sleep_ns(&s->common.job, BLOCK_JOB_SLICE_TIME);
43
}
153
+ }
44
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
45
+ if (array->len > 0) {
46
+ printf("%s options:\n", type);
47
+ } else {
154
+ } else {
48
+ printf("There are no options for %s.\n", type);
155
+ block_job_ratelimit_sleep(&s->common);
49
+ }
156
}
50
for (i = 0; i < array->len; i++) {
157
- trace_mirror_before_sleep(s, cnt, job_is_ready(&s->common.job),
51
printf("%s\n", (char *)array->pdata[i]);
158
- delay_ns);
52
}
159
- job_sleep_ns(&s->common.job, delay_ns);
160
s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
161
}
162
163
diff --git a/block/stream.c b/block/stream.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/block/stream.c
166
+++ b/block/stream.c
167
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
168
BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs);
169
int64_t len;
170
int64_t offset = 0;
171
- uint64_t delay_ns = 0;
172
int error = 0;
173
int64_t n = 0; /* bytes */
174
175
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
176
/* Note that even when no rate limit is applied we need to yield
177
* with no pending I/O here so that bdrv_drain_all() returns.
178
*/
179
- job_sleep_ns(&s->common.job, delay_ns);
180
+ block_job_ratelimit_sleep(&s->common);
181
if (job_is_cancelled(&s->common.job)) {
182
break;
183
}
184
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
185
/* Publish progress */
186
job_progress_update(&s->common.job, n);
187
if (copy) {
188
- delay_ns = block_job_ratelimit_get_delay(&s->common, n);
189
- } else {
190
- delay_ns = 0;
191
+ block_job_ratelimit_processed_bytes(&s->common, n);
192
}
193
}
194
195
diff --git a/blockjob.c b/blockjob.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/blockjob.c
198
+++ b/blockjob.c
199
@@ -XXX,XX +XXX,XX @@ static bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
200
return block_job_set_speed_locked(job, speed, errp);
201
}
202
203
-int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
204
+void block_job_ratelimit_processed_bytes(BlockJob *job, uint64_t n)
205
{
206
IO_CODE();
207
- return ratelimit_calculate_delay(&job->limit, n);
208
+ ratelimit_calculate_delay(&job->limit, n);
209
+}
210
+
211
+void block_job_ratelimit_sleep(BlockJob *job)
212
+{
213
+ uint64_t delay_ns;
214
+
215
+ /*
216
+ * Sleep at least once. If the job is reentered early, keep waiting until
217
+ * we've waited for the full time that is necessary to keep the job at the
218
+ * right speed.
219
+ *
220
+ * Make sure to recalculate the delay after each (possibly interrupted)
221
+ * sleep because the speed can change while the job has yielded.
222
+ */
223
+ do {
224
+ delay_ns = ratelimit_calculate_delay(&job->limit, 0);
225
+ job_sleep_ns(&job->job, delay_ns);
226
+ } while (delay_ns && !job_is_cancelled(&job->job));
227
}
228
229
BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
53
--
230
--
54
2.19.1
231
2.40.1
55
56
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
There are some conditions under which we don't actually need to do
2
anything for taking a reader lock: Writing the graph is only possible
3
from the main context while holding the BQL. So if a reader is running
4
in the main context under the BQL and knows that it won't be interrupted
5
until the next writer runs, we don't actually need to do anything.
2
6
3
Taking the address of a field in a packed struct is a bad idea, because
7
This is the case if the reader code neither has a nested event loop
4
it might not be actually aligned enough for that pointer type (and
8
(this is forbidden anyway while you hold the lock) nor is a coroutine
5
thus cause a crash on dereference on some host architectures). Newer
9
(because a writer could run when the coroutine has yielded).
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
10
9
There are a few places where the in-place swap function is
11
These conditions are exactly what bdrv_graph_rdlock_main_loop() asserts.
10
used on something other than a packed struct field; we convert
12
They are not fulfilled in bdrv_graph_co_rdlock(), which always runs in a
11
those anyway, for consistency.
13
coroutine.
12
14
13
This patch was produced with the following spatch script
15
This deletes the shortcuts in bdrv_graph_co_rdlock() that skip taking
14
(and hand-editing to fold a few resulting overlength lines):
16
the reader lock in the main thread.
15
17
16
@@
18
Reported-by: Fiona Ebner <f.ebner@proxmox.com>
17
expression E;
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
@@
20
Message-Id: <20230510203601.418015-9-kwolf@redhat.com>
19
-be16_to_cpus(&E);
21
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
52
---
23
---
53
block/qcow2.c | 64 +++++++++++++++++++++++++++------------------------
24
block/graph-lock.c | 10 ----------
54
1 file changed, 34 insertions(+), 30 deletions(-)
25
1 file changed, 10 deletions(-)
55
26
56
diff --git a/block/qcow2.c b/block/qcow2.c
27
diff --git a/block/graph-lock.c b/block/graph-lock.c
57
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
58
--- a/block/qcow2.c
29
--- a/block/graph-lock.c
59
+++ b/block/qcow2.c
30
+++ b/block/graph-lock.c
60
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
31
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_graph_co_rdlock(void)
61
"pread fail from offset %" PRIu64, offset);
32
BdrvGraphRWlock *bdrv_graph;
62
return 1;
33
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
63
}
34
64
- be32_to_cpus(&ext.magic);
35
- /* Do not lock if in main thread */
65
- be32_to_cpus(&ext.len);
36
- if (qemu_in_main_thread()) {
66
+ ext.magic = be32_to_cpu(ext.magic);
37
- return;
67
+ ext.len = be32_to_cpu(ext.len);
38
- }
68
offset += sizeof(ext);
39
-
69
#ifdef DEBUG_EXT
40
for (;;) {
70
printf("ext.magic = 0x%x\n", ext.magic);
41
qatomic_set(&bdrv_graph->reader_count,
71
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
42
bdrv_graph->reader_count + 1);
72
"Unable to read CRYPTO header extension");
43
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_graph_co_rdunlock(void)
73
return ret;
44
BdrvGraphRWlock *bdrv_graph;
74
}
45
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
75
- be64_to_cpus(&s->crypto_header.offset);
46
76
- be64_to_cpus(&s->crypto_header.length);
47
- /* Do not lock if in main thread */
77
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
48
- if (qemu_in_main_thread()) {
78
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
49
- return;
79
50
- }
80
if ((s->crypto_header.offset % s->cluster_size) != 0) {
51
-
81
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
52
qatomic_store_release(&bdrv_graph->reader_count,
82
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
53
bdrv_graph->reader_count - 1);
83
return -EINVAL;
54
/* make sure writer sees reader_count before we check has_writer */
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
--
55
--
177
2.19.1
56
2.40.1
178
179
diff view generated by jsdifflib
Deleted patch
1
From: Peter Maydell <peter.maydell@linaro.org>
2
1
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
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>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
---
52
block/qcow.c | 18 +++++++++---------
53
1 file changed, 9 insertions(+), 9 deletions(-)
54
55
diff --git a/block/qcow.c b/block/qcow.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qcow.c
58
+++ b/block/qcow.c
59
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
60
if (ret < 0) {
61
goto fail;
62
}
63
- be32_to_cpus(&header.magic);
64
- be32_to_cpus(&header.version);
65
- be64_to_cpus(&header.backing_file_offset);
66
- be32_to_cpus(&header.backing_file_size);
67
- be32_to_cpus(&header.mtime);
68
- be64_to_cpus(&header.size);
69
- be32_to_cpus(&header.crypt_method);
70
- be64_to_cpus(&header.l1_table_offset);
71
+ header.magic = be32_to_cpu(header.magic);
72
+ header.version = be32_to_cpu(header.version);
73
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
74
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
75
+ header.mtime = be32_to_cpu(header.mtime);
76
+ header.size = be64_to_cpu(header.size);
77
+ header.crypt_method = be32_to_cpu(header.crypt_method);
78
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
79
80
if (header.magic != QCOW_MAGIC) {
81
error_setg(errp, "Image not in qcow format");
82
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
83
}
84
85
for(i = 0;i < s->l1_size; i++) {
86
- be64_to_cpus(&s->l1_table[i]);
87
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
88
}
89
90
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
91
--
92
2.19.1
93
94
diff view generated by jsdifflib
1
From: Cleber Rosa <crosa@redhat.com>
1
Skip TestBlockdevReopen.test_insert_compress_filter() if the 'compress'
2
driver isn't available.
2
3
3
While testing the Python 3 changes which touch the 083 test, I noticed
4
In order to make the test succeed when the case is skipped, we also need
4
that it would fail with qcow2. Expanding the testing, I noticed it
5
to remove any output from it (which would be missing in the case where
5
had nothing to do with the Python 3 changes, and in fact, it would not
6
we skip it). This is done by replacing qemu_io_log() with qemu_io(). In
6
pass on anything but raw:
7
case of failure, qemu_io() raises an exception with the output of the
8
qemu-io binary in its message, so we don't actually lose anything.
7
9
8
raw: pass
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
bochs: not generic
11
Message-Id: <20230511143801.255021-1-kwolf@redhat.com>
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>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
41
---
13
---
42
tests/qemu-iotests/083 | 2 +-
14
tests/qemu-iotests/245 | 7 ++++---
43
1 file changed, 1 insertion(+), 1 deletion(-)
15
tests/qemu-iotests/245.out | 9 +--------
16
2 files changed, 5 insertions(+), 11 deletions(-)
44
17
45
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
18
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
46
index XXXXXXX..XXXXXXX 100755
19
index XXXXXXX..XXXXXXX 100755
47
--- a/tests/qemu-iotests/083
20
--- a/tests/qemu-iotests/245
48
+++ b/tests/qemu-iotests/083
21
+++ b/tests/qemu-iotests/245
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
22
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
50
. ./common.rc
23
self.reopen(hd0_opts, {'file': 'hd0-file'})
51
. ./common.filter
24
52
25
# Insert (and remove) a compress filter
53
-_supported_fmt generic
26
+ @iotests.skip_if_unsupported(['compress'])
54
+_supported_fmt raw
27
def test_insert_compress_filter(self):
55
_supported_proto nbd
28
# Add an image to the VM: hd (raw) -> hd0 (qcow2) -> hd0-file (file)
56
_supported_os Linux
29
opts = {'driver': 'raw', 'node-name': 'hd', 'file': hd_opts(0)}
30
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
31
32
# Check the first byte of the first three L2 entries and verify that
33
# the second one is compressed (0x40) while the others are not (0x80)
34
- iotests.qemu_io_log('-f', 'raw', '-c', 'read -P 0x80 0x40000 1',
35
- '-c', 'read -P 0x40 0x40008 1',
36
- '-c', 'read -P 0x80 0x40010 1', hd_path[0])
37
+ iotests.qemu_io('-f', 'raw', '-c', 'read -P 0x80 0x40000 1',
38
+ '-c', 'read -P 0x40 0x40008 1',
39
+ '-c', 'read -P 0x80 0x40010 1', hd_path[0])
40
41
# Swap the disk images of two active block devices
42
def test_swap_files(self):
43
diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
44
index XXXXXXX..XXXXXXX 100644
45
--- a/tests/qemu-iotests/245.out
46
+++ b/tests/qemu-iotests/245.out
47
@@ -XXX,XX +XXX,XX @@
48
{"return": {}}
49
{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
50
{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
51
-....read 1/1 bytes at offset 262144
52
-1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
53
-read 1/1 bytes at offset 262152
54
-1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
55
-read 1/1 bytes at offset 262160
56
-1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
57
-
58
-................
59
+....................
60
----------------------------------------------------------------------
61
Ran 26 tests
57
62
58
--
63
--
59
2.19.1
64
2.40.1
60
61
diff view generated by jsdifflib
1
From: Daniel P. Berrangé <berrange@redhat.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
The qcow2 block driver expects to see a valid sector size even when it
3
QEMU's event loop supports nesting, which means that event handler
4
has opened the crypto layer with QCRYPTO_BLOCK_OPEN_NO_IO.
4
functions may themselves call aio_poll(). The condition that triggered a
5
handler must be reset before the nested aio_poll() call, otherwise the
6
same handler will be called and immediately re-enter aio_poll. This
7
leads to an infinite loop and stack exhaustion.
5
8
6
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
9
Poll handlers are especially prone to this issue, because they typically
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
reset their condition by finishing the processing of pending work.
11
Unfortunately it is during the processing of pending work that nested
12
aio_poll() calls typically occur and the condition has not yet been
13
reset.
14
15
Disable a poll handler during ->io_poll_ready() so that a nested
16
aio_poll() call cannot invoke ->io_poll_ready() again. As a result, the
17
disabled poll handler and its associated fd handler do not run during
18
the nested aio_poll(). Calling aio_set_fd_handler() from inside nested
19
aio_poll() could cause it to run again. If the fd handler is pending
20
inside nested aio_poll(), then it will also run again.
21
22
In theory fd handlers can be affected by the same issue, but they are
23
more likely to reset the condition before calling nested aio_poll().
24
25
This is a special case and it's somewhat complex, but I don't see a way
26
around it as long as nested aio_poll() is supported.
27
28
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2186181
29
Fixes: c38270692593 ("block: Mark bdrv_co_io_(un)plug() and callers GRAPH_RDLOCK")
30
Cc: Kevin Wolf <kwolf@redhat.com>
31
Cc: Emanuele Giuseppe Esposito <eesposit@redhat.com>
32
Cc: Paolo Bonzini <pbonzini@redhat.com>
33
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
34
Message-Id: <20230502184134.534703-2-stefanha@redhat.com>
35
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
36
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
37
---
10
crypto/block-qcow.c | 2 ++
38
util/aio-posix.c | 11 +++++++++++
11
1 file changed, 2 insertions(+)
39
1 file changed, 11 insertions(+)
12
40
13
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
41
diff --git a/util/aio-posix.c b/util/aio-posix.c
14
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
15
--- a/crypto/block-qcow.c
43
--- a/util/aio-posix.c
16
+++ b/crypto/block-qcow.c
44
+++ b/util/aio-posix.c
17
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
45
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handler(AioContext *ctx, AioHandler *node)
18
Error **errp)
46
poll_ready && revents == 0 &&
19
{
47
aio_node_check(ctx, node->is_external) &&
20
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
48
node->io_poll_ready) {
21
+ block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
49
+ /*
22
+ block->payload_offset = 0;
50
+ * Remove temporarily to avoid infinite loops when ->io_poll_ready()
23
return 0;
51
+ * calls aio_poll() before clearing the condition that made the poll
24
} else {
52
+ * handler become ready.
25
if (!options->u.qcow.key_secret) {
53
+ */
54
+ QLIST_SAFE_REMOVE(node, node_poll);
55
+
56
node->io_poll_ready(node->opaque);
57
58
+ if (!QLIST_IS_INSERTED(node, node_poll)) {
59
+ QLIST_INSERT_HEAD(&ctx->poll_aio_handlers, node, node_poll);
60
+ }
61
+
62
/*
63
* Return early since revents was zero. aio_notify() does not count as
64
* progress.
26
--
65
--
27
2.19.1
66
2.40.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Li Qiang <liq3ea@163.com>
2
1
3
Signed-off-by: Li Qiang <liq3ea@163.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
include/sysemu/block-backend.h | 6 +++---
8
block/block-backend.c | 8 ++++----
9
2 files changed, 7 insertions(+), 7 deletions(-)
10
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/sysemu/block-backend.h
14
+++ b/include/sysemu/block-backend.h
15
@@ -XXX,XX +XXX,XX @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
16
int error);
17
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
18
bool is_read, int error);
19
-int blk_is_read_only(BlockBackend *blk);
20
-int blk_is_sg(BlockBackend *blk);
21
-int blk_enable_write_cache(BlockBackend *blk);
22
+bool blk_is_read_only(BlockBackend *blk);
23
+bool blk_is_sg(BlockBackend *blk);
24
+bool blk_enable_write_cache(BlockBackend *blk);
25
void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
26
void blk_invalidate_cache(BlockBackend *blk, Error **errp);
27
bool blk_is_inserted(BlockBackend *blk);
28
diff --git a/block/block-backend.c b/block/block-backend.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/block-backend.c
31
+++ b/block/block-backend.c
32
@@ -XXX,XX +XXX,XX @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
33
}
34
}
35
36
-int blk_is_read_only(BlockBackend *blk)
37
+bool blk_is_read_only(BlockBackend *blk)
38
{
39
BlockDriverState *bs = blk_bs(blk);
40
41
@@ -XXX,XX +XXX,XX @@ int blk_is_read_only(BlockBackend *blk)
42
}
43
}
44
45
-int blk_is_sg(BlockBackend *blk)
46
+bool blk_is_sg(BlockBackend *blk)
47
{
48
BlockDriverState *bs = blk_bs(blk);
49
50
if (!bs) {
51
- return 0;
52
+ return false;
53
}
54
55
return bdrv_is_sg(bs);
56
}
57
58
-int blk_enable_write_cache(BlockBackend *blk)
59
+bool blk_enable_write_cache(BlockBackend *blk)
60
{
61
return blk->enable_write_cache;
62
}
63
--
64
2.19.1
65
66
diff view generated by jsdifflib
Deleted 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(+)
6
1
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
Deleted patch
1
From: Peter Maydell <peter.maydell@linaro.org>
2
1
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
Deleted patch
1
From: Peter Maydell <peter.maydell@linaro.org>
2
1
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
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
This is a static function with only one caller, so there's no need to
4
keep it. Inlining the code in quorum_compare() makes it much simpler.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reported-by: Markus Armbruster <armbru@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/quorum.c | 24 +++++-------------------
11
1 file changed, 5 insertions(+), 19 deletions(-)
12
13
diff --git a/block/quorum.c b/block/quorum.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/quorum.c
16
+++ b/block/quorum.c
17
@@ -XXX,XX +XXX,XX @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
18
return true;
19
}
20
21
-static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
22
- const char *fmt, ...)
23
-{
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);
33
-}
34
-
35
-static bool quorum_compare(QuorumAIOCB *acb,
36
- QEMUIOVector *a,
37
- QEMUIOVector *b)
38
+static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
39
{
40
BDRVQuorumState *s = acb->bs->opaque;
41
ssize_t offset;
42
@@ -XXX,XX +XXX,XX @@ static bool quorum_compare(QuorumAIOCB *acb,
43
if (s->is_blkverify) {
44
offset = qemu_iovec_compare(a, b);
45
if (offset != -1) {
46
- quorum_err(acb, "contents mismatch at offset %" PRIu64,
47
- acb->offset + offset);
48
+ fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
49
+ " contents mismatch at offset %" PRIu64 "\n",
50
+ acb->offset, acb->bytes, acb->offset + offset);
51
+ exit(1);
52
}
53
return true;
54
}
55
--
56
2.19.1
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
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
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
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
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
3
The blkverify mode of Quorum only works when the number of children is
4
exactly two, so any attempt to add a new one must return an error.
5
6
quorum_del_child() on the other hand doesn't need any additional check
7
because decreasing the number of children would make it go under the
8
vote threshold.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reported-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/quorum.c | 8 ++++++++
15
1 file changed, 8 insertions(+)
16
17
diff --git a/block/quorum.c b/block/quorum.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/quorum.c
20
+++ b/block/quorum.c
21
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
22
char indexstr[32];
23
int ret;
24
25
+ if (s->is_blkverify) {
26
+ error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
27
+ return;
28
+ }
29
+
30
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
31
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
32
s->next_child_index == UINT_MAX) {
33
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
34
return;
35
}
36
37
+ /* We know now that num_children > threshold, so blkverify must be false */
38
+ assert(!s->is_blkverify);
39
+
40
bdrv_drained_begin(bs);
41
42
/* We can safely remove this child now */
43
--
44
2.19.1
45
46
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Garcia <berto@igalia.com>
2
1
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
Deleted 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.
5
1
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
Deleted patch
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.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
block/nbd-client.c | 10 +++++-----
9
1 file changed, 5 insertions(+), 5 deletions(-)
10
11
diff --git a/block/nbd-client.c b/block/nbd-client.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/nbd-client.c
14
+++ b/block/nbd-client.c
15
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
16
logout("Failed to negotiate with the NBD server\n");
17
return ret;
18
}
19
- if (client->info.flags & NBD_FLAG_READ_ONLY &&
20
- !bdrv_is_read_only(bs)) {
21
- error_setg(errp,
22
- "request for write access conflicts with read-only export");
23
- return -EACCES;
24
+ if (client->info.flags & NBD_FLAG_READ_ONLY) {
25
+ ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
26
+ if (ret < 0) {
27
+ return ret;
28
+ }
29
}
30
if (client->info.flags & NBD_FLAG_SEND_FUA) {
31
bs->supported_write_flags = BDRV_REQ_FUA;
32
--
33
2.19.1
34
35
diff view generated by jsdifflib
Deleted 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.
4
1
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
Deleted patch
1
If read-only=off, but auto-read-only=on is given, just degrade to
2
read-only.
3
1
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
Deleted 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.
4
1
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
Deleted 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.
4
1
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
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
3
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
Message-Id: <20230502184134.534703-3-stefanha@redhat.com>
5
Tested-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
7
---
4
tests/qemu-iotests/232 | 147 +++++++++++++++++++++++++++++++++++++
8
tests/unit/test-nested-aio-poll.c | 130 ++++++++++++++++++++++++++++++
5
tests/qemu-iotests/232.out | 59 +++++++++++++++
9
tests/unit/meson.build | 1 +
6
tests/qemu-iotests/group | 1 +
10
2 files changed, 131 insertions(+)
7
3 files changed, 207 insertions(+)
11
create mode 100644 tests/unit/test-nested-aio-poll.c
8
create mode 100755 tests/qemu-iotests/232
9
create mode 100644 tests/qemu-iotests/232.out
10
12
11
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
13
diff --git a/tests/unit/test-nested-aio-poll.c b/tests/unit/test-nested-aio-poll.c
12
new file mode 100755
13
index XXXXXXX..XXXXXXX
14
--- /dev/null
15
+++ b/tests/qemu-iotests/232
16
@@ -XXX,XX +XXX,XX @@
17
+#!/bin/bash
18
+#
19
+# Test for auto-read-only
20
+#
21
+# Copyright (C) 2018 Red Hat, Inc.
22
+#
23
+# This program is free software; you can redistribute it and/or modify
24
+# it under the terms of the GNU General Public License as published by
25
+# the Free Software Foundation; either version 2 of the License, or
26
+# (at your option) any later version.
27
+#
28
+# This program is distributed in the hope that it will be useful,
29
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
30
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
+# GNU General Public License for more details.
32
+#
33
+# You should have received a copy of the GNU General Public License
34
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+#
36
+
37
+# creator
38
+owner=kwolf@redhat.com
39
+
40
+seq=`basename $0`
41
+echo "QA output created by $seq"
42
+
43
+here=`pwd`
44
+status=1    # failure is the default!
45
+
46
+_cleanup()
47
+{
48
+ _cleanup_test_img
49
+ rm -f $TEST_IMG.snap
50
+}
51
+trap "_cleanup; exit \$status" 0 1 2 3 15
52
+
53
+# get standard environment, filters and checks
54
+. ./common.rc
55
+. ./common.filter
56
+
57
+_supported_fmt generic
58
+_supported_proto file
59
+_supported_os Linux
60
+
61
+function do_run_qemu()
62
+{
63
+ echo Testing: "$@"
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 "$@"
72
+ echo
73
+}
74
+
75
+function run_qemu()
76
+{
77
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp |
78
+ _filter_generated_node_ids | _filter_imgfmt
79
+}
80
+
81
+function run_qemu_info_block()
82
+{
83
+ echo "info block -n" | run_qemu "$@" | grep -e "(file" -e "QEMU_PROG"
84
+}
85
+
86
+size=128M
87
+
88
+_make_test_img $size
89
+
90
+echo
91
+echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
92
+echo
93
+
94
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
95
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
96
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
97
+echo
98
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
99
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
100
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
101
+echo
102
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
103
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
104
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
105
+
106
+echo
107
+echo "=== -drive with read-only image: read-only/auto-read-only combinations ==="
108
+echo
109
+
110
+chmod a-w $TEST_IMG
111
+
112
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
113
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
114
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
115
+echo
116
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
117
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
118
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
119
+echo
120
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
121
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
122
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
123
+
124
+echo
125
+echo "=== -blockdev with read-write image: read-only/auto-read-only combinations ==="
126
+echo
127
+
128
+chmod a+w $TEST_IMG
129
+
130
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
131
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
132
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
133
+echo
134
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
135
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
136
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
137
+echo
138
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
139
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
140
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
141
+
142
+echo
143
+echo "=== -blockdev with read-only image: read-only/auto-read-only combinations ==="
144
+echo
145
+
146
+chmod a-w $TEST_IMG
147
+
148
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
149
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
150
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
151
+echo
152
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
153
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
154
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
155
+echo
156
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
157
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
158
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
159
+
160
+# success, all done
161
+echo "*** done"
162
+rm -f $seq.full
163
+status=0
164
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
165
new file mode 100644
14
new file mode 100644
166
index XXXXXXX..XXXXXXX
15
index XXXXXXX..XXXXXXX
167
--- /dev/null
16
--- /dev/null
168
+++ b/tests/qemu-iotests/232.out
17
+++ b/tests/unit/test-nested-aio-poll.c
169
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
170
+QA output created by 232
19
+/* SPDX-License-Identifier: GPL-2.0-or-later */
171
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
20
+/*
21
+ * Test that poll handlers are not re-entrant in nested aio_poll()
22
+ *
23
+ * Copyright Red Hat
24
+ *
25
+ * Poll handlers are usually level-triggered. That means they continue firing
26
+ * until the condition is reset (e.g. a virtqueue becomes empty). If a poll
27
+ * handler calls nested aio_poll() before the condition is reset, then infinite
28
+ * recursion occurs.
29
+ *
30
+ * aio_poll() is supposed to prevent this by disabling poll handlers in nested
31
+ * aio_poll() calls. This test case checks that this is indeed what happens.
32
+ */
33
+#include "qemu/osdep.h"
34
+#include "block/aio.h"
35
+#include "qapi/error.h"
172
+
36
+
173
+=== -drive with read-write image: read-only/auto-read-only combinations ===
37
+typedef struct {
38
+ AioContext *ctx;
174
+
39
+
175
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
40
+ /* This is the EventNotifier that drives the test */
176
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
41
+ EventNotifier poll_notifier;
177
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
178
+
42
+
179
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
43
+ /* This EventNotifier is only used to wake aio_poll() */
180
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
44
+ EventNotifier dummy_notifier;
181
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
182
+
45
+
183
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
46
+ bool nested;
184
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
47
+} TestData;
185
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
186
+
48
+
187
+=== -drive with read-only image: read-only/auto-read-only combinations ===
49
+static void io_read(EventNotifier *notifier)
50
+{
51
+ fprintf(stderr, "%s %p\n", __func__, notifier);
52
+ event_notifier_test_and_clear(notifier);
53
+}
188
+
54
+
189
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
55
+static bool io_poll_true(void *opaque)
190
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
56
+{
191
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
57
+ fprintf(stderr, "%s %p\n", __func__, opaque);
58
+ return true;
59
+}
192
+
60
+
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
61
+static bool io_poll_false(void *opaque)
194
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
62
+{
195
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
63
+ fprintf(stderr, "%s %p\n", __func__, opaque);
64
+ return false;
65
+}
196
+
66
+
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
67
+static void io_poll_ready(EventNotifier *notifier)
198
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
68
+{
199
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
69
+ TestData *td = container_of(notifier, TestData, poll_notifier);
200
+
70
+
201
+=== -blockdev with read-write image: read-only/auto-read-only combinations ===
71
+ fprintf(stderr, "> %s\n", __func__);
202
+
72
+
203
+node0: TEST_DIR/t.IMGFMT (file, read-only)
73
+ g_assert(!td->nested);
204
+node0: TEST_DIR/t.IMGFMT (file, read-only)
74
+ td->nested = true;
205
+node0: TEST_DIR/t.IMGFMT (file, read-only)
206
+
75
+
207
+node0: TEST_DIR/t.IMGFMT (file)
76
+ /* Wake the following nested aio_poll() call */
208
+node0: TEST_DIR/t.IMGFMT (file)
77
+ event_notifier_set(&td->dummy_notifier);
209
+node0: TEST_DIR/t.IMGFMT (file)
210
+
78
+
211
+node0: TEST_DIR/t.IMGFMT (file)
79
+ /* This nested event loop must not call io_poll()/io_poll_ready() */
212
+node0: TEST_DIR/t.IMGFMT (file)
80
+ g_assert(aio_poll(td->ctx, true));
213
+node0: TEST_DIR/t.IMGFMT (file)
214
+
81
+
215
+=== -blockdev with read-only image: read-only/auto-read-only combinations ===
82
+ td->nested = false;
216
+
83
+
217
+node0: TEST_DIR/t.IMGFMT (file, read-only)
84
+ fprintf(stderr, "< %s\n", __func__);
218
+node0: TEST_DIR/t.IMGFMT (file, read-only)
85
+}
219
+node0: TEST_DIR/t.IMGFMT (file, read-only)
220
+
86
+
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
87
+/* dummy_notifier never triggers */
222
+node0: TEST_DIR/t.IMGFMT (file, read-only)
88
+static void io_poll_never_ready(EventNotifier *notifier)
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
89
+{
90
+ g_assert_not_reached();
91
+}
224
+
92
+
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
93
+static void test(void)
226
+node0: TEST_DIR/t.IMGFMT (file, read-only)
94
+{
227
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
95
+ TestData td = {
228
+*** done
96
+ .ctx = aio_context_new(&error_abort),
229
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
97
+ };
98
+
99
+ qemu_set_current_aio_context(td.ctx);
100
+
101
+ /* Enable polling */
102
+ aio_context_set_poll_params(td.ctx, 1000000, 2, 2, &error_abort);
103
+
104
+ /*
105
+ * The GSource is unused but this has the side-effect of changing the fdmon
106
+ * that AioContext uses.
107
+ */
108
+ aio_get_g_source(td.ctx);
109
+
110
+ /* Make the event notifier active (set) right away */
111
+ event_notifier_init(&td.poll_notifier, 1);
112
+ aio_set_event_notifier(td.ctx, &td.poll_notifier, false,
113
+ io_read, io_poll_true, io_poll_ready);
114
+
115
+ /* This event notifier will be used later */
116
+ event_notifier_init(&td.dummy_notifier, 0);
117
+ aio_set_event_notifier(td.ctx, &td.dummy_notifier, false,
118
+ io_read, io_poll_false, io_poll_never_ready);
119
+
120
+ /* Consume aio_notify() */
121
+ g_assert(!aio_poll(td.ctx, false));
122
+
123
+ /*
124
+ * Run the io_read() handler. This has the side-effect of activating
125
+ * polling in future aio_poll() calls.
126
+ */
127
+ g_assert(aio_poll(td.ctx, true));
128
+
129
+ /* The second time around the io_poll()/io_poll_ready() handler runs */
130
+ g_assert(aio_poll(td.ctx, true));
131
+
132
+ /* Run io_poll()/io_poll_ready() one more time to show it keeps working */
133
+ g_assert(aio_poll(td.ctx, true));
134
+
135
+ aio_set_event_notifier(td.ctx, &td.dummy_notifier, false,
136
+ NULL, NULL, NULL);
137
+ aio_set_event_notifier(td.ctx, &td.poll_notifier, false, NULL, NULL, NULL);
138
+ event_notifier_cleanup(&td.dummy_notifier);
139
+ event_notifier_cleanup(&td.poll_notifier);
140
+ aio_context_unref(td.ctx);
141
+}
142
+
143
+int main(int argc, char **argv)
144
+{
145
+ g_test_init(&argc, &argv, NULL);
146
+ g_test_add_func("/nested-aio-poll", test);
147
+ return g_test_run();
148
+}
149
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
230
index XXXXXXX..XXXXXXX 100644
150
index XXXXXXX..XXXXXXX 100644
231
--- a/tests/qemu-iotests/group
151
--- a/tests/unit/meson.build
232
+++ b/tests/qemu-iotests/group
152
+++ b/tests/unit/meson.build
233
@@ -XXX,XX +XXX,XX @@
153
@@ -XXX,XX +XXX,XX @@ if have_block
234
227 auto quick
154
'test-coroutine': [testblock],
235
229 auto quick
155
'test-aio': [testblock],
236
231 auto quick
156
'test-aio-multithread': [testblock],
237
+232 auto quick
157
+ 'test-nested-aio-poll': [testblock],
158
'test-throttle': [testblock],
159
'test-thread-pool': [testblock],
160
'test-hbitmap': [testblock],
238
--
161
--
239
2.19.1
162
2.40.1
240
241
diff view generated by jsdifflib