1
The following changes since commit 718d7f4f9cf772e5784093d8e6085680a235acdb:
1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
2
2
3
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging (2017-07-18 13:09:51 +0100)
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
7
6
8
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
9
8
10
for you to fetch changes up to 6e6e55f5c2e5b520d6506c2716287ba3b5d1bbc8:
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
11
10
12
qemu-img: Check for backing image if specified during create (2017-07-18 15:27:37 +0200)
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
13
12
14
----------------------------------------------------------------
13
----------------------------------------------------------------
15
Block layer patches
14
Block layer patches:
15
16
- Fix resize (extending) of short overlays
17
- nvme: introduce PMR support from NVMe 1.4 spec
18
- qemu-storage-daemon: Fix non-string --object properties
16
19
17
----------------------------------------------------------------
20
----------------------------------------------------------------
18
Hervé Poussineau (4):
21
Alberto Garcia (1):
19
vvfat: add constants for special values of name[0]
22
qcow2: Add incompatibility note between backing files and raw external data files
20
vvfat: add a constant for bootsector name
21
vvfat: correctly parse non-ASCII short and long file names
22
vvfat: initialize memory after allocating it
23
23
24
John Snow (2):
24
Andrzej Jakowski (1):
25
blockdev: move BDRV_O_NO_BACKING option forward
25
nvme: introduce PMR support from NVMe 1.4 spec
26
qemu-img: Check for backing image if specified during create
27
26
28
Kevin Wolf (10):
27
Kevin Wolf (12):
29
commit: Add NULL check for overlay_bs
28
block: Add flags to BlockDriver.bdrv_co_truncate()
30
block: Make blk_get_attached_dev_id() public
29
block: Add flags to bdrv(_co)_truncate()
31
block/qapi: Add qdev device name to query-block
30
block-backend: Add flags to blk_truncate()
32
block: Make blk_all_next() public
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
33
block/qapi: Use blk_all_next() for query-block
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
34
block: List anonymous device BBs in query-block
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
35
ide: bdrv_attach_dev() for empty CD-ROM
34
block: truncate: Don't make backing file data visible
36
scsi-disk: bdrv_attach_dev() for empty CD-ROM
35
iotests: Filter testfiles out in filter_img_info()
37
qemu-iotests: Test 'info block'
36
iotests: Test committing to short backing file
38
qemu-iotests: Test unplug of -device without drive
37
qcow2: Forward ZERO_WRITE flag for full preallocation
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
39
40
40
Manos Pitsidianakis (2):
41
Paolo Bonzini (1):
41
block: add clock_type field to ThrottleGroup
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
42
block: remove timer canceling in throttle_config()
43
43
44
Max Reitz (1):
44
docs/interop/qcow2.txt | 3 +
45
block/vvfat: Fix compiler warning with gcc 7
45
hw/block/nvme.h | 2 +
46
include/block/block.h | 5 +-
47
include/block/block_int.h | 10 +-
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
49
include/qom/object_interfaces.h | 16 +++
50
include/sysemu/block-backend.h | 2 +-
51
block.c | 3 +-
52
block/block-backend.c | 4 +-
53
block/commit.c | 4 +-
54
block/crypto.c | 7 +-
55
block/file-posix.c | 6 +-
56
block/file-win32.c | 2 +-
57
block/gluster.c | 1 +
58
block/io.c | 43 ++++++-
59
block/iscsi.c | 2 +-
60
block/mirror.c | 2 +-
61
block/nfs.c | 3 +-
62
block/parallels.c | 6 +-
63
block/qcow.c | 4 +-
64
block/qcow2-cluster.c | 2 +-
65
block/qcow2-refcount.c | 2 +-
66
block/qcow2.c | 73 +++++++++--
67
block/qed.c | 3 +-
68
block/raw-format.c | 6 +-
69
block/rbd.c | 1 +
70
block/sheepdog.c | 4 +-
71
block/ssh.c | 2 +-
72
block/vdi.c | 2 +-
73
block/vhdx-log.c | 2 +-
74
block/vhdx.c | 6 +-
75
block/vmdk.c | 8 +-
76
block/vpc.c | 2 +-
77
blockdev.c | 2 +-
78
hw/block/nvme.c | 109 ++++++++++++++++
79
qemu-img.c | 2 +-
80
qemu-io-cmds.c | 2 +-
81
qemu-storage-daemon.c | 4 +-
82
qom/object_interfaces.c | 31 +++++
83
qom/qom-qmp-cmds.c | 24 +---
84
tests/test-block-iothread.c | 9 +-
85
tests/qemu-iotests/iotests.py | 5 +-
86
hw/block/Makefile.objs | 2 +-
87
hw/block/trace-events | 4 +
88
tests/qemu-iotests/244 | 10 +-
89
tests/qemu-iotests/244.out | 9 +-
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
92
tests/qemu-iotests/group | 1 +
93
49 files changed, 951 insertions(+), 96 deletions(-)
94
create mode 100755 tests/qemu-iotests/274
95
create mode 100644 tests/qemu-iotests/274.out
46
96
47
Peter Maydell (2):
48
block/vmdk: Report failures in vmdk_read_cid()
49
block/vpc.c: Handle write failures in get_image_offset()
50
97
51
block.c | 94 ++++----
52
block/block-backend.c | 5 +-
53
block/commit.c | 4 +-
54
block/qapi.c | 20 +-
55
block/throttle-groups.c | 28 +--
56
block/vmdk.c | 44 +++-
57
block/vpc.c | 30 ++-
58
block/vvfat.c | 90 +++++---
59
blockdev.c | 11 +-
60
fsdev/qemu-fsdev-throttle.c | 2 +-
61
hmp.c | 11 +-
62
hw/ide/qdev.c | 3 +
63
hw/scsi/scsi-disk.c | 5 +
64
include/qemu/throttle.h | 2 +-
65
include/sysemu/block-backend.h | 2 +
66
qapi/block-core.json | 9 +-
67
qemu-img-cmds.hx | 4 +-
68
qemu-img.c | 16 +-
69
qemu-img.texi | 9 +-
70
tests/qemu-iotests/067 | 13 ++
71
tests/qemu-iotests/067.out | 40 ++++
72
tests/qemu-iotests/082 | 4 +-
73
tests/qemu-iotests/082.out | 4 +-
74
tests/qemu-iotests/085 | 2 +-
75
tests/qemu-iotests/111.out | 1 +
76
tests/qemu-iotests/139 | 2 +-
77
tests/qemu-iotests/156 | 2 +-
78
tests/qemu-iotests/158 | 2 +-
79
tests/qemu-iotests/186 | 147 +++++++++++++
80
tests/qemu-iotests/186.out | 489 +++++++++++++++++++++++++++++++++++++++++
81
tests/qemu-iotests/189 | 2 +-
82
tests/qemu-iotests/group | 1 +
83
tests/test-throttle.c | 4 +-
84
util/throttle.c | 18 +-
85
34 files changed, 958 insertions(+), 162 deletions(-)
86
create mode 100755 tests/qemu-iotests/186
87
create mode 100644 tests/qemu-iotests/186.out
88
diff view generated by jsdifflib
Deleted patch
1
I can't see how overlay_bs could become NULL with the current code, but
2
other code in this function already checks it and we can make Coverity
3
happy with this check, so let's add it.
4
1
5
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
block/commit.c | 4 +++-
10
1 file changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/block/commit.c b/block/commit.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/commit.c
15
+++ b/block/commit.c
16
@@ -XXX,XX +XXX,XX @@ static void commit_complete(BlockJob *job, void *opaque)
17
18
/* Make sure overlay_bs and top stay around until bdrv_set_backing_hd() */
19
bdrv_ref(top);
20
- bdrv_ref(overlay_bs);
21
+ if (overlay_bs) {
22
+ bdrv_ref(overlay_bs);
23
+ }
24
25
/* Remove base node parent that still uses BLK_PERM_WRITE/RESIZE before
26
* the normal backing chain can be restored. */
27
--
28
1.8.3.1
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
2
1
3
Clock type in throttling is currently inferred by the ThrottleTimer's
4
clock type even though it is a per-ThrottleGroup property; it doesn't
5
make sense to have different clock types in the same group. Moving this
6
to a field in ThrottleGroup can simplify some of the throttle functions.
7
8
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/throttle-groups.c | 20 ++++++++++----------
13
fsdev/qemu-fsdev-throttle.c | 2 +-
14
include/qemu/throttle.h | 1 +
15
tests/test-throttle.c | 4 ++--
16
util/throttle.c | 4 +++-
17
5 files changed, 17 insertions(+), 14 deletions(-)
18
19
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/throttle-groups.c
22
+++ b/block/throttle-groups.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct ThrottleGroup {
24
QLIST_HEAD(, BlockBackendPublic) head;
25
BlockBackend *tokens[2];
26
bool any_timer_armed[2];
27
+ QEMUClockType clock_type;
28
29
/* These two are protected by the global throttle_groups_lock */
30
unsigned refcount;
31
@@ -XXX,XX +XXX,XX @@ ThrottleState *throttle_group_incref(const char *name)
32
if (!tg) {
33
tg = g_new0(ThrottleGroup, 1);
34
tg->name = g_strdup(name);
35
+ tg->clock_type = QEMU_CLOCK_REALTIME;
36
+
37
+ if (qtest_enabled()) {
38
+ /* For testing block IO throttling only */
39
+ tg->clock_type = QEMU_CLOCK_VIRTUAL;
40
+ }
41
qemu_mutex_init(&tg->lock);
42
throttle_init(&tg->ts);
43
QLIST_INIT(&tg->head);
44
@@ -XXX,XX +XXX,XX @@ static void schedule_next_request(BlockBackend *blk, bool is_write)
45
token = blk;
46
} else {
47
ThrottleTimers *tt = &blk_get_public(token)->throttle_timers;
48
- int64_t now = qemu_clock_get_ns(tt->clock_type);
49
+ int64_t now = qemu_clock_get_ns(tg->clock_type);
50
timer_mod(tt->timers[is_write], now);
51
tg->any_timer_armed[is_write] = true;
52
}
53
@@ -XXX,XX +XXX,XX @@ void throttle_group_config(BlockBackend *blk, ThrottleConfig *cfg)
54
if (timer_pending(tt->timers[1])) {
55
tg->any_timer_armed[1] = false;
56
}
57
- throttle_config(ts, tt, cfg);
58
+ throttle_config(ts, tg->clock_type, tt, cfg);
59
qemu_mutex_unlock(&tg->lock);
60
61
throttle_group_restart_blk(blk);
62
@@ -XXX,XX +XXX,XX @@ void throttle_group_register_blk(BlockBackend *blk, const char *groupname)
63
BlockBackendPublic *blkp = blk_get_public(blk);
64
ThrottleState *ts = throttle_group_incref(groupname);
65
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
66
- int clock_type = QEMU_CLOCK_REALTIME;
67
-
68
- if (qtest_enabled()) {
69
- /* For testing block IO throttling only */
70
- clock_type = QEMU_CLOCK_VIRTUAL;
71
- }
72
-
73
blkp->throttle_state = ts;
74
75
qemu_mutex_lock(&tg->lock);
76
@@ -XXX,XX +XXX,XX @@ void throttle_group_register_blk(BlockBackend *blk, const char *groupname)
77
78
throttle_timers_init(&blkp->throttle_timers,
79
blk_get_aio_context(blk),
80
- clock_type,
81
+ tg->clock_type,
82
read_timer_cb,
83
write_timer_cb,
84
blk);
85
diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/fsdev/qemu-fsdev-throttle.c
88
+++ b/fsdev/qemu-fsdev-throttle.c
89
@@ -XXX,XX +XXX,XX @@ void fsdev_throttle_init(FsThrottle *fst)
90
fsdev_throttle_read_timer_cb,
91
fsdev_throttle_write_timer_cb,
92
fst);
93
- throttle_config(&fst->ts, &fst->tt, &fst->cfg);
94
+ throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->tt, &fst->cfg);
95
qemu_co_queue_init(&fst->throttled_reqs[0]);
96
qemu_co_queue_init(&fst->throttled_reqs[1]);
97
}
98
diff --git a/include/qemu/throttle.h b/include/qemu/throttle.h
99
index XXXXXXX..XXXXXXX 100644
100
--- a/include/qemu/throttle.h
101
+++ b/include/qemu/throttle.h
102
@@ -XXX,XX +XXX,XX @@ bool throttle_enabled(ThrottleConfig *cfg);
103
bool throttle_is_valid(ThrottleConfig *cfg, Error **errp);
104
105
void throttle_config(ThrottleState *ts,
106
+ QEMUClockType clock_type,
107
ThrottleTimers *tt,
108
ThrottleConfig *cfg);
109
110
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/test-throttle.c
113
+++ b/tests/test-throttle.c
114
@@ -XXX,XX +XXX,XX @@ static void test_config_functions(void)
115
read_timer_cb, write_timer_cb, &ts);
116
/* structure reset by throttle_init previous_leak should be null */
117
g_assert(!ts.previous_leak);
118
- throttle_config(&ts, &tt, &orig_cfg);
119
+ throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &tt, &orig_cfg);
120
121
/* has previous leak been initialized by throttle_config ? */
122
g_assert(ts.previous_leak);
123
@@ -XXX,XX +XXX,XX @@ static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
124
throttle_init(&ts);
125
throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
126
read_timer_cb, write_timer_cb, &ts);
127
- throttle_config(&ts, &tt, &cfg);
128
+ throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &tt, &cfg);
129
130
/* account a read */
131
throttle_account(&ts, false, size);
132
diff --git a/util/throttle.c b/util/throttle.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/util/throttle.c
135
+++ b/util/throttle.c
136
@@ -XXX,XX +XXX,XX @@ static void throttle_cancel_timer(QEMUTimer *timer)
137
/* Used to configure the throttle
138
*
139
* @ts: the throttle state we are working on
140
+ * @clock_type: the group's clock_type
141
* @tt: the throttle timers we use in this aio context
142
* @cfg: the config to set
143
*/
144
void throttle_config(ThrottleState *ts,
145
+ QEMUClockType clock_type,
146
ThrottleTimers *tt,
147
ThrottleConfig *cfg)
148
{
149
@@ -XXX,XX +XXX,XX @@ void throttle_config(ThrottleState *ts,
150
throttle_fix_bucket(&ts->cfg.buckets[i]);
151
}
152
153
- ts->previous_leak = qemu_clock_get_ns(tt->clock_type);
154
+ ts->previous_leak = qemu_clock_get_ns(clock_type);
155
156
for (i = 0; i < 2; i++) {
157
throttle_cancel_timer(tt->timers[i]);
158
--
159
1.8.3.1
160
161
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
For both external_snapshot_prepare and qmp_drive_mirror, we eventually
3
Backing files and raw external data files are mutually exclusive.
4
append the option BDRV_O_NO_BACKING. However, we generally do so after
4
The documentation of the raw external data bit (in autoclear_features)
5
we create the image.
5
already indicates that, but we should also mention it on the other
6
side.
6
7
7
To accommodate image creation wanting to verify that a backing file
8
Suggested-by: Eric Blake <eblake@redhat.com>
8
exists or not, add this option prior to create to override checking
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
the existence of the backing file. This prevents QEMU from trying to
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
10
re-open a backing file that's already in use (thanks to qcow2 locking).
11
12
Signed-off-by: John Snow <jsnow@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
13
---
16
blockdev.c | 11 ++++++-----
14
docs/interop/qcow2.txt | 3 +++
17
1 file changed, 6 insertions(+), 5 deletions(-)
15
1 file changed, 3 insertions(+)
18
16
19
diff --git a/blockdev.c b/blockdev.c
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/blockdev.c
19
--- a/docs/interop/qcow2.txt
22
+++ b/blockdev.c
20
+++ b/docs/interop/qcow2.txt
23
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
24
}
22
is stored (NB: The string is not null terminated). 0 if the
25
23
image doesn't have a backing file.
26
flags = state->old_bs->open_flags;
24
27
- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
25
+ Note: backing files are incompatible with raw external data
28
+ flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_COPY_ON_READ);
26
+ files (auto-clear feature bit 1).
29
+ flags |= BDRV_O_NO_BACKING;
30
31
/* create new image w/backing file */
32
mode = s->has_mode ? s->mode : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
33
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
34
qdict_put_str(options, "node-name", snapshot_node_name);
35
}
36
qdict_put_str(options, "driver", format);
37
-
38
- flags |= BDRV_O_NO_BACKING;
39
}
40
41
state->new_bs = bdrv_open(new_image_file, snapshot_ref, options, flags,
42
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
43
backing_mode = MIRROR_OPEN_BACKING_CHAIN;
44
}
45
46
+ /* Don't open backing image in create() */
47
+ flags |= BDRV_O_NO_BACKING;
48
+
27
+
49
if ((arg->sync == MIRROR_SYNC_MODE_FULL || !source)
28
16 - 19: backing_file_size
50
&& arg->mode != NEW_IMAGE_MODE_EXISTING)
29
Length of the backing file name in bytes. Must not be
51
{
30
longer than 1023 bytes. Undefined if the image doesn't have
52
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
53
/* Mirroring takes care of copy-on-write using the source's backing
54
* file.
55
*/
56
- target_bs = bdrv_open(arg->target, NULL, options,
57
- flags | BDRV_O_NO_BACKING, errp);
58
+ target_bs = bdrv_open(arg->target, NULL, options, flags, errp);
59
if (!target_bs) {
60
goto out;
61
}
62
--
31
--
63
1.8.3.1
32
2.25.3
64
33
65
34
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
This prevents some host to guest memory content leaks.
3
Test 244 checks the expected behavior of qcow2 external data files
4
with respect to zero and discarded clusters. Filesystems however
5
are free to ignore discard requests, and this seems to be the
6
case for overlayfs. Relax the tests to skip checks on the
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
4
9
5
Fixes: https://bugs.launchpad.net/qemu/+bug/1599539
10
This fixes docker tests on RHEL8.
6
11
7
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
12
Cc: Kevin Wolf <kwolf@redhat.com>
13
Cc: qemu-block@nongnu.org
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
17
---
10
block/vvfat.c | 1 +
18
tests/qemu-iotests/244 | 10 ++++++++--
11
1 file changed, 1 insertion(+)
19
tests/qemu-iotests/244.out | 9 ++++++---
20
2 files changed, 14 insertions(+), 5 deletions(-)
12
21
13
diff --git a/block/vvfat.c b/block/vvfat.c
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/244
25
+++ b/tests/qemu-iotests/244
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
27
echo
28
$QEMU_IO -c 'read -P 0 0 1M' \
29
-c 'read -P 0x11 1M 1M' \
30
- -c 'read -P 0 2M 2M' \
31
-c 'read -P 0x11 4M 1M' \
32
-c 'read -P 0 5M 1M' \
33
-f raw "$TEST_IMG.data" |
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
35
-f $IMGFMT "$TEST_IMG" |
36
_filter_qemu_io
37
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
39
+# they can contain stale data in the external data file. Instead, zero
40
+# clusters must be zeroed in the external data file too.
41
echo
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
43
+$QEMU_IO -c 'read -P 0 0 1M' \
44
+ -c 'read -P 0x11 1M 1M' \
45
+ -c 'read -P 0 3M 3M' \
46
+ -f raw "$TEST_IMG".data |
47
+ _filter_qemu_io
48
49
echo -n "qcow2 file size after I/O: "
50
du -b $TEST_IMG | cut -f1
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
14
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
15
--- a/block/vvfat.c
53
--- a/tests/qemu-iotests/244.out
16
+++ b/block/vvfat.c
54
+++ b/tests/qemu-iotests/244.out
17
@@ -XXX,XX +XXX,XX @@ static inline int array_ensure_allocated(array_t* array, int index)
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
18
array->pointer = g_realloc(array->pointer, new_size);
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
19
if (!array->pointer)
57
read 1048576/1048576 bytes at offset 1048576
20
return -1;
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
21
+ memset(array->pointer + array->size, 0, new_size - array->size);
59
-read 2097152/2097152 bytes at offset 2097152
22
array->size = new_size;
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
23
array->next = index + 1;
61
read 1048576/1048576 bytes at offset 4194304
24
}
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
63
read 1048576/1048576 bytes at offset 5242880
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
65
read 4194304/4194304 bytes at offset 2097152
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
68
-Images are identical.
69
+read 1048576/1048576 bytes at offset 0
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
+read 1048576/1048576 bytes at offset 1048576
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+read 3145728/3145728 bytes at offset 3145728
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
qcow2 file size after I/O: 327680
76
77
=== bdrv_co_block_status test for file and offset=0 ===
25
--
78
--
26
1.8.3.1
79
2.25.3
27
80
28
81
diff view generated by jsdifflib
1
With -blockdev/-device, users can indirectly create anonymous
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
2
BlockBackends, while the state of such backends is still of interest. As
2
driver callbacks, and a supported_truncate_flags field in
3
a preparation for making such BBs visible in query-block, make sure that
3
BlockDriverState that allows drivers to advertise support for request
4
they can be identified even without a name by adding the ID/QOM path of
4
flags in the context of truncate.
5
their qdev device to BlockInfo.
5
6
For now, we always pass 0 and no drivers declare support for any flag.
6
7
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
14
---
10
block/qapi.c | 10 ++++++++++
15
include/block/block_int.h | 10 +++++++++-
11
hmp.c | 3 +++
16
block/crypto.c | 3 ++-
12
qapi/block-core.json | 9 ++++++++-
17
block/file-posix.c | 2 +-
13
tests/qemu-iotests/067.out | 1 +
18
block/file-win32.c | 2 +-
14
4 files changed, 22 insertions(+), 1 deletion(-)
19
block/gluster.c | 1 +
15
20
block/io.c | 8 +++++++-
16
diff --git a/block/qapi.c b/block/qapi.c
21
block/iscsi.c | 2 +-
17
index XXXXXXX..XXXXXXX 100644
22
block/nfs.c | 3 ++-
18
--- a/block/qapi.c
23
block/qcow2.c | 2 +-
19
+++ b/block/qapi.c
24
block/qed.c | 1 +
20
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
25
block/raw-format.c | 2 +-
21
{
26
block/rbd.c | 1 +
22
BlockInfo *info = g_malloc0(sizeof(*info));
27
block/sheepdog.c | 4 ++--
23
BlockDriverState *bs = blk_bs(blk);
28
block/ssh.c | 2 +-
24
+ char *qdev;
29
tests/test-block-iothread.c | 3 ++-
25
+
30
15 files changed, 33 insertions(+), 13 deletions(-)
26
info->device = g_strdup(blk_name(blk));
31
27
info->type = g_strdup("unknown");
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
28
info->locked = blk_dev_is_medium_locked(blk);
33
index XXXXXXX..XXXXXXX 100644
29
info->removable = blk_dev_has_removable_media(blk);
34
--- a/include/block/block_int.h
30
35
+++ b/include/block/block_int.h
31
+ qdev = blk_get_attached_dev_id(blk);
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
32
+ if (qdev && *qdev) {
37
*/
33
+ info->has_qdev = true;
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
34
+ info->qdev = qdev;
39
bool exact, PreallocMode prealloc,
35
+ } else {
40
- Error **errp);
36
+ g_free(qdev);
41
+ BdrvRequestFlags flags, Error **errp);
37
+ }
42
38
+
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
39
if (blk_dev_has_tray(blk)) {
44
bool has_variable_length;
40
info->has_tray_open = true;
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
41
info->tray_open = blk_dev_is_tray_open(blk);
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
42
diff --git a/hmp.c b/hmp.c
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
43
index XXXXXXX..XXXXXXX 100644
48
unsigned int supported_zero_flags;
44
--- a/hmp.c
49
+ /*
45
+++ b/hmp.c
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
46
@@ -XXX,XX +XXX,XX @@ static void print_block_info(Monitor *mon, BlockInfo *info,
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
63
+++ b/block/crypto.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
65
66
static int coroutine_fn
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
68
- PreallocMode prealloc, Error **errp)
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
70
+ Error **errp)
71
{
72
BlockCrypto *crypto = bs->opaque;
73
uint64_t payload_offset =
74
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
79
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
82
- Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
84
{
85
BDRVRawState *s = bs->opaque;
86
struct stat st;
87
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
90
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
92
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
94
bool exact, PreallocMode prealloc,
95
- Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
97
{
98
BDRVRawState *s = bs->opaque;
99
LONG low, high;
100
diff --git a/block/gluster.c b/block/gluster.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/gluster.c
103
+++ b/block/gluster.c
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
105
int64_t offset,
106
bool exact,
107
PreallocMode prealloc,
108
+ BdrvRequestFlags flags,
109
Error **errp)
110
{
111
BDRVGlusterState *s = bs->opaque;
112
diff --git a/block/io.c b/block/io.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/block/io.c
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
117
BlockDriverState *bs = child->bs;
118
BlockDriver *drv = bs->drv;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
47
}
125
}
48
126
49
if (info) {
127
if (drv->bdrv_co_truncate) {
50
+ if (info->has_qdev) {
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
51
+ monitor_printf(mon, " Attached to: %s\n", info->qdev);
129
+ if (flags & ~bs->supported_truncate_flags) {
130
+ error_setg(errp, "Block driver does not support requested flags");
131
+ ret = -ENOTSUP;
132
+ goto out;
52
+ }
133
+ }
53
if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) {
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
54
monitor_printf(mon, " I/O status: %s\n",
135
} else if (bs->file && drv->is_filter) {
55
BlockDeviceIoStatus_lookup[info->io_status]);
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
56
diff --git a/qapi/block-core.json b/qapi/block-core.json
137
} else {
57
index XXXXXXX..XXXXXXX 100644
138
diff --git a/block/iscsi.c b/block/iscsi.c
58
--- a/qapi/block-core.json
139
index XXXXXXX..XXXXXXX 100644
59
+++ b/qapi/block-core.json
140
--- a/block/iscsi.c
60
@@ -XXX,XX +XXX,XX @@
141
+++ b/block/iscsi.c
61
#
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
62
# @device: The device name associated with the virtual device.
143
63
#
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
64
+# @qdev: The qdev ID, or if no ID is assigned, the QOM path of the block
145
bool exact, PreallocMode prealloc,
65
+# device. (since 2.10)
146
- Error **errp)
66
+#
147
+ BdrvRequestFlags flags, Error **errp)
67
# @type: This field is returned only for compatibility reasons, it should
148
{
68
# not be used (always returns 'unknown')
149
IscsiLun *iscsilun = bs->opaque;
69
#
150
int64_t cur_length;
70
@@ -XXX,XX +XXX,XX @@
151
diff --git a/block/nfs.c b/block/nfs.c
71
# Since: 0.14.0
152
index XXXXXXX..XXXXXXX 100644
72
##
153
--- a/block/nfs.c
73
{ 'struct': 'BlockInfo',
154
+++ b/block/nfs.c
74
- 'data': {'device': 'str', 'type': 'str', 'removable': 'bool',
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
75
+ 'data': {'device': 'str', '*qdev': 'str', 'type': 'str', 'removable': 'bool',
156
76
'locked': 'bool', '*inserted': 'BlockDeviceInfo',
157
static int coroutine_fn
77
'*tray_open': 'bool', '*io-status': 'BlockDeviceIoStatus',
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
78
'*dirty-bitmaps': ['BlockDirtyInfo'] } }
159
- PreallocMode prealloc, Error **errp)
79
@@ -XXX,XX +XXX,XX @@
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
# }
161
+ Error **errp)
81
# }
162
{
82
# },
163
NFSClient *client = bs->opaque;
83
+# "qdev": "ide_disk",
164
int ret;
84
# "type":"unknown"
165
diff --git a/block/qcow2.c b/block/qcow2.c
85
# },
166
index XXXXXXX..XXXXXXX 100644
86
# {
167
--- a/block/qcow2.c
87
@@ -XXX,XX +XXX,XX @@
168
+++ b/block/qcow2.c
88
# "device":"ide1-cd0",
169
@@ -XXX,XX +XXX,XX @@ fail:
89
# "locked":false,
170
90
# "removable":true,
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
91
+# "qdev": "/machine/unattached/device[23]",
172
bool exact, PreallocMode prealloc,
92
+# "tray_open": false,
173
- Error **errp)
93
# "type":"unknown"
174
+ BdrvRequestFlags flags, Error **errp)
94
# },
175
{
95
# {
176
BDRVQcow2State *s = bs->opaque;
96
# "device":"floppy0",
177
uint64_t old_length;
97
# "locked":false,
178
diff --git a/block/qed.c b/block/qed.c
98
# "removable":true,
179
index XXXXXXX..XXXXXXX 100644
99
+# "qdev": "/machine/unattached/device[20]",
180
--- a/block/qed.c
100
# "type":"unknown"
181
+++ b/block/qed.c
101
# },
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
102
# {
183
int64_t offset,
103
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
184
bool exact,
104
index XXXXXXX..XXXXXXX 100644
185
PreallocMode prealloc,
105
--- a/tests/qemu-iotests/067.out
186
+ BdrvRequestFlags flags,
106
+++ b/tests/qemu-iotests/067.out
187
Error **errp)
107
@@ -XXX,XX +XXX,XX @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
188
{
108
"file": "TEST_DIR/t.qcow2",
189
BDRVQEDState *s = bs->opaque;
109
"encryption_key_missing": false
190
diff --git a/block/raw-format.c b/block/raw-format.c
110
},
191
index XXXXXXX..XXXXXXX 100644
111
+ "qdev": "/machine/peripheral/virtio0/virtio-backend",
192
--- a/block/raw-format.c
112
"type": "unknown"
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
113
}
236
}
114
]
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
115
--
264
--
116
1.8.3.1
265
2.25.3
117
266
118
267
diff view generated by jsdifflib
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
bdrv_truncate().
4
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
3
Reviewed-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
---
11
---
5
block/block-backend.c | 2 +-
12
include/block/block.h | 5 +++--
6
include/sysemu/block-backend.h | 1 +
13
block/block-backend.c | 2 +-
7
2 files changed, 2 insertions(+), 1 deletion(-)
14
block/crypto.c | 2 +-
15
block/io.c | 12 +++++++-----
16
block/parallels.c | 6 +++---
17
block/qcow.c | 4 ++--
18
block/qcow2-refcount.c | 2 +-
19
block/qcow2.c | 15 +++++++++------
20
block/raw-format.c | 2 +-
21
block/vhdx-log.c | 2 +-
22
block/vhdx.c | 2 +-
23
block/vmdk.c | 2 +-
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
8
26
27
diff --git a/include/block/block.h b/include/block/block.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block.h
30
+++ b/include/block/block.h
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
32
void bdrv_refresh_filename(BlockDriverState *bs);
33
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
35
- PreallocMode prealloc, Error **errp);
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
37
+ Error **errp);
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
39
- PreallocMode prealloc, Error **errp);
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
41
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
43
int64_t bdrv_getlength(BlockDriverState *bs);
9
diff --git a/block/block-backend.c b/block/block-backend.c
44
diff --git a/block/block-backend.c b/block/block-backend.c
10
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
11
--- a/block/block-backend.c
46
--- a/block/block-backend.c
12
+++ b/block/block-backend.c
47
+++ b/block/block-backend.c
13
@@ -XXX,XX +XXX,XX @@ void blk_unref(BlockBackend *blk)
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
14
* Behaves similarly to blk_next() but iterates over all BlockBackends, even the
49
return -ENOMEDIUM;
15
* ones which are hidden (i.e. are not referenced by the monitor).
50
}
51
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
54
}
55
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
57
diff --git a/block/crypto.c b/block/crypto.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.c
60
+++ b/block/crypto.c
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
62
63
offset += payload_offset;
64
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
67
}
68
69
static void block_crypto_close(BlockDriverState *bs)
70
diff --git a/block/io.c b/block/io.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
73
+++ b/block/io.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
75
* 'offset' bytes in length.
16
*/
76
*/
17
-static BlockBackend *blk_all_next(BlockBackend *blk)
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
18
+BlockBackend *blk_all_next(BlockBackend *blk)
78
- PreallocMode prealloc, Error **errp)
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
+ Error **errp)
19
{
81
{
20
return blk ? QTAILQ_NEXT(blk, link)
82
BlockDriverState *bs = child->bs;
21
: QTAILQ_FIRST(&block_backends);
83
BlockDriver *drv = bs->drv;
22
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
84
BdrvTrackedRequest req;
23
index XXXXXXX..XXXXXXX 100644
85
- BdrvRequestFlags flags = 0;
24
--- a/include/sysemu/block-backend.h
86
int64_t old_size, new_bytes;
25
+++ b/include/sysemu/block-backend.h
87
int ret;
26
@@ -XXX,XX +XXX,XX @@ void blk_remove_all_bs(void);
88
27
const char *blk_name(const BlockBackend *blk);
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
28
BlockBackend *blk_by_name(const char *name);
90
}
29
BlockBackend *blk_next(BlockBackend *blk);
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
30
+BlockBackend *blk_all_next(BlockBackend *blk);
92
} else if (bs->file && drv->is_filter) {
31
bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp);
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
32
void monitor_remove_blk(BlockBackend *blk);
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
33
95
} else {
96
error_setg(errp, "Image format driver does not support resize");
97
ret = -ENOTSUP;
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
99
int64_t offset;
100
bool exact;
101
PreallocMode prealloc;
102
+ BdrvRequestFlags flags;
103
Error **errp;
104
int ret;
105
} TruncateCo;
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
107
{
108
TruncateCo *tco = opaque;
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
110
- tco->prealloc, tco->errp);
111
+ tco->prealloc, tco->flags, tco->errp);
112
aio_wait_kick();
113
}
114
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
116
- PreallocMode prealloc, Error **errp)
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
118
{
119
Coroutine *co;
120
TruncateCo tco = {
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
122
.offset = offset,
123
.exact = exact,
124
.prealloc = prealloc,
125
+ .flags = flags,
126
.errp = errp,
127
.ret = NOT_DONE,
128
};
129
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
132
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
134
} else {
135
ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
139
}
140
if (ret < 0) {
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
143
* That means we have to pass exact=true.
144
*/
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
149
error_report_err(local_err);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
163
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
165
return -E2BIG;
166
}
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
168
- false, PREALLOC_MODE_OFF, NULL);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
170
if (ret < 0) {
171
return ret;
172
}
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
174
l1_length) < 0)
175
return -1;
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
179
if (ret < 0)
180
return ret;
181
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
187
}
188
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
190
- PREALLOC_MODE_OFF, &local_err);
191
+ PREALLOC_MODE_OFF, 0, &local_err);
192
if (ret < 0) {
193
error_report_err(local_err);
194
goto resize_fail;
195
diff --git a/block/qcow2.c b/block/qcow2.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/block/qcow2.c
198
+++ b/block/qcow2.c
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
200
mode = PREALLOC_MODE_OFF;
201
}
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
203
- mode, errp);
204
+ mode, 0, errp);
205
if (ret < 0) {
206
return ret;
207
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
209
* always fulfilled, so there is no need to pass it on.)
210
*/
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
212
- false, PREALLOC_MODE_OFF, &local_err);
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
214
if (local_err) {
215
warn_reportf_err(local_err,
216
"Failed to truncate the tail of the image: ");
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
218
* file should be resized to the exact target size, too,
219
* so we pass @exact here.
220
*/
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
223
+ errp);
224
if (ret < 0) {
225
goto fail;
226
}
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
228
new_file_size = allocation_start +
229
nb_new_data_clusters * s->cluster_size;
230
/* Image file grows, so @exact does not matter */
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
233
+ errp);
234
if (ret < 0) {
235
error_prepend(errp, "Failed to resize underlying file: ");
236
qcow2_free_clusters(bs, allocation_start,
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
if (len < 0) {
239
return len;
240
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
243
+ NULL);
244
}
245
246
if (offset_into_cluster(s, offset)) {
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
248
}
249
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
251
- PREALLOC_MODE_OFF, &local_err);
252
+ PREALLOC_MODE_OFF, 0, &local_err);
253
if (ret < 0) {
254
error_report_err(local_err);
255
goto fail;
256
diff --git a/block/raw-format.c b/block/raw-format.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/raw-format.c
259
+++ b/block/raw-format.c
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
261
262
s->size = offset;
263
offset += s->offset;
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
266
}
267
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
274
goto exit;
275
}
276
ret = bdrv_truncate(bs->file, new_file_size, false,
277
- PREALLOC_MODE_OFF, NULL);
278
+ PREALLOC_MODE_OFF, 0, NULL);
279
if (ret < 0) {
280
goto exit;
281
}
282
diff --git a/block/vhdx.c b/block/vhdx.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/vhdx.c
285
+++ b/block/vhdx.c
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
287
}
288
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
290
- PREALLOC_MODE_OFF, NULL);
291
+ PREALLOC_MODE_OFF, 0, NULL);
292
}
293
294
/*
295
diff --git a/block/vmdk.c b/block/vmdk.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/block/vmdk.c
298
+++ b/block/vmdk.c
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
300
}
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
302
ret = bdrv_truncate(s->extents[i].file, length, false,
303
- PREALLOC_MODE_OFF, NULL);
304
+ PREALLOC_MODE_OFF, 0, NULL);
305
if (ret < 0) {
306
return ret;
307
}
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/tests/test-block-iothread.c
311
+++ b/tests/test-block-iothread.c
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
313
int ret;
314
315
/* Normal success path */
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
318
g_assert_cmpint(ret, ==, 0);
319
320
/* Early error: Negative offset */
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
323
g_assert_cmpint(ret, ==, -EINVAL);
324
325
/* Error: Read-only image */
326
c->bs->read_only = true;
327
c->bs->open_flags &= ~BDRV_O_RDWR;
328
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
331
g_assert_cmpint(ret, ==, -EACCES);
332
333
c->bs->read_only = false;
34
--
334
--
35
1.8.3.1
335
2.25.3
36
336
37
337
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
Now that node level interface bdrv_truncate() supports passing request
2
2
flags to the block driver, expose this on the BlockBackend level, too.
3
Or, rather, force the open of a backing image if one was specified
3
4
for creation. Using a similar -unsafe option as rebase, allow qemu-img
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
to ignore the backing file validation if possible.
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
It may not always be possible, as in the existing case when a filesize
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
for the new image was not specified.
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
10
This is accomplished by shifting around the conditionals in
11
bdrv_img_create, such that a backing file is always opened unless we
12
provide BDRV_O_NO_BACKING. qemu-img is adjusted to pass this new flag
13
when -u is provided to create.
14
15
Sorry for the heinous looking diffstat, but it's mostly whitespace.
16
17
Inspired by: https://bugzilla.redhat.com/show_bug.cgi?id=1213786
18
19
Signed-off-by: John Snow <jsnow@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
10
---
22
block.c | 94 +++++++++++++++++++++++++---------------------
11
include/sysemu/block-backend.h | 2 +-
23
qemu-img-cmds.hx | 4 +-
12
block.c | 3 ++-
24
qemu-img.c | 16 +++++---
13
block/block-backend.c | 4 ++--
25
qemu-img.texi | 9 ++++-
14
block/commit.c | 4 ++--
26
tests/qemu-iotests/082 | 4 +-
15
block/crypto.c | 2 +-
27
tests/qemu-iotests/082.out | 4 +-
16
block/mirror.c | 2 +-
28
tests/qemu-iotests/085 | 2 +-
17
block/qcow2.c | 4 ++--
29
tests/qemu-iotests/111.out | 1 +
18
block/qed.c | 2 +-
30
tests/qemu-iotests/139 | 2 +-
19
block/vdi.c | 2 +-
31
tests/qemu-iotests/156 | 2 +-
20
block/vhdx.c | 4 ++--
32
tests/qemu-iotests/158 | 2 +-
21
block/vmdk.c | 6 +++---
33
tests/qemu-iotests/189 | 2 +-
22
block/vpc.c | 2 +-
34
12 files changed, 83 insertions(+), 59 deletions(-)
23
blockdev.c | 2 +-
35
24
qemu-img.c | 2 +-
25
qemu-io-cmds.c | 2 +-
26
15 files changed, 22 insertions(+), 21 deletions(-)
27
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/sysemu/block-backend.h
31
+++ b/include/sysemu/block-backend.h
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
34
int bytes);
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
36
- PreallocMode prealloc, Error **errp);
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
40
int64_t pos, int size);
36
diff --git a/block.c b/block.c
41
diff --git a/block.c b/block.c
37
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
38
--- a/block.c
43
--- a/block.c
39
+++ b/block.c
44
+++ b/block.c
40
@@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt,
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
41
46
int64_t size;
42
backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
47
int ret;
43
48
44
- // The size for the image must always be specified, with one exception:
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
45
- // If we are using a backing file, we can obtain the size from there
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
46
+ /* The size for the image must always be specified, unless we have a backing
47
+ * file and we have not been forbidden from opening it. */
48
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
49
- if (size == -1) {
50
- if (backing_file) {
51
- BlockDriverState *bs;
52
- char *full_backing = g_new0(char, PATH_MAX);
53
- int64_t size;
54
- int back_flags;
55
- QDict *backing_options = NULL;
56
-
57
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
58
- full_backing, PATH_MAX,
59
- &local_err);
60
- if (local_err) {
61
- g_free(full_backing);
62
- goto out;
63
- }
64
+ if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
65
+ BlockDriverState *bs;
66
+ char *full_backing = g_new0(char, PATH_MAX);
67
+ int back_flags;
68
+ QDict *backing_options = NULL;
69
+
70
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
71
+ full_backing, PATH_MAX,
72
+ &local_err);
73
+ if (local_err) {
74
+ g_free(full_backing);
75
+ goto out;
76
+ }
77
78
- /* backing files always opened read-only */
79
- back_flags = flags;
80
- back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
81
+ /* backing files always opened read-only */
82
+ back_flags = flags;
83
+ back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
84
85
- if (backing_fmt) {
86
- backing_options = qdict_new();
87
- qdict_put_str(backing_options, "driver", backing_fmt);
88
- }
89
+ if (backing_fmt) {
90
+ backing_options = qdict_new();
91
+ qdict_put_str(backing_options, "driver", backing_fmt);
92
+ }
93
94
- bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
95
- &local_err);
96
- g_free(full_backing);
97
- if (!bs) {
98
- goto out;
99
- }
100
- size = bdrv_getlength(bs);
101
- if (size < 0) {
102
- error_setg_errno(errp, -size, "Could not get size of '%s'",
103
- backing_file);
104
- bdrv_unref(bs);
105
- goto out;
106
+ bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
107
+ &local_err);
51
+ &local_err);
108
+ g_free(full_backing);
52
if (ret < 0 && ret != -ENOTSUP) {
109
+ if (!bs && size != -1) {
53
error_propagate(errp, local_err);
110
+ /* Couldn't open BS, but we have a size, so it's nonfatal */
54
return ret;
111
+ warn_reportf_err(local_err,
55
diff --git a/block/block-backend.c b/block/block-backend.c
112
+ "Could not verify backing image. "
56
index XXXXXXX..XXXXXXX 100644
113
+ "This may become an error in future versions.\n");
57
--- a/block/block-backend.c
114
+ local_err = NULL;
58
+++ b/block/block-backend.c
115
+ } else if (!bs) {
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
116
+ /* Couldn't open bs, do not have size */
60
}
117
+ error_append_hint(&local_err,
61
118
+ "Could not open backing image to determine size.\n");
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
119
+ goto out;
63
- PreallocMode prealloc, Error **errp)
120
+ } else {
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
121
+ if (size == -1) {
65
{
122
+ /* Opened BS, have no size */
66
if (!blk_is_available(blk)) {
123
+ size = bdrv_getlength(bs);
67
error_setg(errp, "No medium inserted");
124
+ if (size < 0) {
68
return -ENOMEDIUM;
125
+ error_setg_errno(errp, -size, "Could not get size of '%s'",
69
}
126
+ backing_file);
70
127
+ bdrv_unref(bs);
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
128
+ goto out;
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
129
+ }
73
}
130
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort);
74
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
76
diff --git a/block/commit.c b/block/commit.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/block/commit.c
79
+++ b/block/commit.c
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
81
}
82
83
if (base_len < len) {
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
86
if (ret) {
87
goto out;
88
}
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
90
* grow the backing file image if possible. If not possible,
91
* we must return an error */
92
if (length > backing_length) {
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
95
&local_err);
96
if (ret < 0) {
97
error_report_err(local_err);
98
diff --git a/block/crypto.c b/block/crypto.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/crypto.c
101
+++ b/block/crypto.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
108
}
109
110
111
diff --git a/block/mirror.c b/block/mirror.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/mirror.c
114
+++ b/block/mirror.c
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
116
117
if (s->bdev_length > base_length) {
118
ret = blk_truncate(s->target, s->bdev_length, false,
119
- PREALLOC_MODE_OFF, NULL);
120
+ PREALLOC_MODE_OFF, 0, NULL);
121
if (ret < 0) {
122
goto immediate_exit;
131
}
123
}
132
-
124
diff --git a/block/qcow2.c b/block/qcow2.c
133
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort);
125
index XXXXXXX..XXXXXXX 100644
134
-
126
--- a/block/qcow2.c
135
bdrv_unref(bs);
127
+++ b/block/qcow2.c
136
- } else {
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
137
- error_setg(errp, "Image creation needs a size parameter");
129
138
- goto out;
130
/* Okay, now that we have a valid image, let's give it the right size */
139
}
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
140
+ } /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */
132
- errp);
141
+
133
+ 0, errp);
142
+ if (size == -1) {
134
if (ret < 0) {
143
+ error_setg(errp, "Image creation needs a size parameter");
135
error_prepend(errp, "Could not resize image: ");
144
+ goto out;
136
goto out;
145
}
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
146
138
* Amending image options should ensure that the image has
147
if (!quiet) {
139
* exactly the given new values, so pass exact=true here.
148
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
140
*/
149
index XXXXXXX..XXXXXXX 100644
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
150
--- a/qemu-img-cmds.hx
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
151
+++ b/qemu-img-cmds.hx
143
blk_unref(blk);
152
@@ -XXX,XX +XXX,XX @@ STEXI
144
if (ret < 0) {
153
ETEXI
145
return ret;
154
146
diff --git a/block/qed.c b/block/qed.c
155
DEF("create", img_create,
147
index XXXXXXX..XXXXXXX 100644
156
- "create [-q] [--object objectdef] [-f fmt] [-b backing_file] [-F backing_fmt] [-o options] filename [size]")
148
--- a/block/qed.c
157
+ "create [-q] [--object objectdef] [-f fmt] [-b backing_file] [-F backing_fmt] [-u] [-o options] filename [size]")
149
+++ b/block/qed.c
158
STEXI
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
159
-@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}]
151
* The QED format associates file length with allocation status,
160
+@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-u] [-o @var{options}] @var{filename} [@var{size}]
152
* so a new file (which is empty) must have a length of 0.
161
ETEXI
153
*/
162
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
163
DEF("commit", img_commit,
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
158
}
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
185
} else if (type == VHDX_TYPE_FIXED) {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
187
- PREALLOC_MODE_OFF, errp);
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
192
diff --git a/block/vmdk.c b/block/vmdk.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/vmdk.c
195
+++ b/block/vmdk.c
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
197
int gd_buf_size;
198
199
if (flat) {
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
202
goto exit;
203
}
204
magic = cpu_to_be32(VMDK4_MAGIC);
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
206
}
207
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
209
- PREALLOC_MODE_OFF, errp);
210
+ PREALLOC_MODE_OFF, 0, errp);
211
if (ret < 0) {
212
goto exit;
213
}
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
216
* for description file */
217
if (desc_offset == 0) {
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
220
if (ret < 0) {
221
goto exit;
222
}
223
diff --git a/block/vpc.c b/block/vpc.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/block/vpc.c
226
+++ b/block/vpc.c
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
228
/* Add footer to total size */
229
total_size += HEADER_SIZE;
230
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
233
if (ret < 0) {
234
return ret;
235
}
236
diff --git a/blockdev.c b/blockdev.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/blockdev.c
239
+++ b/blockdev.c
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
241
}
242
243
bdrv_drained_begin(bs);
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
246
bdrv_drained_end(bs);
247
248
out:
164
diff --git a/qemu-img.c b/qemu-img.c
249
diff --git a/qemu-img.c b/qemu-img.c
165
index XXXXXXX..XXXXXXX 100644
250
index XXXXXXX..XXXXXXX 100644
166
--- a/qemu-img.c
251
--- a/qemu-img.c
167
+++ b/qemu-img.c
252
+++ b/qemu-img.c
168
@@ -XXX,XX +XXX,XX @@ static void QEMU_NORETURN help(void)
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
169
" 'snapshot_id_or_name' is deprecated, use 'snapshot_param'\n"
254
* resizing, so pass @exact=true. It is of no use to report
170
" instead\n"
255
* success when the image has not actually been resized.
171
" '-c' indicates that target image must be compressed (qcow format only)\n"
256
*/
172
- " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
173
- " match exactly. The image doesn't need a working backing file before\n"
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
174
- " rebasing in this case (useful for renaming the backing file)\n"
259
if (!ret) {
175
+ " '-u' allows unsafe backing chains. For rebasing, it is assumed that old and\n"
260
qprintf(quiet, "Image resized.\n");
176
+ " new backing file match exactly. The image doesn't need a working\n"
261
} else {
177
+ " backing file before rebasing in this case (useful for renaming the\n"
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
178
+ " backing file). For image creation, allow creating without attempting\n"
263
index XXXXXXX..XXXXXXX 100644
179
+ " to open the backing file.\n"
264
--- a/qemu-io-cmds.c
180
" '-h' with or without a command shows this help and lists the supported formats\n"
265
+++ b/qemu-io-cmds.c
181
" '-p' show progress of command (only certain commands)\n"
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
182
" '-q' use Quiet mode - do not print any output (except errors)\n"
267
* exact=true. It is better to err on the "emit more errors" side
183
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
268
* than to be overly permissive.
184
char *options = NULL;
269
*/
185
Error *local_err = NULL;
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
186
bool quiet = false;
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
187
+ int flags = 0;
272
if (ret < 0) {
188
273
error_report_err(local_err);
189
for(;;) {
274
return ret;
190
static const struct option long_options[] = {
191
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
192
{"object", required_argument, 0, OPTION_OBJECT},
193
{0, 0, 0, 0}
194
};
195
- c = getopt_long(argc, argv, ":F:b:f:ho:q",
196
+ c = getopt_long(argc, argv, ":F:b:f:ho:qu",
197
long_options, NULL);
198
if (c == -1) {
199
break;
200
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
201
case 'q':
202
quiet = true;
203
break;
204
+ case 'u':
205
+ flags |= BDRV_O_NO_BACKING;
206
+ break;
207
case OPTION_OBJECT: {
208
QemuOpts *opts;
209
opts = qemu_opts_parse_noisily(&qemu_object_opts,
210
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
211
}
212
213
bdrv_img_create(filename, fmt, base_filename, base_fmt,
214
- options, img_size, 0, quiet, &local_err);
215
+ options, img_size, flags, quiet, &local_err);
216
if (local_err) {
217
error_reportf_err(local_err, "%s: ", filename);
218
goto fail;
219
diff --git a/qemu-img.texi b/qemu-img.texi
220
index XXXXXXX..XXXXXXX 100644
221
--- a/qemu-img.texi
222
+++ b/qemu-img.texi
223
@@ -XXX,XX +XXX,XX @@ If @code{-r} is specified, exit codes representing the image state refer to the
224
state after (the attempt at) repairing it. That is, a successful @code{-r all}
225
will yield the exit code 0, independently of the image state before.
226
227
-@item create [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}]
228
+@item create [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-u] [-o @var{options}] @var{filename} [@var{size}]
229
230
Create the new disk image @var{filename} of size @var{size} and format
231
@var{fmt}. Depending on the file format, you can add one or more @var{options}
232
@@ -XXX,XX +XXX,XX @@ only the differences from @var{backing_file}. No size needs to be specified in
233
this case. @var{backing_file} will never be modified unless you use the
234
@code{commit} monitor command (or qemu-img commit).
235
236
+Note that a given backing file will be opened to check that it is valid. Use
237
+the @code{-u} option to enable unsafe backing file mode, which means that the
238
+image will be created even if the associated backing file cannot be opened. A
239
+matching backing file must be created or additional options be used to make the
240
+backing file specification valid when you want to use an image created this
241
+way.
242
+
243
The size can also be specified using the @var{size} option with @code{-o},
244
it doesn't need to be specified separately in this case.
245
246
diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082
247
index XXXXXXX..XXXXXXX 100755
248
--- a/tests/qemu-iotests/082
249
+++ b/tests/qemu-iotests/082
250
@@ -XXX,XX +XXX,XX @@ run_qemu_img create -f $IMGFMT -o cluster_size=4k -o help "$TEST_IMG" $size
251
run_qemu_img create -f $IMGFMT -o cluster_size=4k -o \? "$TEST_IMG" $size
252
253
# Looks like a help option, but is part of the backing file name
254
-run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG",,help "$TEST_IMG" $size
255
-run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG",,\? "$TEST_IMG" $size
256
+run_qemu_img create -f $IMGFMT -u -o backing_file="$TEST_IMG",,help "$TEST_IMG" $size
257
+run_qemu_img create -f $IMGFMT -u -o backing_file="$TEST_IMG",,\? "$TEST_IMG" $size
258
259
# Try to trick qemu-img into creating escaped commas
260
run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG", -o help "$TEST_IMG" $size
261
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
262
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/qemu-iotests/082.out
264
+++ b/tests/qemu-iotests/082.out
265
@@ -XXX,XX +XXX,XX @@ lazy_refcounts Postpone refcount updates
266
refcount_bits Width of a reference count entry in bits
267
nocow Turn off copy-on-write (valid only on btrfs)
268
269
-Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
270
+Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
271
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
272
273
-Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M
274
+Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M
275
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
277
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M
278
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
279
index XXXXXXX..XXXXXXX 100755
280
--- a/tests/qemu-iotests/085
281
+++ b/tests/qemu-iotests/085
282
@@ -XXX,XX +XXX,XX @@ function add_snapshot_image()
283
{
284
base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}"
285
snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
286
- _make_test_img -b "${base_image}" "$size"
287
+ _make_test_img -u -b "${base_image}" "$size"
288
mv "${TEST_IMG}" "${snapshot_file}"
289
do_blockdev_add "$1" "'backing': '', " "${snapshot_file}"
290
}
291
diff --git a/tests/qemu-iotests/111.out b/tests/qemu-iotests/111.out
292
index XXXXXXX..XXXXXXX 100644
293
--- a/tests/qemu-iotests/111.out
294
+++ b/tests/qemu-iotests/111.out
295
@@ -XXX,XX +XXX,XX @@
296
QA output created by 111
297
qemu-img: TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT.inexistent': No such file or directory
298
+Could not open backing image to determine size.
299
*** done
300
diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139
301
index XXXXXXX..XXXXXXX 100644
302
--- a/tests/qemu-iotests/139
303
+++ b/tests/qemu-iotests/139
304
@@ -XXX,XX +XXX,XX @@ class TestBlockdevDel(iotests.QMPTestCase):
305
# Add a BlockDriverState that will be used as overlay for the base_img BDS
306
def addBlockDriverStateOverlay(self, node):
307
self.checkBlockDriverState(node, False)
308
- iotests.qemu_img('create', '-f', iotests.imgfmt,
309
+ iotests.qemu_img('create', '-u', '-f', iotests.imgfmt,
310
'-b', base_img, new_img, '1M')
311
opts = {'driver': iotests.imgfmt,
312
'node-name': node,
313
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
314
index XXXXXXX..XXXXXXX 100755
315
--- a/tests/qemu-iotests/156
316
+++ b/tests/qemu-iotests/156
317
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
318
'return'
319
320
# Create snapshot
321
-TEST_IMG="$TEST_IMG.overlay" _make_test_img -b "$TEST_IMG" 1M
322
+TEST_IMG="$TEST_IMG.overlay" _make_test_img -u -b "$TEST_IMG" 1M
323
_send_qemu_cmd $QEMU_HANDLE \
324
"{ 'execute': 'blockdev-snapshot-sync',
325
'arguments': { 'device': 'source',
326
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
327
index XXXXXXX..XXXXXXX 100755
328
--- a/tests/qemu-iotests/158
329
+++ b/tests/qemu-iotests/158
330
@@ -XXX,XX +XXX,XX @@ echo "== verify pattern =="
331
$QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
332
333
echo "== create overlay =="
334
-_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" $size
335
+_make_test_img -u --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" $size
336
337
echo
338
echo "== writing part of a cluster =="
339
diff --git a/tests/qemu-iotests/189 b/tests/qemu-iotests/189
340
index XXXXXXX..XXXXXXX 100755
341
--- a/tests/qemu-iotests/189
342
+++ b/tests/qemu-iotests/189
343
@@ -XXX,XX +XXX,XX @@ echo "== verify pattern =="
344
$QEMU_IO --object $SECRET0 -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
345
346
echo "== create overlay =="
347
-_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -b "$TEST_IMG_BASE" $size
348
+_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -u -b "$TEST_IMG_BASE" $size
349
350
echo
351
echo "== writing part of a cluster =="
352
--
275
--
353
1.8.3.1
276
2.25.3
354
277
355
278
diff view generated by jsdifflib
1
If no drive=... option is passed (for an empty drive), we don't only
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
2
lack the BlockBackend normally created by parse_drive(), but we also
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
need to manually call blk_attach_dev().
3
undo any previous preallocation, but just adds the zero flag to all
4
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
This fixes at least a segfault when unplugging such devices, the bug
5
request to the data file is made instead.
6
that they didn't show up in query-block, and probably some more
7
problems.
8
6
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
12
---
13
hw/scsi/scsi-disk.c | 5 +++++
13
block/qcow2-cluster.c | 2 +-
14
1 file changed, 5 insertions(+)
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
15
2 files changed, 35 insertions(+), 1 deletion(-)
15
16
16
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/scsi/scsi-disk.c
19
--- a/block/qcow2-cluster.c
19
+++ b/hw/scsi/scsi-disk.c
20
+++ b/block/qcow2-cluster.c
20
@@ -XXX,XX +XXX,XX @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
21
static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
22
/* Caller must pass aligned values, except at image end */
22
{
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
23
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
24
+ int ret;
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
25
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
26
if (!dev->conf.blk) {
27
27
+ /* Anonymous BlockBackend for an empty drive. As we put it into
28
/* The zero flag is only supported by version 3 and newer */
28
+ * dev->conf, qdev takes care of detaching on unplug. */
29
if (s->qcow_version < 3) {
29
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
30
diff --git a/block/qcow2.c b/block/qcow2.c
30
+ ret = blk_attach_dev(dev->conf.blk, &dev->qdev);
31
index XXXXXXX..XXXXXXX 100644
31
+ assert(ret == 0);
32
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
35
36
bs->supported_zero_flags = header.version >= 3 ?
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
39
40
/* Repair image if dirty */
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
43
g_assert_not_reached();
32
}
44
}
33
45
34
s->qdev.blocksize = 2048;
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
48
+
49
+ /*
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
52
+ * at the end of the image (which it is here).
53
+ */
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
55
+ if (ret < 0) {
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
57
+ goto fail;
58
+ }
59
+
60
+ /* Write explicit zeros for the unaligned head */
61
+ if (zero_start > old_length) {
62
+ uint64_t len = zero_start - old_length;
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
64
+ QEMUIOVector qiov;
65
+ qemu_iovec_init_buf(&qiov, buf, len);
66
+
67
+ qemu_co_mutex_unlock(&s->lock);
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
69
+ qemu_co_mutex_lock(&s->lock);
70
+
71
+ qemu_vfree(buf);
72
+ if (ret < 0) {
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
74
+ goto fail;
75
+ }
76
+ }
77
+ }
78
+
79
if (prealloc != PREALLOC_MODE_OFF) {
80
/* Flush metadata before actually changing the image size */
81
ret = qcow2_write_caches(bs);
35
--
82
--
36
1.8.3.1
83
2.25.3
37
84
38
85
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
The raw format driver can simply forward the flag and let its bs->file
2
child take care of actually providing the zeros.
2
3
3
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
10
---
6
block/vvfat.c | 17 +++++++++++------
11
block/raw-format.c | 4 +++-
7
1 file changed, 11 insertions(+), 6 deletions(-)
12
1 file changed, 3 insertions(+), 1 deletion(-)
8
13
9
diff --git a/block/vvfat.c b/block/vvfat.c
14
diff --git a/block/raw-format.c b/block/raw-format.c
10
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
11
--- a/block/vvfat.c
16
--- a/block/raw-format.c
12
+++ b/block/vvfat.c
17
+++ b/block/raw-format.c
13
@@ -XXX,XX +XXX,XX @@ void nonono(const char* file, int line, const char* msg) {
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
14
19
15
#endif
20
s->size = offset;
16
21
offset += s->offset;
17
+#define DIR_DELETED 0xe5
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
18
+#define DIR_KANJI DIR_DELETED
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
19
+#define DIR_KANJI_FAKE 0x05
20
+#define DIR_FREE 0x00
21
+
22
/* dynamic array functions */
23
typedef struct array_t {
24
char* pointer;
25
@@ -XXX,XX +XXX,XX @@ static direntry_t *create_long_filename(BDRVVVFATState *s, const char *filename)
26
27
static char is_free(const direntry_t* direntry)
28
{
29
- return direntry->name[0]==0xe5 || direntry->name[0]==0x00;
30
+ return direntry->name[0] == DIR_DELETED || direntry->name[0] == DIR_FREE;
31
}
24
}
32
25
33
static char is_volume_label(const direntry_t* direntry)
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
34
@@ -XXX,XX +XXX,XX @@ static char is_short_name(const direntry_t* direntry)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
35
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
36
static char is_directory(const direntry_t* direntry)
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
37
{
30
bs->file->bs->supported_zero_flags);
38
- return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
39
+ return direntry->attributes & 0x10 && direntry->name[0] != DIR_DELETED;
32
+ BDRV_REQ_ZERO_WRITE;
40
}
33
41
34
if (bs->probed && !bdrv_is_read_only(bs)) {
42
static inline char is_dot(const direntry_t* direntry)
35
bdrv_refresh_filename(bs->file->bs);
43
@@ -XXX,XX +XXX,XX @@ static direntry_t *create_short_filename(BDRVVVFATState *s,
44
}
45
}
46
47
- if (entry->name[0] == 0xe5) {
48
- entry->name[0] = 0x05;
49
+ if (entry->name[0] == DIR_KANJI) {
50
+ entry->name[0] = DIR_KANJI_FAKE;
51
}
52
53
/* numeric-tail generation */
54
@@ -XXX,XX +XXX,XX @@ static int parse_short_name(BDRVVVFATState* s,
55
} else
56
lfn->name[i + j + 1] = '\0';
57
58
- if (lfn->name[0] == 0x05) {
59
- lfn->name[0] = 0xe5;
60
+ if (lfn->name[0] == DIR_KANJI_FAKE) {
61
+ lfn->name[0] = DIR_KANJI;
62
}
63
lfn->len = strlen((char*)lfn->name);
64
65
--
36
--
66
1.8.3.1
37
2.25.3
67
38
68
39
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
2
OS, so we can advertise the flag and just ignore it.
2
3
3
Also add links to related compatibility problems.
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
10
---
9
block/vvfat.c | 8 +++++++-
11
block/file-posix.c | 4 ++++
10
1 file changed, 7 insertions(+), 1 deletion(-)
12
1 file changed, 4 insertions(+)
11
13
12
diff --git a/block/vvfat.c b/block/vvfat.c
14
diff --git a/block/file-posix.c b/block/file-posix.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vvfat.c
16
--- a/block/file-posix.c
15
+++ b/block/vvfat.c
17
+++ b/block/file-posix.c
16
@@ -XXX,XX +XXX,XX @@ void nonono(const char* file, int line, const char* msg) {
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
17
18
#endif
19
#endif
19
20
20
+/* bootsector OEM name. see related compatibility problems at:
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
21
+ * https://jdebp.eu/FGA/volume-boot-block-oem-name-field.html
22
+ if (S_ISREG(st.st_mode)) {
22
+ * http://seasip.info/Misc/oemid.html
23
+ /* When extending regular files, we get zeros from the OS */
23
+ */
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
24
+#define BOOTSECTOR_OEM_NAME "MSWIN4.1"
25
+ }
25
+
26
ret = 0;
26
#define DIR_DELETED 0xe5
27
fail:
27
#define DIR_KANJI DIR_DELETED
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
28
#define DIR_KANJI_FAKE 0x05
29
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
30
bootsector->jump[0]=0xeb;
31
bootsector->jump[1]=0x3e;
32
bootsector->jump[2]=0x90;
33
- memcpy(bootsector->name, "MSWIN4.1", 8);
34
+ memcpy(bootsector->name, BOOTSECTOR_OEM_NAME, 8);
35
bootsector->sector_size=cpu_to_le16(0x200);
36
bootsector->sectors_per_cluster=s->sectors_per_cluster;
37
bootsector->reserved_sectors=cpu_to_le16(1);
38
--
29
--
39
1.8.3.1
30
2.25.3
40
31
41
32
diff view generated by jsdifflib
1
If no drive=... option is passed (for an empty drive), we don't only
1
When extending the size of an image that has a backing file larger than
2
lack the BlockBackend normally created by parse_drive(), but we also
2
its old size, make sure that the backing file data doesn't become
3
need to manually call blk_attach_dev().
3
visible in the guest, but the added area is properly zeroed out.
4
4
5
IDE does not support hot unplug, but if it did, qdev would take care to
5
Consider the following scenario where the overlay is shorter than its
6
call the matching blk_detach_dev() on unplug.
6
backing file:
7
7
8
This fixes at least the bug that such devices didn't show up in
8
base.qcow2: AAAAAAAA
9
query-block, and probably some more problems.
9
overlay.qcow2: BBBB
10
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
10
29
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: John Snow <jsnow@redhat.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
35
---
15
hw/ide/qdev.c | 3 +++
36
block/io.c | 25 +++++++++++++++++++++++++
16
1 file changed, 3 insertions(+)
37
1 file changed, 25 insertions(+)
17
38
18
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
39
diff --git a/block/io.c b/block/io.c
19
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/ide/qdev.c
41
--- a/block/io.c
21
+++ b/hw/ide/qdev.c
42
+++ b/block/io.c
22
@@ -XXX,XX +XXX,XX @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
23
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
44
goto out;
24
IDEState *s = bus->ifs + dev->unit;
25
Error *err = NULL;
26
+ int ret;
27
28
if (!dev->conf.blk) {
29
if (kind != IDE_CD) {
30
@@ -XXX,XX +XXX,XX @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
31
} else {
32
/* Anonymous BlockBackend for an empty drive */
33
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
34
+ ret = blk_attach_dev(dev->conf.blk, &dev->qdev);
35
+ assert(ret == 0);
36
}
37
}
45
}
38
46
47
+ /*
48
+ * If the image has a backing file that is large enough that it would
49
+ * provide data for the new area, we cannot leave it unallocated because
50
+ * then the backing file content would become visible. Instead, zero-fill
51
+ * the new area.
52
+ *
53
+ * Note that if the image has a backing file, but was opened without the
54
+ * backing file, taking care of keeping things consistent with that backing
55
+ * file is the user's responsibility.
56
+ */
57
+ if (new_bytes && bs->backing) {
58
+ int64_t backing_len;
59
+
60
+ backing_len = bdrv_getlength(backing_bs(bs));
61
+ if (backing_len < 0) {
62
+ ret = backing_len;
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
64
+ goto out;
65
+ }
66
+
67
+ if (backing_len > old_size) {
68
+ flags |= BDRV_REQ_ZERO_WRITE;
69
+ }
70
+ }
71
+
72
if (drv->bdrv_co_truncate) {
73
if (flags & ~bs->supported_truncate_flags) {
74
error_setg(errp, "Block driver does not support requested flags");
39
--
75
--
40
1.8.3.1
76
2.25.3
41
77
42
78
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
We want to keep TEST_IMG for the full path of the main test image, but
2
filter_testfiles() must be called for other test images before replacing
3
other things like the image format because the test directory path could
4
contain the format as a substring.
2
5
3
gcc 7 complains that the sprintf() might write a null byte beyond the
6
Insert a filter_testfiles() call between both.
4
end of the tail buffer. That is wrong, but we can silence it by making
5
i unsigned (it can never be negative anyway, see the if condition right
6
before). For some reason, this allows gcc to suddenly accurately
7
calculate the range of i so we can give the tail[] array the exact size
8
it needs to have (which is 8 bytes) without gcc complaining.
9
7
10
In addition, let us convert the sprintf() to snprintf(), because that is
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
always nicer, and add an assertion about the range of the return value
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
afterwards so we can see that "8 - len" will never be negative and thus
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
"entry->name + MIN(j, 8 - len)" will never be out of bounds.
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
14
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
13
---
19
block/vvfat.c | 5 +++--
14
tests/qemu-iotests/iotests.py | 5 +++--
20
1 file changed, 3 insertions(+), 2 deletions(-)
15
1 file changed, 3 insertions(+), 2 deletions(-)
21
16
22
diff --git a/block/vvfat.c b/block/vvfat.c
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
23
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
24
--- a/block/vvfat.c
19
--- a/tests/qemu-iotests/iotests.py
25
+++ b/block/vvfat.c
20
+++ b/tests/qemu-iotests/iotests.py
26
@@ -XXX,XX +XXX,XX @@ static direntry_t *create_short_filename(BDRVVVFATState *s,
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
27
const gchar *p, *last_dot = NULL;
22
for line in output.split('\n'):
28
gunichar c;
23
if 'disk size' in line or 'actual-size' in line:
29
bool lossy_conversion = false;
24
continue
30
- char tail[11];
25
- line = line.replace(filename, 'TEST_IMG') \
31
+ char tail[8];
26
- .replace(imgfmt, 'IMGFMT')
32
27
+ line = line.replace(filename, 'TEST_IMG')
33
if (!entry) {
28
+ line = filter_testfiles(line)
34
return NULL;
29
+ line = line.replace(imgfmt, 'IMGFMT')
35
@@ -XXX,XX +XXX,XX @@ static direntry_t *create_short_filename(BDRVVVFATState *s,
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
36
for (i = lossy_conversion ? 1 : 0; i < 999999; i++) {
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
37
direntry_t *entry1;
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
38
if (i > 0) {
39
- int len = sprintf(tail, "~%d", i);
40
+ int len = snprintf(tail, sizeof(tail), "~%u", (unsigned)i);
41
+ assert(len <= 7);
42
memcpy(entry->name + MIN(j, 8 - len), tail, len);
43
}
44
for (entry1 = array_get(&(s->directory), directory_start);
45
--
33
--
46
1.8.3.1
34
2.25.3
47
35
48
36
diff view generated by jsdifflib
1
This test makes sure that all block devices show up on 'info block',
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
with all of the expected information, in different configurations.
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 424 insertions(+)
11
create mode 100755 tests/qemu-iotests/274
12
create mode 100644 tests/qemu-iotests/274.out
3
13
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
---
8
tests/qemu-iotests/186 | 147 ++++++++++++++
9
tests/qemu-iotests/186.out | 489 +++++++++++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/group | 1 +
11
3 files changed, 637 insertions(+)
12
create mode 100755 tests/qemu-iotests/186
13
create mode 100644 tests/qemu-iotests/186.out
14
15
diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186
16
new file mode 100755
15
new file mode 100755
17
index XXXXXXX..XXXXXXX
16
index XXXXXXX..XXXXXXX
18
--- /dev/null
17
--- /dev/null
19
+++ b/tests/qemu-iotests/186
18
+++ b/tests/qemu-iotests/274
20
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
21
+#!/bin/bash
20
+#!/usr/bin/env python3
22
+#
21
+#
23
+# Test 'info block' with all kinds of configurations
22
+# Copyright (C) 2019 Red Hat, Inc.
24
+#
25
+# Copyright (C) 2017 Red Hat, Inc.
26
+#
23
+#
27
+# This program is free software; you can redistribute it and/or modify
24
+# This program is free software; you can redistribute it and/or modify
28
+# it under the terms of the GNU General Public License as published by
25
+# it under the terms of the GNU General Public License as published by
29
+# the Free Software Foundation; either version 2 of the License, or
26
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
27
+# (at your option) any later version.
...
...
35
+# GNU General Public License for more details.
32
+# GNU General Public License for more details.
36
+#
33
+#
37
+# You should have received a copy of the GNU General Public License
34
+# You should have received a copy of the GNU General Public License
38
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+#
36
+#
40
+
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
41
+# creator
38
+#
42
+owner=kwolf@redhat.com
39
+# Some tests for short backing files and short overlays
43
+
40
+
44
+seq=`basename $0`
41
+import iotests
45
+echo "QA output created by $seq"
42
+
46
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
47
+here=`pwd`
44
+iotests.verify_platform(['linux'])
48
+status=1    # failure is the default!
45
+
49
+
46
+size_short = 1 * 1024 * 1024
50
+_cleanup()
47
+size_long = 2 * 1024 * 1024
51
+{
48
+size_diff = size_long - size_short
52
+    _cleanup_test_img
49
+
53
+}
50
+def create_chain() -> None:
54
+trap "_cleanup; exit \$status" 0 1 2 3 15
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
55
+
52
+ str(size_long))
56
+# get standard environment, filters and checks
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
57
+. ./common.rc
54
+ str(size_short))
58
+. ./common.filter
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
59
+
56
+ str(size_long))
60
+_supported_fmt qcow2
57
+
61
+_supported_proto file
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
62
+_supported_os Linux
59
+
63
+
60
+def create_vm() -> iotests.VM:
64
+if [ "$QEMU_DEFAULT_MACHINE" != "pc" ]; then
61
+ vm = iotests.VM()
65
+ _notrun "Requires a PC machine"
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
66
+fi
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
67
+
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
68
+function do_run_qemu()
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
69
+{
66
+ % iotests.imgfmt)
70
+ echo Testing: "$@"
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
71
+
68
+ return vm
72
+ (
69
+
73
+ if ! test -t 0; then
70
+with iotests.FilePath('base') as base, \
74
+ while read cmd; do
71
+ iotests.FilePath('mid') as mid, \
75
+ echo $cmd
72
+ iotests.FilePath('top') as top:
76
+ done
73
+
77
+ fi
74
+ iotests.log('== Commit tests ==')
78
+ echo quit
75
+
79
+ ) | $QEMU -S -nodefaults -display none -device virtio-scsi-pci -monitor stdio "$@"
76
+ create_chain()
80
+ echo
77
+
81
+}
78
+ iotests.log('=== Check visible data ===')
82
+
79
+
83
+function check_info_block()
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
84
+{
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
85
+ echo "info block" |
82
+
86
+ QEMU_OPTIONS="" do_run_qemu "$@" | _filter_win32 | _filter_hmp |
83
+ iotests.log('=== Checking allocation status ===')
87
+ _filter_qemu | _filter_generated_node_ids
84
+
88
+}
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
89
+
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
90
+
87
+ base)
91
+size=64M
88
+
92
+_make_test_img $size
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
93
+
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
94
+removable="floppy ide-cd scsi-cd"
91
+ mid)
95
+fixed="ide-hd scsi-hd virtio-blk-pci"
92
+
96
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
97
+echo
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
98
+echo "=== Empty drives ==="
95
+ top)
99
+echo
96
+
100
+
97
+ iotests.log('=== Checking map ===')
101
+for dev in $removable; do
98
+
102
+ check_info_block -device $dev
99
+ iotests.qemu_img_log('map', '--output=json', base)
103
+ check_info_block -device $dev,id=qdev_id
100
+ iotests.qemu_img_log('map', '--output=human', base)
104
+done
101
+ iotests.qemu_img_log('map', '--output=json', mid)
105
+
102
+ iotests.qemu_img_log('map', '--output=human', mid)
106
+echo
103
+ iotests.qemu_img_log('map', '--output=json', top)
107
+echo "=== -blockdev/-device=<node-name> ==="
104
+ iotests.qemu_img_log('map', '--output=human', top)
108
+echo
105
+
109
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
110
+for dev in $fixed $removable; do
107
+
111
+ check_info_block -blockdev driver=null-co,node-name=null -device $dev,drive=null
108
+ iotests.qemu_img_log('commit', top)
112
+ check_info_block -blockdev driver=null-co,node-name=null -device $dev,drive=null,id=qdev_id
109
+ iotests.img_info_log(mid)
113
+done
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
114
+
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
115
+echo
112
+
116
+echo "=== -drive if=none/-device=<node-name> ==="
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
117
+echo
114
+
118
+
115
+ create_chain()
119
+# This creates two BlockBackends that will show up in 'info block'!
116
+ with create_vm() as vm:
120
+# A monitor-owned one from -drive, and anonymous one from -device
117
+ vm.launch()
121
+for dev in $fixed $removable; do
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
122
+ check_info_block -drive if=none,driver=null-co,node-name=null -device $dev,drive=null,id=qdev_id
119
+
123
+done
120
+ iotests.img_info_log(mid)
124
+
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
125
+echo
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
126
+echo "=== -drive if=none/-device=<bb-name> (with medium) ==="
123
+
127
+echo
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
128
+
125
+
129
+for dev in $fixed $removable; do
126
+ create_chain()
130
+ check_info_block -drive if=none,driver=null-co,node-name=null -device $dev,drive=none0
127
+ with create_vm() as vm:
131
+ check_info_block -drive if=none,driver=null-co,node-name=null -device $dev,drive=none0,id=qdev_id
128
+ vm.launch()
132
+done
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
133
+
130
+ job_id='job0', auto_dismiss=False)
134
+echo
131
+ vm.run_job('job0', wait=5)
135
+echo "=== -drive if=none/-device=<bb-name> (without medium) ==="
132
+
136
+echo
133
+ iotests.img_info_log(mid)
137
+
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
138
+check_info_block -drive if=none
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
139
+
136
+
140
+for dev in $removable; do
137
+
141
+ check_info_block -drive if=none -device $dev,drive=none0
138
+ iotests.log('== Resize tests ==')
142
+ check_info_block -drive if=none -device $dev,drive=none0,id=qdev_id
139
+
143
+done
140
+ # Use different sizes for different allocation modes:
144
+
141
+ #
145
+echo
142
+ # We want to have at least one test where 32 bit truncation in the size of
146
+echo "=== -drive if=... ==="
143
+ # the overlapping area becomes visible. This is covered by the
147
+echo
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
148
+
145
+ #
149
+check_info_block -drive if=floppy
146
+ # However, we can only do this for modes that don't preallocate data
150
+check_info_block -drive if=floppy,driver=null-co
147
+ # because otherwise we might run out of space on the test host.
151
+
148
+ #
152
+check_info_block -drive if=ide,driver=null-co
149
+ # We also want to test some unaligned combinations.
153
+check_info_block -drive if=ide,media=cdrom
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
154
+check_info_block -drive if=ide,driver=null-co,media=cdrom
151
+ ('off', '6G', '1G', '8G', '5G'),
155
+
152
+ ('metadata', '32G', '30G', '33G', '31G'),
156
+check_info_block -drive if=scsi,driver=null-co
153
+ ('falloc', '10M', '5M', '15M', '9M'),
157
+check_info_block -drive if=scsi,media=cdrom
154
+ ('full', '16M', '8M', '12M', '11M'),
158
+check_info_block -drive if=scsi,driver=null-co,media=cdrom
155
+ ('off', '384k', '253k', '512k', '253k'),
159
+
156
+ ('off', '400k', '256k', '512k', '336k'),
160
+check_info_block -drive if=virtio,driver=null-co
157
+ ('off', '512k', '256k', '500k', '436k')]:
161
+
158
+
162
+check_info_block -drive if=pflash,driver=null-co,size=1M
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
163
+
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
164
+# success, all done
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
165
+echo "*** done"
162
+ top_size_old)
166
+rm -f $seq.full
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
167
+status=0
164
+
168
diff --git a/tests/qemu-iotests/186.out b/tests/qemu-iotests/186.out
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
166
+ #
167
+ # In theory, leaving base_size to top_size_new unallocated would be
168
+ # correct, but in practice, if we zero out anything, we zero out
169
+ # everything up to top_size_new.
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
171
+ '--preallocation', prealloc, top, top_size_new)
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
173
+ iotests.qemu_io_log('-c', 'map', top)
174
+ iotests.qemu_img_log('map', '--output=json', top)
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
169
new file mode 100644
176
new file mode 100644
170
index XXXXXXX..XXXXXXX
177
index XXXXXXX..XXXXXXX
171
--- /dev/null
178
--- /dev/null
172
+++ b/tests/qemu-iotests/186.out
179
+++ b/tests/qemu-iotests/274.out
173
@@ -XXX,XX +XXX,XX @@
180
@@ -XXX,XX +XXX,XX @@
174
+QA output created by 186
181
+== Commit tests ==
175
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
176
+
183
+
177
+=== Empty drives ===
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
178
+
185
+
179
+Testing: -device floppy
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
180
+QEMU X.Y.Z monitor - type 'help' for more information
187
+
181
+(qemu) info block
188
+wrote 2097152/2097152 bytes at offset 0
182
+/machine/peripheral-anon/device[1]: [not inserted]
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
183
+ Attached to: /machine/peripheral-anon/device[1]
190
+
184
+ Removable device: not locked, tray closed
191
+=== Check visible data ===
185
+(qemu) quit
192
+read 1048576/1048576 bytes at offset 0
186
+
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
187
+Testing: -device floppy,id=qdev_id
194
+
188
+QEMU X.Y.Z monitor - type 'help' for more information
195
+read 1048576/1048576 bytes at offset 1048576
189
+(qemu) info block
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+qdev_id: [not inserted]
197
+
191
+ Attached to: qdev_id
198
+=== Checking allocation status ===
192
+ Removable device: not locked, tray closed
199
+1048576/1048576 bytes allocated at offset 0 bytes
193
+(qemu) quit
200
+1048576/1048576 bytes allocated at offset 1 MiB
194
+
201
+
195
+Testing: -device ide-cd
202
+0/1048576 bytes allocated at offset 0 bytes
196
+QEMU X.Y.Z monitor - type 'help' for more information
203
+0/0 bytes allocated at offset 1 MiB
197
+(qemu) info block
204
+
198
+/machine/peripheral-anon/device[1]: [not inserted]
205
+0/1048576 bytes allocated at offset 0 bytes
199
+ Attached to: /machine/peripheral-anon/device[1]
206
+0/1048576 bytes allocated at offset 1 MiB
200
+ Removable device: not locked, tray closed
207
+
201
+(qemu) quit
208
+=== Checking map ===
202
+
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
203
+Testing: -device ide-cd,id=qdev_id
210
+
204
+QEMU X.Y.Z monitor - type 'help' for more information
211
+Offset Length Mapped to File
205
+(qemu) info block
212
+0 0x200000 0x50000 TEST_DIR/PID-base
206
+qdev_id: [not inserted]
213
+
207
+ Attached to: qdev_id
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
208
+ Removable device: not locked, tray closed
215
+
209
+(qemu) quit
216
+Offset Length Mapped to File
210
+
217
+0 0x100000 0x50000 TEST_DIR/PID-base
211
+Testing: -device scsi-cd
218
+
212
+QEMU X.Y.Z monitor - type 'help' for more information
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
213
+(qemu) info block
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
214
+/machine/peripheral-anon/device[1]: [not inserted]
221
+
215
+ Attached to: /machine/peripheral-anon/device[1]
222
+Offset Length Mapped to File
216
+ Removable device: not locked, tray closed
223
+0 0x100000 0x50000 TEST_DIR/PID-base
217
+(qemu) quit
224
+
218
+
225
+=== Testing qemu-img commit (top -> mid) ===
219
+Testing: -device scsi-cd,id=qdev_id
226
+Image committed.
220
+QEMU X.Y.Z monitor - type 'help' for more information
227
+
221
+(qemu) info block
228
+image: TEST_IMG
222
+qdev_id: [not inserted]
229
+file format: IMGFMT
223
+ Attached to: qdev_id
230
+virtual size: 2 MiB (2097152 bytes)
224
+ Removable device: not locked, tray closed
231
+cluster_size: 65536
225
+(qemu) quit
232
+backing file: TEST_DIR/PID-base
226
+
233
+Format specific information:
227
+
234
+ compat: 1.1
228
+=== -blockdev/-device=<node-name> ===
235
+ lazy refcounts: false
229
+
236
+ refcount bits: 16
230
+Testing: -blockdev driver=null-co,node-name=null -device ide-hd,drive=null
237
+ corrupt: false
231
+QEMU X.Y.Z monitor - type 'help' for more information
238
+
232
+(qemu) info block
239
+read 1048576/1048576 bytes at offset 0
233
+null: null-co:// (null-co)
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
234
+ Attached to: /machine/peripheral-anon/device[1]
241
+
235
+ Cache mode: writeback
242
+read 1048576/1048576 bytes at offset 1048576
236
+(qemu) quit
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
237
+
244
+
238
+Testing: -blockdev driver=null-co,node-name=null -device ide-hd,drive=null,id=qdev_id
245
+=== Testing HMP commit (top -> mid) ===
239
+QEMU X.Y.Z monitor - type 'help' for more information
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
240
+(qemu) info block
247
+
241
+null: null-co:// (null-co)
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
242
+ Attached to: qdev_id
249
+
243
+ Cache mode: writeback
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
244
+(qemu) quit
251
+
245
+
252
+wrote 2097152/2097152 bytes at offset 0
246
+Testing: -blockdev driver=null-co,node-name=null -device scsi-hd,drive=null
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
247
+QEMU X.Y.Z monitor - type 'help' for more information
254
+
248
+(qemu) info block
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
249
+null: null-co:// (null-co)
256
+{"return": ""}
250
+ Attached to: /machine/peripheral-anon/device[1]
257
+image: TEST_IMG
251
+ Cache mode: writeback
258
+file format: IMGFMT
252
+(qemu) quit
259
+virtual size: 2 MiB (2097152 bytes)
253
+
260
+cluster_size: 65536
254
+Testing: -blockdev driver=null-co,node-name=null -device scsi-hd,drive=null,id=qdev_id
261
+backing file: TEST_DIR/PID-base
255
+QEMU X.Y.Z monitor - type 'help' for more information
262
+Format specific information:
256
+(qemu) info block
263
+ compat: 1.1
257
+null: null-co:// (null-co)
264
+ lazy refcounts: false
258
+ Attached to: qdev_id
265
+ refcount bits: 16
259
+ Cache mode: writeback
266
+ corrupt: false
260
+(qemu) quit
267
+
261
+
268
+read 1048576/1048576 bytes at offset 0
262
+Testing: -blockdev driver=null-co,node-name=null -device virtio-blk-pci,drive=null
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
263
+QEMU X.Y.Z monitor - type 'help' for more information
270
+
264
+(qemu) info block
271
+read 1048576/1048576 bytes at offset 1048576
265
+null: null-co:// (null-co)
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
266
+ Attached to: /machine/peripheral-anon/device[1]/virtio-backend
273
+
267
+ Cache mode: writeback
274
+=== Testing QMP active commit (top -> mid) ===
268
+(qemu) quit
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
269
+
276
+
270
+Testing: -blockdev driver=null-co,node-name=null -device virtio-blk-pci,drive=null,id=qdev_id
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
271
+QEMU X.Y.Z monitor - type 'help' for more information
278
+
272
+(qemu) info block
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
273
+null: null-co:// (null-co)
280
+
274
+ Attached to: /machine/peripheral/qdev_id/virtio-backend
281
+wrote 2097152/2097152 bytes at offset 0
275
+ Cache mode: writeback
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
276
+(qemu) quit
283
+
277
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
278
+Testing: -blockdev driver=null-co,node-name=null -device floppy,drive=null
285
+{"return": {}}
279
+QEMU X.Y.Z monitor - type 'help' for more information
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
280
+(qemu) info block
287
+{"return": {}}
281
+null: null-co:// (null-co)
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
282
+ Attached to: /machine/peripheral-anon/device[1]
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
283
+ Removable device: not locked, tray closed
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
284
+ Cache mode: writeback
291
+{"return": {}}
285
+(qemu) quit
292
+image: TEST_IMG
286
+
293
+file format: IMGFMT
287
+Testing: -blockdev driver=null-co,node-name=null -device floppy,drive=null,id=qdev_id
294
+virtual size: 2 MiB (2097152 bytes)
288
+QEMU X.Y.Z monitor - type 'help' for more information
295
+cluster_size: 65536
289
+(qemu) info block
296
+backing file: TEST_DIR/PID-base
290
+null: null-co:// (null-co)
297
+Format specific information:
291
+ Attached to: qdev_id
298
+ compat: 1.1
292
+ Removable device: not locked, tray closed
299
+ lazy refcounts: false
293
+ Cache mode: writeback
300
+ refcount bits: 16
294
+(qemu) quit
301
+ corrupt: false
295
+
302
+
296
+Testing: -blockdev driver=null-co,node-name=null -device ide-cd,drive=null
303
+read 1048576/1048576 bytes at offset 0
297
+QEMU X.Y.Z monitor - type 'help' for more information
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
298
+(qemu) info block
305
+
299
+null: null-co:// (null-co)
306
+read 1048576/1048576 bytes at offset 1048576
300
+ Attached to: /machine/peripheral-anon/device[1]
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
301
+ Removable device: not locked, tray closed
308
+
302
+ Cache mode: writeback
309
+== Resize tests ==
303
+(qemu) quit
310
+=== preallocation=off ===
304
+
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
305
+Testing: -blockdev driver=null-co,node-name=null -device ide-cd,drive=null,id=qdev_id
312
+
306
+QEMU X.Y.Z monitor - type 'help' for more information
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
307
+(qemu) info block
314
+
308
+null: null-co:// (null-co)
315
+wrote 65536/65536 bytes at offset 5368709120
309
+ Attached to: qdev_id
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
310
+ Removable device: not locked, tray closed
317
+
311
+ Cache mode: writeback
318
+Image resized.
312
+(qemu) quit
319
+
313
+
320
+read 65536/65536 bytes at offset 5368709120
314
+Testing: -blockdev driver=null-co,node-name=null -device scsi-cd,drive=null
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
315
+QEMU X.Y.Z monitor - type 'help' for more information
322
+
316
+(qemu) info block
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
317
+null: null-co:// (null-co)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
318
+ Attached to: /machine/peripheral-anon/device[1]
325
+
319
+ Removable device: not locked, tray closed
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
320
+ Cache mode: writeback
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
321
+(qemu) quit
328
+
322
+
329
+=== preallocation=metadata ===
323
+Testing: -blockdev driver=null-co,node-name=null -device scsi-cd,drive=null,id=qdev_id
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
324
+QEMU X.Y.Z monitor - type 'help' for more information
331
+
325
+(qemu) info block
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
326
+null: null-co:// (null-co)
333
+
327
+ Attached to: qdev_id
334
+wrote 65536/65536 bytes at offset 33285996544
328
+ Removable device: not locked, tray closed
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
329
+ Cache mode: writeback
336
+
330
+(qemu) quit
337
+Image resized.
331
+
338
+
332
+
339
+read 65536/65536 bytes at offset 33285996544
333
+=== -drive if=none/-device=<node-name> ===
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
334
+
341
+
335
+Testing: -drive if=none,driver=null-co,node-name=null -device ide-hd,drive=null,id=qdev_id
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
336
+QEMU X.Y.Z monitor - type 'help' for more information
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
337
+(qemu) info block
344
+
338
+none0 (null): null-co:// (null-co)
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
339
+ Removable device: not locked, tray closed
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
340
+ Cache mode: writeback
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
341
+
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
342
+null: null-co:// (null-co)
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
343
+ Attached to: qdev_id
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
344
+ Cache mode: writeback
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
345
+(qemu) quit
352
+
346
+
353
+=== preallocation=falloc ===
347
+Testing: -drive if=none,driver=null-co,node-name=null -device scsi-hd,drive=null,id=qdev_id
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
348
+QEMU X.Y.Z monitor - type 'help' for more information
355
+
349
+(qemu) info block
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
350
+none0 (null): null-co:// (null-co)
357
+
351
+ Removable device: not locked, tray closed
358
+wrote 65536/65536 bytes at offset 9437184
352
+ Cache mode: writeback
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
353
+
360
+
354
+null: null-co:// (null-co)
361
+Image resized.
355
+ Attached to: qdev_id
362
+
356
+ Cache mode: writeback
363
+read 65536/65536 bytes at offset 9437184
357
+(qemu) quit
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
358
+
365
+
359
+Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,drive=null,id=qdev_id
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
360
+QEMU X.Y.Z monitor - type 'help' for more information
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
361
+(qemu) info block
368
+
362
+none0 (null): null-co:// (null-co)
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
363
+ Removable device: not locked, tray closed
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
364
+ Cache mode: writeback
371
+
365
+
372
+=== preallocation=full ===
366
+null: null-co:// (null-co)
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
367
+ Attached to: /machine/peripheral/qdev_id/virtio-backend
374
+
368
+ Cache mode: writeback
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
369
+(qemu) quit
376
+
370
+
377
+wrote 65536/65536 bytes at offset 11534336
371
+Testing: -drive if=none,driver=null-co,node-name=null -device floppy,drive=null,id=qdev_id
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
372
+QEMU X.Y.Z monitor - type 'help' for more information
379
+
373
+(qemu) info block
380
+Image resized.
374
+none0 (null): null-co:// (null-co)
381
+
375
+ Removable device: not locked, tray closed
382
+read 65536/65536 bytes at offset 11534336
376
+ Cache mode: writeback
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
377
+
384
+
378
+null: null-co:// (null-co)
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
379
+ Attached to: qdev_id
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
380
+ Removable device: not locked, tray closed
387
+
381
+ Cache mode: writeback
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
382
+(qemu) quit
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
383
+
390
+
384
+Testing: -drive if=none,driver=null-co,node-name=null -device ide-cd,drive=null,id=qdev_id
391
+=== preallocation=off ===
385
+QEMU X.Y.Z monitor - type 'help' for more information
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
386
+(qemu) info block
393
+
387
+none0 (null): null-co:// (null-co)
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
388
+ Removable device: not locked, tray closed
395
+
389
+ Cache mode: writeback
396
+wrote 65536/65536 bytes at offset 259072
390
+
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
391
+null: null-co:// (null-co)
398
+
392
+ Attached to: qdev_id
399
+Image resized.
393
+ Removable device: not locked, tray closed
400
+
394
+ Cache mode: writeback
401
+read 65536/65536 bytes at offset 259072
395
+(qemu) quit
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
396
+
403
+
397
+Testing: -drive if=none,driver=null-co,node-name=null -device scsi-cd,drive=null,id=qdev_id
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
398
+QEMU X.Y.Z monitor - type 'help' for more information
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
399
+(qemu) info block
406
+
400
+none0 (null): null-co:// (null-co)
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
401
+ Removable device: not locked, tray closed
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
402
+ Cache mode: writeback
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
403
+
410
+
404
+null: null-co:// (null-co)
411
+=== preallocation=off ===
405
+ Attached to: qdev_id
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
406
+ Removable device: not locked, tray closed
413
+
407
+ Cache mode: writeback
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
408
+(qemu) quit
415
+
409
+
416
+wrote 65536/65536 bytes at offset 344064
410
+
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
411
+=== -drive if=none/-device=<bb-name> (with medium) ===
418
+
412
+
419
+Image resized.
413
+Testing: -drive if=none,driver=null-co,node-name=null -device ide-hd,drive=none0
420
+
414
+QEMU X.Y.Z monitor - type 'help' for more information
421
+read 65536/65536 bytes at offset 344064
415
+(qemu) info block
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
416
+none0 (null): null-co:// (null-co)
423
+
417
+ Attached to: /machine/peripheral-anon/device[1]
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
418
+ Cache mode: writeback
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
419
+(qemu) quit
426
+
420
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
421
+Testing: -drive if=none,driver=null-co,node-name=null -device ide-hd,drive=none0,id=qdev_id
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
422
+QEMU X.Y.Z monitor - type 'help' for more information
429
+
423
+(qemu) info block
430
+=== preallocation=off ===
424
+none0 (null): null-co:// (null-co)
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
425
+ Attached to: qdev_id
432
+
426
+ Cache mode: writeback
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
427
+(qemu) quit
434
+
428
+
435
+wrote 65536/65536 bytes at offset 446464
429
+Testing: -drive if=none,driver=null-co,node-name=null -device scsi-hd,drive=none0
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
430
+QEMU X.Y.Z monitor - type 'help' for more information
437
+
431
+(qemu) info block
438
+Image resized.
432
+none0 (null): null-co:// (null-co)
439
+
433
+ Attached to: /machine/peripheral-anon/device[1]
440
+read 65536/65536 bytes at offset 446464
434
+ Cache mode: writeback
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
435
+(qemu) quit
442
+
436
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
437
+Testing: -drive if=none,driver=null-co,node-name=null -device scsi-hd,drive=none0,id=qdev_id
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
438
+QEMU X.Y.Z monitor - type 'help' for more information
445
+
439
+(qemu) info block
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
440
+none0 (null): null-co:// (null-co)
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
441
+ Attached to: qdev_id
448
+
442
+ Cache mode: writeback
443
+(qemu) quit
444
+
445
+Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,drive=none0
446
+QEMU X.Y.Z monitor - type 'help' for more information
447
+(qemu) info block
448
+none0 (null): null-co:// (null-co)
449
+ Attached to: /machine/peripheral-anon/device[1]/virtio-backend
450
+ Cache mode: writeback
451
+(qemu) quit
452
+
453
+Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,drive=none0,id=qdev_id
454
+QEMU X.Y.Z monitor - type 'help' for more information
455
+(qemu) info block
456
+none0 (null): null-co:// (null-co)
457
+ Attached to: /machine/peripheral/qdev_id/virtio-backend
458
+ Cache mode: writeback
459
+(qemu) quit
460
+
461
+Testing: -drive if=none,driver=null-co,node-name=null -device floppy,drive=none0
462
+QEMU X.Y.Z monitor - type 'help' for more information
463
+(qemu) info block
464
+none0 (null): null-co:// (null-co)
465
+ Attached to: /machine/peripheral-anon/device[1]
466
+ Removable device: not locked, tray closed
467
+ Cache mode: writeback
468
+(qemu) quit
469
+
470
+Testing: -drive if=none,driver=null-co,node-name=null -device floppy,drive=none0,id=qdev_id
471
+QEMU X.Y.Z monitor - type 'help' for more information
472
+(qemu) info block
473
+none0 (null): null-co:// (null-co)
474
+ Attached to: qdev_id
475
+ Removable device: not locked, tray closed
476
+ Cache mode: writeback
477
+(qemu) quit
478
+
479
+Testing: -drive if=none,driver=null-co,node-name=null -device ide-cd,drive=none0
480
+QEMU X.Y.Z monitor - type 'help' for more information
481
+(qemu) info block
482
+none0 (null): null-co:// (null-co)
483
+ Attached to: /machine/peripheral-anon/device[1]
484
+ Removable device: not locked, tray closed
485
+ Cache mode: writeback
486
+(qemu) quit
487
+
488
+Testing: -drive if=none,driver=null-co,node-name=null -device ide-cd,drive=none0,id=qdev_id
489
+QEMU X.Y.Z monitor - type 'help' for more information
490
+(qemu) info block
491
+none0 (null): null-co:// (null-co)
492
+ Attached to: qdev_id
493
+ Removable device: not locked, tray closed
494
+ Cache mode: writeback
495
+(qemu) quit
496
+
497
+Testing: -drive if=none,driver=null-co,node-name=null -device scsi-cd,drive=none0
498
+QEMU X.Y.Z monitor - type 'help' for more information
499
+(qemu) info block
500
+none0 (null): null-co:// (null-co)
501
+ Attached to: /machine/peripheral-anon/device[1]
502
+ Removable device: not locked, tray closed
503
+ Cache mode: writeback
504
+(qemu) quit
505
+
506
+Testing: -drive if=none,driver=null-co,node-name=null -device scsi-cd,drive=none0,id=qdev_id
507
+QEMU X.Y.Z monitor - type 'help' for more information
508
+(qemu) info block
509
+none0 (null): null-co:// (null-co)
510
+ Attached to: qdev_id
511
+ Removable device: not locked, tray closed
512
+ Cache mode: writeback
513
+(qemu) quit
514
+
515
+
516
+=== -drive if=none/-device=<bb-name> (without medium) ===
517
+
518
+Testing: -drive if=none
519
+QEMU X.Y.Z monitor - type 'help' for more information
520
+(qemu) info block
521
+none0: [not inserted]
522
+ Removable device: not locked, tray closed
523
+(qemu) quit
524
+
525
+Testing: -drive if=none -device floppy,drive=none0
526
+QEMU X.Y.Z monitor - type 'help' for more information
527
+(qemu) info block
528
+none0: [not inserted]
529
+ Attached to: /machine/peripheral-anon/device[1]
530
+ Removable device: not locked, tray closed
531
+(qemu) quit
532
+
533
+Testing: -drive if=none -device floppy,drive=none0,id=qdev_id
534
+QEMU X.Y.Z monitor - type 'help' for more information
535
+(qemu) info block
536
+none0: [not inserted]
537
+ Attached to: qdev_id
538
+ Removable device: not locked, tray closed
539
+(qemu) quit
540
+
541
+Testing: -drive if=none -device ide-cd,drive=none0
542
+QEMU X.Y.Z monitor - type 'help' for more information
543
+(qemu) info block
544
+none0: [not inserted]
545
+ Attached to: /machine/peripheral-anon/device[1]
546
+ Removable device: not locked, tray closed
547
+(qemu) quit
548
+
549
+Testing: -drive if=none -device ide-cd,drive=none0,id=qdev_id
550
+QEMU X.Y.Z monitor - type 'help' for more information
551
+(qemu) info block
552
+none0: [not inserted]
553
+ Attached to: qdev_id
554
+ Removable device: not locked, tray closed
555
+(qemu) quit
556
+
557
+Testing: -drive if=none -device scsi-cd,drive=none0
558
+QEMU X.Y.Z monitor - type 'help' for more information
559
+(qemu) info block
560
+none0: [not inserted]
561
+ Attached to: /machine/peripheral-anon/device[1]
562
+ Removable device: not locked, tray closed
563
+(qemu) quit
564
+
565
+Testing: -drive if=none -device scsi-cd,drive=none0,id=qdev_id
566
+QEMU X.Y.Z monitor - type 'help' for more information
567
+(qemu) info block
568
+none0: [not inserted]
569
+ Attached to: qdev_id
570
+ Removable device: not locked, tray closed
571
+(qemu) quit
572
+
573
+
574
+=== -drive if=... ===
575
+
576
+Testing: -drive if=floppy
577
+QEMU X.Y.Z monitor - type 'help' for more information
578
+(qemu) info block
579
+floppy0: [not inserted]
580
+ Attached to: /machine/unattached/device[17]
581
+ Removable device: not locked, tray closed
582
+(qemu) quit
583
+
584
+Testing: -drive if=floppy,driver=null-co
585
+QEMU X.Y.Z monitor - type 'help' for more information
586
+(qemu) info block
587
+floppy0 (NODE_NAME): null-co:// (null-co)
588
+ Attached to: /machine/unattached/device[17]
589
+ Removable device: not locked, tray closed
590
+ Cache mode: writeback
591
+(qemu) quit
592
+
593
+Testing: -drive if=ide,driver=null-co
594
+QEMU X.Y.Z monitor - type 'help' for more information
595
+(qemu) info block
596
+ide0-hd0 (NODE_NAME): null-co:// (null-co)
597
+ Attached to: /machine/unattached/device[18]
598
+ Cache mode: writeback
599
+(qemu) quit
600
+
601
+Testing: -drive if=ide,media=cdrom
602
+QEMU X.Y.Z monitor - type 'help' for more information
603
+(qemu) info block
604
+ide0-cd0: [not inserted]
605
+ Attached to: /machine/unattached/device[18]
606
+ Removable device: not locked, tray closed
607
+(qemu) quit
608
+
609
+Testing: -drive if=ide,driver=null-co,media=cdrom
610
+QEMU X.Y.Z monitor - type 'help' for more information
611
+(qemu) info block
612
+ide0-cd0 (NODE_NAME): null-co:// (null-co, read-only)
613
+ Attached to: /machine/unattached/device[18]
614
+ Removable device: not locked, tray closed
615
+ Cache mode: writeback
616
+(qemu) quit
617
+
618
+warning: qemu-system-x86_64: -drive if=scsi,driver=null-co: bus=0,unit=0 is deprecated with this machine type
619
+Testing: -drive if=scsi,driver=null-co
620
+QEMU X.Y.Z monitor - type 'help' for more information
621
+(qemu) info block
622
+scsi0-hd0 (NODE_NAME): null-co:// (null-co)
623
+ Attached to: /machine/unattached/device[27]/scsi.0/legacy[0]
624
+ Cache mode: writeback
625
+(qemu) quit
626
+
627
+warning: qemu-system-x86_64: -drive if=scsi,media=cdrom: bus=0,unit=0 is deprecated with this machine type
628
+Testing: -drive if=scsi,media=cdrom
629
+QEMU X.Y.Z monitor - type 'help' for more information
630
+(qemu) info block
631
+scsi0-cd0: [not inserted]
632
+ Attached to: /machine/unattached/device[27]/scsi.0/legacy[0]
633
+ Removable device: not locked, tray closed
634
+(qemu) quit
635
+
636
+warning: qemu-system-x86_64: -drive if=scsi,driver=null-co,media=cdrom: bus=0,unit=0 is deprecated with this machine type
637
+Testing: -drive if=scsi,driver=null-co,media=cdrom
638
+QEMU X.Y.Z monitor - type 'help' for more information
639
+(qemu) info block
640
+scsi0-cd0 (NODE_NAME): null-co:// (null-co, read-only)
641
+ Attached to: /machine/unattached/device[27]/scsi.0/legacy[0]
642
+ Removable device: not locked, tray closed
643
+ Cache mode: writeback
644
+(qemu) quit
645
+
646
+Testing: -drive if=virtio,driver=null-co
647
+QEMU X.Y.Z monitor - type 'help' for more information
648
+(qemu) info block
649
+virtio0 (NODE_NAME): null-co:// (null-co)
650
+ Attached to: /machine/peripheral-anon/device[1]/virtio-backend
651
+ Cache mode: writeback
652
+(qemu) quit
653
+
654
+Testing: -drive if=pflash,driver=null-co,size=1M
655
+QEMU X.Y.Z monitor - type 'help' for more information
656
+(qemu) info block
657
+pflash0 (NODE_NAME): json:{"driver": "null-co", "size": "1M"} (null-co)
658
+ Attached to: /machine/unattached/device[2]
659
+ Cache mode: writeback
660
+(qemu) quit
661
+
662
+*** done
663
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
664
index XXXXXXX..XXXXXXX 100644
450
index XXXXXXX..XXXXXXX 100644
665
--- a/tests/qemu-iotests/group
451
--- a/tests/qemu-iotests/group
666
+++ b/tests/qemu-iotests/group
452
+++ b/tests/qemu-iotests/group
667
@@ -XXX,XX +XXX,XX @@
453
@@ -XXX,XX +XXX,XX @@
668
182 rw auto quick
454
270 rw backing quick
669
183 rw auto migration
455
272 rw
670
185 rw auto
456
273 backing quick
671
+186 rw auto
457
+274 rw backing
672
188 rw auto quick
458
277 rw quick
673
189 rw auto quick
459
279 rw backing quick
460
280 rw migration quick
674
--
461
--
675
1.8.3.1
462
2.25.3
676
463
677
464
diff view generated by jsdifflib
1
This caused an assertion failure until recently because the BlockBackend
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
2
would be detached on unplug, but was in fact never attached in the first
2
image is possibly preallocated and then the zero flag is added to all
3
place. Add a regression test.
3
clusters. This means that a copy-on-write operation may be needed when
4
writing to these clusters, despite having used preallocation, negating
5
one of the major benefits of preallocation.
6
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
8
and if the protocol driver can ensure that the new area reads as zeros,
9
we can skip setting the zero flag in the qcow2 layer.
10
11
Unfortunately, the same approach doesn't work for metadata
12
preallocation, so we'll still set the zero flag there.
4
13
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
19
---
9
tests/qemu-iotests/067 | 13 +++++++++++++
20
block/qcow2.c | 22 +++++++++++++++++++---
10
tests/qemu-iotests/067.out | 39 +++++++++++++++++++++++++++++++++++++++
21
tests/qemu-iotests/274.out | 4 ++--
11
2 files changed, 52 insertions(+)
22
2 files changed, 21 insertions(+), 5 deletions(-)
12
23
13
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
24
diff --git a/block/qcow2.c b/block/qcow2.c
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/067
16
+++ b/tests/qemu-iotests/067
17
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
18
{ "execute": "quit" }
19
EOF
20
21
+echo
22
+echo === Empty drive with -device and device_del ===
23
+echo
24
+
25
+run_qemu -device virtio-scsi-pci -device scsi-cd,id=cd0 <<EOF
26
+{ "execute": "qmp_capabilities" }
27
+{ "execute": "query-block" }
28
+{ "execute": "device_del", "arguments": { "id": "cd0" } }
29
+{ "execute": "system_reset" }
30
+{ "execute": "query-block" }
31
+{ "execute": "quit" }
32
+EOF
33
+
34
# success, all done
35
echo "*** done"
36
rm -f $seq.full
37
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
38
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
39
--- a/tests/qemu-iotests/067.out
26
--- a/block/qcow2.c
40
+++ b/tests/qemu-iotests/067.out
27
+++ b/block/qcow2.c
41
@@ -XXX,XX +XXX,XX @@ Testing:
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
42
"return": {
29
/* Allocate the data area */
43
}
30
new_file_size = allocation_start +
44
}
31
nb_new_data_clusters * s->cluster_size;
45
+
32
- /* Image file grows, so @exact does not matter */
46
+=== Empty drive with -device and device_del ===
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
47
+
34
- errp);
48
+Testing: -device virtio-scsi-pci -device scsi-cd,id=cd0
35
+ /*
49
+{
36
+ * Image file grows, so @exact does not matter.
50
+ QMP_VERSION
37
+ *
51
+}
38
+ * If we need to zero out the new area, try first whether the protocol
52
+{
39
+ * driver can already take care of this.
53
+ "return": {
40
+ */
54
+ }
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
55
+}
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
56
+{
43
+ BDRV_REQ_ZERO_WRITE, NULL);
57
+ "return": [
44
+ if (ret >= 0) {
58
+ {
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
59
+ "device": "",
46
+ }
60
+ "locked": false,
47
+ } else {
61
+ "removable": true,
48
+ ret = -1;
62
+ "qdev": "cd0",
63
+ "tray_open": false,
64
+ "type": "unknown"
65
+ }
49
+ }
66
+ ]
50
+ if (ret < 0) {
67
+}
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
68
+{
52
+ errp);
69
+ "return": {
53
+ }
70
+ }
54
if (ret < 0) {
71
+}
55
error_prepend(errp, "Failed to resize underlying file: ");
72
+{
56
qcow2_free_clusters(bs, allocation_start,
73
+ "return": {
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
74
+ }
58
index XXXXXXX..XXXXXXX 100644
75
+}
59
--- a/tests/qemu-iotests/274.out
76
+{
60
+++ b/tests/qemu-iotests/274.out
77
+ "return": [
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
78
+ ]
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
79
+}
63
80
+{
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
81
+ "return": {
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
82
+ }
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
83
+}
67
84
*** done
68
=== preallocation=full ===
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
72
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
85
--
79
--
86
1.8.3.1
80
2.25.3
87
81
88
82
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
2
2
3
Write support works again when image contains non-ASCII names. It is either the
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
case when user created a non-ASCII filename, or when initial directory contained
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
a non-ASCII filename (since 0c36111f57ec2188f679e7fa810291b7386bdca1)
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
persistent across system reboot.
6
8
7
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
15
---
10
block/vvfat.c | 59 +++++++++++++++++++++++++++++++++++++----------------------
16
hw/block/nvme.h | 2 +
11
1 file changed, 37 insertions(+), 22 deletions(-)
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
19
hw/block/Makefile.objs | 2 +-
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
12
22
13
diff --git a/block/vvfat.c b/block/vvfat.c
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
14
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
15
--- a/block/vvfat.c
25
--- a/hw/block/nvme.h
16
+++ b/block/vvfat.c
26
+++ b/hw/block/nvme.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
18
* filename length is 0x3f * 13 bytes.
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
19
*/
29
20
unsigned char name[0x3f * 13 + 1];
30
char *serial;
21
+ gunichar2 name2[0x3f * 13 + 1];
31
+ HostMemoryBackend *pmrdev;
22
int checksum, len;
32
+
23
int sequence_number;
33
NvmeNamespace *namespaces;
24
} long_file_name;
34
NvmeSQueue **sq;
25
@@ -XXX,XX +XXX,XX @@ static int parse_long_name(long_file_name* lfn,
35
NvmeCQueue **cq;
26
return 1;
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
27
37
index XXXXXXX..XXXXXXX 100644
28
if (pointer[0] & 0x40) {
38
--- a/include/block/nvme.h
29
+ /* first entry; do some initialization */
39
+++ b/include/block/nvme.h
30
lfn->sequence_number = pointer[0] & 0x3f;
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
31
lfn->checksum = pointer[13];
41
uint64_t acq;
32
lfn->name[0] = 0;
42
uint32_t cmbloc;
33
lfn->name[lfn->sequence_number * 13] = 0;
43
uint32_t cmbsz;
34
- } else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
44
+ uint8_t padding[3520]; /* not used by QEMU */
35
+ } else if ((pointer[0] & 0x3f) != --lfn->sequence_number) {
45
+ uint32_t pmrcap;
36
+ /* not the expected sequence number */
46
+ uint32_t pmrctl;
37
return -1;
47
+ uint32_t pmrsts;
38
- else if (pointer[13] != lfn->checksum)
48
+ uint32_t pmrebs;
39
+ } else if (pointer[13] != lfn->checksum) {
49
+ uint32_t pmrswtp;
40
+ /* not the expected checksum */
50
+ uint32_t pmrmsc;
41
return -2;
51
} NvmeBar;
42
- else if (pointer[12] || pointer[26] || pointer[27])
52
43
+ } else if (pointer[12] || pointer[26] || pointer[27]) {
53
enum NvmeCapShift {
44
+ /* invalid zero fields */
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
45
return -3;
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
284
return;
285
+ case 0xE00: /* PMRCAP */
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
309
}
310
311
if (addr < sizeof(n->bar)) {
312
+ /*
313
+ * When PMRWBM bit 1 is set then read from
314
+ * from PMRSTS should ensure prior writes
315
+ * made it to persistent media
316
+ */
317
+ if (addr == 0xE08 &&
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
320
+ 0, n->pmrdev->size);
321
+ }
322
memcpy(&val, ptr + addr, size);
323
} else {
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
326
error_setg(errp, "serial property not set");
327
return;
328
}
329
+
330
+ if (!n->cmb_size_mb && n->pmrdev) {
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
334
+ g_free(path);
335
+ return;
336
+ }
337
+
338
+ if (!is_power_of_2(n->pmrdev->size)) {
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
340
+ return;
341
+ }
342
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
46
+ }
344
+ }
47
345
+
48
offset = 13 * (lfn->sequence_number - 1);
346
blkconf_blocksizes(&n->conf);
49
for (i = 0, j = 1; i < 13; i++, j+=2) {
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
50
@@ -XXX,XX +XXX,XX @@ static int parse_long_name(long_file_name* lfn,
348
false, errp)) {
51
else if (j == 26)
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
52
j = 28;
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
53
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
54
- if (pointer[j+1] == 0)
352
55
- lfn->name[offset + i] = pointer[j];
353
+ } else if (n->pmrdev) {
56
- else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
354
+ /* Controller Capabilities register */
57
- return -4;
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
58
- else
356
+
59
- lfn->name[offset + i] = 0;
357
+ /* PMR Capabities register */
60
+ if (pointer[j] == 0 && pointer[j + 1] == 0) {
358
+ n->bar.pmrcap = 0;
61
+ /* end of long file name */
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
62
+ break;
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
63
+ }
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
64
+ gunichar2 c = (pointer[j + 1] << 8) + pointer[j];
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
65
+ lfn->name2[offset + i] = c;
363
+ /* Turn on bit 1 support */
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
367
+
368
+ /* PMR Control register */
369
+ n->bar.pmrctl = 0;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
66
}
398
}
67
399
68
- if (pointer[0] & 0x40)
400
for (i = 0; i < n->num_namespaces; i++) {
69
- lfn->len = offset + strlen((char*)lfn->name + offset);
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
70
+ if (pointer[0] & 0x40) {
402
if (n->cmb_size_mb) {
71
+ /* first entry; set len */
403
g_free(n->cmbuf);
72
+ lfn->len = offset + i;
404
}
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
73
+ }
408
+ }
74
+ if ((pointer[0] & 0x3f) == 0x01) {
409
msix_uninit_exclusive_bar(pci_dev);
75
+ /* last entry; finalize entry */
76
+ glong olen;
77
+ gchar *utf8 = g_utf16_to_utf8(lfn->name2, lfn->len, NULL, &olen, NULL);
78
+ if (!utf8) {
79
+ return -4;
80
+ }
81
+ lfn->len = olen;
82
+ memcpy(lfn->name, utf8, olen + 1);
83
+ g_free(utf8);
84
+ }
85
86
return 0;
87
}
410
}
88
@@ -XXX,XX +XXX,XX @@ static int parse_short_name(BDRVVVFATState* s,
411
89
412
static Property nvme_props[] = {
90
for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
91
for (i = 0; i <= j; i++) {
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
92
- if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
415
+ HostMemoryBackend *),
93
+ uint8_t c = direntry->name[i];
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
94
+ if (c != to_valid_short_char(c)) {
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
95
return -1;
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
96
- else if (s->downcase_short_names)
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
97
+ } else if (s->downcase_short_names) {
420
index XXXXXXX..XXXXXXX 100644
98
lfn->name[i] = qemu_tolower(direntry->name[i]);
421
--- a/hw/block/Makefile.objs
99
- else
422
+++ b/hw/block/Makefile.objs
100
+ } else {
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
101
lfn->name[i] = direntry->name[i];
424
common-obj-$(CONFIG_XEN) += xen-block.o
102
+ }
425
common-obj-$(CONFIG_ECC) += ecc.o
103
}
426
common-obj-$(CONFIG_ONENAND) += onenand.o
104
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
105
for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
428
common-obj-$(CONFIG_SWIM) += swim.o
106
@@ -XXX,XX +XXX,XX @@ static int parse_short_name(BDRVVVFATState* s,
429
107
lfn->name[i + j + 1] = '\0';
430
common-obj-$(CONFIG_SH4) += tc58128.o
108
for (;j >= 0; j--) {
431
109
uint8_t c = direntry->name[8 + j];
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
110
- if (c <= ' ' || c > 0x7f) {
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
111
+ if (c != to_valid_short_char(c)) {
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
112
return -2;
435
113
} else if (s->downcase_short_names) {
436
obj-y += dataplane/
114
lfn->name[i + j] = qemu_tolower(c);
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
115
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
438
index XXXXXXX..XXXXXXX 100644
116
/*
439
--- a/hw/block/trace-events
117
* Some sanity checks:
440
+++ b/hw/block/trace-events
118
* - do not allow writing to the boot sector
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
119
- * - do not allow to write non-ASCII filenames
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
120
*/
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
121
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
122
if (sector_num < s->offset_to_fat)
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
123
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
124
direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
125
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
126
for (k = 0; k < (end - begin) * 0x10; k++) {
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
127
- /* do not allow non-ASCII filenames */
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
128
- if (parse_long_name(&lfn, direntries + k) < 0) {
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
129
- fprintf(stderr, "Warning: non-ASCII filename\n");
130
- return -1;
131
- }
132
/* no access to the direntry of a read-only file */
133
- else if (is_short_name(direntries+k) &&
134
+ if (is_short_name(direntries + k) &&
135
(direntries[k].attributes & 1)) {
136
if (memcmp(direntries + k,
137
array_get(&(s->directory), dir_index + k),
138
--
452
--
139
1.8.3.1
453
2.25.3
140
454
141
455
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
The QMP handler qmp_object_add() and the implementation of --object in
2
qemu-storage-daemon can share most of the code. Currently,
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
2
5
3
The function vmdk_read_cid() can fail if the read on the underlying
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
4
block device fails, or if there's a format error in the VMDK file.
7
new function user_creatable_add_dict() that can get an additional
5
However its API doesn't provide a mechanism to report these errors,
8
parameter. The handling of "props" is only required for compatibility
6
and in some cases we were returning a CID of 0 and in some cases a
9
and not required for the qemu-storage-daemon command line, so it stays
7
CID of 0xffffffff, either of which might potentially be valid values.
10
in qmp_object_add().
8
11
9
Change the function to return 0 on success or a negative errno, and
10
return the CID via a uint32_t* argument. Update the callsites to
11
handle and propagate the error appropriately.
12
13
This fixes in passing a Coverity-spotted issue (CID 1350038) where
14
we weren't checking the return value from sscanf().
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Fam Zheng <famz@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
13
---
20
block/vmdk.c | 44 ++++++++++++++++++++++++++++++++------------
14
include/qom/object_interfaces.h | 12 ++++++++++++
21
1 file changed, 32 insertions(+), 12 deletions(-)
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
17
3 files changed, 40 insertions(+), 23 deletions(-)
22
18
23
diff --git a/block/vmdk.c b/block/vmdk.c
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
24
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
25
--- a/block/vmdk.c
21
--- a/include/qom/object_interfaces.h
26
+++ b/block/vmdk.c
22
+++ b/include/qom/object_interfaces.h
27
@@ -XXX,XX +XXX,XX @@ static void vmdk_free_last_extent(BlockDriverState *bs)
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
28
s->extents = g_renew(VmdkExtent, s->extents, s->num_extents);
24
const QDict *qdict,
25
Visitor *v, Error **errp);
26
27
+/**
28
+ * user_creatable_add_dict:
29
+ * @qdict: the object definition
30
+ * @errp: if an error occurs, a pointer to an area to store the error
31
+ *
32
+ * Create an instance of the user creatable object that is defined by
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
35
+ * initialize the object properties.
36
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
38
+
39
/**
40
* user_creatable_add_opts:
41
* @opts: the object definition
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
45
+++ b/qom/object_interfaces.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "qapi/qmp/qerror.h"
48
#include "qapi/qmp/qjson.h"
49
#include "qapi/qmp/qstring.h"
50
+#include "qapi/qobject-input-visitor.h"
51
#include "qom/object_interfaces.h"
52
#include "qemu/help_option.h"
53
#include "qemu/module.h"
54
@@ -XXX,XX +XXX,XX @@ out:
55
return obj;
29
}
56
}
30
57
31
-static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
32
+/* Return -ve errno, or 0 on success and write CID into *pcid. */
59
+{
33
+static int vmdk_read_cid(BlockDriverState *bs, int parent, uint32_t *pcid)
60
+ Visitor *v;
61
+ Object *obj;
62
+ g_autofree char *type = NULL;
63
+ g_autofree char *id = NULL;
64
+
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
66
+ if (!type) {
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
68
+ return;
69
+ }
70
+ qdict_del(qdict, "qom-type");
71
+
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
76
+ }
77
+ qdict_del(qdict, "id");
78
+
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
82
+ object_unref(obj);
83
+}
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
34
{
86
{
35
char *desc;
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
36
- uint32_t cid = 0xffffffff;
88
index XXXXXXX..XXXXXXX 100644
37
+ uint32_t cid;
89
--- a/qom/qom-qmp-cmds.c
38
const char *p_name, *cid_str;
90
+++ b/qom/qom-qmp-cmds.c
39
size_t cid_str_size;
91
@@ -XXX,XX +XXX,XX @@
40
BDRVVmdkState *s = bs->opaque;
92
#include "qapi/qapi-commands-qom.h"
41
@@ -XXX,XX +XXX,XX @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
93
#include "qapi/qmp/qdict.h"
42
desc = g_malloc0(DESC_SIZE);
94
#include "qapi/qmp/qerror.h"
43
ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
95
-#include "qapi/qobject-input-visitor.h"
44
if (ret < 0) {
96
#include "qemu/cutils.h"
45
- g_free(desc);
97
#include "qom/object_interfaces.h"
46
- return 0;
98
#include "qom/qom-qobject.h"
47
+ goto out;
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
100
{
101
QObject *props;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
48
}
126
}
49
127
50
if (parent) {
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
51
@@ -XXX,XX +XXX,XX @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
52
130
- visit_free(v);
53
desc[DESC_SIZE - 1] = '\0';
131
- object_unref(obj);
54
p_name = strstr(desc, cid_str);
132
+ user_creatable_add_dict(qdict, errp);
55
- if (p_name != NULL) {
56
- p_name += cid_str_size;
57
- sscanf(p_name, "%" SCNx32, &cid);
58
+ if (p_name == NULL) {
59
+ ret = -EINVAL;
60
+ goto out;
61
}
62
+ p_name += cid_str_size;
63
+ if (sscanf(p_name, "%" SCNx32, &cid) != 1) {
64
+ ret = -EINVAL;
65
+ goto out;
66
+ }
67
+ *pcid = cid;
68
+ ret = 0;
69
70
+out:
71
g_free(desc);
72
- return cid;
73
+ return ret;
74
}
133
}
75
134
76
static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
135
void qmp_object_del(const char *id, Error **errp)
77
@@ -XXX,XX +XXX,XX @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
78
if (!s->cid_checked && bs->backing) {
79
BlockDriverState *p_bs = bs->backing->bs;
80
81
- cur_pcid = vmdk_read_cid(p_bs, 0);
82
+ if (vmdk_read_cid(p_bs, 0, &cur_pcid) != 0) {
83
+ /* read failure: report as not valid */
84
+ return 0;
85
+ }
86
if (s->parent_cid != cur_pcid) {
87
/* CID not valid */
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
90
if (ret) {
91
goto fail;
92
}
93
- s->cid = vmdk_read_cid(bs, 0);
94
- s->parent_cid = vmdk_read_cid(bs, 1);
95
+ ret = vmdk_read_cid(bs, 0, &s->cid);
96
+ if (ret) {
97
+ goto fail;
98
+ }
99
+ ret = vmdk_read_cid(bs, 1, &s->parent_cid);
100
+ if (ret) {
101
+ goto fail;
102
+ }
103
qemu_co_mutex_init(&s->lock);
104
105
/* Disable migration when VMDK images are used */
106
@@ -XXX,XX +XXX,XX @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
107
ret = -EINVAL;
108
goto exit;
109
}
110
- parent_cid = vmdk_read_cid(blk_bs(blk), 0);
111
+ ret = vmdk_read_cid(blk_bs(blk), 0, &parent_cid);
112
blk_unref(blk);
113
+ if (ret) {
114
+ goto exit;
115
+ }
116
snprintf(parent_desc_line, BUF_SIZE,
117
"parentFileNameHint=\"%s\"", backing_file);
118
}
119
--
136
--
120
1.8.3.1
137
2.25.3
121
138
122
139
diff view generated by jsdifflib
1
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
1
After processing the option string with the keyval parser, we get a
2
QDict that contains only strings. This QDict must be fed to a keyval
3
visitor which converts the strings into the right data types.
2
4
3
throttle_config() cancels the timers of the calling BlockBackend. This
5
qmp_object_add(), however, uses the normal QObject input visitor, which
4
doesn't make sense because other BlockBackends in the group remain
6
expects a QDict where all properties already have the QType that matches
5
untouched. There's no need to cancel the timers in the one specific
7
the data type required by the QOM object type.
6
BlockBackend so let's not do that. Throttled requests will run as
7
scheduled and future requests will follow the new configuration. This
8
also allows a throttle group's configuration to be changed even when it
9
has no members.
10
8
11
Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
9
Change the --object implementation in qemu-storage-daemon so that it
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
11
directly instead and pass it a new keyval boolean that decides which
12
visitor must be used.
13
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
16
---
15
block/throttle-groups.c | 10 +---------
17
include/qom/object_interfaces.h | 6 +++++-
16
fsdev/qemu-fsdev-throttle.c | 2 +-
18
qemu-storage-daemon.c | 4 +---
17
include/qemu/throttle.h | 1 -
19
qom/object_interfaces.c | 8 ++++++--
18
tests/test-throttle.c | 4 ++--
20
qom/qom-qmp-cmds.c | 2 +-
19
util/throttle.c | 14 --------------
21
4 files changed, 13 insertions(+), 7 deletions(-)
20
5 files changed, 4 insertions(+), 27 deletions(-)
21
22
22
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
23
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
24
--- a/block/throttle-groups.c
25
--- a/include/qom/object_interfaces.h
25
+++ b/block/throttle-groups.c
26
+++ b/include/qom/object_interfaces.h
26
@@ -XXX,XX +XXX,XX @@ void throttle_group_restart_blk(BlockBackend *blk)
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
27
void throttle_group_config(BlockBackend *blk, ThrottleConfig *cfg)
28
/**
29
* user_creatable_add_dict:
30
* @qdict: the object definition
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
32
+ * assume that all @qdict values are strings); otherwise, use
33
+ * the normal QObject visitor (i.e. assume all @qdict values
34
+ * have the QType expected by the QOM object type)
35
* @errp: if an error occurs, a pointer to an area to store the error
36
*
37
* Create an instance of the user creatable object that is defined by
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-storage-daemon.c
50
+++ b/qemu-storage-daemon.c
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
52
QemuOpts *opts;
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
76
}
77
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
28
{
80
{
29
BlockBackendPublic *blkp = blk_get_public(blk);
81
Visitor *v;
30
- ThrottleTimers *tt = &blkp->throttle_timers;
82
Object *obj;
31
ThrottleState *ts = blkp->throttle_state;
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
32
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
84
}
33
qemu_mutex_lock(&tg->lock);
85
qdict_del(qdict, "id");
34
- /* throttle_config() cancels the timers */
86
35
- if (timer_pending(tt->timers[0])) {
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
36
- tg->any_timer_armed[0] = false;
88
+ if (keyval) {
37
- }
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
38
- if (timer_pending(tt->timers[1])) {
90
+ } else {
39
- tg->any_timer_armed[1] = false;
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
40
- }
92
+ }
41
- throttle_config(ts, tg->clock_type, tt, cfg);
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
42
+ throttle_config(ts, tg->clock_type, cfg);
94
visit_free(v);
43
qemu_mutex_unlock(&tg->lock);
95
object_unref(obj);
44
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
45
throttle_group_restart_blk(blk);
46
diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
47
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
48
--- a/fsdev/qemu-fsdev-throttle.c
98
--- a/qom/qom-qmp-cmds.c
49
+++ b/fsdev/qemu-fsdev-throttle.c
99
+++ b/qom/qom-qmp-cmds.c
50
@@ -XXX,XX +XXX,XX @@ void fsdev_throttle_init(FsThrottle *fst)
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
51
fsdev_throttle_read_timer_cb,
101
qobject_unref(pdict);
52
fsdev_throttle_write_timer_cb,
53
fst);
54
- throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->tt, &fst->cfg);
55
+ throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg);
56
qemu_co_queue_init(&fst->throttled_reqs[0]);
57
qemu_co_queue_init(&fst->throttled_reqs[1]);
58
}
102
}
59
diff --git a/include/qemu/throttle.h b/include/qemu/throttle.h
103
60
index XXXXXXX..XXXXXXX 100644
104
- user_creatable_add_dict(qdict, errp);
61
--- a/include/qemu/throttle.h
105
+ user_creatable_add_dict(qdict, false, errp);
62
+++ b/include/qemu/throttle.h
63
@@ -XXX,XX +XXX,XX @@ bool throttle_is_valid(ThrottleConfig *cfg, Error **errp);
64
65
void throttle_config(ThrottleState *ts,
66
QEMUClockType clock_type,
67
- ThrottleTimers *tt,
68
ThrottleConfig *cfg);
69
70
void throttle_get_config(ThrottleState *ts, ThrottleConfig *cfg);
71
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/tests/test-throttle.c
74
+++ b/tests/test-throttle.c
75
@@ -XXX,XX +XXX,XX @@ static void test_config_functions(void)
76
read_timer_cb, write_timer_cb, &ts);
77
/* structure reset by throttle_init previous_leak should be null */
78
g_assert(!ts.previous_leak);
79
- throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &tt, &orig_cfg);
80
+ throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg);
81
82
/* has previous leak been initialized by throttle_config ? */
83
g_assert(ts.previous_leak);
84
@@ -XXX,XX +XXX,XX @@ static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
85
throttle_init(&ts);
86
throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
87
read_timer_cb, write_timer_cb, &ts);
88
- throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &tt, &cfg);
89
+ throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
90
91
/* account a read */
92
throttle_account(&ts, false, size);
93
diff --git a/util/throttle.c b/util/throttle.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/util/throttle.c
96
+++ b/util/throttle.c
97
@@ -XXX,XX +XXX,XX @@ static void throttle_unfix_bucket(LeakyBucket *bkt)
98
}
99
}
106
}
100
107
101
-/* take care of canceling a timer */
108
void qmp_object_del(const char *id, Error **errp)
102
-static void throttle_cancel_timer(QEMUTimer *timer)
103
-{
104
- assert(timer != NULL);
105
-
106
- timer_del(timer);
107
-}
108
-
109
/* Used to configure the throttle
110
*
111
* @ts: the throttle state we are working on
112
* @clock_type: the group's clock_type
113
- * @tt: the throttle timers we use in this aio context
114
* @cfg: the config to set
115
*/
116
void throttle_config(ThrottleState *ts,
117
QEMUClockType clock_type,
118
- ThrottleTimers *tt,
119
ThrottleConfig *cfg)
120
{
121
int i;
122
@@ -XXX,XX +XXX,XX @@ void throttle_config(ThrottleState *ts,
123
}
124
125
ts->previous_leak = qemu_clock_get_ns(clock_type);
126
-
127
- for (i = 0; i < 2; i++) {
128
- throttle_cancel_timer(tt->timers[i]);
129
- }
130
}
131
132
/* used to get config
133
--
109
--
134
1.8.3.1
110
2.25.3
135
111
136
112
diff view generated by jsdifflib
Deleted patch
1
From: Peter Maydell <peter.maydell@linaro.org>
2
1
3
Coverity (CID 1355236) points out that get_image_offset() doesn't check that
4
it actually succeeded in writing the updated block bitmap to the file.
5
Check the error return from bdrv_pwrite_sync() and propagate an error
6
response back up to the function which calls get_image_offset() for
7
a write so that it can return the error to its caller.
8
9
get_sector_offset() is only used for reads, but we move it to the
10
same API for consistency.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/vpc.c | 30 +++++++++++++++++++++++-------
16
1 file changed, 23 insertions(+), 7 deletions(-)
17
18
diff --git a/block/vpc.c b/block/vpc.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/vpc.c
21
+++ b/block/vpc.c
22
@@ -XXX,XX +XXX,XX @@ static int vpc_reopen_prepare(BDRVReopenState *state,
23
/*
24
* Returns the absolute byte offset of the given sector in the image file.
25
* If the sector is not allocated, -1 is returned instead.
26
+ * If an error occurred trying to write an updated block bitmap back to
27
+ * the file, -2 is returned, and the error value is written to *err.
28
+ * This can only happen for a write operation.
29
*
30
* The parameter write must be 1 if the offset will be used for a write
31
* operation (the block bitmaps is updated then), 0 otherwise.
32
+ * If write is true then err must not be NULL.
33
*/
34
static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset,
35
- bool write)
36
+ bool write, int *err)
37
{
38
BDRVVPCState *s = bs->opaque;
39
uint64_t bitmap_offset, block_offset;
40
uint32_t pagetable_index, offset_in_block;
41
42
+ assert(!(write && err == NULL));
43
+
44
pagetable_index = offset / s->block_size;
45
offset_in_block = offset % s->block_size;
46
47
@@ -XXX,XX +XXX,XX @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset,
48
correctness. */
49
if (write && (s->last_bitmap_offset != bitmap_offset)) {
50
uint8_t bitmap[s->bitmap_size];
51
+ int r;
52
53
s->last_bitmap_offset = bitmap_offset;
54
memset(bitmap, 0xff, s->bitmap_size);
55
- bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
56
+ r = bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
57
+ if (r < 0) {
58
+ *err = r;
59
+ return -2;
60
+ }
61
}
62
63
return block_offset;
64
@@ -XXX,XX +XXX,XX @@ static int64_t alloc_block(BlockDriverState* bs, int64_t offset)
65
if (ret < 0)
66
goto fail;
67
68
- return get_image_offset(bs, offset, false);
69
+ return get_image_offset(bs, offset, false, NULL);
70
71
fail:
72
s->free_data_block_offset -= (s->block_size + s->bitmap_size);
73
@@ -XXX,XX +XXX,XX @@ vpc_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
74
qemu_iovec_init(&local_qiov, qiov->niov);
75
76
while (bytes > 0) {
77
- image_offset = get_image_offset(bs, offset, false);
78
+ image_offset = get_image_offset(bs, offset, false, NULL);
79
n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
80
81
if (image_offset == -1) {
82
@@ -XXX,XX +XXX,XX @@ vpc_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
83
qemu_iovec_init(&local_qiov, qiov->niov);
84
85
while (bytes > 0) {
86
- image_offset = get_image_offset(bs, offset, true);
87
+ image_offset = get_image_offset(bs, offset, true, &ret);
88
+ if (image_offset == -2) {
89
+ /* Failed to write block bitmap: can't proceed with write */
90
+ goto fail;
91
+ }
92
n_bytes = MIN(bytes, s->block_size - (offset % s->block_size));
93
94
if (image_offset == -1) {
95
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
96
97
qemu_co_mutex_lock(&s->lock);
98
99
- offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false);
100
+ offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false, NULL);
101
start = offset;
102
allocated = (offset != -1);
103
*pnum = 0;
104
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
105
if (nb_sectors == 0) {
106
break;
107
}
108
- offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false);
109
+ offset = get_image_offset(bs, sector_num << BDRV_SECTOR_BITS, false,
110
+ NULL);
111
} while (offset == -1);
112
113
qemu_co_mutex_unlock(&s->lock);
114
--
115
1.8.3.1
116
117
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
Reviewed-by: John Snow <jsnow@redhat.com>
4
---
5
block/block-backend.c | 3 +--
6
include/sysemu/block-backend.h | 1 +
7
2 files changed, 2 insertions(+), 2 deletions(-)
8
1
9
diff --git a/block/block-backend.c b/block/block-backend.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/block/block-backend.c
12
+++ b/block/block-backend.c
13
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo block_backend_aiocb_info = {
14
15
static void drive_info_del(DriveInfo *dinfo);
16
static BlockBackend *bdrv_first_blk(BlockDriverState *bs);
17
-static char *blk_get_attached_dev_id(BlockBackend *blk);
18
19
/* All BlockBackends */
20
static QTAILQ_HEAD(, BlockBackend) block_backends =
21
@@ -XXX,XX +XXX,XX @@ void *blk_get_attached_dev(BlockBackend *blk)
22
23
/* Return the qdev ID, or if no ID is assigned the QOM path, of the block
24
* device attached to the BlockBackend. */
25
-static char *blk_get_attached_dev_id(BlockBackend *blk)
26
+char *blk_get_attached_dev_id(BlockBackend *blk)
27
{
28
DeviceState *dev;
29
30
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/sysemu/block-backend.h
33
+++ b/include/sysemu/block-backend.h
34
@@ -XXX,XX +XXX,XX @@ int blk_attach_dev(BlockBackend *blk, DeviceState *dev);
35
void blk_attach_dev_legacy(BlockBackend *blk, void *dev);
36
void blk_detach_dev(BlockBackend *blk, void *dev);
37
void *blk_get_attached_dev(BlockBackend *blk);
38
+char *blk_get_attached_dev_id(BlockBackend *blk);
39
BlockBackend *blk_by_dev(void *dev);
40
BlockBackend *blk_by_qdev_id(const char *id, Error **errp);
41
void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque);
42
--
43
1.8.3.1
44
45
diff view generated by jsdifflib
Deleted patch
1
This patch replaces the blk_next() loop in query-block by a
2
blk_all_next() one so that we also get access to BlockBackends that
3
aren't owned by the monitor. For now, the next thing we do is check
4
whether each BB has a name, so there is no semantic difference.
5
1
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
---
10
block/qapi.c | 10 ++++++++--
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
13
diff --git a/block/qapi.c b/block/qapi.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qapi.c
16
+++ b/block/qapi.c
17
@@ -XXX,XX +XXX,XX @@ BlockInfoList *qmp_query_block(Error **errp)
18
BlockBackend *blk;
19
Error *local_err = NULL;
20
21
- for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
22
- BlockInfoList *info = g_malloc0(sizeof(*info));
23
+ for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
24
+ BlockInfoList *info;
25
+
26
+ if (!*blk_name(blk)) {
27
+ continue;
28
+ }
29
+
30
+ info = g_malloc0(sizeof(*info));
31
bdrv_query_info(blk, &info->value, &local_err);
32
if (local_err) {
33
error_propagate(errp, local_err);
34
--
35
1.8.3.1
36
37
diff view generated by jsdifflib
Deleted patch
1
Instead of listing only monitor-owned BlockBackends in query-block, also
2
add those anonymous BlockBackends that are owned by a qdev device and as
3
such under the control of the user.
4
1
5
This allows using query-block to inspect BlockBackends for the modern
6
configuration syntax with -blockdev and -device.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
---
12
block/qapi.c | 2 +-
13
hmp.c | 8 ++++----
14
2 files changed, 5 insertions(+), 5 deletions(-)
15
16
diff --git a/block/qapi.c b/block/qapi.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qapi.c
19
+++ b/block/qapi.c
20
@@ -XXX,XX +XXX,XX @@ BlockInfoList *qmp_query_block(Error **errp)
21
for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
22
BlockInfoList *info;
23
24
- if (!*blk_name(blk)) {
25
+ if (!*blk_name(blk) && !blk_get_attached_dev(blk)) {
26
continue;
27
}
28
29
diff --git a/hmp.c b/hmp.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hmp.c
32
+++ b/hmp.c
33
@@ -XXX,XX +XXX,XX @@ static void print_block_info(Monitor *mon, BlockInfo *info,
34
35
assert(!info || !info->has_inserted || info->inserted == inserted);
36
37
- if (info) {
38
+ if (info && *info->device) {
39
monitor_printf(mon, "%s", info->device);
40
if (inserted && inserted->has_node_name) {
41
monitor_printf(mon, " (%s)", inserted->node_name);
42
}
43
} else {
44
- assert(inserted);
45
+ assert(info || inserted);
46
monitor_printf(mon, "%s",
47
- inserted->has_node_name
48
- ? inserted->node_name
49
+ inserted && inserted->has_node_name ? inserted->node_name
50
+ : info && info->has_qdev ? info->qdev
51
: "<anonymous>");
52
}
53
54
--
55
1.8.3.1
56
57
diff view generated by jsdifflib