1
The following changes since commit 3fbd3405d2b0604ea530fc7a1828f19da1e95ff9:
1
The following changes since commit 711c0418c8c1ce3a24346f058b001c4c5a2f0f81:
2
2
3
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2019-08-17' into staging (2019-08-19 14:14:09 +0100)
3
Merge remote-tracking branch 'remotes/philmd/tags/mips-20210702' into staging (2021-07-04 14:04:12 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2019-08-19
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to fa27c478102a6b5d1c6b02c005607ad9404b915f:
9
for you to fetch changes up to 9f460c64e13897117f35ffb61f6f5e0102cabc70:
10
10
11
doc: Preallocation does not require writing zeroes (2019-08-19 17:13:26 +0200)
11
block/io: Merge discard request alignments (2021-07-06 14:28:55 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- preallocation=falloc/full support for LUKS
16
- Various minor fixes
17
15
18
----------------------------------------------------------------
16
----------------------------------------------------------------
19
Max Reitz (16):
20
qemu-img: Fix bdrv_has_zero_init() use in convert
21
mirror: Fix bdrv_has_zero_init() use
22
block: Add bdrv_has_zero_init_truncate()
23
block: Implement .bdrv_has_zero_init_truncate()
24
block: Use bdrv_has_zero_init_truncate()
25
qcow2: Fix .bdrv_has_zero_init()
26
vdi: Fix .bdrv_has_zero_init()
27
vhdx: Fix .bdrv_has_zero_init()
28
iotests: Convert to preallocated encrypted qcow2
29
iotests: Test convert -n to pre-filled image
30
iotests: Full mirror to existing non-zero image
31
vdi: Make block_status recurse for fixed images
32
vmdk: Make block_status recurse for flat extents
33
vpc: Do not return RAW from block_status
34
iotests: Fix 141 when run with qed
35
doc: Preallocation does not require writing zeroes
36
17
37
Maxim Levitsky (1):
18
Akihiko Odaki (3):
38
LUKS: support preallocation
19
block/file-posix: Optimize for macOS
20
block: Add backend_defaults property
21
block/io: Merge discard request alignments
39
22
40
qapi/block-core.json | 15 +++++---
23
Stefan Hajnoczi (2):
41
include/block/block.h | 1 +
24
util/async: add a human-readable name to BHs for debugging
42
include/block/block_int.h | 9 +++++
25
util/async: print leaked BH name when AioContext finalizes
43
block.c | 21 +++++++++++
26
44
block/crypto.c | 30 ++++++++++++++--
27
include/block/aio.h | 31 ++++++++++++++++++++++---
45
block/file-posix.c | 1 +
28
include/hw/block/block.h | 3 +++
46
block/file-win32.c | 1 +
29
include/qemu/main-loop.h | 4 +++-
47
block/gluster.c | 4 +++
30
block/file-posix.c | 27 ++++++++++++++++++++--
48
block/mirror.c | 11 ++++--
31
block/io.c | 2 ++
49
block/nfs.c | 1 +
32
hw/block/block.c | 42 ++++++++++++++++++++++++++++++----
50
block/parallels.c | 2 +-
33
tests/unit/ptimer-test-stubs.c | 2 +-
51
block/qcow2.c | 30 +++++++++++++++-
34
util/async.c | 25 ++++++++++++++++----
52
block/qed.c | 1 +
35
util/main-loop.c | 4 ++--
53
block/raw-format.c | 6 ++++
36
tests/qemu-iotests/172.out | 38 ++++++++++++++++++++++++++++++
54
block/rbd.c | 1 +
37
10 files changed, 161 insertions(+), 17 deletions(-)
55
block/sheepdog.c | 1 +
56
block/ssh.c | 1 +
57
block/vdi.c | 16 +++++++--
58
block/vhdx.c | 28 +++++++++++++--
59
block/vmdk.c | 3 ++
60
block/vpc.c | 2 +-
61
blockdev.c | 16 +++++++--
62
qemu-img.c | 11 ++++--
63
tests/test-block-iothread.c | 2 +-
64
docs/qemu-block-drivers.texi | 4 +--
65
qemu-img.texi | 4 +--
66
tests/qemu-iotests/041 | 62 +++++++++++++++++++++++++++++---
67
tests/qemu-iotests/041.out | 4 +--
68
tests/qemu-iotests/122 | 17 +++++++++
69
tests/qemu-iotests/122.out | 8 +++++
70
tests/qemu-iotests/141 | 9 +++--
71
tests/qemu-iotests/141.out | 5 ---
72
tests/qemu-iotests/188 | 20 ++++++++++-
73
tests/qemu-iotests/188.out | 4 +++
74
tests/qemu-iotests/common.filter | 5 +++
75
35 files changed, 313 insertions(+), 43 deletions(-)
76
38
77
--
39
--
78
2.21.0
40
2.31.1
79
41
80
diff view generated by jsdifflib
1
69f47505ee has changed qcow2 in such a way that the commit job run in
1
It can be difficult to debug issues with BHs in production environments.
2
test 141 (and 144[1]) returns before it emits the READY event. However,
2
Although BHs can usually be identified by looking up their ->cb()
3
141 also runs with qed, where the order is still the other way around.
3
function pointer, this requires debug information for the program. It is
4
Just filter out the {"return": {}} so the test passes for qed again.
4
also not possible to print human-readable diagnostics about BHs because
5
they have no identifier.
5
6
6
[1] 144 only runs with qcow2, so it is fine as it is.
7
This patch adds a name to each BH. The name is not unique per instance
8
but differentiates between cb() functions, which is usually enough. It's
9
done by changing aio_bh_new() and friends to macros that stringify cb.
7
10
8
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
The next patch will use the name field when reporting leaked BHs.
9
Fixes: 69f47505ee66afaa513305de0c1895a224e52c45
12
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 20190809185253.17535-1-mreitz@redhat.com
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <20210414200247.917496-2-stefanha@redhat.com>
13
Reviewed-by: John Snow <jsnow@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
---
16
tests/qemu-iotests/141 | 9 +++++++--
17
include/block/aio.h | 31 ++++++++++++++++++++++++++++---
17
tests/qemu-iotests/141.out | 5 -----
18
include/qemu/main-loop.h | 4 +++-
18
tests/qemu-iotests/common.filter | 5 +++++
19
tests/unit/ptimer-test-stubs.c | 2 +-
19
3 files changed, 12 insertions(+), 7 deletions(-)
20
util/async.c | 9 +++++++--
21
util/main-loop.c | 4 ++--
22
5 files changed, 41 insertions(+), 9 deletions(-)
20
23
21
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
24
diff --git a/include/block/aio.h b/include/block/aio.h
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/141
24
+++ b/tests/qemu-iotests/141
25
@@ -XXX,XX +XXX,XX @@ test_blockjob()
26
}}}" \
27
'return'
28
29
+ # If "$2" is an event, we may or may not see it before the
30
+ # {"return": {}}. Therefore, filter the {"return": {}} out both
31
+ # here and in the next command. (Naturally, if we do not see it
32
+ # here, we will see it before the next command can be executed,
33
+ # so it will appear in the next _send_qemu_cmd's output.)
34
_send_qemu_cmd $QEMU_HANDLE \
35
"$1" \
36
"$2" \
37
- | _filter_img_create
38
+ | _filter_img_create | _filter_qmp_empty_return
39
40
# We want this to return an error because the block job is still running
41
_send_qemu_cmd $QEMU_HANDLE \
42
"{'execute': 'blockdev-del',
43
'arguments': {'node-name': 'drv0'}}" \
44
- 'error' | _filter_generated_node_ids
45
+ 'error' | _filter_generated_node_ids | _filter_qmp_empty_return
46
47
_send_qemu_cmd $QEMU_HANDLE \
48
"{'execute': 'block-job-cancel',
49
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
50
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
51
--- a/tests/qemu-iotests/141.out
26
--- a/include/block/aio.h
52
+++ b/tests/qemu-iotests/141.out
27
+++ b/include/block/aio.h
53
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
28
@@ -XXX,XX +XXX,XX @@ void aio_context_acquire(AioContext *ctx);
54
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
29
/* Relinquish ownership of the AioContext. */
55
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
30
void aio_context_release(AioContext *ctx);
56
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
31
57
-{"return": {}}
32
+/**
58
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
33
+ * aio_bh_schedule_oneshot_full: Allocate a new bottom half structure that will
59
{"return": {}}
34
+ * run only once and as soon as possible.
60
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
35
+ *
61
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
36
+ * @name: A human-readable identifier for debugging purposes.
62
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
37
+ */
63
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
38
+void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
64
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
39
+ const char *name);
65
-{"return": {}}
40
+
66
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
41
/**
67
{"return": {}}
42
* aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run
68
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
43
* only once and as soon as possible.
69
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
44
+ *
70
{"return": {}}
45
+ * A convenience wrapper for aio_bh_schedule_oneshot_full() that uses cb as the
71
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
46
+ * name string.
72
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
47
*/
73
-{"return": {}}
48
-void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
74
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
49
+#define aio_bh_schedule_oneshot(ctx, cb, opaque) \
75
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
50
+ aio_bh_schedule_oneshot_full((ctx), (cb), (opaque), (stringify(cb)))
76
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
51
77
@@ -XXX,XX +XXX,XX @@ wrote 1048576/1048576 bytes at offset 0
52
/**
78
{"return": {}}
53
- * aio_bh_new: Allocate a new bottom half structure.
79
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
54
+ * aio_bh_new_full: Allocate a new bottom half structure.
80
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
55
*
81
-{"return": {}}
56
* Bottom halves are lightweight callbacks whose invocation is guaranteed
82
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
57
* to be wait-free, thread-safe and signal-safe. The #QEMUBH structure
83
{"return": {}}
58
* is opaque and must be allocated prior to its use.
84
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
59
+ *
85
@@ -XXX,XX +XXX,XX @@ wrote 1048576/1048576 bytes at offset 0
60
+ * @name: A human-readable identifier for debugging purposes.
86
{"return": {}}
61
*/
87
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
62
-QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
88
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
63
+QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
89
-{"return": {}}
64
+ const char *name);
90
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
65
+
91
{"return": {}}
66
+/**
92
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
67
+ * aio_bh_new: Allocate a new bottom half structure
93
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
68
+ *
69
+ * A convenience wrapper for aio_bh_new_full() that uses the cb as the name
70
+ * string.
71
+ */
72
+#define aio_bh_new(ctx, cb, opaque) \
73
+ aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)))
74
75
/**
76
* aio_notify: Force processing of pending events.
77
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
94
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
95
--- a/tests/qemu-iotests/common.filter
79
--- a/include/qemu/main-loop.h
96
+++ b/tests/qemu-iotests/common.filter
80
+++ b/include/qemu/main-loop.h
97
@@ -XXX,XX +XXX,XX @@ _filter_nbd()
81
@@ -XXX,XX +XXX,XX @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms);
98
-e 's#\(foo\|PORT/\?\|.sock\): Failed to .*$#\1#'
82
83
void qemu_fd_register(int fd);
84
85
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
86
+#define qemu_bh_new(cb, opaque) \
87
+ qemu_bh_new_full((cb), (opaque), (stringify(cb)))
88
+QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name);
89
void qemu_bh_schedule_idle(QEMUBH *bh);
90
91
enum {
92
diff --git a/tests/unit/ptimer-test-stubs.c b/tests/unit/ptimer-test-stubs.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/tests/unit/ptimer-test-stubs.c
95
+++ b/tests/unit/ptimer-test-stubs.c
96
@@ -XXX,XX +XXX,XX @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
97
return deadline;
99
}
98
}
100
99
101
+_filter_qmp_empty_return()
100
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
102
+{
101
+QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
103
+ grep -v '{"return": {}}'
102
{
104
+}
103
QEMUBH *bh = g_new(QEMUBH, 1);
105
+
104
106
# make sure this script returns success
105
diff --git a/util/async.c b/util/async.c
107
true
106
index XXXXXXX..XXXXXXX 100644
107
--- a/util/async.c
108
+++ b/util/async.c
109
@@ -XXX,XX +XXX,XX @@ enum {
110
111
struct QEMUBH {
112
AioContext *ctx;
113
+ const char *name;
114
QEMUBHFunc *cb;
115
void *opaque;
116
QSLIST_ENTRY(QEMUBH) next;
117
@@ -XXX,XX +XXX,XX @@ static QEMUBH *aio_bh_dequeue(BHList *head, unsigned *flags)
118
return bh;
119
}
120
121
-void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
122
+void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb,
123
+ void *opaque, const char *name)
124
{
125
QEMUBH *bh;
126
bh = g_new(QEMUBH, 1);
127
@@ -XXX,XX +XXX,XX @@ void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
128
.ctx = ctx,
129
.cb = cb,
130
.opaque = opaque,
131
+ .name = name,
132
};
133
aio_bh_enqueue(bh, BH_SCHEDULED | BH_ONESHOT);
134
}
135
136
-QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
137
+QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
138
+ const char *name)
139
{
140
QEMUBH *bh;
141
bh = g_new(QEMUBH, 1);
142
@@ -XXX,XX +XXX,XX @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
143
.ctx = ctx,
144
.cb = cb,
145
.opaque = opaque,
146
+ .name = name,
147
};
148
return bh;
149
}
150
diff --git a/util/main-loop.c b/util/main-loop.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/util/main-loop.c
153
+++ b/util/main-loop.c
154
@@ -XXX,XX +XXX,XX @@ void main_loop_wait(int nonblocking)
155
156
/* Functions to operate on the main QEMU AioContext. */
157
158
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
159
+QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
160
{
161
- return aio_bh_new(qemu_aio_context, cb, opaque);
162
+ return aio_bh_new_full(qemu_aio_context, cb, opaque, name);
163
}
164
165
/*
108
--
166
--
109
2.21.0
167
2.31.1
110
168
111
diff view generated by jsdifflib
1
From: Maxim Levitsky <mlevitsk@redhat.com>
1
BHs must be deleted before the AioContext is finalized. If not, it's a
2
bug and probably indicates that some part of the program still expects
3
the BH to run in the future. That can lead to memory leaks, inconsistent
4
state, or just hangs.
2
5
3
preallocation=off and preallocation=metadata
6
Unfortunately the assert(flags & BH_DELETED) call in aio_ctx_finalize()
4
both allocate luks header only, and preallocation=falloc/full
7
is difficult to debug because the assertion failure contains no
5
is passed to underlying file.
8
information about the BH!
6
9
7
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1534951
10
Use the QEMUBH name field added in the previous patch to show a useful
11
error when a leaked BH is detected.
8
12
9
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
13
Suggested-by: Eric Ernst <eric.g.ernst@gmail.com>
10
Message-id: 20190716161901.1430-1-mlevitsk@redhat.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <20210414200247.917496-3-stefanha@redhat.com>
12
---
16
---
13
qapi/block-core.json | 6 +++++-
17
util/async.c | 16 ++++++++++++++--
14
block/crypto.c | 30 +++++++++++++++++++++++++++---
18
1 file changed, 14 insertions(+), 2 deletions(-)
15
2 files changed, 32 insertions(+), 4 deletions(-)
16
19
17
diff --git a/qapi/block-core.json b/qapi/block-core.json
20
diff --git a/util/async.c b/util/async.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/qapi/block-core.json
22
--- a/util/async.c
20
+++ b/qapi/block-core.json
23
+++ b/util/async.c
21
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ aio_ctx_finalize(GSource *source)
22
#
25
assert(QSIMPLEQ_EMPTY(&ctx->bh_slice_list));
23
# @file Node to create the image format on
26
24
# @size Size of the virtual disk in bytes
27
while ((bh = aio_bh_dequeue(&ctx->bh_list, &flags))) {
25
+# @preallocation Preallocation mode for the new image
28
- /* qemu_bh_delete() must have been called on BHs in this AioContext */
26
+# (since: 4.2)
29
- assert(flags & BH_DELETED);
27
+# (default: off; allowed values: off, metadata, falloc, full)
30
+ /*
28
#
31
+ * qemu_bh_delete() must have been called on BHs in this AioContext. In
29
# Since: 2.12
32
+ * many cases memory leaks, hangs, or inconsistent state occur when a
30
##
33
+ * BH is leaked because something still expects it to run.
31
{ 'struct': 'BlockdevCreateOptionsLUKS',
34
+ *
32
'base': 'QCryptoBlockCreateOptionsLUKS',
35
+ * If you hit this, fix the lifecycle of the BH so that
33
'data': { 'file': 'BlockdevRef',
36
+ * qemu_bh_delete() and any associated cleanup is called before the
34
- 'size': 'size' } }
37
+ * AioContext is finalized.
35
+ 'size': 'size',
38
+ */
36
+ '*preallocation': 'PreallocMode' } }
39
+ if (unlikely(!(flags & BH_DELETED))) {
37
40
+ fprintf(stderr, "%s: BH '%s' leaked, aborting...\n",
38
##
41
+ __func__, bh->name);
39
# @BlockdevCreateOptionsNfs:
42
+ abort();
40
diff --git a/block/crypto.c b/block/crypto.c
43
+ }
41
index XXXXXXX..XXXXXXX 100644
44
42
--- a/block/crypto.c
45
g_free(bh);
43
+++ b/block/crypto.c
44
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
45
struct BlockCryptoCreateData {
46
BlockBackend *blk;
47
uint64_t size;
48
+ PreallocMode prealloc;
49
};
50
51
52
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
53
* available to the guest, so we must take account of that
54
* which will be used by the crypto header
55
*/
56
- return blk_truncate(data->blk, data->size + headerlen, PREALLOC_MODE_OFF,
57
+ return blk_truncate(data->blk, data->size + headerlen, data->prealloc,
58
errp);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
62
static int block_crypto_co_create_generic(BlockDriverState *bs,
63
int64_t size,
64
QCryptoBlockCreateOptions *opts,
65
+ PreallocMode prealloc,
66
Error **errp)
67
{
68
int ret;
69
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
70
goto cleanup;
71
}
72
73
+ if (prealloc == PREALLOC_MODE_METADATA) {
74
+ prealloc = PREALLOC_MODE_OFF;
75
+ }
76
+
77
data = (struct BlockCryptoCreateData) {
78
.blk = blk,
79
.size = size,
80
+ .prealloc = prealloc,
81
};
82
83
crypto = qcrypto_block_create(opts, NULL,
84
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
85
BlockdevCreateOptionsLUKS *luks_opts;
86
BlockDriverState *bs = NULL;
87
QCryptoBlockCreateOptions create_opts;
88
+ PreallocMode preallocation = PREALLOC_MODE_OFF;
89
int ret;
90
91
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
92
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
93
.u.luks = *qapi_BlockdevCreateOptionsLUKS_base(luks_opts),
94
};
95
96
+ if (luks_opts->has_preallocation) {
97
+ preallocation = luks_opts->preallocation;
98
+ }
99
+
100
ret = block_crypto_co_create_generic(bs, luks_opts->size, &create_opts,
101
- errp);
102
+ preallocation, errp);
103
if (ret < 0) {
104
goto fail;
105
}
106
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
107
QCryptoBlockCreateOptions *create_opts = NULL;
108
BlockDriverState *bs = NULL;
109
QDict *cryptoopts;
110
+ PreallocMode prealloc;
111
+ char *buf = NULL;
112
int64_t size;
113
int ret;
114
+ Error *local_err = NULL;
115
116
/* Parse options */
117
size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
118
119
+ buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
120
+ prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
121
+ PREALLOC_MODE_OFF, &local_err);
122
+ g_free(buf);
123
+ if (local_err) {
124
+ error_propagate(errp, local_err);
125
+ return -EINVAL;
126
+ }
127
+
128
cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
129
&block_crypto_create_opts_luks,
130
true);
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
132
}
133
134
/* Create format layer */
135
- ret = block_crypto_co_create_generic(bs, size, create_opts, errp);
136
+ ret = block_crypto_co_create_generic(bs, size, create_opts, prealloc, errp);
137
if (ret < 0) {
138
goto fail;
139
}
46
}
140
--
47
--
141
2.21.0
48
2.31.1
142
49
143
diff view generated by jsdifflib
1
We need to implement .bdrv_has_zero_init_truncate() for every block
1
From: Akihiko Odaki <akihiko.odaki@gmail.com>
2
driver that supports truncation and has a .bdrv_has_zero_init()
3
implementation.
4
2
5
Implement it the same way each driver implements .bdrv_has_zero_init().
3
This commit introduces "punch hole" operation and optimizes transfer
6
This is at least not any more unsafe than what we had before.
4
block size for macOS.
7
5
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Thanks to Konstantin Nazarov for detailed analysis of a flaw in an
9
Message-id: 20190724171239.8764-5-mreitz@redhat.com
7
old version of this change:
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
8
https://gist.github.com/akihikodaki/87df4149e7ca87f18dc56807ec5a1bc5#gistcomment-3654667
11
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
9
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
11
Message-id: 20210705130458.97642-1-akihiko.odaki@gmail.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
13
---
14
block/file-posix.c | 1 +
14
block/file-posix.c | 27 +++++++++++++++++++++++++--
15
block/file-win32.c | 1 +
15
1 file changed, 25 insertions(+), 2 deletions(-)
16
block/gluster.c | 4 ++++
17
block/nfs.c | 1 +
18
block/qcow2.c | 1 +
19
block/qed.c | 1 +
20
block/raw-format.c | 6 ++++++
21
block/rbd.c | 1 +
22
block/sheepdog.c | 1 +
23
block/ssh.c | 1 +
24
10 files changed, 18 insertions(+)
25
16
26
diff --git a/block/file-posix.c b/block/file-posix.c
17
diff --git a/block/file-posix.c b/block/file-posix.c
27
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
28
--- a/block/file-posix.c
19
--- a/block/file-posix.c
29
+++ b/block/file-posix.c
20
+++ b/block/file-posix.c
30
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
21
@@ -XXX,XX +XXX,XX @@
31
.bdrv_co_create = raw_co_create,
22
#if defined(HAVE_HOST_BLOCK_DEVICE)
32
.bdrv_co_create_opts = raw_co_create_opts,
23
#include <paths.h>
33
.bdrv_has_zero_init = bdrv_has_zero_init_1,
24
#include <sys/param.h>
34
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
25
+#include <sys/mount.h>
35
.bdrv_co_block_status = raw_co_block_status,
26
#include <IOKit/IOKitLib.h>
36
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
27
#include <IOKit/IOBSD.h>
37
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
28
#include <IOKit/storage/IOMediaBSDClient.h>
38
diff --git a/block/file-win32.c b/block/file-win32.c
29
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
39
index XXXXXXX..XXXXXXX 100644
30
return;
40
--- a/block/file-win32.c
31
}
41
+++ b/block/file-win32.c
32
42
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
33
+#if defined(__APPLE__) && (__MACH__)
43
.bdrv_close = raw_close,
34
+ struct statfs buf;
44
.bdrv_co_create_opts = raw_co_create_opts,
35
+
45
.bdrv_has_zero_init = bdrv_has_zero_init_1,
36
+ if (!fstatfs(s->fd, &buf)) {
46
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
37
+ bs->bl.opt_transfer = buf.f_iosize;
47
38
+ bs->bl.pdiscard_alignment = buf.f_bsize;
48
.bdrv_aio_preadv = raw_aio_preadv,
39
+ }
49
.bdrv_aio_pwritev = raw_aio_pwritev,
40
+#endif
50
diff --git a/block/gluster.c b/block/gluster.c
41
+
51
index XXXXXXX..XXXXXXX 100644
42
if (bs->sg || S_ISBLK(st.st_mode)) {
52
--- a/block/gluster.c
43
int ret = hdev_get_max_hw_transfer(s->fd, &st);
53
+++ b/block/gluster.c
44
54
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
45
@@ -XXX,XX +XXX,XX @@ out:
55
.bdrv_co_writev = qemu_gluster_co_writev,
46
}
56
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
47
}
57
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
48
58
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
49
+#if defined(CONFIG_FALLOCATE) || defined(BLKZEROOUT) || defined(BLKDISCARD)
59
#ifdef CONFIG_GLUSTERFS_DISCARD
50
static int translate_err(int err)
60
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
51
{
52
if (err == -ENODEV || err == -ENOSYS || err == -EOPNOTSUPP ||
53
@@ -XXX,XX +XXX,XX @@ static int translate_err(int err)
54
}
55
return err;
56
}
57
+#endif
58
59
#ifdef CONFIG_FALLOCATE
60
static int do_fallocate(int fd, int mode, off_t offset, off_t len)
61
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_discard(void *opaque)
62
}
63
} while (errno == EINTR);
64
65
- ret = -errno;
66
+ ret = translate_err(-errno);
61
#endif
67
#endif
62
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
68
} else {
63
.bdrv_co_writev = qemu_gluster_co_writev,
69
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
64
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
70
ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
65
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
71
aiocb->aio_offset, aiocb->aio_nbytes);
66
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
72
+ ret = translate_err(-errno);
67
#ifdef CONFIG_GLUSTERFS_DISCARD
73
+#elif defined(__APPLE__) && (__MACH__)
68
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
74
+ fpunchhole_t fpunchhole;
75
+ fpunchhole.fp_flags = 0;
76
+ fpunchhole.reserved = 0;
77
+ fpunchhole.fp_offset = aiocb->aio_offset;
78
+ fpunchhole.fp_length = aiocb->aio_nbytes;
79
+ if (fcntl(s->fd, F_PUNCHHOLE, &fpunchhole) == -1) {
80
+ ret = errno == ENODEV ? -ENOTSUP : -errno;
81
+ } else {
82
+ ret = 0;
83
+ }
69
#endif
84
#endif
70
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
85
}
71
.bdrv_co_writev = qemu_gluster_co_writev,
86
72
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
87
- ret = translate_err(ret);
73
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
88
if (ret == -ENOTSUP) {
74
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
89
s->has_discard = false;
75
#ifdef CONFIG_GLUSTERFS_DISCARD
90
}
76
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
77
#endif
78
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
79
.bdrv_co_writev = qemu_gluster_co_writev,
80
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
81
.bdrv_has_zero_init = qemu_gluster_has_zero_init,
82
+ .bdrv_has_zero_init_truncate = qemu_gluster_has_zero_init,
83
#ifdef CONFIG_GLUSTERFS_DISCARD
84
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
85
#endif
86
diff --git a/block/nfs.c b/block/nfs.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/nfs.c
89
+++ b/block/nfs.c
90
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
91
.create_opts = &nfs_create_opts,
92
93
.bdrv_has_zero_init = nfs_has_zero_init,
94
+ .bdrv_has_zero_init_truncate = nfs_has_zero_init,
95
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
96
.bdrv_co_truncate = nfs_file_co_truncate,
97
98
diff --git a/block/qcow2.c b/block/qcow2.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/qcow2.c
101
+++ b/block/qcow2.c
102
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
103
.bdrv_co_create_opts = qcow2_co_create_opts,
104
.bdrv_co_create = qcow2_co_create,
105
.bdrv_has_zero_init = bdrv_has_zero_init_1,
106
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
107
.bdrv_co_block_status = qcow2_co_block_status,
108
109
.bdrv_co_preadv = qcow2_co_preadv,
110
diff --git a/block/qed.c b/block/qed.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/qed.c
113
+++ b/block/qed.c
114
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
115
.bdrv_co_create = bdrv_qed_co_create,
116
.bdrv_co_create_opts = bdrv_qed_co_create_opts,
117
.bdrv_has_zero_init = bdrv_has_zero_init_1,
118
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
119
.bdrv_co_block_status = bdrv_qed_co_block_status,
120
.bdrv_co_readv = bdrv_qed_co_readv,
121
.bdrv_co_writev = bdrv_qed_co_writev,
122
diff --git a/block/raw-format.c b/block/raw-format.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/raw-format.c
125
+++ b/block/raw-format.c
126
@@ -XXX,XX +XXX,XX @@ static int raw_has_zero_init(BlockDriverState *bs)
127
return bdrv_has_zero_init(bs->file->bs);
128
}
129
130
+static int raw_has_zero_init_truncate(BlockDriverState *bs)
131
+{
132
+ return bdrv_has_zero_init_truncate(bs->file->bs);
133
+}
134
+
135
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
136
Error **errp)
137
{
138
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
139
.bdrv_co_ioctl = &raw_co_ioctl,
140
.create_opts = &raw_create_opts,
141
.bdrv_has_zero_init = &raw_has_zero_init,
142
+ .bdrv_has_zero_init_truncate = &raw_has_zero_init_truncate,
143
.strong_runtime_opts = raw_strong_runtime_opts,
144
.mutable_opts = mutable_opts,
145
};
146
diff --git a/block/rbd.c b/block/rbd.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/rbd.c
149
+++ b/block/rbd.c
150
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
151
.bdrv_co_create = qemu_rbd_co_create,
152
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
153
.bdrv_has_zero_init = bdrv_has_zero_init_1,
154
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
155
.bdrv_get_info = qemu_rbd_getinfo,
156
.create_opts = &qemu_rbd_create_opts,
157
.bdrv_getlength = qemu_rbd_getlength,
158
diff --git a/block/sheepdog.c b/block/sheepdog.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/block/sheepdog.c
161
+++ b/block/sheepdog.c
162
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
163
.bdrv_co_create = sd_co_create,
164
.bdrv_co_create_opts = sd_co_create_opts,
165
.bdrv_has_zero_init = bdrv_has_zero_init_1,
166
+ .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
167
.bdrv_getlength = sd_getlength,
168
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
169
.bdrv_co_truncate = sd_co_truncate,
170
diff --git a/block/ssh.c b/block/ssh.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/block/ssh.c
173
+++ b/block/ssh.c
174
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
175
.bdrv_co_create_opts = ssh_co_create_opts,
176
.bdrv_close = ssh_close,
177
.bdrv_has_zero_init = ssh_has_zero_init,
178
+ .bdrv_has_zero_init_truncate = ssh_has_zero_init,
179
.bdrv_co_readv = ssh_co_readv,
180
.bdrv_co_writev = ssh_co_writev,
181
.bdrv_getlength = ssh_getlength,
182
--
91
--
183
2.21.0
92
2.31.1
184
93
185
diff view generated by jsdifflib
1
bdrv_has_zero_init() only has meaning for newly created images or image
1
From: Akihiko Odaki <akihiko.odaki@gmail.com>
2
areas. If qemu-img convert did not create the image itself, it cannot
2
3
rely on bdrv_has_zero_init()'s result to carry any meaning.
3
backend_defaults property allow users to control if default block
4
4
properties should be decided with backend information.
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
6
Message-id: 20190724171239.8764-2-mreitz@redhat.com
6
If it is off, any backend information will be discarded, which is
7
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
7
suitable if you plan to perform live migration to a different disk backend.
8
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
If it is on, a block device may utilize backend information more
10
aggressively.
11
12
By default, it is auto, which uses backend information for block
13
sizes and ignores the others, which is consistent with the older
14
versions.
15
16
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
17
Message-id: 20210705130458.97642-2-akihiko.odaki@gmail.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
19
---
11
qemu-img.c | 11 ++++++++---
20
include/hw/block/block.h | 3 +++
12
1 file changed, 8 insertions(+), 3 deletions(-)
21
hw/block/block.c | 42 ++++++++++++++++++++++++++++++++++----
13
22
tests/qemu-iotests/172.out | 38 ++++++++++++++++++++++++++++++++++
14
diff --git a/qemu-img.c b/qemu-img.c
23
3 files changed, 79 insertions(+), 4 deletions(-)
24
25
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-img.c
27
--- a/include/hw/block/block.h
17
+++ b/qemu-img.c
28
+++ b/include/hw/block/block.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct ImgConvertState {
29
@@ -XXX,XX +XXX,XX @@
19
bool has_zero_init;
30
20
bool compressed;
31
typedef struct BlockConf {
21
bool unallocated_blocks_are_zero;
32
BlockBackend *blk;
22
+ bool target_is_new;
33
+ OnOffAuto backend_defaults;
23
bool target_has_backing;
34
uint32_t physical_block_size;
24
int64_t target_backing_sectors; /* negative if unknown */
35
uint32_t logical_block_size;
25
bool wr_in_order;
36
uint32_t min_io_size;
26
@@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s)
37
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
27
int64_t sector_num = 0;
38
}
28
39
29
/* Check whether we have zero initialisation or can get it efficiently */
40
#define DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf) \
30
- s->has_zero_init = s->min_sparse && !s->target_has_backing
41
+ DEFINE_PROP_ON_OFF_AUTO("backend_defaults", _state, \
31
- ? bdrv_has_zero_init(blk_bs(s->target))
42
+ _conf.backend_defaults, ON_OFF_AUTO_AUTO), \
32
- : false;
43
DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \
33
+ if (s->target_is_new && s->min_sparse && !s->target_has_backing) {
44
_conf.logical_block_size), \
34
+ s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target));
45
DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \
35
+ } else {
46
diff --git a/hw/block/block.c b/hw/block/block.c
36
+ s->has_zero_init = false;
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/block/block.c
49
+++ b/hw/block/block.c
50
@@ -XXX,XX +XXX,XX @@ bool blkconf_blocksizes(BlockConf *conf, Error **errp)
51
{
52
BlockBackend *blk = conf->blk;
53
BlockSizes blocksizes;
54
- int backend_ret;
55
+ BlockDriverState *bs;
56
+ bool use_blocksizes;
57
+ bool use_bs;
58
+
59
+ switch (conf->backend_defaults) {
60
+ case ON_OFF_AUTO_AUTO:
61
+ use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
62
+ use_bs = false;
63
+ break;
64
+
65
+ case ON_OFF_AUTO_ON:
66
+ use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
67
+ bs = blk_bs(blk);
68
+ use_bs = bs;
69
+ break;
70
+
71
+ case ON_OFF_AUTO_OFF:
72
+ use_blocksizes = false;
73
+ use_bs = false;
74
+ break;
75
+
76
+ default:
77
+ abort();
37
+ }
78
+ }
38
79
39
if (!s->has_zero_init && !s->target_has_backing &&
80
- backend_ret = blk_probe_blocksizes(blk, &blocksizes);
40
bdrv_can_write_zeroes_with_unmap(blk_bs(s->target)))
81
/* fill in detected values if they are not defined via qemu command line */
41
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
82
if (!conf->physical_block_size) {
83
- if (!backend_ret) {
84
+ if (use_blocksizes) {
85
conf->physical_block_size = blocksizes.phys;
86
} else {
87
conf->physical_block_size = BDRV_SECTOR_SIZE;
42
}
88
}
43
}
89
}
44
90
if (!conf->logical_block_size) {
45
+ s.target_is_new = !skip_create;
91
- if (!backend_ret) {
46
+
92
+ if (use_blocksizes) {
47
flags = s.min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR;
93
conf->logical_block_size = blocksizes.log;
48
ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
94
} else {
49
if (ret < 0) {
95
conf->logical_block_size = BDRV_SECTOR_SIZE;
96
}
97
}
98
+ if (use_bs) {
99
+ if (!conf->opt_io_size) {
100
+ conf->opt_io_size = bs->bl.opt_transfer;
101
+ }
102
+ if (conf->discard_granularity == -1) {
103
+ if (bs->bl.pdiscard_alignment) {
104
+ conf->discard_granularity = bs->bl.pdiscard_alignment;
105
+ } else if (bs->bl.request_alignment != 1) {
106
+ conf->discard_granularity = bs->bl.request_alignment;
107
+ }
108
+ }
109
+ }
110
111
if (conf->logical_block_size > conf->physical_block_size) {
112
error_setg(errp,
113
diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out
114
index XXXXXXX..XXXXXXX 100644
115
--- a/tests/qemu-iotests/172.out
116
+++ b/tests/qemu-iotests/172.out
117
@@ -XXX,XX +XXX,XX @@ Testing:
118
dev: floppy, id ""
119
unit = 0 (0x0)
120
drive = "floppy0"
121
+ backend_defaults = "auto"
122
logical_block_size = 512 (512 B)
123
physical_block_size = 512 (512 B)
124
min_io_size = 0 (0 B)
125
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2
126
dev: floppy, id ""
127
unit = 0 (0x0)
128
drive = "floppy0"
129
+ backend_defaults = "auto"
130
logical_block_size = 512 (512 B)
131
physical_block_size = 512 (512 B)
132
min_io_size = 0 (0 B)
133
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2
134
dev: floppy, id ""
135
unit = 1 (0x1)
136
drive = "floppy1"
137
+ backend_defaults = "auto"
138
logical_block_size = 512 (512 B)
139
physical_block_size = 512 (512 B)
140
min_io_size = 0 (0 B)
141
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2
142
dev: floppy, id ""
143
unit = 0 (0x0)
144
drive = "floppy0"
145
+ backend_defaults = "auto"
146
logical_block_size = 512 (512 B)
147
physical_block_size = 512 (512 B)
148
min_io_size = 0 (0 B)
149
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
150
dev: floppy, id ""
151
unit = 1 (0x1)
152
drive = "floppy1"
153
+ backend_defaults = "auto"
154
logical_block_size = 512 (512 B)
155
physical_block_size = 512 (512 B)
156
min_io_size = 0 (0 B)
157
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
158
dev: floppy, id ""
159
unit = 0 (0x0)
160
drive = "floppy0"
161
+ backend_defaults = "auto"
162
logical_block_size = 512 (512 B)
163
physical_block_size = 512 (512 B)
164
min_io_size = 0 (0 B)
165
@@ -XXX,XX +XXX,XX @@ Testing: -fdb
166
dev: floppy, id ""
167
unit = 1 (0x1)
168
drive = "floppy1"
169
+ backend_defaults = "auto"
170
logical_block_size = 512 (512 B)
171
physical_block_size = 512 (512 B)
172
min_io_size = 0 (0 B)
173
@@ -XXX,XX +XXX,XX @@ Testing: -fdb
174
dev: floppy, id ""
175
unit = 0 (0x0)
176
drive = "floppy0"
177
+ backend_defaults = "auto"
178
logical_block_size = 512 (512 B)
179
physical_block_size = 512 (512 B)
180
min_io_size = 0 (0 B)
181
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2
182
dev: floppy, id ""
183
unit = 0 (0x0)
184
drive = "floppy0"
185
+ backend_defaults = "auto"
186
logical_block_size = 512 (512 B)
187
physical_block_size = 512 (512 B)
188
min_io_size = 0 (0 B)
189
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
190
dev: floppy, id ""
191
unit = 1 (0x1)
192
drive = "floppy1"
193
+ backend_defaults = "auto"
194
logical_block_size = 512 (512 B)
195
physical_block_size = 512 (512 B)
196
min_io_size = 0 (0 B)
197
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
198
dev: floppy, id ""
199
unit = 0 (0x0)
200
drive = "floppy0"
201
+ backend_defaults = "auto"
202
logical_block_size = 512 (512 B)
203
physical_block_size = 512 (512 B)
204
min_io_size = 0 (0 B)
205
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
206
dev: floppy, id ""
207
unit = 1 (0x1)
208
drive = "floppy1"
209
+ backend_defaults = "auto"
210
logical_block_size = 512 (512 B)
211
physical_block_size = 512 (512 B)
212
min_io_size = 0 (0 B)
213
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
214
dev: floppy, id ""
215
unit = 0 (0x0)
216
drive = "floppy0"
217
+ backend_defaults = "auto"
218
logical_block_size = 512 (512 B)
219
physical_block_size = 512 (512 B)
220
min_io_size = 0 (0 B)
221
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
222
dev: floppy, id ""
223
unit = 0 (0x0)
224
drive = "none0"
225
+ backend_defaults = "auto"
226
logical_block_size = 512 (512 B)
227
physical_block_size = 512 (512 B)
228
min_io_size = 0 (0 B)
229
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
230
dev: floppy, id ""
231
unit = 1 (0x1)
232
drive = "none0"
233
+ backend_defaults = "auto"
234
logical_block_size = 512 (512 B)
235
physical_block_size = 512 (512 B)
236
min_io_size = 0 (0 B)
237
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
238
dev: floppy, id ""
239
unit = 1 (0x1)
240
drive = "none1"
241
+ backend_defaults = "auto"
242
logical_block_size = 512 (512 B)
243
physical_block_size = 512 (512 B)
244
min_io_size = 0 (0 B)
245
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
246
dev: floppy, id ""
247
unit = 0 (0x0)
248
drive = "none0"
249
+ backend_defaults = "auto"
250
logical_block_size = 512 (512 B)
251
physical_block_size = 512 (512 B)
252
min_io_size = 0 (0 B)
253
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
254
dev: floppy, id ""
255
unit = 1 (0x1)
256
drive = "none0"
257
+ backend_defaults = "auto"
258
logical_block_size = 512 (512 B)
259
physical_block_size = 512 (512 B)
260
min_io_size = 0 (0 B)
261
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
262
dev: floppy, id ""
263
unit = 0 (0x0)
264
drive = "floppy0"
265
+ backend_defaults = "auto"
266
logical_block_size = 512 (512 B)
267
physical_block_size = 512 (512 B)
268
min_io_size = 0 (0 B)
269
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
270
dev: floppy, id ""
271
unit = 1 (0x1)
272
drive = "none0"
273
+ backend_defaults = "auto"
274
logical_block_size = 512 (512 B)
275
physical_block_size = 512 (512 B)
276
min_io_size = 0 (0 B)
277
@@ -XXX,XX +XXX,XX @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
278
dev: floppy, id ""
279
unit = 0 (0x0)
280
drive = "floppy0"
281
+ backend_defaults = "auto"
282
logical_block_size = 512 (512 B)
283
physical_block_size = 512 (512 B)
284
min_io_size = 0 (0 B)
285
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
286
dev: floppy, id ""
287
unit = 0 (0x0)
288
drive = "none0"
289
+ backend_defaults = "auto"
290
logical_block_size = 512 (512 B)
291
physical_block_size = 512 (512 B)
292
min_io_size = 0 (0 B)
293
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
294
dev: floppy, id ""
295
unit = 1 (0x1)
296
drive = "floppy1"
297
+ backend_defaults = "auto"
298
logical_block_size = 512 (512 B)
299
physical_block_size = 512 (512 B)
300
min_io_size = 0 (0 B)
301
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
302
dev: floppy, id ""
303
unit = 0 (0x0)
304
drive = "none0"
305
+ backend_defaults = "auto"
306
logical_block_size = 512 (512 B)
307
physical_block_size = 512 (512 B)
308
min_io_size = 0 (0 B)
309
@@ -XXX,XX +XXX,XX @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
310
dev: floppy, id ""
311
unit = 1 (0x1)
312
drive = "floppy1"
313
+ backend_defaults = "auto"
314
logical_block_size = 512 (512 B)
315
physical_block_size = 512 (512 B)
316
min_io_size = 0 (0 B)
317
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
318
dev: floppy, id ""
319
unit = 1 (0x1)
320
drive = "none0"
321
+ backend_defaults = "auto"
322
logical_block_size = 512 (512 B)
323
physical_block_size = 512 (512 B)
324
min_io_size = 0 (0 B)
325
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
326
dev: floppy, id ""
327
unit = 0 (0x0)
328
drive = "floppy0"
329
+ backend_defaults = "auto"
330
logical_block_size = 512 (512 B)
331
physical_block_size = 512 (512 B)
332
min_io_size = 0 (0 B)
333
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
334
dev: floppy, id ""
335
unit = 1 (0x1)
336
drive = "none0"
337
+ backend_defaults = "auto"
338
logical_block_size = 512 (512 B)
339
physical_block_size = 512 (512 B)
340
min_io_size = 0 (0 B)
341
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
342
dev: floppy, id ""
343
unit = 0 (0x0)
344
drive = "floppy0"
345
+ backend_defaults = "auto"
346
logical_block_size = 512 (512 B)
347
physical_block_size = 512 (512 B)
348
min_io_size = 0 (0 B)
349
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device
350
dev: floppy, id ""
351
unit = 0 (0x0)
352
drive = "none0"
353
+ backend_defaults = "auto"
354
logical_block_size = 512 (512 B)
355
physical_block_size = 512 (512 B)
356
min_io_size = 0 (0 B)
357
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy
358
dev: floppy, id ""
359
unit = 0 (0x0)
360
drive = ""
361
+ backend_defaults = "auto"
362
logical_block_size = 512 (512 B)
363
physical_block_size = 512 (512 B)
364
min_io_size = 0 (0 B)
365
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy,drive-type=120
366
dev: floppy, id ""
367
unit = 0 (0x0)
368
drive = ""
369
+ backend_defaults = "auto"
370
logical_block_size = 512 (512 B)
371
physical_block_size = 512 (512 B)
372
min_io_size = 0 (0 B)
373
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy,drive-type=144
374
dev: floppy, id ""
375
unit = 0 (0x0)
376
drive = ""
377
+ backend_defaults = "auto"
378
logical_block_size = 512 (512 B)
379
physical_block_size = 512 (512 B)
380
min_io_size = 0 (0 B)
381
@@ -XXX,XX +XXX,XX @@ Testing: -device floppy,drive-type=288
382
dev: floppy, id ""
383
unit = 0 (0x0)
384
drive = ""
385
+ backend_defaults = "auto"
386
logical_block_size = 512 (512 B)
387
physical_block_size = 512 (512 B)
388
min_io_size = 0 (0 B)
389
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
390
dev: floppy, id ""
391
unit = 0 (0x0)
392
drive = "none0"
393
+ backend_defaults = "auto"
394
logical_block_size = 512 (512 B)
395
physical_block_size = 512 (512 B)
396
min_io_size = 0 (0 B)
397
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
398
dev: floppy, id ""
399
unit = 0 (0x0)
400
drive = "none0"
401
+ backend_defaults = "auto"
402
logical_block_size = 512 (512 B)
403
physical_block_size = 512 (512 B)
404
min_io_size = 0 (0 B)
405
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical
406
dev: floppy, id ""
407
unit = 0 (0x0)
408
drive = "none0"
409
+ backend_defaults = "auto"
410
logical_block_size = 512 (512 B)
411
physical_block_size = 512 (512 B)
412
min_io_size = 0 (0 B)
413
@@ -XXX,XX +XXX,XX @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
414
dev: floppy, id ""
415
unit = 0 (0x0)
416
drive = "none0"
417
+ backend_defaults = "auto"
418
logical_block_size = 512 (512 B)
419
physical_block_size = 512 (512 B)
420
min_io_size = 0 (0 B)
50
--
421
--
51
2.21.0
422
2.31.1
52
423
53
diff view generated by jsdifflib
Deleted patch
1
bdrv_has_zero_init() only has meaning for newly created images or image
2
areas. If the mirror job itself did not create the image, it cannot
3
rely on bdrv_has_zero_init()'s result to carry any meaning.
4
1
5
This is the case for drive-mirror with mode=existing and always for
6
blockdev-mirror.
7
8
Note that we only have to zero-initialize the target with sync=full,
9
because other modes actually do not promise that the target will contain
10
the same data as the source after the job -- sync=top only promises to
11
copy anything allocated in the top layer, and sync=none will only copy
12
new I/O. (Which is how mirror has always handled it.)
13
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-id: 20190724171239.8764-3-mreitz@redhat.com
16
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
include/block/block_int.h | 2 ++
20
block/mirror.c | 11 ++++++++---
21
blockdev.c | 16 +++++++++++++---
22
tests/test-block-iothread.c | 2 +-
23
4 files changed, 24 insertions(+), 7 deletions(-)
24
25
diff --git a/include/block/block_int.h b/include/block/block_int.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block_int.h
28
+++ b/include/block/block_int.h
29
@@ -XXX,XX +XXX,XX @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
30
* @buf_size: The amount of data that can be in flight at one time.
31
* @mode: Whether to collapse all images in the chain to the target.
32
* @backing_mode: How to establish the target's backing chain after completion.
33
+ * @zero_target: Whether the target should be explicitly zero-initialized
34
* @on_source_error: The action to take upon error reading from the source.
35
* @on_target_error: The action to take upon error writing to the target.
36
* @unmap: Whether to unmap target where source sectors only contain zeroes.
37
@@ -XXX,XX +XXX,XX @@ void mirror_start(const char *job_id, BlockDriverState *bs,
38
int creation_flags, int64_t speed,
39
uint32_t granularity, int64_t buf_size,
40
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
41
+ bool zero_target,
42
BlockdevOnError on_source_error,
43
BlockdevOnError on_target_error,
44
bool unmap, const char *filter_node_name,
45
diff --git a/block/mirror.c b/block/mirror.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/mirror.c
48
+++ b/block/mirror.c
49
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorBlockJob {
50
Error *replace_blocker;
51
bool is_none_mode;
52
BlockMirrorBackingMode backing_mode;
53
+ /* Whether the target image requires explicit zero-initialization */
54
+ bool zero_target;
55
MirrorCopyMode copy_mode;
56
BlockdevOnError on_source_error, on_target_error;
57
bool synced;
58
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
59
int ret;
60
int64_t count;
61
62
- if (base == NULL && !bdrv_has_zero_init(target_bs)) {
63
+ if (s->zero_target) {
64
if (!bdrv_can_write_zeroes_with_unmap(target_bs)) {
65
bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length);
66
return 0;
67
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
68
const char *replaces, int64_t speed,
69
uint32_t granularity, int64_t buf_size,
70
BlockMirrorBackingMode backing_mode,
71
+ bool zero_target,
72
BlockdevOnError on_source_error,
73
BlockdevOnError on_target_error,
74
bool unmap,
75
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
76
s->on_target_error = on_target_error;
77
s->is_none_mode = is_none_mode;
78
s->backing_mode = backing_mode;
79
+ s->zero_target = zero_target;
80
s->copy_mode = copy_mode;
81
s->base = base;
82
s->granularity = granularity;
83
@@ -XXX,XX +XXX,XX @@ void mirror_start(const char *job_id, BlockDriverState *bs,
84
int creation_flags, int64_t speed,
85
uint32_t granularity, int64_t buf_size,
86
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
87
+ bool zero_target,
88
BlockdevOnError on_source_error,
89
BlockdevOnError on_target_error,
90
bool unmap, const char *filter_node_name,
91
@@ -XXX,XX +XXX,XX @@ void mirror_start(const char *job_id, BlockDriverState *bs,
92
is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
93
base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL;
94
mirror_start_job(job_id, bs, creation_flags, target, replaces,
95
- speed, granularity, buf_size, backing_mode,
96
+ speed, granularity, buf_size, backing_mode, zero_target,
97
on_source_error, on_target_error, unmap, NULL, NULL,
98
&mirror_job_driver, is_none_mode, base, false,
99
filter_node_name, true, copy_mode, errp);
100
@@ -XXX,XX +XXX,XX @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
101
102
ret = mirror_start_job(
103
job_id, bs, creation_flags, base, NULL, speed, 0, 0,
104
- MIRROR_LEAVE_BACKING_CHAIN,
105
+ MIRROR_LEAVE_BACKING_CHAIN, false,
106
on_error, on_error, true, cb, opaque,
107
&commit_active_job_driver, false, base, auto_complete,
108
filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND,
109
diff --git a/blockdev.c b/blockdev.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/blockdev.c
112
+++ b/blockdev.c
113
@@ -XXX,XX +XXX,XX @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
114
bool has_replaces, const char *replaces,
115
enum MirrorSyncMode sync,
116
BlockMirrorBackingMode backing_mode,
117
+ bool zero_target,
118
bool has_speed, int64_t speed,
119
bool has_granularity, uint32_t granularity,
120
bool has_buf_size, int64_t buf_size,
121
@@ -XXX,XX +XXX,XX @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
122
*/
123
mirror_start(job_id, bs, target,
124
has_replaces ? replaces : NULL, job_flags,
125
- speed, granularity, buf_size, sync, backing_mode,
126
+ speed, granularity, buf_size, sync, backing_mode, zero_target,
127
on_source_error, on_target_error, unmap, filter_node_name,
128
copy_mode, errp);
129
}
130
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
131
int flags;
132
int64_t size;
133
const char *format = arg->format;
134
+ bool zero_target;
135
int ret;
136
137
bs = qmp_get_root_bs(arg->device, errp);
138
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
139
goto out;
140
}
141
142
+ zero_target = (arg->sync == MIRROR_SYNC_MODE_FULL &&
143
+ (arg->mode == NEW_IMAGE_MODE_EXISTING ||
144
+ !bdrv_has_zero_init(target_bs)));
145
+
146
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
147
if (ret < 0) {
148
bdrv_unref(target_bs);
149
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
150
151
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
152
arg->has_replaces, arg->replaces, arg->sync,
153
- backing_mode, arg->has_speed, arg->speed,
154
+ backing_mode, zero_target,
155
+ arg->has_speed, arg->speed,
156
arg->has_granularity, arg->granularity,
157
arg->has_buf_size, arg->buf_size,
158
arg->has_on_source_error, arg->on_source_error,
159
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
160
AioContext *aio_context;
161
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
162
Error *local_err = NULL;
163
+ bool zero_target;
164
int ret;
165
166
bs = qmp_get_root_bs(device, errp);
167
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
168
return;
169
}
170
171
+ zero_target = (sync == MIRROR_SYNC_MODE_FULL);
172
+
173
aio_context = bdrv_get_aio_context(bs);
174
aio_context_acquire(aio_context);
175
176
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
177
178
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
179
has_replaces, replaces, sync, backing_mode,
180
- has_speed, speed,
181
+ zero_target, has_speed, speed,
182
has_granularity, granularity,
183
has_buf_size, buf_size,
184
has_on_source_error, on_source_error,
185
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/tests/test-block-iothread.c
188
+++ b/tests/test-block-iothread.c
189
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
190
191
/* Start a mirror job */
192
mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0,
193
- MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN,
194
+ MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false,
195
BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
196
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
197
&error_abort);
198
--
199
2.21.0
200
201
diff view generated by jsdifflib
Deleted patch
1
No .bdrv_has_zero_init() implementation returns 1 if growing the file
2
would add non-zero areas (at least with PREALLOC_MODE_OFF), so using it
3
in lieu of this new function was always safe.
4
1
5
But on the other hand, it is possible that growing an image that is not
6
zero-initialized would still add a zero-initialized area, like when
7
using nonpreallocating truncation on a preallocated image. For callers
8
that care only about truncation, not about creation with potential
9
preallocation, this new function is useful.
10
11
Alternatively, we could have added a PreallocMode parameter to
12
bdrv_has_zero_init(). But the only user would have been qemu-img
13
convert, which does not have a plain PreallocMode value right now -- it
14
would have to parse the creation option to obtain it. Therefore, the
15
simpler solution is to let bdrv_has_zero_init() inquire the
16
preallocation status and add the new bdrv_has_zero_init_truncate() that
17
presupposes PREALLOC_MODE_OFF.
18
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Message-id: 20190724171239.8764-4-mreitz@redhat.com
21
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
22
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
25
include/block/block.h | 1 +
26
include/block/block_int.h | 7 +++++++
27
block.c | 21 +++++++++++++++++++++
28
3 files changed, 29 insertions(+)
29
30
diff --git a/include/block/block.h b/include/block/block.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/block.h
33
+++ b/include/block/block.h
34
@@ -XXX,XX +XXX,XX @@ int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
35
int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
36
int bdrv_has_zero_init_1(BlockDriverState *bs);
37
int bdrv_has_zero_init(BlockDriverState *bs);
38
+int bdrv_has_zero_init_truncate(BlockDriverState *bs);
39
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
40
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
41
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
42
diff --git a/include/block/block_int.h b/include/block/block_int.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/block/block_int.h
45
+++ b/include/block/block_int.h
46
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
47
/*
48
* Returns 1 if newly created images are guaranteed to contain only
49
* zeros, 0 otherwise.
50
+ * Must return 0 if .bdrv_has_zero_init_truncate() returns 0.
51
*/
52
int (*bdrv_has_zero_init)(BlockDriverState *bs);
53
54
+ /*
55
+ * Returns 1 if new areas added by growing the image with
56
+ * PREALLOC_MODE_OFF contain only zeros, 0 otherwise.
57
+ */
58
+ int (*bdrv_has_zero_init_truncate)(BlockDriverState *bs);
59
+
60
/* Remove fd handlers, timers, and other event loop callbacks so the event
61
* loop is no longer in use. Called with no in-flight requests and in
62
* depth-first traversal order with parents before child nodes.
63
diff --git a/block.c b/block.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block.c
66
+++ b/block.c
67
@@ -XXX,XX +XXX,XX @@ int bdrv_has_zero_init(BlockDriverState *bs)
68
return 0;
69
}
70
71
+int bdrv_has_zero_init_truncate(BlockDriverState *bs)
72
+{
73
+ if (!bs->drv) {
74
+ return 0;
75
+ }
76
+
77
+ if (bs->backing) {
78
+ /* Depends on the backing image length, but better safe than sorry */
79
+ return 0;
80
+ }
81
+ if (bs->drv->bdrv_has_zero_init_truncate) {
82
+ return bs->drv->bdrv_has_zero_init_truncate(bs);
83
+ }
84
+ if (bs->file && bs->drv->is_filter) {
85
+ return bdrv_has_zero_init_truncate(bs->file->bs);
86
+ }
87
+
88
+ /* safe default */
89
+ return 0;
90
+}
91
+
92
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs)
93
{
94
BlockDriverInfo bdi;
95
--
96
2.21.0
97
98
diff view generated by jsdifflib
Deleted patch
1
vhdx and parallels call bdrv_has_zero_init() when they do not really
2
care about an image's post-create state but only about what happens when
3
you grow an image. That is a bit ugly, and also overly safe when
4
growing preallocated images without preallocating the new areas.
5
1
6
Let them use bdrv_has_zero_init_truncate() instead.
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20190724171239.8764-6-mreitz@redhat.com
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
12
[mreitz: Added commit message]
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/parallels.c | 2 +-
16
block/vhdx.c | 2 +-
17
2 files changed, 2 insertions(+), 2 deletions(-)
18
19
diff --git a/block/parallels.c b/block/parallels.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/parallels.c
22
+++ b/block/parallels.c
23
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
24
goto fail_options;
25
}
26
27
- if (!bdrv_has_zero_init(bs->file->bs)) {
28
+ if (!bdrv_has_zero_init_truncate(bs->file->bs)) {
29
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
30
}
31
32
diff --git a/block/vhdx.c b/block/vhdx.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/vhdx.c
35
+++ b/block/vhdx.c
36
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
37
/* Queue another write of zero buffers if the underlying file
38
* does not zero-fill on file extension */
39
40
- if (bdrv_has_zero_init(bs->file->bs) == 0) {
41
+ if (bdrv_has_zero_init_truncate(bs->file->bs) == 0) {
42
use_zero_buffers = true;
43
44
/* zero fill the front, if any */
45
--
46
2.21.0
47
48
diff view generated by jsdifflib
Deleted patch
1
If a qcow2 file is preallocated, it can no longer guarantee that it
2
initially appears as filled with zeroes.
3
1
4
So implement .bdrv_has_zero_init() by checking whether the file is
5
preallocated; if so, forward the call to the underlying storage node,
6
except for when it is encrypted: Encrypted preallocated images always
7
return effectively random data, so .bdrv_has_zero_init() must always
8
return 0 for them.
9
10
.bdrv_has_zero_init_truncate() can remain bdrv_has_zero_init_1(),
11
because it presupposes PREALLOC_MODE_OFF.
12
13
Reported-by: Stefano Garzarella <sgarzare@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-id: 20190724171239.8764-7-mreitz@redhat.com
16
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/qcow2.c | 29 ++++++++++++++++++++++++++++-
20
1 file changed, 28 insertions(+), 1 deletion(-)
21
22
diff --git a/block/qcow2.c b/block/qcow2.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2.c
25
+++ b/block/qcow2.c
26
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
27
return spec_info;
28
}
29
30
+static int qcow2_has_zero_init(BlockDriverState *bs)
31
+{
32
+ BDRVQcow2State *s = bs->opaque;
33
+ bool preallocated;
34
+
35
+ if (qemu_in_coroutine()) {
36
+ qemu_co_mutex_lock(&s->lock);
37
+ }
38
+ /*
39
+ * Check preallocation status: Preallocated images have all L2
40
+ * tables allocated, nonpreallocated images have none. It is
41
+ * therefore enough to check the first one.
42
+ */
43
+ preallocated = s->l1_size > 0 && s->l1_table[0] != 0;
44
+ if (qemu_in_coroutine()) {
45
+ qemu_co_mutex_unlock(&s->lock);
46
+ }
47
+
48
+ if (!preallocated) {
49
+ return 1;
50
+ } else if (bs->encrypted) {
51
+ return 0;
52
+ } else {
53
+ return bdrv_has_zero_init(s->data_file->bs);
54
+ }
55
+}
56
+
57
static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
58
int64_t pos)
59
{
60
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
61
.bdrv_child_perm = bdrv_format_default_perms,
62
.bdrv_co_create_opts = qcow2_co_create_opts,
63
.bdrv_co_create = qcow2_co_create,
64
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
65
+ .bdrv_has_zero_init = qcow2_has_zero_init,
66
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
67
.bdrv_co_block_status = qcow2_co_block_status,
68
69
--
70
2.21.0
71
72
diff view generated by jsdifflib
Deleted patch
1
Static VDI images cannot guarantee to be zero-initialized. If the image
2
has been statically allocated, forward the call to the underlying
3
storage node.
4
1
5
Reported-by: Stefano Garzarella <sgarzare@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Stefan Weil <sw@weilnetz.de>
8
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
9
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
10
Message-id: 20190724171239.8764-8-mreitz@redhat.com
11
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/vdi.c | 13 ++++++++++++-
15
1 file changed, 12 insertions(+), 1 deletion(-)
16
17
diff --git a/block/vdi.c b/block/vdi.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/vdi.c
20
+++ b/block/vdi.c
21
@@ -XXX,XX +XXX,XX @@ static void vdi_close(BlockDriverState *bs)
22
error_free(s->migration_blocker);
23
}
24
25
+static int vdi_has_zero_init(BlockDriverState *bs)
26
+{
27
+ BDRVVdiState *s = bs->opaque;
28
+
29
+ if (s->header.image_type == VDI_TYPE_STATIC) {
30
+ return bdrv_has_zero_init(bs->file->bs);
31
+ } else {
32
+ return 1;
33
+ }
34
+}
35
+
36
static QemuOptsList vdi_create_opts = {
37
.name = "vdi-create-opts",
38
.head = QTAILQ_HEAD_INITIALIZER(vdi_create_opts.head),
39
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
40
.bdrv_child_perm = bdrv_format_default_perms,
41
.bdrv_co_create = vdi_co_create,
42
.bdrv_co_create_opts = vdi_co_create_opts,
43
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
44
+ .bdrv_has_zero_init = vdi_has_zero_init,
45
.bdrv_co_block_status = vdi_co_block_status,
46
.bdrv_make_empty = vdi_make_empty,
47
48
--
49
2.21.0
50
51
diff view generated by jsdifflib
Deleted patch
1
Fixed VHDX images cannot guarantee to be zero-initialized. If the image
2
has the "fixed" subformat, forward the call to the underlying storage
3
node.
4
1
5
Reported-by: Stefano Garzarella <sgarzare@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190724171239.8764-9-mreitz@redhat.com
8
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/vhdx.c | 26 +++++++++++++++++++++++++-
12
1 file changed, 25 insertions(+), 1 deletion(-)
13
14
diff --git a/block/vhdx.c b/block/vhdx.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/vhdx.c
17
+++ b/block/vhdx.c
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_check(BlockDriverState *bs,
19
return 0;
20
}
21
22
+static int vhdx_has_zero_init(BlockDriverState *bs)
23
+{
24
+ BDRVVHDXState *s = bs->opaque;
25
+ int state;
26
+
27
+ /*
28
+ * Check the subformat: Fixed images have all BAT entries present,
29
+ * dynamic images have none (right after creation). It is
30
+ * therefore enough to check the first BAT entry.
31
+ */
32
+ if (!s->bat_entries) {
33
+ return 1;
34
+ }
35
+
36
+ state = s->bat[0] & VHDX_BAT_STATE_BIT_MASK;
37
+ if (state == PAYLOAD_BLOCK_FULLY_PRESENT) {
38
+ /* Fixed subformat */
39
+ return bdrv_has_zero_init(bs->file->bs);
40
+ }
41
+
42
+ /* Dynamic subformat */
43
+ return 1;
44
+}
45
+
46
static QemuOptsList vhdx_create_opts = {
47
.name = "vhdx-create-opts",
48
.head = QTAILQ_HEAD_INITIALIZER(vhdx_create_opts.head),
49
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
50
.bdrv_co_create_opts = vhdx_co_create_opts,
51
.bdrv_get_info = vhdx_get_info,
52
.bdrv_co_check = vhdx_co_check,
53
- .bdrv_has_zero_init = bdrv_has_zero_init_1,
54
+ .bdrv_has_zero_init = vhdx_has_zero_init,
55
56
.create_opts = &vhdx_create_opts,
57
};
58
--
59
2.21.0
60
61
diff view generated by jsdifflib
Deleted patch
1
Add a test case for converting an empty image (which only returns zeroes
2
when read) to a preallocated encrypted qcow2 image.
3
qcow2_has_zero_init() should return 0 then, thus forcing qemu-img
4
convert to create zero clusters.
5
1
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Acked-by: Stefano Garzarella <sgarzare@redhat.com>
8
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
9
Message-id: 20190724171239.8764-10-mreitz@redhat.com
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/188 | 20 +++++++++++++++++++-
14
tests/qemu-iotests/188.out | 4 ++++
15
2 files changed, 23 insertions(+), 1 deletion(-)
16
17
diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/188
20
+++ b/tests/qemu-iotests/188
21
@@ -XXX,XX +XXX,XX @@ SECRETALT="secret,id=sec0,data=platypus"
22
23
_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size
24
25
-IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
26
+IMGSPEC="driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
27
28
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
29
30
@@ -XXX,XX +XXX,XX @@ echo
31
echo "== verify open failure with wrong password =="
32
$QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
33
34
+_cleanup_test_img
35
+
36
+echo
37
+echo "== verify that has_zero_init returns false when preallocating =="
38
+
39
+# Empty source file
40
+if [ -n "$TEST_IMG_FILE" ]; then
41
+ TEST_IMG_FILE="${TEST_IMG_FILE}.orig" _make_test_img $size
42
+else
43
+ TEST_IMG="${TEST_IMG}.orig" _make_test_img $size
44
+fi
45
+
46
+$QEMU_IMG convert -O "$IMGFMT" --object $SECRET \
47
+ -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,preallocation=metadata" \
48
+ "${TEST_IMG}.orig" "$TEST_IMG"
49
+
50
+$QEMU_IMG compare --object $SECRET --image-opts "${IMGSPEC}.orig" "$IMGSPEC"
51
+
52
53
# success, all done
54
echo "*** done"
55
diff --git a/tests/qemu-iotests/188.out b/tests/qemu-iotests/188.out
56
index XXXXXXX..XXXXXXX 100644
57
--- a/tests/qemu-iotests/188.out
58
+++ b/tests/qemu-iotests/188.out
59
@@ -XXX,XX +XXX,XX @@ read 16777216/16777216 bytes at offset 0
60
61
== verify open failure with wrong password ==
62
qemu-io: can't open: Invalid password, cannot unlock any keyslot
63
+
64
+== verify that has_zero_init returns false when preallocating ==
65
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=16777216
66
+Images are identical.
67
*** done
68
--
69
2.21.0
70
71
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Message-id: 20190724171239.8764-11-mreitz@redhat.com
3
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
6
tests/qemu-iotests/122 | 17 +++++++++++++++++
7
tests/qemu-iotests/122.out | 8 ++++++++
8
2 files changed, 25 insertions(+)
9
1
10
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
11
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/122
13
+++ b/tests/qemu-iotests/122
14
@@ -XXX,XX +XXX,XX @@ for min_sparse in 4k 8k; do
15
$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map
16
done
17
18
+
19
+echo
20
+echo '=== -n to a non-zero image ==='
21
+echo
22
+
23
+# Keep source zero
24
+_make_test_img 64M
25
+
26
+# Output is not zero, but has bdrv_has_zero_init() == 1
27
+TEST_IMG="$TEST_IMG".orig _make_test_img 64M
28
+$QEMU_IO -c "write -P 42 0 64k" "$TEST_IMG".orig | _filter_qemu_io
29
+
30
+# Convert with -n, which should not assume that the target is zeroed
31
+$QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig
32
+
33
+$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig
34
+
35
# success, all done
36
echo '*** done'
37
rm -f $seq.full
38
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
39
index XXXXXXX..XXXXXXX 100644
40
--- a/tests/qemu-iotests/122.out
41
+++ b/tests/qemu-iotests/122.out
42
@@ -XXX,XX +XXX,XX @@ convert -c -S 8k
43
{ "start": 9216, "length": 8192, "depth": 0, "zero": true, "data": false},
44
{ "start": 17408, "length": 1024, "depth": 0, "zero": false, "data": true},
45
{ "start": 18432, "length": 67090432, "depth": 0, "zero": true, "data": false}]
46
+
47
+=== -n to a non-zero image ===
48
+
49
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
50
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
51
+wrote 65536/65536 bytes at offset 0
52
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
53
+Images are identical.
54
*** done
55
--
56
2.21.0
57
58
diff view generated by jsdifflib
Deleted patch
1
The result of a sync=full mirror should always be the equal to the
2
input. Therefore, existing images should be treated as potentially
3
non-zero and thus should be explicitly initialized to be zero
4
beforehand.
5
1
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190724171239.8764-12-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/041 | 62 +++++++++++++++++++++++++++++++++++---
11
tests/qemu-iotests/041.out | 4 +--
12
2 files changed, 60 insertions(+), 6 deletions(-)
13
14
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/041
17
+++ b/tests/qemu-iotests/041
18
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
19
def setUp(self):
20
qemu_img('create', '-f', iotests.imgfmt, test_img,
21
str(TestUnbackedSource.image_len))
22
- self.vm = iotests.VM().add_drive(test_img)
23
+ self.vm = iotests.VM()
24
self.vm.launch()
25
+ result = self.vm.qmp('blockdev-add', node_name='drive0',
26
+ driver=iotests.imgfmt,
27
+ file={
28
+ 'driver': 'file',
29
+ 'filename': test_img,
30
+ })
31
+ self.assert_qmp(result, 'return', {})
32
33
def tearDown(self):
34
self.vm.shutdown()
35
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
36
37
def test_absolute_paths_full(self):
38
self.assert_no_active_block_jobs()
39
- result = self.vm.qmp('drive-mirror', device='drive0',
40
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
41
sync='full', target=target_img,
42
mode='absolute-paths')
43
self.assert_qmp(result, 'return', {})
44
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
45
46
def test_absolute_paths_top(self):
47
self.assert_no_active_block_jobs()
48
- result = self.vm.qmp('drive-mirror', device='drive0',
49
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
50
sync='top', target=target_img,
51
mode='absolute-paths')
52
self.assert_qmp(result, 'return', {})
53
@@ -XXX,XX +XXX,XX @@ class TestUnbackedSource(iotests.QMPTestCase):
54
55
def test_absolute_paths_none(self):
56
self.assert_no_active_block_jobs()
57
- result = self.vm.qmp('drive-mirror', device='drive0',
58
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
59
sync='none', target=target_img,
60
mode='absolute-paths')
61
self.assert_qmp(result, 'return', {})
62
self.complete_and_wait()
63
self.assert_no_active_block_jobs()
64
65
+ def test_existing_full(self):
66
+ qemu_img('create', '-f', iotests.imgfmt, target_img,
67
+ str(self.image_len))
68
+ qemu_io('-c', 'write -P 42 0 64k', target_img)
69
+
70
+ self.assert_no_active_block_jobs()
71
+ result = self.vm.qmp('drive-mirror', job_id='drive0', device='drive0',
72
+ sync='full', target=target_img, mode='existing')
73
+ self.assert_qmp(result, 'return', {})
74
+ self.complete_and_wait()
75
+ self.assert_no_active_block_jobs()
76
+
77
+ result = self.vm.qmp('blockdev-del', node_name='drive0')
78
+ self.assert_qmp(result, 'return', {})
79
+
80
+ self.assertTrue(iotests.compare_images(test_img, target_img),
81
+ 'target image does not match source after mirroring')
82
+
83
+ def test_blockdev_full(self):
84
+ qemu_img('create', '-f', iotests.imgfmt, target_img,
85
+ str(self.image_len))
86
+ qemu_io('-c', 'write -P 42 0 64k', target_img)
87
+
88
+ result = self.vm.qmp('blockdev-add', node_name='target',
89
+ driver=iotests.imgfmt,
90
+ file={
91
+ 'driver': 'file',
92
+ 'filename': target_img,
93
+ })
94
+ self.assert_qmp(result, 'return', {})
95
+
96
+ self.assert_no_active_block_jobs()
97
+ result = self.vm.qmp('blockdev-mirror', job_id='drive0', device='drive0',
98
+ sync='full', target='target')
99
+ self.assert_qmp(result, 'return', {})
100
+ self.complete_and_wait()
101
+ self.assert_no_active_block_jobs()
102
+
103
+ result = self.vm.qmp('blockdev-del', node_name='drive0')
104
+ self.assert_qmp(result, 'return', {})
105
+
106
+ result = self.vm.qmp('blockdev-del', node_name='target')
107
+ self.assert_qmp(result, 'return', {})
108
+
109
+ self.assertTrue(iotests.compare_images(test_img, target_img),
110
+ 'target image does not match source after mirroring')
111
+
112
class TestGranularity(iotests.QMPTestCase):
113
image_len = 10 * 1024 * 1024 # MB
114
115
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
116
index XXXXXXX..XXXXXXX 100644
117
--- a/tests/qemu-iotests/041.out
118
+++ b/tests/qemu-iotests/041.out
119
@@ -XXX,XX +XXX,XX @@
120
-........................................................................................
121
+..........................................................................................
122
----------------------------------------------------------------------
123
-Ran 88 tests
124
+Ran 90 tests
125
126
OK
127
--
128
2.21.0
129
130
diff view generated by jsdifflib
Deleted patch
1
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
Fixes: 69f47505ee66afaa513305de0c1895a224e52c45
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190725155512.9827-2-mreitz@redhat.com
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
block/vdi.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
1
12
diff --git a/block/vdi.c b/block/vdi.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vdi.c
15
+++ b/block/vdi.c
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_block_status(BlockDriverState *bs,
17
*map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
18
index_in_block;
19
*file = bs->file->bs;
20
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
21
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID |
22
+ (s->header.image_type == VDI_TYPE_STATIC ? BDRV_BLOCK_RECURSE : 0);
23
}
24
25
static int coroutine_fn
26
--
27
2.21.0
28
29
diff view generated by jsdifflib
Deleted patch
1
Fixes: 69f47505ee66afaa513305de0c1895a224e52c45
2
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Message-id: 20190725155512.9827-3-mreitz@redhat.com
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
block/vmdk.c | 3 +++
9
1 file changed, 3 insertions(+)
10
1
11
diff --git a/block/vmdk.c b/block/vmdk.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/vmdk.c
14
+++ b/block/vmdk.c
15
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
16
if (!extent->compressed) {
17
ret |= BDRV_BLOCK_OFFSET_VALID;
18
*map = cluster_offset + index_in_cluster;
19
+ if (extent->flat) {
20
+ ret |= BDRV_BLOCK_RECURSE;
21
+ }
22
}
23
*file = extent->file->bs;
24
break;
25
--
26
2.21.0
27
28
diff view generated by jsdifflib
Deleted patch
1
vpc is not really a passthrough driver, even when using the fixed
2
subformat (where host and guest offsets are equal). It should handle
3
preallocation like all other drivers do, namely by returning
4
DATA | RECURSE instead of RAW.
5
1
6
There is no tangible difference but the fact that bdrv_is_allocated() no
7
longer falls through to the protocol layer.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 20190725155512.9827-4-mreitz@redhat.com
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/vpc.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/block/vpc.c b/block/vpc.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/vpc.c
20
+++ b/block/vpc.c
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_block_status(BlockDriverState *bs,
22
*pnum = bytes;
23
*map = offset;
24
*file = bs->file->bs;
25
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
26
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_RECURSE;
27
}
28
29
qemu_co_mutex_lock(&s->lock);
30
--
31
2.21.0
32
33
diff view generated by jsdifflib
1
When preallocating an encrypted qcow2 image, it just lets the protocol
1
From: Akihiko Odaki <akihiko.odaki@gmail.com>
2
driver write data and then does not mark the clusters as zero.
3
Therefore, reading this image will yield effectively random data.
4
2
5
As such, we have not fulfilled the promise of always writing zeroes when
3
Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
6
preallocating an image in a while. It seems that nobody has really
4
Message-id: 20210705130458.97642-3-akihiko.odaki@gmail.com
7
cared, so change the documentation to conform to qemu's actual behavior.
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
block/io.c | 2 ++
8
1 file changed, 2 insertions(+)
8
9
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
diff --git a/block/io.c b/block/io.c
10
Message-id: 20190711132935.13070-1-mreitz@redhat.com
11
index XXXXXXX..XXXXXXX 100644
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
--- a/block/io.c
12
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
13
+++ b/block/io.c
13
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
14
@@ -XXX,XX +XXX,XX @@ void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
15
---
16
static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
16
qapi/block-core.json | 9 +++++----
17
{
17
docs/qemu-block-drivers.texi | 4 ++--
18
+ dst->pdiscard_alignment = MAX(dst->pdiscard_alignment,
18
qemu-img.texi | 4 ++--
19
+ src->pdiscard_alignment);
19
3 files changed, 9 insertions(+), 8 deletions(-)
20
dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer);
21
dst->max_transfer = MIN_NON_ZERO(dst->max_transfer, src->max_transfer);
22
dst->max_hw_transfer = MIN_NON_ZERO(dst->max_hw_transfer,
23
--
24
2.31.1
20
25
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
index XXXXXXX..XXXXXXX 100644
23
--- a/qapi/block-core.json
24
+++ b/qapi/block-core.json
25
@@ -XXX,XX +XXX,XX @@
26
# @off: no preallocation
27
# @metadata: preallocate only for metadata
28
# @falloc: like @full preallocation but allocate disk space by
29
-# posix_fallocate() rather than writing zeros.
30
-# @full: preallocate all data by writing zeros to device to ensure disk
31
-# space is really available. @full preallocation also sets up
32
-# metadata correctly.
33
+# posix_fallocate() rather than writing data.
34
+# @full: preallocate all data by writing it to the device to ensure
35
+# disk space is really available. This data may or may not be
36
+# zero, depending on the image format and storage.
37
+# @full preallocation also sets up metadata correctly.
38
#
39
# Since: 2.2
40
##
41
diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi
42
index XXXXXXX..XXXXXXX 100644
43
--- a/docs/qemu-block-drivers.texi
44
+++ b/docs/qemu-block-drivers.texi
45
@@ -XXX,XX +XXX,XX @@ Supported options:
46
@item preallocation
47
Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
48
@code{falloc} mode preallocates space for image by calling posix_fallocate().
49
-@code{full} mode preallocates space for image by writing zeros to underlying
50
-storage.
51
+@code{full} mode preallocates space for image by writing data to underlying
52
+storage. This data may or may not be zero, depending on the storage location.
53
@end table
54
55
@item qcow2
56
diff --git a/qemu-img.texi b/qemu-img.texi
57
index XXXXXXX..XXXXXXX 100644
58
--- a/qemu-img.texi
59
+++ b/qemu-img.texi
60
@@ -XXX,XX +XXX,XX @@ Supported options:
61
@item preallocation
62
Preallocation mode (allowed values: @code{off}, @code{falloc}, @code{full}).
63
@code{falloc} mode preallocates space for image by calling posix_fallocate().
64
-@code{full} mode preallocates space for image by writing zeros to underlying
65
-storage.
66
+@code{full} mode preallocates space for image by writing data to underlying
67
+storage. This data may or may not be zero, depending on the storage location.
68
@end table
69
70
@item qcow2
71
--
72
2.21.0
73
74
diff view generated by jsdifflib