1
The following changes since commit ae49fbbcd8e4e9d8bf7131add34773f579e1aff7:
1
The following changes since commit 344744e148e6e865f5a57e745b02a87e5ea534ad:
2
2
3
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20171025' into staging (2017-10-25 16:38:57 +0100)
3
Merge tag 'dump-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging (2022-10-26 10:53:49 -0400)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 4254d01ce4eec9a3ccf320d14e2da132b8ad4a51:
9
for you to fetch changes up to be8da05b5ed8fb546731b9edb997f303f272bad8:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-10-26' into queue-block (2017-10-26 15:02:40 +0200)
11
block/block-backend: blk_set_enable_write_cache is IO_CODE (2022-10-27 20:27:37 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches
15
15
16
- Cleanup bs->backing and bs->file handling
17
- Refactor bdrv_try_set_aio_context using transactions
18
- Changes for improved coroutine_fn consistency
19
- vhost-user-blk: fix the resize crash
20
- io_uring: Use of io_uring_register_ring_fd() led to breakage, revert
21
- vvfat: Fix some problems with r/w mode
22
- Code cleanup
23
- MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"
24
16
----------------------------------------------------------------
25
----------------------------------------------------------------
17
Alberto Garcia (1):
26
Alberto Faria (20):
18
qcow2: Use BDRV_SECTOR_BITS instead of its literal value
27
backup: remove incorrect coroutine_fn annotation
28
block: remove incorrect coroutine_fn annotation
29
monitor: add missing coroutine_fn annotation
30
ssh: add missing coroutine_fn annotation
31
block: add missing coroutine_fn annotation to prototypes
32
coroutine-lock: add missing coroutine_fn annotation to prototypes
33
coroutine-io: add missing coroutine_fn annotation to prototypes
34
block: add missing coroutine_fn annotation to BlockDriverState callbacks
35
qcow2: add coroutine_fn annotation for indirect-called functions
36
commit: switch to *_co_* functions
37
block: switch to *_co_* functions
38
mirror: switch to *_co_* functions
39
parallels: switch to *_co_* functions
40
qcow: switch to *_co_* functions
41
qcow2: switch to *_co_* functions
42
qed: switch to *_co_* functions
43
vdi: switch to *_co_* functions
44
vhdx: switch to *_co_* functions
45
vmdk: switch to *_co_* functions
46
monitor: switch to *_co_* functions
19
47
20
Eric Blake (24):
48
Bin Meng (3):
21
block: Allow NULL file for bdrv_get_block_status()
49
block: Ignore close() failure in get_tmp_filename()
22
block: Add flag to avoid wasted work in bdrv_is_allocated()
50
block: Refactor get_tmp_filename()
23
block: Make bdrv_round_to_clusters() signature more useful
51
block/nfs: Fix 32-bit Windows build
24
qcow2: Switch is_zero_sectors() to byte-based
25
block: Switch bdrv_make_zero() to byte-based
26
qemu-img: Switch get_block_status() to byte-based
27
block: Convert bdrv_get_block_status() to bytes
28
block: Switch bdrv_co_get_block_status() to byte-based
29
block: Switch BdrvCoGetBlockStatusData to byte-based
30
block: Switch bdrv_common_block_status_above() to byte-based
31
block: Switch bdrv_co_get_block_status_above() to byte-based
32
block: Convert bdrv_get_block_status_above() to bytes
33
qemu-img: Simplify logic in img_compare()
34
qemu-img: Speed up compare on pre-allocated larger file
35
qemu-img: Add find_nonzero()
36
qemu-img: Drop redundant error message in compare
37
qemu-img: Change check_empty_sectors() to byte-based
38
qemu-img: Change compare_sectors() to be byte-based
39
qemu-img: Change img_rebase() to be byte-based
40
qemu-img: Change img_compare() to be byte-based
41
block: Align block status requests
42
block: Reduce bdrv_aligned_preadv() rounding
43
qcow2: Reduce is_zero() rounding
44
qemu-io: Relax 'alloc' now that block-status doesn't assert
45
52
46
Kevin Wolf (2):
53
Emanuele Giuseppe Esposito (11):
47
qemu-iotests: Test backing_fmt with backing node reference
54
block.c: assert bs->aio_context is written under BQL and drains
48
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-10-26' into queue-block
55
block: use transactions as a replacement of ->{can_}set_aio_context()
56
bdrv_change_aio_context: use hash table instead of list of visited nodes
57
blockjob: implement .change_aio_ctx in child_job
58
block: implement .change_aio_ctx in child_of_bds
59
block-backend: implement .change_aio_ctx in child_root
60
block: use the new _change_ API instead of _can_set_ and _set_
61
block: remove all unused ->can_set_aio_ctx and ->set_aio_ctx callbacks
62
block: rename bdrv_child_try_change_aio_context in bdrv_try_change_aio_context
63
block: remove bdrv_try_set_aio_context and replace it with bdrv_try_change_aio_context
64
block/block-backend: blk_set_enable_write_cache is IO_CODE
49
65
50
Max Reitz (8):
66
Hervé Poussineau (2):
51
qemu-img.1: Image invalidation on qemu-img commit
67
vvfat: allow some writes to bootsector
52
iotests: Add test for dataplane mirroring
68
vvfat: allow spaces in file names
53
iotests: Pull _filter_actual_image_size from 67/87
54
iotests: Filter actual image size in 184 and 191
55
qcow2: Emit errp when truncating the image tail
56
qcow2: Fix unaligned preallocated truncation
57
qcow2: Always execute preallocate() in a coroutine
58
iotests: Add cluster_size=64k to 125
59
69
60
Peter Krempa (1):
70
Li Feng (1):
61
block: don't add 'driver' to options when referring to backing via node name
71
vhost-user-blk: fix the resize crash
62
72
63
include/block/block.h | 29 ++-
73
Markus Armbruster (1):
64
include/block/block_int.h | 11 +-
74
MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"
65
block.c | 3 +-
66
block/blkdebug.c | 13 +-
67
block/io.c | 334 ++++++++++++++++-----------
68
block/mirror.c | 26 +--
69
block/qcow2-cluster.c | 2 +-
70
block/qcow2.c | 116 ++++++----
71
qemu-img.c | 381 ++++++++++++++-----------------
72
qemu-io-cmds.c | 13 --
73
block/trace-events | 2 +-
74
qemu-img.texi | 9 +-
75
tests/qemu-iotests/067 | 2 +-
76
tests/qemu-iotests/074.out | 2 -
77
tests/qemu-iotests/087 | 2 +-
78
tests/qemu-iotests/125 | 7 +-
79
tests/qemu-iotests/125.out | 480 +++++++++++++++++++++++++++++++++++----
80
tests/qemu-iotests/127 | 97 ++++++++
81
tests/qemu-iotests/127.out | 14 ++
82
tests/qemu-iotests/177 | 12 +-
83
tests/qemu-iotests/177.out | 19 +-
84
tests/qemu-iotests/184 | 3 +-
85
tests/qemu-iotests/184.out | 6 +-
86
tests/qemu-iotests/191 | 7 +-
87
tests/qemu-iotests/191.out | 48 ++--
88
tests/qemu-iotests/common.filter | 6 +
89
tests/qemu-iotests/group | 1 +
90
27 files changed, 1102 insertions(+), 543 deletions(-)
91
create mode 100755 tests/qemu-iotests/127
92
create mode 100644 tests/qemu-iotests/127.out
93
75
76
Paolo Bonzini (4):
77
blkdebug: add missing coroutine_fn annotation for indirect-called functions
78
qcow: manually add more coroutine_fn annotations
79
qcow2: manually add more coroutine_fn annotations
80
vmdk: manually add more coroutine_fn annotations
81
82
Sam Li (1):
83
block/io_uring: revert "Use io_uring_register_ring_fd() to skip fd operations"
84
85
Vladimir Sementsov-Ogievskiy (15):
86
block: BlockDriver: add .filtered_child_is_backing field
87
block: introduce bdrv_open_file_child() helper
88
block/blklogwrites: don't care to remove bs->file child on failure
89
test-bdrv-graph-mod: update test_parallel_perm_update test case
90
tests-bdrv-drain: bdrv_replace_test driver: declare supports_backing
91
test-bdrv-graph-mod: fix filters to be filters
92
block: document connection between child roles and bs->backing/bs->file
93
block/snapshot: stress that we fallback to primary child
94
Revert "block: Let replace_child_noperm free children"
95
Revert "block: Let replace_child_tran keep indirect pointer"
96
Revert "block: Restructure remove_file_or_backing_child()"
97
Revert "block: Pass BdrvChild ** to replace_child_noperm"
98
block: Manipulate bs->file / bs->backing pointers in .attach/.detach
99
block/snapshot: drop indirection around bdrv_snapshot_fallback_ptr
100
block: refactor bdrv_remove_file_or_backing_child to bdrv_remove_child
101
102
docs/devel/multiple-iothreads.txt | 4 +-
103
block/qcow2.h | 32 +-
104
include/block/block-common.h | 39 ++
105
include/block/block-global-state.h | 18 +-
106
include/block/block-hmp-cmds.h | 2 +-
107
include/block/block-io.h | 5 +-
108
include/block/block_int-common.h | 49 ++-
109
include/monitor/hmp.h | 3 +-
110
include/qemu/coroutine.h | 18 +-
111
block.c | 855 +++++++++++++++++--------------------
112
block/backup.c | 2 +-
113
block/blkdebug.c | 11 +-
114
block/blklogwrites.c | 11 +-
115
block/blkreplay.c | 7 +-
116
block/blkverify.c | 9 +-
117
block/block-backend.c | 76 ++--
118
block/bochs.c | 7 +-
119
block/cloop.c | 7 +-
120
block/commit.c | 3 +-
121
block/copy-before-write.c | 9 +-
122
block/copy-on-read.c | 9 +-
123
block/crypto.c | 11 +-
124
block/dmg.c | 7 +-
125
block/export/export.c | 2 +-
126
block/filter-compress.c | 8 +-
127
block/io.c | 8 +-
128
block/io_uring.c | 13 +-
129
block/mirror.c | 5 +-
130
block/monitor/block-hmp-cmds.c | 2 +-
131
block/nfs.c | 8 +
132
block/parallels.c | 35 +-
133
block/preallocate.c | 9 +-
134
block/qcow.c | 66 +--
135
block/qcow2-bitmap.c | 4 +-
136
block/qcow2-cluster.c | 29 +-
137
block/qcow2-refcount.c | 18 +-
138
block/qcow2-snapshot.c | 6 +-
139
block/qcow2.c | 40 +-
140
block/qed-table.c | 2 +-
141
block/qed.c | 20 +-
142
block/raw-format.c | 4 +-
143
block/replication.c | 8 +-
144
block/snapshot-access.c | 6 +-
145
block/snapshot.c | 59 +--
146
block/ssh.c | 6 +-
147
block/throttle.c | 8 +-
148
block/vdi.c | 24 +-
149
block/vhdx.c | 15 +-
150
block/vmdk.c | 95 ++---
151
block/vpc.c | 7 +-
152
block/vvfat.c | 35 +-
153
blockdev.c | 24 +-
154
blockjob.c | 50 ++-
155
hw/block/vhost-user-blk.c | 4 +
156
job.c | 2 +-
157
tests/unit/test-bdrv-drain.c | 17 +-
158
tests/unit/test-bdrv-graph-mod.c | 104 +++--
159
tests/unit/test-block-iothread.c | 10 +-
160
MAINTAINERS | 12 +-
161
meson.build | 1 -
162
tests/qemu-iotests/051 | 3 +-
163
tests/qemu-iotests/051.out | 2 +-
164
tests/qemu-iotests/051.pc.out | 2 +-
165
63 files changed, 984 insertions(+), 983 deletions(-)
166
167
diff view generated by jsdifflib
New patch
1
From: Markus Armbruster <armbru@redhat.com>
1
2
3
Section "Block QAPI, monitor, command line" is about the external
4
interfaces we provide for block devices. It covers the relevant QAPI
5
schema parts, monitor and command line code, more or less.
6
7
The section's files are also covered by section "Block layer core",
8
except for the QAPI schema files.
9
10
I haven't acted as maintainer in this area for a long time. Make it
11
official: add the QAPI schema files to section "Block layer core", and
12
delete section "Block QAPI, monitor, command line".
13
14
Cc: Kevin Wolf <kwolf@redhat.com>
15
Cc: Hanna Reitz <hreitz@redhat.com>
16
Signed-off-by: Markus Armbruster <armbru@redhat.com>
17
Message-Id: <20221020120541.80757-1-armbru@redhat.com>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
MAINTAINERS | 12 ++----------
22
1 file changed, 2 insertions(+), 10 deletions(-)
23
24
diff --git a/MAINTAINERS b/MAINTAINERS
25
index XXXXXXX..XXXXXXX 100644
26
--- a/MAINTAINERS
27
+++ b/MAINTAINERS
28
@@ -XXX,XX +XXX,XX @@ S: Supported
29
F: block*
30
F: block/
31
F: hw/block/
32
+F: qapi/block*.json
33
+F: qapi/transaction.json
34
F: include/block/
35
F: qemu-img*
36
F: docs/tools/qemu-img.rst
37
@@ -XXX,XX +XXX,XX @@ F: include/qemu/co-shared-resource.h
38
T: git https://gitlab.com/jsnow/qemu.git jobs
39
T: git https://gitlab.com/vsementsov/qemu.git block
40
41
-Block QAPI, monitor, command line
42
-M: Markus Armbruster <armbru@redhat.com>
43
-S: Supported
44
-F: blockdev.c
45
-F: blockdev-hmp-cmds.c
46
-F: block/qapi.c
47
-F: qapi/block*.json
48
-F: qapi/transaction.json
49
-T: git https://repo.or.cz/qemu/armbru.git block-next
50
-
51
Compute Express Link
52
M: Ben Widawsky <ben.widawsky@intel.com>
53
M: Jonathan Cameron <jonathan.cameron@huawei.com>
54
--
55
2.37.3
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bin.meng@windriver.com>
1
2
3
The temporary file has been created and is ready for use. Checking
4
return value of close() does not seem useful. The file descriptor
5
is almost certainly closed; see close(2) under "Dealing with error
6
returns from close()".
7
8
Let's simply ignore close() failure here.
9
10
Suggested-by: Markus Armbruster <armbru@redhat.com>
11
Signed-off-by: Bin Meng <bin.meng@windriver.com>
12
Reviewed-by: Markus Armbruster <armbru@redhat.com>
13
Message-Id: <20221010040432.3380478-1-bin.meng@windriver.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block.c | 5 +----
18
1 file changed, 1 insertion(+), 4 deletions(-)
19
20
diff --git a/block.c b/block.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block.c
23
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ int get_tmp_filename(char *filename, int size)
25
if (fd < 0) {
26
return -errno;
27
}
28
- if (close(fd) != 0) {
29
- unlink(filename);
30
- return -errno;
31
- }
32
+ close(fd);
33
return 0;
34
#endif
35
}
36
--
37
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
At present there are two callers of get_tmp_filename() and they are
4
easier to reason about than sector-based. Convert another internal
4
inconsistent.
5
type (no semantic change), and rename it to match the corresponding
5
6
public function rename.
6
One does:
7
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
8
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
9
char *tmp_filename = g_malloc0(PATH_MAX + 1);
10
...
11
ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
12
13
while the other does:
14
15
s->qcow_filename = g_malloc(PATH_MAX);
16
ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
17
18
As we can see different 'size' arguments are passed. There are also
19
platform specific implementations inside the function, and the use
20
of snprintf is really undesirable.
21
22
The function name is also misleading. It creates a temporary file,
23
not just a filename.
24
25
Refactor this routine by changing its name and signature to:
26
27
char *create_tmp_file(Error **errp)
28
29
and use g_get_tmp_dir() / g_mkstemp() for a consistent implementation.
30
31
While we are here, add some comments to mention that /var/tmp is
32
preferred over /tmp on non-win32 hosts.
33
34
Signed-off-by: Bin Meng <bin.meng@windriver.com>
35
Message-Id: <20221010040432.3380478-2-bin.meng@windriver.com>
36
[kwolf: Fixed incorrect errno negation and iotest 051]
37
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
39
---
11
block/io.c | 68 ++++++++++++++++++++++----------------------------------------
40
include/block/block_int-common.h | 2 +-
12
1 file changed, 24 insertions(+), 44 deletions(-)
41
block.c | 56 +++++++++++++++++---------------
13
42
block/vvfat.c | 7 ++--
14
diff --git a/block/io.c b/block/io.c
43
tests/qemu-iotests/051 | 3 +-
15
index XXXXXXX..XXXXXXX 100644
44
tests/qemu-iotests/051.out | 2 +-
16
--- a/block/io.c
45
tests/qemu-iotests/051.pc.out | 2 +-
17
+++ b/block/io.c
46
6 files changed, 38 insertions(+), 34 deletions(-)
18
@@ -XXX,XX +XXX,XX @@ early_out:
47
19
return ret;
48
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/block/block_int-common.h
51
+++ b/include/block/block_int-common.h
52
@@ -XXX,XX +XXX,XX @@ static inline BlockDriverState *child_bs(BdrvChild *child)
20
}
53
}
21
54
22
-static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
55
int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp);
23
- BlockDriverState *base,
56
-int get_tmp_filename(char *filename, int size);
24
- bool want_zero,
57
+char *create_tmp_file(Error **errp);
25
- int64_t sector_num,
58
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
26
- int nb_sectors,
59
QDict *options);
27
- int *pnum,
60
28
- BlockDriverState **file)
61
diff --git a/block.c b/block.c
29
+static int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
62
index XXXXXXX..XXXXXXX 100644
30
+ BlockDriverState *base,
63
--- a/block.c
31
+ bool want_zero,
64
+++ b/block.c
32
+ int64_t offset,
65
@@ -XXX,XX +XXX,XX @@ int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
33
+ int64_t bytes,
66
34
+ int64_t *pnum,
67
/*
35
+ int64_t *map,
68
* Create a uniquely-named empty temporary file.
36
+ BlockDriverState **file)
69
- * Return 0 upon success, otherwise a negative errno value.
70
+ * Return the actual file name used upon success, otherwise NULL.
71
+ * This string should be freed with g_free() when not needed any longer.
72
+ *
73
+ * Note: creating a temporary file for the caller to (re)open is
74
+ * inherently racy. Use g_file_open_tmp() instead whenever practical.
75
*/
76
-int get_tmp_filename(char *filename, int size)
77
+char *create_tmp_file(Error **errp)
37
{
78
{
38
BlockDriverState *p;
79
-#ifdef _WIN32
39
- int64_t ret = 0;
80
- char temp_dir[MAX_PATH];
40
+ int ret = 0;
81
- /* GetTempFileName requires that its output buffer (4th param)
41
bool first = true;
82
- have length MAX_PATH or greater. */
42
- int64_t map = 0;
83
- assert(size >= MAX_PATH);
43
84
- return (GetTempPath(MAX_PATH, temp_dir)
44
assert(bs != base);
85
- && GetTempFileName(temp_dir, "qem", 0, filename)
45
for (p = bs; p != base; p = backing_bs(p)) {
86
- ? 0 : -GetLastError());
46
- int64_t count;
87
-#else
47
-
88
int fd;
48
- ret = bdrv_co_block_status(p, want_zero,
89
const char *tmpdir;
49
- sector_num * BDRV_SECTOR_SIZE,
90
- tmpdir = getenv("TMPDIR");
50
- nb_sectors * BDRV_SECTOR_SIZE, &count,
91
- if (!tmpdir) {
51
- &map, file);
92
+ g_autofree char *filename = NULL;
52
+ ret = bdrv_co_block_status(p, want_zero, offset, bytes, pnum, map,
93
+
53
+ file);
94
+ tmpdir = g_get_tmp_dir();
54
if (ret < 0) {
95
+#ifndef _WIN32
55
break;
96
+ /*
56
}
97
+ * See commit 69bef79 ("block: use /var/tmp instead of /tmp for -snapshot")
57
- assert(QEMU_IS_ALIGNED(count | map, BDRV_SECTOR_SIZE));
98
+ *
58
- ret |= map;
99
+ * This function is used to create temporary disk images (like -snapshot),
59
- *pnum = count >> BDRV_SECTOR_BITS;
100
+ * so the files can become very large. /tmp is often a tmpfs where as
60
if (ret & BDRV_BLOCK_ZERO && ret & BDRV_BLOCK_EOF && !first) {
101
+ * /var/tmp is usually on a disk, so more appropriate for disk images.
61
/*
102
+ */
62
* Reading beyond the end of the file continues to read
103
+ if (!g_strcmp0(tmpdir, "/tmp")) {
63
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
104
tmpdir = "/var/tmp";
64
* unallocated length we learned from an earlier
105
}
65
* iteration.
106
- if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
66
*/
107
- return -EOVERFLOW;
67
- *pnum = nb_sectors;
108
- }
68
+ *pnum = bytes;
109
- fd = mkstemp(filename);
69
}
110
+#endif
70
if (ret & (BDRV_BLOCK_ZERO | BDRV_BLOCK_DATA)) {
111
+
71
break;
112
+ filename = g_strdup_printf("%s/vl.XXXXXX", tmpdir);
72
}
113
+ fd = g_mkstemp(filename);
73
- /* [sector_num, pnum] unallocated on this layer, which could be only
114
if (fd < 0) {
74
- * the first part of [sector_num, nb_sectors]. */
115
- return -errno;
75
- nb_sectors = MIN(nb_sectors, *pnum);
116
+ error_setg_errno(errp, errno, "Could not open temporary file '%s'",
76
+ /* [offset, pnum] unallocated on this layer, which could be only
117
+ filename);
77
+ * the first part of [offset, bytes]. */
118
+ return NULL;
78
+ bytes = MIN(bytes, *pnum);
119
}
79
first = false;
120
close(fd);
80
}
121
- return 0;
81
return ret;
122
-#endif
123
+
124
+ return g_steal_pointer(&filename);
82
}
125
}
83
126
84
/* Coroutine wrapper for bdrv_get_block_status_above() */
127
/*
85
-static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque)
128
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
86
+static void coroutine_fn bdrv_block_status_above_co_entry(void *opaque)
129
QDict *snapshot_options,
130
Error **errp)
87
{
131
{
88
BdrvCoBlockStatusData *data = opaque;
132
- /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
89
- int n = 0;
133
- char *tmp_filename = g_malloc0(PATH_MAX + 1);
90
- int64_t ret;
134
+ g_autofree char *tmp_filename = NULL;
91
135
int64_t total_size;
92
- ret = bdrv_co_get_block_status_above(data->bs, data->base,
136
QemuOpts *opts = NULL;
93
- data->want_zero,
137
BlockDriverState *bs_snapshot = NULL;
94
- data->offset >> BDRV_SECTOR_BITS,
138
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
95
- data->bytes >> BDRV_SECTOR_BITS,
139
}
96
- &n,
140
97
- data->file);
141
/* Create the temporary image */
142
- ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
98
- if (ret < 0) {
143
- if (ret < 0) {
99
- assert(INT_MIN <= ret);
144
- error_setg_errno(errp, -ret, "Could not get temporary filename");
100
- data->ret = ret;
145
+ tmp_filename = create_tmp_file(errp);
101
- } else {
146
+ if (!tmp_filename) {
102
- *data->pnum = n * BDRV_SECTOR_SIZE;
147
goto out;
103
- *data->map = ret & BDRV_BLOCK_OFFSET_MASK;
148
}
104
- data->ret = ret & ~BDRV_BLOCK_OFFSET_MASK;
149
105
- }
150
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
106
+ data->ret = bdrv_co_block_status_above(data->bs, data->base,
151
107
+ data->want_zero,
152
out:
108
+ data->offset, data->bytes,
153
qobject_unref(snapshot_options);
109
+ data->pnum, data->map, data->file);
154
- g_free(tmp_filename);
110
data->done = true;
155
return bs_snapshot;
111
}
156
}
112
157
113
/*
158
diff --git a/block/vvfat.c b/block/vvfat.c
114
- * Synchronous wrapper around bdrv_co_get_block_status_above().
159
index XXXXXXX..XXXXXXX 100644
115
+ * Synchronous wrapper around bdrv_co_block_status_above().
160
--- a/block/vvfat.c
116
*
161
+++ b/block/vvfat.c
117
- * See bdrv_co_get_block_status_above() for details.
162
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
118
+ * See bdrv_co_block_status_above() for details.
163
119
*/
164
array_init(&(s->commits), sizeof(commit_t));
120
static int bdrv_common_block_status_above(BlockDriverState *bs,
165
121
BlockDriverState *base,
166
- s->qcow_filename = g_malloc(PATH_MAX);
122
@@ -XXX,XX +XXX,XX @@ static int bdrv_common_block_status_above(BlockDriverState *bs,
167
- ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
123
168
- if (ret < 0) {
124
if (qemu_in_coroutine()) {
169
- error_setg_errno(errp, -ret, "can't create temporary file");
125
/* Fast-path if already in coroutine context */
170
+ s->qcow_filename = create_tmp_file(errp);
126
- bdrv_get_block_status_above_co_entry(&data);
171
+ if (!s->qcow_filename) {
127
+ bdrv_block_status_above_co_entry(&data);
172
+ ret = -ENOENT;
128
} else {
173
goto err;
129
- co = qemu_coroutine_create(bdrv_get_block_status_above_co_entry,
174
}
130
- &data);
175
131
+ co = qemu_coroutine_create(bdrv_block_status_above_co_entry, &data);
176
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
132
bdrv_coroutine_enter(bs, co);
177
index XXXXXXX..XXXXXXX 100755
133
BDRV_POLL_WHILE(bs, !data.done);
178
--- a/tests/qemu-iotests/051
134
}
179
+++ b/tests/qemu-iotests/051
180
@@ -XXX,XX +XXX,XX @@ if [ "${VALGRIND_QEMU_VM}" == "y" ]; then
181
_casenotrun "Valgrind needs a valid TMPDIR for itself"
182
fi
183
VALGRIND_QEMU_VM= \
184
-TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on
185
+TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on |
186
+ sed -e "s#'[^']*/vl\.[A-Za-z0-9]\{6\}'#SNAPSHOT_PATH#g"
187
188
# Using snapshot=on together with read-only=on
189
echo "info block" |
190
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
191
index XXXXXXX..XXXXXXX 100644
192
--- a/tests/qemu-iotests/051.out
193
+++ b/tests/qemu-iotests/051.out
194
@@ -XXX,XX +XXX,XX @@ wrote 4096/4096 bytes at offset 0
195
read 4096/4096 bytes at offset 0
196
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
Testing: -drive driver=null-co,snapshot=on
198
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
199
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
200
201
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
202
QEMU X.Y.Z monitor - type 'help' for more information
203
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
204
index XXXXXXX..XXXXXXX 100644
205
--- a/tests/qemu-iotests/051.pc.out
206
+++ b/tests/qemu-iotests/051.pc.out
207
@@ -XXX,XX +XXX,XX @@ wrote 4096/4096 bytes at offset 0
208
read 4096/4096 bytes at offset 0
209
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
210
Testing: -drive driver=null-co,snapshot=on
211
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
212
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
213
214
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
215
QEMU X.Y.Z monitor - type 'help' for more information
135
--
216
--
136
2.13.6
217
2.37.3
137
138
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
2
3
qemu-img commit invalidates all images between base and top. This
3
'reserved1' field in bootsector is used to mark volume dirty, or need to verify.
4
should be mentioned in the man page.
4
Allow writes to bootsector which only changes the 'reserved1' field.
5
5
6
Suggested-by: Ping Li <pingl@redhat.com>
6
This fixes I/O errors on Windows guests.
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
8
Resolves: https://bugs.launchpad.net/qemu/+bug/1889421
9
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
10
Message-Id: <20221010175511.3414357-2-hpoussin@reactos.org>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
qemu-img.texi | 9 ++++-----
14
block/vvfat.c | 26 +++++++++++++++++++++++++-
12
1 file changed, 4 insertions(+), 5 deletions(-)
15
1 file changed, 25 insertions(+), 1 deletion(-)
13
16
14
diff --git a/qemu-img.texi b/qemu-img.texi
17
diff --git a/block/vvfat.c b/block/vvfat.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-img.texi
19
--- a/block/vvfat.c
17
+++ b/qemu-img.texi
20
+++ b/block/vvfat.c
18
@@ -XXX,XX +XXX,XX @@ If the backing chain of the given image file @var{filename} has more than one
21
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
19
layer, the backing file into which the changes will be committed may be
22
20
specified as @var{base} (which has to be part of @var{filename}'s backing
23
vvfat_close_current_file(s);
21
chain). If @var{base} is not specified, the immediate backing file of the top
24
22
-image (which is @var{filename}) will be used. For reasons of consistency,
25
+ if (sector_num == s->offset_to_bootsector && nb_sectors == 1) {
23
-explicitly specifying @var{base} will always imply @code{-d} (since emptying an
26
+ /*
24
-image after committing to an indirect backing file would lead to different data
27
+ * Write on bootsector. Allow only changing the reserved1 field,
25
-being read from the image due to content in the intermediate backing chain
28
+ * used to mark volume dirtiness
26
-overruling the commit target).
29
+ */
27
+image (which is @var{filename}) will be used. Note that after a commit operation
30
+ unsigned char *bootsector = s->first_sectors
28
+all images between @var{base} and the top image will be invalid and may return
31
+ + s->offset_to_bootsector * 0x200;
29
+garbage data when read. For this reason, @code{-b} implies @code{-d} (so that
32
+ /*
30
+the top image stays valid).
33
+ * LATER TODO: if FAT32, this is wrong (see init_directories(),
31
34
+ * which always creates a FAT16 bootsector)
32
@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-s] [-q] @var{filename1} @var{filename2}
35
+ */
36
+ const int reserved1_offset = offsetof(bootsector_t, u.fat16.reserved1);
37
+
38
+ for (i = 0; i < 0x200; i++) {
39
+ if (i != reserved1_offset && bootsector[i] != buf[i]) {
40
+ fprintf(stderr, "Tried to write to protected bootsector\n");
41
+ return -1;
42
+ }
43
+ }
44
+
45
+ /* Update bootsector with the only updatable byte, and return success */
46
+ bootsector[reserved1_offset] = buf[reserved1_offset];
47
+ return 0;
48
+ }
49
+
50
/*
51
* Some sanity checks:
52
* - do not allow writing to the boot sector
53
*/
54
-
55
if (sector_num < s->offset_to_fat)
56
return -1;
33
57
34
--
58
--
35
2.13.6
59
2.37.3
36
60
37
61
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
2
3
Apparently it would be a good idea to test that, too.
3
In R/W mode, files with spaces were never created on host side.
4
4
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1176
6
Message-id: 20171009215533.12530-4-mreitz@redhat.com
6
Fixes: c79e243ed67683d6d06692bd7040f7394da178b0
7
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20221010175511.3414357-3-hpoussin@reactos.org>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
---
12
tests/qemu-iotests/125 | 7 +-
13
block/vvfat.c | 2 +-
13
tests/qemu-iotests/125.out | 480 ++++++++++++++++++++++++++++++++++++++++-----
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
2 files changed, 437 insertions(+), 50 deletions(-)
15
15
16
diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
16
diff --git a/block/vvfat.c b/block/vvfat.c
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/125
19
+++ b/tests/qemu-iotests/125
20
@@ -XXX,XX +XXX,XX @@ fi
21
# in B
22
CREATION_SIZE=$((2 * 1024 * 1024 - 48 * 1024))
23
24
+# 512 is the actual test -- but it's good to test 64k as well, just to be sure.
25
+for cluster_size in 512 64k; do
26
# in kB
27
for GROWTH_SIZE in 16 48 80; do
28
for create_mode in off metadata falloc full; do
29
for growth_mode in off metadata falloc full; do
30
- echo "--- growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
31
+ echo "--- cluster_size=$cluster_size growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
32
33
- IMGOPTS="preallocation=$create_mode,cluster_size=512" _make_test_img ${CREATION_SIZE}
34
+ IMGOPTS="preallocation=$create_mode,cluster_size=$cluster_size" _make_test_img ${CREATION_SIZE}
35
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
36
37
host_size_0=$(get_image_size_on_host)
38
@@ -XXX,XX +XXX,XX @@ for GROWTH_SIZE in 16 48 80; do
39
done
40
done
41
done
42
+done
43
44
# success, all done
45
echo '*** done'
46
diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out
47
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
48
--- a/tests/qemu-iotests/125.out
18
--- a/block/vvfat.c
49
+++ b/tests/qemu-iotests/125.out
19
+++ b/block/vvfat.c
50
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static bool valid_filename(const unsigned char *name)
51
QA output created by 125
21
(c >= 'A' && c <= 'Z') ||
52
---- growth_size=16 create_mode=off growth_mode=off ---
22
(c >= 'a' && c <= 'z') ||
53
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=off ---
23
c > 127 ||
54
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
24
- strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
55
Image resized.
25
+ strchr(" $%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
56
wrote 2048000/2048000 bytes at offset 0
26
{
57
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
27
return false;
58
wrote 16384/16384 bytes at offset 2048000
28
}
59
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
60
61
---- growth_size=16 create_mode=off growth_mode=metadata ---
62
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=metadata ---
63
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
64
Image resized.
65
wrote 2048000/2048000 bytes at offset 0
66
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
67
wrote 16384/16384 bytes at offset 2048000
68
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
69
70
---- growth_size=16 create_mode=off growth_mode=falloc ---
71
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=falloc ---
72
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
73
Image resized.
74
wrote 2048000/2048000 bytes at offset 0
75
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
76
wrote 16384/16384 bytes at offset 2048000
77
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
78
79
---- growth_size=16 create_mode=off growth_mode=full ---
80
+--- cluster_size=512 growth_size=16 create_mode=off growth_mode=full ---
81
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
82
Image resized.
83
wrote 2048000/2048000 bytes at offset 0
84
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
85
wrote 16384/16384 bytes at offset 2048000
86
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
87
88
---- growth_size=16 create_mode=metadata growth_mode=off ---
89
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=off ---
90
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
91
Image resized.
92
wrote 2048000/2048000 bytes at offset 0
93
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
94
wrote 16384/16384 bytes at offset 2048000
95
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
96
97
---- growth_size=16 create_mode=metadata growth_mode=metadata ---
98
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=metadata ---
99
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
100
Image resized.
101
wrote 2048000/2048000 bytes at offset 0
102
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
103
wrote 16384/16384 bytes at offset 2048000
104
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
105
106
---- growth_size=16 create_mode=metadata growth_mode=falloc ---
107
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=falloc ---
108
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
109
Image resized.
110
wrote 2048000/2048000 bytes at offset 0
111
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
112
wrote 16384/16384 bytes at offset 2048000
113
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
114
115
---- growth_size=16 create_mode=metadata growth_mode=full ---
116
+--- cluster_size=512 growth_size=16 create_mode=metadata growth_mode=full ---
117
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
118
Image resized.
119
wrote 2048000/2048000 bytes at offset 0
120
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
121
wrote 16384/16384 bytes at offset 2048000
122
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
123
124
---- growth_size=16 create_mode=falloc growth_mode=off ---
125
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=off ---
126
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
127
Image resized.
128
wrote 2048000/2048000 bytes at offset 0
129
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
130
wrote 16384/16384 bytes at offset 2048000
131
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
132
133
---- growth_size=16 create_mode=falloc growth_mode=metadata ---
134
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=metadata ---
135
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
136
Image resized.
137
wrote 2048000/2048000 bytes at offset 0
138
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
139
wrote 16384/16384 bytes at offset 2048000
140
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
141
142
---- growth_size=16 create_mode=falloc growth_mode=falloc ---
143
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=falloc ---
144
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
145
Image resized.
146
wrote 2048000/2048000 bytes at offset 0
147
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
148
wrote 16384/16384 bytes at offset 2048000
149
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
150
151
---- growth_size=16 create_mode=falloc growth_mode=full ---
152
+--- cluster_size=512 growth_size=16 create_mode=falloc growth_mode=full ---
153
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
154
Image resized.
155
wrote 2048000/2048000 bytes at offset 0
156
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
157
wrote 16384/16384 bytes at offset 2048000
158
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
159
160
---- growth_size=16 create_mode=full growth_mode=off ---
161
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=off ---
162
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
163
Image resized.
164
wrote 2048000/2048000 bytes at offset 0
165
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
166
wrote 16384/16384 bytes at offset 2048000
167
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
169
---- growth_size=16 create_mode=full growth_mode=metadata ---
170
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=metadata ---
171
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
172
Image resized.
173
wrote 2048000/2048000 bytes at offset 0
174
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
175
wrote 16384/16384 bytes at offset 2048000
176
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
177
178
---- growth_size=16 create_mode=full growth_mode=falloc ---
179
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=falloc ---
180
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
181
Image resized.
182
wrote 2048000/2048000 bytes at offset 0
183
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
184
wrote 16384/16384 bytes at offset 2048000
185
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
186
187
---- growth_size=16 create_mode=full growth_mode=full ---
188
+--- cluster_size=512 growth_size=16 create_mode=full growth_mode=full ---
189
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
190
Image resized.
191
wrote 2048000/2048000 bytes at offset 0
192
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
193
wrote 16384/16384 bytes at offset 2048000
194
16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
195
196
---- growth_size=48 create_mode=off growth_mode=off ---
197
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=off ---
198
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
199
Image resized.
200
wrote 2048000/2048000 bytes at offset 0
201
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
202
wrote 49152/49152 bytes at offset 2048000
203
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
204
205
---- growth_size=48 create_mode=off growth_mode=metadata ---
206
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=metadata ---
207
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
208
Image resized.
209
wrote 2048000/2048000 bytes at offset 0
210
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
211
wrote 49152/49152 bytes at offset 2048000
212
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
213
214
---- growth_size=48 create_mode=off growth_mode=falloc ---
215
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=falloc ---
216
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
217
Image resized.
218
wrote 2048000/2048000 bytes at offset 0
219
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
220
wrote 49152/49152 bytes at offset 2048000
221
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
222
223
---- growth_size=48 create_mode=off growth_mode=full ---
224
+--- cluster_size=512 growth_size=48 create_mode=off growth_mode=full ---
225
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
226
Image resized.
227
wrote 2048000/2048000 bytes at offset 0
228
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
229
wrote 49152/49152 bytes at offset 2048000
230
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
231
232
---- growth_size=48 create_mode=metadata growth_mode=off ---
233
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=off ---
234
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
235
Image resized.
236
wrote 2048000/2048000 bytes at offset 0
237
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
238
wrote 49152/49152 bytes at offset 2048000
239
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
240
241
---- growth_size=48 create_mode=metadata growth_mode=metadata ---
242
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=metadata ---
243
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
244
Image resized.
245
wrote 2048000/2048000 bytes at offset 0
246
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
247
wrote 49152/49152 bytes at offset 2048000
248
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
249
250
---- growth_size=48 create_mode=metadata growth_mode=falloc ---
251
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=falloc ---
252
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
253
Image resized.
254
wrote 2048000/2048000 bytes at offset 0
255
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
256
wrote 49152/49152 bytes at offset 2048000
257
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
258
259
---- growth_size=48 create_mode=metadata growth_mode=full ---
260
+--- cluster_size=512 growth_size=48 create_mode=metadata growth_mode=full ---
261
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
262
Image resized.
263
wrote 2048000/2048000 bytes at offset 0
264
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
265
wrote 49152/49152 bytes at offset 2048000
266
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
267
268
---- growth_size=48 create_mode=falloc growth_mode=off ---
269
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=off ---
270
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
271
Image resized.
272
wrote 2048000/2048000 bytes at offset 0
273
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
274
wrote 49152/49152 bytes at offset 2048000
275
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
276
277
---- growth_size=48 create_mode=falloc growth_mode=metadata ---
278
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=metadata ---
279
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
280
Image resized.
281
wrote 2048000/2048000 bytes at offset 0
282
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
283
wrote 49152/49152 bytes at offset 2048000
284
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
285
286
---- growth_size=48 create_mode=falloc growth_mode=falloc ---
287
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=falloc ---
288
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
289
Image resized.
290
wrote 2048000/2048000 bytes at offset 0
291
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
292
wrote 49152/49152 bytes at offset 2048000
293
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
294
295
---- growth_size=48 create_mode=falloc growth_mode=full ---
296
+--- cluster_size=512 growth_size=48 create_mode=falloc growth_mode=full ---
297
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
298
Image resized.
299
wrote 2048000/2048000 bytes at offset 0
300
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
301
wrote 49152/49152 bytes at offset 2048000
302
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
303
304
---- growth_size=48 create_mode=full growth_mode=off ---
305
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=off ---
306
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
307
Image resized.
308
wrote 2048000/2048000 bytes at offset 0
309
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
310
wrote 49152/49152 bytes at offset 2048000
311
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
312
313
---- growth_size=48 create_mode=full growth_mode=metadata ---
314
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=metadata ---
315
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
316
Image resized.
317
wrote 2048000/2048000 bytes at offset 0
318
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
319
wrote 49152/49152 bytes at offset 2048000
320
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
321
322
---- growth_size=48 create_mode=full growth_mode=falloc ---
323
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=falloc ---
324
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
325
Image resized.
326
wrote 2048000/2048000 bytes at offset 0
327
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
328
wrote 49152/49152 bytes at offset 2048000
329
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
330
331
---- growth_size=48 create_mode=full growth_mode=full ---
332
+--- cluster_size=512 growth_size=48 create_mode=full growth_mode=full ---
333
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
334
Image resized.
335
wrote 2048000/2048000 bytes at offset 0
336
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
337
wrote 49152/49152 bytes at offset 2048000
338
48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
339
340
---- growth_size=80 create_mode=off growth_mode=off ---
341
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=off ---
342
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
343
Image resized.
344
wrote 2048000/2048000 bytes at offset 0
345
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
346
wrote 81920/81920 bytes at offset 2048000
347
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
348
349
---- growth_size=80 create_mode=off growth_mode=metadata ---
350
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=metadata ---
351
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
352
Image resized.
353
wrote 2048000/2048000 bytes at offset 0
354
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
355
wrote 81920/81920 bytes at offset 2048000
356
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
357
358
---- growth_size=80 create_mode=off growth_mode=falloc ---
359
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=falloc ---
360
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
361
Image resized.
362
wrote 2048000/2048000 bytes at offset 0
363
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
364
wrote 81920/81920 bytes at offset 2048000
365
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
366
367
---- growth_size=80 create_mode=off growth_mode=full ---
368
+--- cluster_size=512 growth_size=80 create_mode=off growth_mode=full ---
369
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
370
Image resized.
371
wrote 2048000/2048000 bytes at offset 0
372
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
373
wrote 81920/81920 bytes at offset 2048000
374
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
375
376
---- growth_size=80 create_mode=metadata growth_mode=off ---
377
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=off ---
378
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
379
Image resized.
380
wrote 2048000/2048000 bytes at offset 0
381
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
382
wrote 81920/81920 bytes at offset 2048000
383
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
385
---- growth_size=80 create_mode=metadata growth_mode=metadata ---
386
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=metadata ---
387
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
388
Image resized.
389
wrote 2048000/2048000 bytes at offset 0
390
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
391
wrote 81920/81920 bytes at offset 2048000
392
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
393
394
---- growth_size=80 create_mode=metadata growth_mode=falloc ---
395
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=falloc ---
396
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
397
Image resized.
398
wrote 2048000/2048000 bytes at offset 0
399
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
400
wrote 81920/81920 bytes at offset 2048000
401
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
402
403
---- growth_size=80 create_mode=metadata growth_mode=full ---
404
+--- cluster_size=512 growth_size=80 create_mode=metadata growth_mode=full ---
405
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
406
Image resized.
407
wrote 2048000/2048000 bytes at offset 0
408
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
409
wrote 81920/81920 bytes at offset 2048000
410
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
411
412
---- growth_size=80 create_mode=falloc growth_mode=off ---
413
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=off ---
414
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
415
Image resized.
416
wrote 2048000/2048000 bytes at offset 0
417
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
418
wrote 81920/81920 bytes at offset 2048000
419
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
420
421
---- growth_size=80 create_mode=falloc growth_mode=metadata ---
422
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=metadata ---
423
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
424
Image resized.
425
wrote 2048000/2048000 bytes at offset 0
426
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
427
wrote 81920/81920 bytes at offset 2048000
428
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
429
430
---- growth_size=80 create_mode=falloc growth_mode=falloc ---
431
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=falloc ---
432
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
433
Image resized.
434
wrote 2048000/2048000 bytes at offset 0
435
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
436
wrote 81920/81920 bytes at offset 2048000
437
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
438
439
---- growth_size=80 create_mode=falloc growth_mode=full ---
440
+--- cluster_size=512 growth_size=80 create_mode=falloc growth_mode=full ---
441
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
442
Image resized.
443
wrote 2048000/2048000 bytes at offset 0
444
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
445
wrote 81920/81920 bytes at offset 2048000
446
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
447
448
---- growth_size=80 create_mode=full growth_mode=off ---
449
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=off ---
450
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
451
Image resized.
452
wrote 2048000/2048000 bytes at offset 0
453
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
454
wrote 81920/81920 bytes at offset 2048000
455
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
456
457
---- growth_size=80 create_mode=full growth_mode=metadata ---
458
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=metadata ---
459
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
460
Image resized.
461
wrote 2048000/2048000 bytes at offset 0
462
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
463
wrote 81920/81920 bytes at offset 2048000
464
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
465
466
---- growth_size=80 create_mode=full growth_mode=falloc ---
467
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=falloc ---
468
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
469
Image resized.
470
wrote 2048000/2048000 bytes at offset 0
471
@@ -XXX,XX +XXX,XX @@ wrote 2048000/2048000 bytes at offset 0
472
wrote 81920/81920 bytes at offset 2048000
473
80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
474
475
---- growth_size=80 create_mode=full growth_mode=full ---
476
+--- cluster_size=512 growth_size=80 create_mode=full growth_mode=full ---
477
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
478
+Image resized.
479
+wrote 2048000/2048000 bytes at offset 0
480
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
481
+wrote 81920/81920 bytes at offset 2048000
482
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
483
+
484
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=off ---
485
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
486
+Image resized.
487
+wrote 2048000/2048000 bytes at offset 0
488
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
489
+wrote 16384/16384 bytes at offset 2048000
490
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
491
+
492
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=metadata ---
493
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
494
+Image resized.
495
+wrote 2048000/2048000 bytes at offset 0
496
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
497
+wrote 16384/16384 bytes at offset 2048000
498
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
499
+
500
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=falloc ---
501
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
502
+Image resized.
503
+wrote 2048000/2048000 bytes at offset 0
504
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
505
+wrote 16384/16384 bytes at offset 2048000
506
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
507
+
508
+--- cluster_size=64k growth_size=16 create_mode=off growth_mode=full ---
509
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
510
+Image resized.
511
+wrote 2048000/2048000 bytes at offset 0
512
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
513
+wrote 16384/16384 bytes at offset 2048000
514
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
515
+
516
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=off ---
517
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
518
+Image resized.
519
+wrote 2048000/2048000 bytes at offset 0
520
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
521
+wrote 16384/16384 bytes at offset 2048000
522
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
523
+
524
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=metadata ---
525
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
526
+Image resized.
527
+wrote 2048000/2048000 bytes at offset 0
528
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
529
+wrote 16384/16384 bytes at offset 2048000
530
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
531
+
532
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=falloc ---
533
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
534
+Image resized.
535
+wrote 2048000/2048000 bytes at offset 0
536
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
537
+wrote 16384/16384 bytes at offset 2048000
538
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
539
+
540
+--- cluster_size=64k growth_size=16 create_mode=metadata growth_mode=full ---
541
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
542
+Image resized.
543
+wrote 2048000/2048000 bytes at offset 0
544
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
545
+wrote 16384/16384 bytes at offset 2048000
546
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
547
+
548
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=off ---
549
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
550
+Image resized.
551
+wrote 2048000/2048000 bytes at offset 0
552
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
553
+wrote 16384/16384 bytes at offset 2048000
554
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
555
+
556
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=metadata ---
557
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
558
+Image resized.
559
+wrote 2048000/2048000 bytes at offset 0
560
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
561
+wrote 16384/16384 bytes at offset 2048000
562
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
563
+
564
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=falloc ---
565
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
566
+Image resized.
567
+wrote 2048000/2048000 bytes at offset 0
568
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
569
+wrote 16384/16384 bytes at offset 2048000
570
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
571
+
572
+--- cluster_size=64k growth_size=16 create_mode=falloc growth_mode=full ---
573
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
574
+Image resized.
575
+wrote 2048000/2048000 bytes at offset 0
576
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
577
+wrote 16384/16384 bytes at offset 2048000
578
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
579
+
580
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=off ---
581
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
582
+Image resized.
583
+wrote 2048000/2048000 bytes at offset 0
584
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
585
+wrote 16384/16384 bytes at offset 2048000
586
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
587
+
588
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=metadata ---
589
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
590
+Image resized.
591
+wrote 2048000/2048000 bytes at offset 0
592
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
593
+wrote 16384/16384 bytes at offset 2048000
594
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
595
+
596
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=falloc ---
597
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
598
+Image resized.
599
+wrote 2048000/2048000 bytes at offset 0
600
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
601
+wrote 16384/16384 bytes at offset 2048000
602
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
603
+
604
+--- cluster_size=64k growth_size=16 create_mode=full growth_mode=full ---
605
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
606
+Image resized.
607
+wrote 2048000/2048000 bytes at offset 0
608
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
609
+wrote 16384/16384 bytes at offset 2048000
610
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
611
+
612
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=off ---
613
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
614
+Image resized.
615
+wrote 2048000/2048000 bytes at offset 0
616
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
617
+wrote 49152/49152 bytes at offset 2048000
618
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
619
+
620
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=metadata ---
621
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
622
+Image resized.
623
+wrote 2048000/2048000 bytes at offset 0
624
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
625
+wrote 49152/49152 bytes at offset 2048000
626
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
627
+
628
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=falloc ---
629
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
630
+Image resized.
631
+wrote 2048000/2048000 bytes at offset 0
632
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
633
+wrote 49152/49152 bytes at offset 2048000
634
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
635
+
636
+--- cluster_size=64k growth_size=48 create_mode=off growth_mode=full ---
637
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
638
+Image resized.
639
+wrote 2048000/2048000 bytes at offset 0
640
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
641
+wrote 49152/49152 bytes at offset 2048000
642
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
643
+
644
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=off ---
645
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
646
+Image resized.
647
+wrote 2048000/2048000 bytes at offset 0
648
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
649
+wrote 49152/49152 bytes at offset 2048000
650
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
651
+
652
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=metadata ---
653
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
654
+Image resized.
655
+wrote 2048000/2048000 bytes at offset 0
656
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
657
+wrote 49152/49152 bytes at offset 2048000
658
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
659
+
660
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=falloc ---
661
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
662
+Image resized.
663
+wrote 2048000/2048000 bytes at offset 0
664
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
665
+wrote 49152/49152 bytes at offset 2048000
666
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
667
+
668
+--- cluster_size=64k growth_size=48 create_mode=metadata growth_mode=full ---
669
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
670
+Image resized.
671
+wrote 2048000/2048000 bytes at offset 0
672
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
673
+wrote 49152/49152 bytes at offset 2048000
674
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
675
+
676
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=off ---
677
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
678
+Image resized.
679
+wrote 2048000/2048000 bytes at offset 0
680
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
681
+wrote 49152/49152 bytes at offset 2048000
682
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
683
+
684
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=metadata ---
685
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
686
+Image resized.
687
+wrote 2048000/2048000 bytes at offset 0
688
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
689
+wrote 49152/49152 bytes at offset 2048000
690
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
691
+
692
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=falloc ---
693
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
694
+Image resized.
695
+wrote 2048000/2048000 bytes at offset 0
696
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
697
+wrote 49152/49152 bytes at offset 2048000
698
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
699
+
700
+--- cluster_size=64k growth_size=48 create_mode=falloc growth_mode=full ---
701
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
702
+Image resized.
703
+wrote 2048000/2048000 bytes at offset 0
704
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
705
+wrote 49152/49152 bytes at offset 2048000
706
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
707
+
708
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=off ---
709
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
710
+Image resized.
711
+wrote 2048000/2048000 bytes at offset 0
712
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
713
+wrote 49152/49152 bytes at offset 2048000
714
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
715
+
716
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=metadata ---
717
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
718
+Image resized.
719
+wrote 2048000/2048000 bytes at offset 0
720
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
721
+wrote 49152/49152 bytes at offset 2048000
722
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
723
+
724
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=falloc ---
725
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
726
+Image resized.
727
+wrote 2048000/2048000 bytes at offset 0
728
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
729
+wrote 49152/49152 bytes at offset 2048000
730
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
731
+
732
+--- cluster_size=64k growth_size=48 create_mode=full growth_mode=full ---
733
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
734
+Image resized.
735
+wrote 2048000/2048000 bytes at offset 0
736
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
737
+wrote 49152/49152 bytes at offset 2048000
738
+48 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
739
+
740
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=off ---
741
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
742
+Image resized.
743
+wrote 2048000/2048000 bytes at offset 0
744
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
745
+wrote 81920/81920 bytes at offset 2048000
746
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
747
+
748
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=metadata ---
749
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
750
+Image resized.
751
+wrote 2048000/2048000 bytes at offset 0
752
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
753
+wrote 81920/81920 bytes at offset 2048000
754
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
755
+
756
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=falloc ---
757
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
758
+Image resized.
759
+wrote 2048000/2048000 bytes at offset 0
760
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
761
+wrote 81920/81920 bytes at offset 2048000
762
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
763
+
764
+--- cluster_size=64k growth_size=80 create_mode=off growth_mode=full ---
765
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=off
766
+Image resized.
767
+wrote 2048000/2048000 bytes at offset 0
768
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
769
+wrote 81920/81920 bytes at offset 2048000
770
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
771
+
772
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=off ---
773
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
774
+Image resized.
775
+wrote 2048000/2048000 bytes at offset 0
776
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
777
+wrote 81920/81920 bytes at offset 2048000
778
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
779
+
780
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=metadata ---
781
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
782
+Image resized.
783
+wrote 2048000/2048000 bytes at offset 0
784
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
785
+wrote 81920/81920 bytes at offset 2048000
786
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
787
+
788
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=falloc ---
789
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
790
+Image resized.
791
+wrote 2048000/2048000 bytes at offset 0
792
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
793
+wrote 81920/81920 bytes at offset 2048000
794
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
795
+
796
+--- cluster_size=64k growth_size=80 create_mode=metadata growth_mode=full ---
797
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=metadata
798
+Image resized.
799
+wrote 2048000/2048000 bytes at offset 0
800
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
801
+wrote 81920/81920 bytes at offset 2048000
802
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
803
+
804
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=off ---
805
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
806
+Image resized.
807
+wrote 2048000/2048000 bytes at offset 0
808
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
809
+wrote 81920/81920 bytes at offset 2048000
810
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
811
+
812
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=metadata ---
813
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
814
+Image resized.
815
+wrote 2048000/2048000 bytes at offset 0
816
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
817
+wrote 81920/81920 bytes at offset 2048000
818
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
819
+
820
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=falloc ---
821
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
822
+Image resized.
823
+wrote 2048000/2048000 bytes at offset 0
824
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
825
+wrote 81920/81920 bytes at offset 2048000
826
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
827
+
828
+--- cluster_size=64k growth_size=80 create_mode=falloc growth_mode=full ---
829
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=falloc
830
+Image resized.
831
+wrote 2048000/2048000 bytes at offset 0
832
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
833
+wrote 81920/81920 bytes at offset 2048000
834
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
835
+
836
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=off ---
837
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
838
+Image resized.
839
+wrote 2048000/2048000 bytes at offset 0
840
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
841
+wrote 81920/81920 bytes at offset 2048000
842
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
843
+
844
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=metadata ---
845
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
846
+Image resized.
847
+wrote 2048000/2048000 bytes at offset 0
848
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
849
+wrote 81920/81920 bytes at offset 2048000
850
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
851
+
852
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=falloc ---
853
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
854
+Image resized.
855
+wrote 2048000/2048000 bytes at offset 0
856
+1.953 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
857
+wrote 81920/81920 bytes at offset 2048000
858
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
859
+
860
+--- cluster_size=64k growth_size=80 create_mode=full growth_mode=full ---
861
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2048000 preallocation=full
862
Image resized.
863
wrote 2048000/2048000 bytes at offset 0
864
--
29
--
865
2.13.6
30
2.37.3
866
31
867
32
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1193
4
easier to reason about than sector-based. Change the internal
5
loop iteration of zeroing a device to track by bytes instead of
6
sectors (although we are still guaranteed that we iterate by steps
7
that are sector-aligned).
8
4
9
Signed-off-by: Eric Blake <eblake@redhat.com>
5
The commit "Use io_uring_register_ring_fd() to skip fd operations" broke
10
Reviewed-by: Fam Zheng <famz@redhat.com>
6
when booting a guest with iothread and io_uring. That is because the
11
Reviewed-by: John Snow <jsnow@redhat.com>
7
io_uring_register_ring_fd() call is made from the main thread instead of
8
IOThread where io_uring_submit() is called. It can not be guaranteed
9
to register the ring fd in the correct thread or unregister the same ring
10
fd if the IOThread is disabled. This optimization is not critical so we
11
will revert previous commit.
12
13
This reverts commit e2848bc574fe2715c694bf8fe9a1ba7f78a1125a
14
and 77e3f038af1764983087e3551a0fde9951952c4d.
15
16
Cc: qemu-stable@nongnu.org
17
Signed-off-by: Sam Li <faithilikerun@gmail.com>
18
Message-Id: <20220924144815.5591-1-faithilikerun@gmail.com>
19
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
20
Tested-by: Dario Faggioli <dfaggioli@suse.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
22
---
14
block/io.c | 32 ++++++++++++++++----------------
23
block/io_uring.c | 13 +------------
15
1 file changed, 16 insertions(+), 16 deletions(-)
24
meson.build | 1 -
25
2 files changed, 1 insertion(+), 13 deletions(-)
16
26
17
diff --git a/block/io.c b/block/io.c
27
diff --git a/block/io_uring.c b/block/io_uring.c
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/block/io.c
29
--- a/block/io_uring.c
20
+++ b/block/io.c
30
+++ b/block/io_uring.c
21
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
31
@@ -XXX,XX +XXX,XX @@
22
*/
32
#include "qemu/osdep.h"
23
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
33
#include <liburing.h>
24
{
34
#include "block/aio.h"
25
- int64_t target_sectors, ret, nb_sectors, sector_num = 0;
35
-#include "qemu/error-report.h"
26
+ int64_t target_size, ret, bytes, offset = 0;
36
#include "qemu/queue.h"
27
BlockDriverState *bs = child->bs;
37
#include "block/block.h"
28
- int n;
38
#include "block/raw-aio.h"
29
+ int n; /* sectors */
39
@@ -XXX,XX +XXX,XX @@
30
40
#include "qapi/error.h"
31
- target_sectors = bdrv_nb_sectors(bs);
41
#include "trace.h"
32
- if (target_sectors < 0) {
42
33
- return target_sectors;
43
-
34
+ target_size = bdrv_getlength(bs);
44
/* io_uring ring size */
35
+ if (target_size < 0) {
45
#define MAX_ENTRIES 128
36
+ return target_size;
46
47
@@ -XXX,XX +XXX,XX @@ LuringState *luring_init(Error **errp)
37
}
48
}
38
49
39
for (;;) {
50
ioq_init(&s->io_q);
40
- nb_sectors = MIN(target_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS);
51
-#ifdef CONFIG_LIBURING_REGISTER_RING_FD
41
- if (nb_sectors <= 0) {
52
- if (io_uring_register_ring_fd(&s->ring) < 0) {
42
+ bytes = MIN(target_size - offset, BDRV_REQUEST_MAX_BYTES);
53
- /*
43
+ if (bytes <= 0) {
54
- * Only warn about this error: we will fallback to the non-optimized
44
return 0;
55
- * io_uring operations.
45
}
56
- */
46
- ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n, NULL);
57
- warn_report("failed to register linux io_uring ring file descriptor");
47
+ ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
58
- }
48
+ bytes >> BDRV_SECTOR_BITS, &n, NULL);
59
-#endif
49
if (ret < 0) {
60
-
50
- error_report("error getting block status at sector %" PRId64 ": %s",
61
return s;
51
- sector_num, strerror(-ret));
62
+
52
+ error_report("error getting block status at offset %" PRId64 ": %s",
53
+ offset, strerror(-ret));
54
return ret;
55
}
56
if (ret & BDRV_BLOCK_ZERO) {
57
- sector_num += n;
58
+ offset += n * BDRV_SECTOR_BITS;
59
continue;
60
}
61
- ret = bdrv_pwrite_zeroes(child, sector_num << BDRV_SECTOR_BITS,
62
- n << BDRV_SECTOR_BITS, flags);
63
+ ret = bdrv_pwrite_zeroes(child, offset, n * BDRV_SECTOR_SIZE, flags);
64
if (ret < 0) {
65
- error_report("error writing zeroes at sector %" PRId64 ": %s",
66
- sector_num, strerror(-ret));
67
+ error_report("error writing zeroes at offset %" PRId64 ": %s",
68
+ offset, strerror(-ret));
69
return ret;
70
}
71
- sector_num += n;
72
+ offset += n * BDRV_SECTOR_SIZE;
73
}
74
}
63
}
75
64
65
void luring_cleanup(LuringState *s)
66
diff --git a/meson.build b/meson.build
67
index XXXXXXX..XXXXXXX 100644
68
--- a/meson.build
69
+++ b/meson.build
70
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_LIBNFS', libnfs.found())
71
config_host_data.set('CONFIG_LIBSSH', libssh.found())
72
config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
73
config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
74
-config_host_data.set('CONFIG_LIBURING_REGISTER_RING_FD', cc.has_function('io_uring_register_ring_fd', prefix: '#include <liburing.h>', dependencies:linux_io_uring))
75
config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
76
config_host_data.set('CONFIG_NUMA', numa.found())
77
config_host_data.set('CONFIG_OPENGL', opengl.found())
76
--
78
--
77
2.13.6
79
2.37.3
78
79
diff view generated by jsdifflib
New patch
1
From: Li Feng <fengli@smartx.com>
1
2
3
If the os is not installed and doesn't have the virtio guest driver,
4
the vhost dev isn't started, so the dev->vdev is NULL.
5
6
Reproduce: mount a Win 2019 iso, go into the install ui, then resize
7
the virtio-blk device, qemu crash.
8
9
Signed-off-by: Li Feng <fengli@smartx.com>
10
Message-Id: <20220919121816.3252223-1-fengli@smartx.com>
11
Reviewed-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
hw/block/vhost-user-blk.c | 4 ++++
16
1 file changed, 4 insertions(+)
17
18
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/block/vhost-user-blk.c
21
+++ b/hw/block/vhost-user-blk.c
22
@@ -XXX,XX +XXX,XX @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
23
VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);
24
Error *local_err = NULL;
25
26
+ if (!dev->started) {
27
+ return 0;
28
+ }
29
+
30
ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,
31
vdev->config_len, &local_err);
32
if (ret < 0) {
33
--
34
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
Unfortunately not all filters use .file child as filtered child. Two
4
exclusions are mirror_top and commit_top. Happily they both are private
5
filters. Bad thing is that this inconsistency is observable through qmp
6
commands query-block / query-named-block-nodes. So, could we just
7
change mirror_top and commit_top to use file child as all other filter
8
driver is an open question. Probably, we could do that with some kind
9
of deprecation period, but how to warn users during it?
10
11
For now, let's just add a field so we can distinguish them in generic
12
code, it will be used in further commits.
13
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
16
Message-Id: <20220726201134.924743-2-vsementsov@yandex-team.ru>
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
include/block/block_int-common.h | 13 +++++++++++++
21
block/commit.c | 1 +
22
block/mirror.c | 1 +
23
3 files changed, 15 insertions(+)
24
25
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block_int-common.h
28
+++ b/include/block/block_int-common.h
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
30
* (And this filtered child must then be bs->file or bs->backing.)
31
*/
32
bool is_filter;
33
+ /*
34
+ * Only make sense for filter drivers, for others must be false.
35
+ * If true, filtered child is bs->backing. Otherwise it's bs->file.
36
+ * Only two internal filters use bs->backing as filtered child and has this
37
+ * field set to true: mirror_top and commit_top.
38
+ *
39
+ * Never create any more such filters!
40
+ *
41
+ * TODO: imagine how to deprecate this behavior and make all filters work
42
+ * similarly using bs->file as filtered child.
43
+ */
44
+ bool filtered_child_is_backing;
45
+
46
/*
47
* Set to true if the BlockDriver is a format driver. Format nodes
48
* generally do not expect their children to be other format nodes
49
diff --git a/block/commit.c b/block/commit.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/commit.c
52
+++ b/block/commit.c
53
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_commit_top = {
54
.bdrv_child_perm = bdrv_commit_top_child_perm,
55
56
.is_filter = true,
57
+ .filtered_child_is_backing = true,
58
};
59
60
void commit_start(const char *job_id, BlockDriverState *bs,
61
diff --git a/block/mirror.c b/block/mirror.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/block/mirror.c
64
+++ b/block/mirror.c
65
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
66
.bdrv_child_perm = bdrv_mirror_top_child_perm,
67
68
.is_filter = true,
69
+ .filtered_child_is_backing = true,
70
};
71
72
static BlockJob *mirror_start_job(
73
--
74
2.37.3
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
A qcow2 image file's length is not required to have a length that is a
3
Almost all drivers call bdrv_open_child() similarly. Let's create a
4
multiple of the cluster size. However, qcow2_refcount_area() expects an
4
helper for this.
5
aligned value for its @start_offset parameter, so we need to round
6
@old_file_size up to the next cluster boundary.
7
5
8
Reported-by: Ping Li <pingl@redhat.com>
6
The only not updated drivers that call bdrv_open_child() to set
9
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1414049
7
bs->file are raw-format and snapshot-access:
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
raw-format sometimes want to have filtered child but
11
Message-id: 20171009215533.12530-2-mreitz@redhat.com
9
don't set drv->is_filter to true.
12
Cc: qemu-stable@nongnu.org
10
snapshot-access wants only DATA | PRIMARY
13
Reviewed-by: Eric Blake <eblake@redhat.com>
11
14
Reviewed-by: Jeff Cody <jcody@redhat.com>
12
Possibly we should implement drv->is_filter_func() handler, to consider
15
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
raw-format as filter when it works as filter.. But it's another story.
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
15
Note also, that we decrease assignments to bs->file in code: it helps
16
us restrict modifying this field in further commit.
17
18
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
19
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
20
Message-Id: <20220726201134.924743-3-vsementsov@yandex-team.ru>
21
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
23
---
18
block/qcow2.c | 1 +
24
include/block/block-global-state.h | 3 +++
19
1 file changed, 1 insertion(+)
25
block.c | 21 +++++++++++++++++++++
26
block/blkdebug.c | 9 +++------
27
block/blklogwrites.c | 7 ++-----
28
block/blkreplay.c | 7 ++-----
29
block/blkverify.c | 9 +++------
30
block/bochs.c | 7 +++----
31
block/cloop.c | 7 +++----
32
block/copy-before-write.c | 9 ++++-----
33
block/copy-on-read.c | 9 ++++-----
34
block/crypto.c | 11 ++++++-----
35
block/dmg.c | 7 +++----
36
block/filter-compress.c | 8 +++-----
37
block/parallels.c | 7 +++----
38
block/preallocate.c | 9 ++++-----
39
block/qcow.c | 6 ++----
40
block/qcow2.c | 8 ++++----
41
block/qed.c | 8 ++++----
42
block/replication.c | 8 +++-----
43
block/throttle.c | 8 +++-----
44
block/vdi.c | 7 +++----
45
block/vhdx.c | 7 +++----
46
block/vmdk.c | 7 +++----
47
block/vpc.c | 7 +++----
48
24 files changed, 95 insertions(+), 101 deletions(-)
20
49
50
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block-global-state.h
53
+++ b/include/block/block-global-state.h
54
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
55
const BdrvChildClass *child_class,
56
BdrvChildRole child_role,
57
bool allow_none, Error **errp);
58
+int bdrv_open_file_child(const char *filename,
59
+ QDict *options, const char *bdref_key,
60
+ BlockDriverState *parent, Error **errp);
61
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
62
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
63
Error **errp);
64
diff --git a/block.c b/block.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/block.c
67
+++ b/block.c
68
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
69
errp);
70
}
71
72
+/*
73
+ * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
74
+ */
75
+int bdrv_open_file_child(const char *filename,
76
+ QDict *options, const char *bdref_key,
77
+ BlockDriverState *parent, Error **errp)
78
+{
79
+ BdrvChildRole role;
80
+
81
+ /* commit_top and mirror_top don't use this function */
82
+ assert(!parent->drv->filtered_child_is_backing);
83
+
84
+ role = parent->drv->is_filter ?
85
+ (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
86
+
87
+ parent->file = bdrv_open_child(filename, options, bdref_key, parent,
88
+ &child_of_bds, role, false, errp);
89
+
90
+ return parent->file ? 0 : -EINVAL;
91
+}
92
+
93
/*
94
* TODO Future callers may need to specify parent/child_class in order for
95
* option inheritance to work. Existing callers use it for the root node.
96
diff --git a/block/blkdebug.c b/block/blkdebug.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/block/blkdebug.c
99
+++ b/block/blkdebug.c
100
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
101
}
102
103
/* Open the image file */
104
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
105
- bs, &child_of_bds,
106
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
107
- false, errp);
108
- if (!bs->file) {
109
- ret = -EINVAL;
110
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image",
111
+ bs, errp);
112
+ if (ret < 0) {
113
goto out;
114
}
115
116
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/block/blklogwrites.c
119
+++ b/block/blklogwrites.c
120
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
121
}
122
123
/* Open the file */
124
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
125
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
126
- errp);
127
- if (!bs->file) {
128
- ret = -EINVAL;
129
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
130
+ if (ret < 0) {
131
goto fail;
132
}
133
134
diff --git a/block/blkreplay.c b/block/blkreplay.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/block/blkreplay.c
137
+++ b/block/blkreplay.c
138
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
139
int ret;
140
141
/* Open the image file */
142
- bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
143
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
144
- false, errp);
145
- if (!bs->file) {
146
- ret = -EINVAL;
147
+ ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
148
+ if (ret < 0) {
149
goto fail;
150
}
151
152
diff --git a/block/blkverify.c b/block/blkverify.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/blkverify.c
155
+++ b/block/blkverify.c
156
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
157
}
158
159
/* Open the raw file */
160
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
161
- bs, &child_of_bds,
162
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
163
- false, errp);
164
- if (!bs->file) {
165
- ret = -EINVAL;
166
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw",
167
+ bs, errp);
168
+ if (ret < 0) {
169
goto fail;
170
}
171
172
diff --git a/block/bochs.c b/block/bochs.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/bochs.c
175
+++ b/block/bochs.c
176
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
177
return ret;
178
}
179
180
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
181
- BDRV_CHILD_IMAGE, false, errp);
182
- if (!bs->file) {
183
- return -EINVAL;
184
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
185
+ if (ret < 0) {
186
+ return ret;
187
}
188
189
ret = bdrv_pread(bs->file, 0, sizeof(bochs), &bochs, 0);
190
diff --git a/block/cloop.c b/block/cloop.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/cloop.c
193
+++ b/block/cloop.c
194
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
195
return ret;
196
}
197
198
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
199
- BDRV_CHILD_IMAGE, false, errp);
200
- if (!bs->file) {
201
- return -EINVAL;
202
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
203
+ if (ret < 0) {
204
+ return ret;
205
}
206
207
/* read header */
208
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/copy-before-write.c
211
+++ b/block/copy-before-write.c
212
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
213
int64_t cluster_size;
214
g_autoptr(BlockdevOptions) full_opts = NULL;
215
BlockdevOptionsCbw *opts;
216
+ int ret;
217
218
full_opts = cbw_parse_options(options, errp);
219
if (!full_opts) {
220
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
221
assert(full_opts->driver == BLOCKDEV_DRIVER_COPY_BEFORE_WRITE);
222
opts = &full_opts->u.copy_before_write;
223
224
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
225
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
226
- false, errp);
227
- if (!bs->file) {
228
- return -EINVAL;
229
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
230
+ if (ret < 0) {
231
+ return ret;
232
}
233
234
s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds,
235
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/block/copy-on-read.c
238
+++ b/block/copy-on-read.c
239
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
240
BDRVStateCOR *state = bs->opaque;
241
/* Find a bottom node name, if any */
242
const char *bottom_node = qdict_get_try_str(options, "bottom");
243
+ int ret;
244
245
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
246
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
247
- false, errp);
248
- if (!bs->file) {
249
- return -EINVAL;
250
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
251
+ if (ret < 0) {
252
+ return ret;
253
}
254
255
bs->supported_read_flags = BDRV_REQ_PREFETCH;
256
diff --git a/block/crypto.c b/block/crypto.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/crypto.c
259
+++ b/block/crypto.c
260
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
261
{
262
BlockCrypto *crypto = bs->opaque;
263
QemuOpts *opts = NULL;
264
- int ret = -EINVAL;
265
+ int ret;
266
QCryptoBlockOpenOptions *open_opts = NULL;
267
unsigned int cflags = 0;
268
QDict *cryptoopts = NULL;
269
270
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
271
- BDRV_CHILD_IMAGE, false, errp);
272
- if (!bs->file) {
273
- return -EINVAL;
274
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
275
+ if (ret < 0) {
276
+ return ret;
277
}
278
279
bs->supported_write_flags = BDRV_REQ_FUA &
280
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
281
282
opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
283
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
284
+ ret = -EINVAL;
285
goto cleanup;
286
}
287
288
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
289
290
open_opts = block_crypto_open_opts_init(cryptoopts, errp);
291
if (!open_opts) {
292
+ ret = -EINVAL;
293
goto cleanup;
294
}
295
296
diff --git a/block/dmg.c b/block/dmg.c
297
index XXXXXXX..XXXXXXX 100644
298
--- a/block/dmg.c
299
+++ b/block/dmg.c
300
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
301
return ret;
302
}
303
304
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
305
- BDRV_CHILD_IMAGE, false, errp);
306
- if (!bs->file) {
307
- return -EINVAL;
308
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
309
+ if (ret < 0) {
310
+ return ret;
311
}
312
313
block_module_load_one("dmg-bz2");
314
diff --git a/block/filter-compress.c b/block/filter-compress.c
315
index XXXXXXX..XXXXXXX 100644
316
--- a/block/filter-compress.c
317
+++ b/block/filter-compress.c
318
@@ -XXX,XX +XXX,XX @@
319
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
320
Error **errp)
321
{
322
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
323
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
324
- false, errp);
325
- if (!bs->file) {
326
- return -EINVAL;
327
+ int ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
328
+ if (ret < 0) {
329
+ return ret;
330
}
331
332
if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {
333
diff --git a/block/parallels.c b/block/parallels.c
334
index XXXXXXX..XXXXXXX 100644
335
--- a/block/parallels.c
336
+++ b/block/parallels.c
337
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
338
Error *local_err = NULL;
339
char *buf;
340
341
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
342
- BDRV_CHILD_IMAGE, false, errp);
343
- if (!bs->file) {
344
- return -EINVAL;
345
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
346
+ if (ret < 0) {
347
+ return ret;
348
}
349
350
ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);
351
diff --git a/block/preallocate.c b/block/preallocate.c
352
index XXXXXXX..XXXXXXX 100644
353
--- a/block/preallocate.c
354
+++ b/block/preallocate.c
355
@@ -XXX,XX +XXX,XX @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
356
Error **errp)
357
{
358
BDRVPreallocateState *s = bs->opaque;
359
+ int ret;
360
361
/*
362
* s->data_end and friends should be initialized on permission update.
363
@@ -XXX,XX +XXX,XX @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
364
*/
365
s->file_end = s->zero_start = s->data_end = -EINVAL;
366
367
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
368
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
369
- false, errp);
370
- if (!bs->file) {
371
- return -EINVAL;
372
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
373
+ if (ret < 0) {
374
+ return ret;
375
}
376
377
if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) {
378
diff --git a/block/qcow.c b/block/qcow.c
379
index XXXXXXX..XXXXXXX 100644
380
--- a/block/qcow.c
381
+++ b/block/qcow.c
382
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
383
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
384
encryptfmt = qdict_get_try_str(encryptopts, "format");
385
386
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
387
- BDRV_CHILD_IMAGE, false, errp);
388
- if (!bs->file) {
389
- ret = -EINVAL;
390
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
391
+ if (ret < 0) {
392
goto fail;
393
}
394
21
diff --git a/block/qcow2.c b/block/qcow2.c
395
diff --git a/block/qcow2.c b/block/qcow2.c
22
index XXXXXXX..XXXXXXX 100644
396
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2.c
397
--- a/block/qcow2.c
24
+++ b/block/qcow2.c
398
+++ b/block/qcow2.c
25
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
399
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
26
"Failed to inquire current file length");
400
.errp = errp,
27
return old_file_size;
401
.ret = -EINPROGRESS
28
}
402
};
29
+ old_file_size = ROUND_UP(old_file_size, s->cluster_size);
403
+ int ret;
30
404
31
nb_new_data_clusters = DIV_ROUND_UP(offset - old_length,
405
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
32
s->cluster_size);
406
- BDRV_CHILD_IMAGE, false, errp);
407
- if (!bs->file) {
408
- return -EINVAL;
409
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
410
+ if (ret < 0) {
411
+ return ret;
412
}
413
414
/* Initialise locks */
415
diff --git a/block/qed.c b/block/qed.c
416
index XXXXXXX..XXXXXXX 100644
417
--- a/block/qed.c
418
+++ b/block/qed.c
419
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
420
.errp = errp,
421
.ret = -EINPROGRESS
422
};
423
+ int ret;
424
425
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
426
- BDRV_CHILD_IMAGE, false, errp);
427
- if (!bs->file) {
428
- return -EINVAL;
429
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
430
+ if (ret < 0) {
431
+ return ret;
432
}
433
434
bdrv_qed_init_state(bs);
435
diff --git a/block/replication.c b/block/replication.c
436
index XXXXXXX..XXXXXXX 100644
437
--- a/block/replication.c
438
+++ b/block/replication.c
439
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
440
const char *mode;
441
const char *top_id;
442
443
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
444
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
445
- false, errp);
446
- if (!bs->file) {
447
- return -EINVAL;
448
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
449
+ if (ret < 0) {
450
+ return ret;
451
}
452
453
ret = -EINVAL;
454
diff --git a/block/throttle.c b/block/throttle.c
455
index XXXXXXX..XXXXXXX 100644
456
--- a/block/throttle.c
457
+++ b/block/throttle.c
458
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
459
char *group;
460
int ret;
461
462
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
463
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
464
- false, errp);
465
- if (!bs->file) {
466
- return -EINVAL;
467
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
468
+ if (ret < 0) {
469
+ return ret;
470
}
471
bs->supported_write_flags = bs->file->bs->supported_write_flags |
472
BDRV_REQ_WRITE_UNCHANGED;
473
diff --git a/block/vdi.c b/block/vdi.c
474
index XXXXXXX..XXXXXXX 100644
475
--- a/block/vdi.c
476
+++ b/block/vdi.c
477
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
478
int ret;
479
QemuUUID uuid_link, uuid_parent;
480
481
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
482
- BDRV_CHILD_IMAGE, false, errp);
483
- if (!bs->file) {
484
- return -EINVAL;
485
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
486
+ if (ret < 0) {
487
+ return ret;
488
}
489
490
logout("\n");
491
diff --git a/block/vhdx.c b/block/vhdx.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/block/vhdx.c
494
+++ b/block/vhdx.c
495
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
496
uint64_t signature;
497
Error *local_err = NULL;
498
499
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
500
- BDRV_CHILD_IMAGE, false, errp);
501
- if (!bs->file) {
502
- return -EINVAL;
503
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
504
+ if (ret < 0) {
505
+ return ret;
506
}
507
508
s->bat = NULL;
509
diff --git a/block/vmdk.c b/block/vmdk.c
510
index XXXXXXX..XXXXXXX 100644
511
--- a/block/vmdk.c
512
+++ b/block/vmdk.c
513
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
514
BDRVVmdkState *s = bs->opaque;
515
uint32_t magic;
516
517
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
518
- BDRV_CHILD_IMAGE, false, errp);
519
- if (!bs->file) {
520
- return -EINVAL;
521
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
522
+ if (ret < 0) {
523
+ return ret;
524
}
525
526
buf = vmdk_read_desc(bs->file, 0, errp);
527
diff --git a/block/vpc.c b/block/vpc.c
528
index XXXXXXX..XXXXXXX 100644
529
--- a/block/vpc.c
530
+++ b/block/vpc.c
531
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
532
int ret;
533
int64_t bs_size;
534
535
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
536
- BDRV_CHILD_IMAGE, false, errp);
537
- if (!bs->file) {
538
- return -EINVAL;
539
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
540
+ if (ret < 0) {
541
+ return ret;
542
}
543
544
opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
33
--
545
--
34
2.13.6
546
2.37.3
35
36
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
We don't need to remove bs->file, generic layer takes care of it. No
4
other driver cares to remove bs->file on failure by hand.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220726201134.924743-4-vsementsov@yandex-team.ru>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/blklogwrites.c | 4 ----
13
1 file changed, 4 deletions(-)
14
15
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/blklogwrites.c
18
+++ b/block/blklogwrites.c
19
@@ -XXX,XX +XXX,XX @@ fail_log:
20
s->log_file = NULL;
21
}
22
fail:
23
- if (ret < 0) {
24
- bdrv_unref_child(bs, bs->file);
25
- bs->file = NULL;
26
- }
27
qemu_opts_del(opts);
28
return ret;
29
}
30
--
31
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
test_parallel_perm_update() does two things that we are going to
4
easier to reason about than sector-based. Continue by converting
4
restrict in the near future:
5
an internal function (no semantic change), and simplifying its
6
caller accordingly.
7
5
8
Signed-off-by: Eric Blake <eblake@redhat.com>
6
1. It updates bs->file field by hand. bs->file will be managed
9
Reviewed-by: Fam Zheng <famz@redhat.com>
7
automatically by generic code (together with bs->children list).
10
Reviewed-by: John Snow <jsnow@redhat.com>
8
9
Let's better refactor our "tricky" bds to have own state where one
10
of children is linked as "selected".
11
This also looks less "tricky", so avoid using this word.
12
13
2. It create FILTERED children that are not PRIMARY. Except for tests
14
all FILTERED children in the Qemu block layer are always PRIMARY as
15
well. We are going to formalize this rule, so let's better use DATA
16
children here.
17
18
3. It creates more than one FILTERED child, which is already abandoned
19
in BDRV_CHILD_FILTERED's description.
20
21
While being here, update the picture to better correspond to the test
22
code.
23
24
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
25
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
26
Message-Id: <20220726201134.924743-5-vsementsov@yandex-team.ru>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
28
---
13
qemu-img.c | 24 +++++++++++-------------
29
tests/unit/test-bdrv-graph-mod.c | 80 +++++++++++++++++++-------------
14
1 file changed, 11 insertions(+), 13 deletions(-)
30
1 file changed, 49 insertions(+), 31 deletions(-)
15
31
16
diff --git a/qemu-img.c b/qemu-img.c
32
diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c
17
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
18
--- a/qemu-img.c
34
--- a/tests/unit/test-bdrv-graph-mod.c
19
+++ b/qemu-img.c
35
+++ b/tests/unit/test-bdrv-graph-mod.c
20
@@ -XXX,XX +XXX,XX @@ static void dump_map_entry(OutputFormat output_format, MapEntry *e,
36
@@ -XXX,XX +XXX,XX @@ static void test_parallel_exclusive_write(void)
37
bdrv_unref(top);
38
}
39
40
-static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
41
- BdrvChildRole role,
42
- BlockReopenQueue *reopen_queue,
43
- uint64_t perm, uint64_t shared,
44
- uint64_t *nperm, uint64_t *nshared)
45
+/*
46
+ * write-to-selected node may have several DATA children, one of them may be
47
+ * "selected". Exclusive write permission is taken on selected child.
48
+ *
49
+ * We don't realize write handler itself, as we need only to test how permission
50
+ * update works.
51
+ */
52
+typedef struct BDRVWriteToSelectedState {
53
+ BdrvChild *selected;
54
+} BDRVWriteToSelectedState;
55
+
56
+static void write_to_selected_perms(BlockDriverState *bs, BdrvChild *c,
57
+ BdrvChildRole role,
58
+ BlockReopenQueue *reopen_queue,
59
+ uint64_t perm, uint64_t shared,
60
+ uint64_t *nperm, uint64_t *nshared)
61
{
62
- if (bs->file && c == bs->file) {
63
+ BDRVWriteToSelectedState *s = bs->opaque;
64
+
65
+ if (s->selected && c == s->selected) {
66
*nperm = BLK_PERM_WRITE;
67
*nshared = BLK_PERM_ALL & ~BLK_PERM_WRITE;
68
} else {
69
@@ -XXX,XX +XXX,XX @@ static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
21
}
70
}
22
}
71
}
23
72
24
-static int get_block_status(BlockDriverState *bs, int64_t sector_num,
73
-static BlockDriver bdrv_write_to_file = {
25
- int nb_sectors, MapEntry *e)
74
- .format_name = "tricky-perm",
26
+static int get_block_status(BlockDriverState *bs, int64_t offset,
75
- .bdrv_child_perm = write_to_file_perms,
27
+ int64_t bytes, MapEntry *e)
76
+static BlockDriver bdrv_write_to_selected = {
77
+ .format_name = "write-to-selected",
78
+ .instance_size = sizeof(BDRVWriteToSelectedState),
79
+ .bdrv_child_perm = write_to_selected_perms,
80
};
81
82
83
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
84
* The following test shows that topological-sort order is required for
85
* permission update, simple DFS is not enough.
86
*
87
- * Consider the block driver which has two filter children: one active
88
- * with exclusive write access and one inactive with no specific
89
- * permissions.
90
+ * Consider the block driver (write-to-selected) which has two children: one is
91
+ * selected so we have exclusive write access to it and for the other one we
92
+ * don't need any specific permissions.
93
*
94
* And, these two children has a common base child, like this:
95
+ * (additional "top" on top is used in test just because the only public
96
+ * function to update permission should get a specific child to update.
97
+ * Making bdrv_refresh_perms() public just for this test isn't worth it)
98
*
99
- * ┌─────┐ ┌──────┐
100
- * │ fl2 │ ◀── │ top │
101
- * └─────┘ └──────┘
102
+ * ┌─────┐ ┌───────────────────┐ ┌─────┐
103
+ * │ fl2 │ ◀── │ write-to-selected │ ◀── │ top │
104
+ * └─────┘ └───────────────────┘ └─────┘
105
* │ │
106
* │ │ w
107
* │ ▼
108
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
109
*
110
* So, exclusive write is propagated.
111
*
112
- * Assume, we want to make fl2 active instead of fl1.
113
- * So, we set some option for top driver and do permission update.
114
+ * Assume, we want to select fl2 instead of fl1.
115
+ * So, we set some option for write-to-selected driver and do permission update.
116
*
117
* With simple DFS, if permission update goes first through
118
- * top->fl1->base branch it will succeed: it firstly drop exclusive write
119
- * permissions and than apply them for another BdrvChildren.
120
- * But if permission update goes first through top->fl2->base branch it
121
- * will fail, as when we try to update fl2->base child, old not yet
122
+ * write-to-selected -> fl1 -> base branch it will succeed: it firstly drop
123
+ * exclusive write permissions and than apply them for another BdrvChildren.
124
+ * But if permission update goes first through write-to-selected -> fl2 -> base
125
+ * branch it will fail, as when we try to update fl2->base child, old not yet
126
* updated fl1->base child will be in conflict.
127
*
128
* With topological-sort order we always update parents before children, so fl1
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
130
static void test_parallel_perm_update(void)
28
{
131
{
29
int64_t ret;
132
BlockDriverState *top = no_perm_node("top");
30
int depth;
133
- BlockDriverState *tricky =
31
BlockDriverState *file;
134
- bdrv_new_open_driver(&bdrv_write_to_file, "tricky", BDRV_O_RDWR,
32
bool has_offset;
135
+ BlockDriverState *ws =
33
+ int nb_sectors = bytes >> BDRV_SECTOR_BITS;
136
+ bdrv_new_open_driver(&bdrv_write_to_selected, "ws", BDRV_O_RDWR,
34
137
&error_abort);
35
+ assert(bytes < INT_MAX);
138
+ BDRVWriteToSelectedState *s = ws->opaque;
36
/* As an optimization, we could cache the current range of unallocated
139
BlockDriverState *base = no_perm_node("base");
37
* clusters in each file of the chain, and avoid querying the same
140
BlockDriverState *fl1 = pass_through_node("fl1");
38
* range repeatedly.
141
BlockDriverState *fl2 = pass_through_node("fl2");
39
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t sector_num,
142
@@ -XXX,XX +XXX,XX @@ static void test_parallel_perm_update(void)
40
143
*/
41
depth = 0;
144
bdrv_ref(base);
42
for (;;) {
145
43
- ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &nb_sectors,
146
- bdrv_attach_child(top, tricky, "file", &child_of_bds, BDRV_CHILD_DATA,
44
- &file);
147
+ bdrv_attach_child(top, ws, "file", &child_of_bds, BDRV_CHILD_DATA,
45
+ ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS, nb_sectors,
148
&error_abort);
46
+ &nb_sectors, &file);
149
- c_fl1 = bdrv_attach_child(tricky, fl1, "first", &child_of_bds,
47
if (ret < 0) {
150
- BDRV_CHILD_FILTERED, &error_abort);
48
return ret;
151
- c_fl2 = bdrv_attach_child(tricky, fl2, "second", &child_of_bds,
49
}
152
- BDRV_CHILD_FILTERED, &error_abort);
50
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t sector_num,
153
+ c_fl1 = bdrv_attach_child(ws, fl1, "first", &child_of_bds,
51
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
154
+ BDRV_CHILD_DATA, &error_abort);
52
155
+ c_fl2 = bdrv_attach_child(ws, fl2, "second", &child_of_bds,
53
*e = (MapEntry) {
156
+ BDRV_CHILD_DATA, &error_abort);
54
- .start = sector_num * BDRV_SECTOR_SIZE,
157
bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
55
+ .start = offset,
158
&error_abort);
56
.length = nb_sectors * BDRV_SECTOR_SIZE,
159
bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
57
.data = !!(ret & BDRV_BLOCK_DATA),
160
&error_abort);
58
.zero = !!(ret & BDRV_BLOCK_ZERO),
161
59
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
162
/* Select fl1 as first child to be active */
60
163
- tricky->file = c_fl1;
61
length = blk_getlength(blk);
164
+ s->selected = c_fl1;
62
while (curr.start + curr.length < length) {
165
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
63
- int64_t nsectors_left;
166
64
- int64_t sector_num;
167
assert(c_fl1->perm & BLK_PERM_WRITE);
65
- int n;
168
assert(!(c_fl2->perm & BLK_PERM_WRITE));
66
-
169
67
- sector_num = (curr.start + curr.length) >> BDRV_SECTOR_BITS;
170
/* Now, try to switch active child and update permissions */
68
+ int64_t offset = curr.start + curr.length;
171
- tricky->file = c_fl2;
69
+ int64_t n;
172
+ s->selected = c_fl2;
70
173
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
71
/* Probe up to 1 GiB at a time. */
174
72
- nsectors_left = DIV_ROUND_UP(length, BDRV_SECTOR_SIZE) - sector_num;
175
assert(c_fl2->perm & BLK_PERM_WRITE);
73
- n = MIN(1 << (30 - BDRV_SECTOR_BITS), nsectors_left);
176
assert(!(c_fl1->perm & BLK_PERM_WRITE));
74
- ret = get_block_status(bs, sector_num, n, &next);
177
75
+ n = QEMU_ALIGN_DOWN(MIN(1 << 30, length - offset), BDRV_SECTOR_SIZE);
178
/* Switch once more, to not care about real child order in the list */
76
+ ret = get_block_status(bs, offset, n, &next);
179
- tricky->file = c_fl1;
77
180
+ s->selected = c_fl1;
78
if (ret < 0) {
181
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
79
error_report("Could not read file metadata: %s", strerror(-ret));
182
183
assert(c_fl1->perm & BLK_PERM_WRITE);
80
--
184
--
81
2.13.6
185
2.37.3
82
186
83
187
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
We do add COW child to the node. In future we are going to forbid
4
adding COW child to the node that doesn't support backing. So, fix it
5
here now.
6
7
Don't worry about setting bs->backing itself: in further commit we'll
8
update the block-layer to automatically set/unset this field in generic
9
code.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
12
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Message-Id: <20220726201134.924743-6-vsementsov@yandex-team.ru>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
tests/unit/test-bdrv-drain.c | 1 +
18
1 file changed, 1 insertion(+)
19
20
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/unit/test-bdrv-drain.c
23
+++ b/tests/unit/test-bdrv-drain.c
24
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_replace_test_co_drain_end(BlockDriverState *bs)
25
static BlockDriver bdrv_replace_test = {
26
.format_name = "replace_test",
27
.instance_size = sizeof(BDRVReplaceTestState),
28
+ .supports_backing = true,
29
30
.bdrv_close = bdrv_replace_test_close,
31
.bdrv_co_preadv = bdrv_replace_test_co_preadv,
32
--
33
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
bdrv_pass_through is used as filter, even all node variables has
4
corresponding names. We want to append it, so it should be
5
backing-child-based filter like mirror_top.
6
So, in test_update_perm_tree, first child should be DATA, as we don't
7
want filters with two filtered children.
8
9
bdrv_exclusive_writer is used as a filter once. So it should be filter
10
anyway. We want to append it, so it should be backing-child-based
11
fitler too.
12
13
Make all FILTERED children to be PRIMARY as well. We are going to force
14
this rule by assertion soon.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
17
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
18
Message-Id: <20220726201134.924743-7-vsementsov@yandex-team.ru>
19
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
22
include/block/block_int-common.h | 5 +++--
23
tests/unit/test-bdrv-graph-mod.c | 24 +++++++++++++++++-------
24
2 files changed, 20 insertions(+), 9 deletions(-)
25
26
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/block/block_int-common.h
29
+++ b/include/block/block_int-common.h
30
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
31
/*
32
* Only make sense for filter drivers, for others must be false.
33
* If true, filtered child is bs->backing. Otherwise it's bs->file.
34
- * Only two internal filters use bs->backing as filtered child and has this
35
- * field set to true: mirror_top and commit_top.
36
+ * Two internal filters use bs->backing as filtered child and has this
37
+ * field set to true: mirror_top and commit_top. There also two such test
38
+ * filters in tests/unit/test-bdrv-graph-mod.c.
39
*
40
* Never create any more such filters!
41
*
42
diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/tests/unit/test-bdrv-graph-mod.c
45
+++ b/tests/unit/test-bdrv-graph-mod.c
46
@@ -XXX,XX +XXX,XX @@
47
48
static BlockDriver bdrv_pass_through = {
49
.format_name = "pass-through",
50
+ .is_filter = true,
51
+ .filtered_child_is_backing = true,
52
.bdrv_child_perm = bdrv_default_perms,
53
};
54
55
@@ -XXX,XX +XXX,XX @@ static void exclusive_write_perms(BlockDriverState *bs, BdrvChild *c,
56
57
static BlockDriver bdrv_exclusive_writer = {
58
.format_name = "exclusive-writer",
59
+ .is_filter = true,
60
+ .filtered_child_is_backing = true,
61
.bdrv_child_perm = exclusive_write_perms,
62
};
63
64
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
65
blk_insert_bs(root, bs, &error_abort);
66
67
bdrv_attach_child(filter, bs, "child", &child_of_bds,
68
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
69
+ BDRV_CHILD_DATA, &error_abort);
70
71
ret = bdrv_append(filter, bs, NULL);
72
g_assert_cmpint(ret, <, 0);
73
@@ -XXX,XX +XXX,XX @@ static void test_parallel_exclusive_write(void)
74
*/
75
bdrv_ref(base);
76
77
- bdrv_attach_child(top, fl1, "backing", &child_of_bds, BDRV_CHILD_DATA,
78
+ bdrv_attach_child(top, fl1, "backing", &child_of_bds,
79
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
80
&error_abort);
81
- bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
82
+ bdrv_attach_child(fl1, base, "backing", &child_of_bds,
83
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
84
&error_abort);
85
- bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
86
+ bdrv_attach_child(fl2, base, "backing", &child_of_bds,
87
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
88
&error_abort);
89
90
bdrv_replace_node(fl1, fl2, &error_abort);
91
@@ -XXX,XX +XXX,XX @@ static void test_parallel_perm_update(void)
92
BDRV_CHILD_DATA, &error_abort);
93
c_fl2 = bdrv_attach_child(ws, fl2, "second", &child_of_bds,
94
BDRV_CHILD_DATA, &error_abort);
95
- bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
96
+ bdrv_attach_child(fl1, base, "backing", &child_of_bds,
97
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
98
&error_abort);
99
- bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
100
+ bdrv_attach_child(fl2, base, "backing", &child_of_bds,
101
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
102
&error_abort);
103
104
/* Select fl1 as first child to be active */
105
@@ -XXX,XX +XXX,XX @@ static void test_append_greedy_filter(void)
106
BlockDriverState *base = no_perm_node("base");
107
BlockDriverState *fl = exclusive_writer_node("fl1");
108
109
- bdrv_attach_child(top, base, "backing", &child_of_bds, BDRV_CHILD_COW,
110
+ bdrv_attach_child(top, base, "backing", &child_of_bds,
111
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
112
&error_abort);
113
114
bdrv_append(fl, base, &error_abort);
115
--
116
2.37.3
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Make the informal rules formal. In further commit we'll add
4
Message-id: 20170929170843.3711-1-mreitz@redhat.com
4
corresponding assertions.
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220726201134.924743-8-vsementsov@yandex-team.ru>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
11
---
8
tests/qemu-iotests/127 | 97 ++++++++++++++++++++++++++++++++++++++++++++++
12
include/block/block-common.h | 39 ++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/127.out | 14 +++++++
13
1 file changed, 39 insertions(+)
10
tests/qemu-iotests/group | 1 +
11
3 files changed, 112 insertions(+)
12
create mode 100755 tests/qemu-iotests/127
13
create mode 100644 tests/qemu-iotests/127.out
14
14
15
diff --git a/tests/qemu-iotests/127 b/tests/qemu-iotests/127
15
diff --git a/include/block/block-common.h b/include/block/block-common.h
16
new file mode 100755
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/tests/qemu-iotests/127
20
@@ -XXX,XX +XXX,XX @@
21
+#!/bin/bash
22
+#
23
+# Test case for mirroring with dataplane
24
+#
25
+# Copyright (C) 2017 Red Hat, Inc.
26
+#
27
+# 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
29
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
31
+#
32
+# This program is distributed in the hope that it will be useful,
33
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
34
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
+# GNU General Public License for more details.
36
+#
37
+# 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/>.
39
+#
40
+
41
+# creator
42
+owner=mreitz@redhat.com
43
+
44
+seq=$(basename $0)
45
+echo "QA output created by $seq"
46
+
47
+here=$PWD
48
+status=1 # failure is the default!
49
+
50
+_cleanup()
51
+{
52
+ _cleanup_qemu
53
+ _cleanup_test_img
54
+ _rm_test_img "$TEST_IMG.overlay0"
55
+ _rm_test_img "$TEST_IMG.overlay1"
56
+}
57
+trap "_cleanup; exit \$status" 0 1 2 3 15
58
+
59
+# get standard environment, filters and qemu instance handling
60
+. ./common.rc
61
+. ./common.filter
62
+. ./common.qemu
63
+
64
+_supported_fmt qcow2
65
+_supported_proto file
66
+_supported_os Linux
67
+
68
+IMG_SIZE=64K
69
+
70
+_make_test_img $IMG_SIZE
71
+TEST_IMG="$TEST_IMG.overlay0" _make_test_img -b "$TEST_IMG" $IMG_SIZE
72
+TEST_IMG="$TEST_IMG.overlay1" _make_test_img -b "$TEST_IMG" $IMG_SIZE
73
+
74
+# So that we actually have something to mirror and the job does not return
75
+# immediately (which may be bad because then we cannot know whether the
76
+# 'return' or the 'BLOCK_JOB_READY' comes first).
77
+$QEMU_IO -c 'write 0 42' "$TEST_IMG.overlay0" | _filter_qemu_io
78
+
79
+# We cannot use virtio-blk here because that does not actually set the attached
80
+# BB's AioContext in qtest mode
81
+_launch_qemu \
82
+ -object iothread,id=iothr \
83
+ -blockdev node-name=source,driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG.overlay0" \
84
+ -device virtio-scsi,id=scsi-bus,iothread=iothr \
85
+ -device scsi-hd,bus=scsi-bus.0,drive=source
86
+
87
+_send_qemu_cmd $QEMU_HANDLE \
88
+ "{ 'execute': 'qmp_capabilities' }" \
89
+ 'return'
90
+
91
+_send_qemu_cmd $QEMU_HANDLE \
92
+ "{ 'execute': 'drive-mirror',
93
+ 'arguments': {
94
+ 'job-id': 'mirror',
95
+ 'device': 'source',
96
+ 'target': '$TEST_IMG.overlay1',
97
+ 'mode': 'existing',
98
+ 'sync': 'top'
99
+ } }" \
100
+ 'BLOCK_JOB_READY'
101
+
102
+# The backing BDS should be assigned the overlay's AioContext
103
+_send_qemu_cmd $QEMU_HANDLE \
104
+ "{ 'execute': 'block-job-complete',
105
+ 'arguments': { 'device': 'mirror' } }" \
106
+ 'BLOCK_JOB_COMPLETED'
107
+
108
+_send_qemu_cmd $QEMU_HANDLE \
109
+ "{ 'execute': 'quit' }" \
110
+ 'return'
111
+
112
+wait=yes _cleanup_qemu
113
+
114
+# success, all done
115
+echo '*** done'
116
+rm -f $seq.full
117
+status=0
118
diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/tests/qemu-iotests/127.out
123
@@ -XXX,XX +XXX,XX @@
124
+QA output created by 127
125
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
126
+Formatting 'TEST_DIR/t.IMGFMT.overlay0', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT
127
+Formatting 'TEST_DIR/t.IMGFMT.overlay1', fmt=IMGFMT size=65536 backing_file=TEST_DIR/t.IMGFMT
128
+wrote 42/42 bytes at offset 0
129
+42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
130
+{"return": {}}
131
+{"return": {}}
132
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
133
+{"return": {}}
134
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
135
+{"return": {}}
136
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
137
+*** done
138
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
139
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
140
--- a/tests/qemu-iotests/group
17
--- a/include/block/block-common.h
141
+++ b/tests/qemu-iotests/group
18
+++ b/include/block/block-common.h
142
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ enum {
143
124 rw auto backing
20
*
144
125 rw auto
21
* At least one of DATA, METADATA, FILTERED, or COW must be set for
145
126 rw auto backing
22
* every child.
146
+127 rw auto backing quick
23
+ *
147
128 rw auto quick
24
+ *
148
129 rw auto quick
25
+ * = Connection with bs->children, bs->file and bs->backing fields =
149
130 rw auto quick
26
+ *
27
+ * 1. Filters
28
+ *
29
+ * Filter drivers have drv->is_filter = true.
30
+ *
31
+ * Filter node has exactly one FILTERED|PRIMARY child, and may have other
32
+ * children which must not have these bits (one example is the
33
+ * copy-before-write filter, which also has its target DATA child).
34
+ *
35
+ * Filter nodes never have COW children.
36
+ *
37
+ * For most filters, the filtered child is linked in bs->file, bs->backing is
38
+ * NULL. For some filters (as an exception), it is the other way around; those
39
+ * drivers will have drv->filtered_child_is_backing set to true (see that
40
+ * field’s documentation for what drivers this concerns)
41
+ *
42
+ * 2. "raw" driver (block/raw-format.c)
43
+ *
44
+ * Formally it's not a filter (drv->is_filter = false)
45
+ *
46
+ * bs->backing is always NULL
47
+ *
48
+ * Only has one child, linked in bs->file. Its role is either FILTERED|PRIMARY
49
+ * (like filter) or DATA|PRIMARY depending on options.
50
+ *
51
+ * 3. Other drivers
52
+ *
53
+ * Don't have any FILTERED children.
54
+ *
55
+ * May have at most one COW child. In this case it's linked in bs->backing.
56
+ * Otherwise bs->backing is NULL. COW child is never PRIMARY.
57
+ *
58
+ * May have at most one PRIMARY child. In this case it's linked in bs->file.
59
+ * Otherwise bs->file is NULL.
60
+ *
61
+ * May also have some other children that don't have the PRIMARY or COW bit set.
62
*/
63
enum BdrvChildRoleBits {
64
/*
150
--
65
--
151
2.13.6
66
2.37.3
152
67
153
68
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
Actually what we chose is a primary child. Let's stress it in the code.
4
5
We are going to drop indirect pointer logic here in future. Actually
6
this commit simplifies the future work: we drop use of indirection in
7
the assertion now.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-9-vsementsov@yandex-team.ru>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/snapshot.c | 30 ++++++++++--------------------
16
1 file changed, 10 insertions(+), 20 deletions(-)
17
18
diff --git a/block/snapshot.c b/block/snapshot.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/snapshot.c
21
+++ b/block/snapshot.c
22
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
23
static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
24
{
25
BdrvChild **fallback;
26
- BdrvChild *child;
27
+ BdrvChild *child = bdrv_primary_child(bs);
28
29
- /*
30
- * The only BdrvChild pointers that are safe to modify (and which
31
- * we can thus return a reference to) are bs->file and
32
- * bs->backing.
33
- */
34
- fallback = &bs->file;
35
- if (!*fallback && bs->drv && bs->drv->is_filter) {
36
- fallback = &bs->backing;
37
- }
38
-
39
- if (!*fallback) {
40
+ /* We allow fallback only to primary child */
41
+ if (!child) {
42
return NULL;
43
}
44
+ fallback = (child == bs->file ? &bs->file : &bs->backing);
45
+ assert(*fallback == child);
46
47
/*
48
* Check that there are no other children that would need to be
49
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
50
}
51
52
/*
53
- * fallback_ptr is &bs->file or &bs->backing. *fallback_ptr
54
- * was closed above and set to NULL, but the .bdrv_open() call
55
- * has opened it again, because we set the respective option
56
- * (with the qdict_put_str() call above).
57
- * Assert that .bdrv_open() has attached some child on
58
- * *fallback_ptr, and that it has attached the one we wanted
59
- * it to (i.e., fallback_bs).
60
+ * fallback was a primary child. It was closed above and set to NULL,
61
+ * but the .bdrv_open() call has opened it again, because we set the
62
+ * respective option (with the qdict_put_str() call above).
63
+ * Assert that .bdrv_open() has attached the right BDS as primary child.
64
*/
65
- assert(*fallback_ptr && fallback_bs == (*fallback_ptr)->bs);
66
+ assert(bdrv_primary_bs(bs) == fallback_bs);
67
bdrv_unref(fallback_bs);
68
return ret;
69
}
70
--
71
2.37.3
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
3
We are going to reimplement this behavior (clear bs->file / bs->backing
4
pointers automatically when child->bs is cleared) in a nicer way, see
5
further commit
6
"block: Manipulate bs->file / bs->backing pointers in .attach/.detach".
7
8
With this revert we bring back a problem that was fixed by b0a9f6fed3d8.
9
Still the problem was mostly theoretical, we don't have concrete bugs
10
fixed by b0a9f6fed3d8, we don't have a specific test. Probably some
11
accidental failures of iotests are related.
12
13
Alternatively, we may merge this and following three reverts into final
14
"block: Manipulate ..." to avoid any kind of regression. But seems that
15
in this case having separate clear revert commits is better.
16
17
This reverts commit b0a9f6fed3d80de610dcd04a7e66f9f30a04174f.
18
19
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
20
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
21
Message-Id: <20220726201134.924743-10-vsementsov@yandex-team.ru>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
24
block.c | 102 +++++++++++++-------------------------------------------
25
1 file changed, 23 insertions(+), 79 deletions(-)
26
27
diff --git a/block.c b/block.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block.c
30
+++ b/block.c
31
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
32
static bool bdrv_recurse_has_child(BlockDriverState *bs,
33
BlockDriverState *child);
34
35
-static void bdrv_child_free(BdrvChild *child);
36
static void bdrv_replace_child_noperm(BdrvChild **child,
37
- BlockDriverState *new_bs,
38
- bool free_empty_child);
39
+ BlockDriverState *new_bs);
40
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
41
BdrvChild *child,
42
Transaction *tran);
43
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvReplaceChildState {
44
BdrvChild *child;
45
BdrvChild **childp;
46
BlockDriverState *old_bs;
47
- bool free_empty_child;
48
} BdrvReplaceChildState;
49
50
static void bdrv_replace_child_commit(void *opaque)
51
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_commit(void *opaque)
52
BdrvReplaceChildState *s = opaque;
53
GLOBAL_STATE_CODE();
54
55
- if (s->free_empty_child && !s->child->bs) {
56
- bdrv_child_free(s->child);
57
- }
58
bdrv_unref(s->old_bs);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
62
* modify the BdrvChild * pointer we indirectly pass to it, i.e. it
63
* will not modify s->child. From that perspective, it does not matter
64
* whether we pass s->childp or &s->child.
65
+ * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
66
+ * pointer anyway (though it will in the future), so at this point it
67
+ * absolutely does not matter whether we pass s->childp or &s->child.)
68
* (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
69
* it here.
70
* (3) If new_bs is NULL, *s->childp will have been NULLed by
71
* bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
72
* must not pass a NULL *s->childp here.
73
+ * (TODO: In its current state, bdrv_replace_child_noperm() will not
74
+ * have NULLed *s->childp, so this does not apply yet. It will in the
75
+ * future.)
76
*
77
* So whether new_bs was NULL or not, we cannot pass s->childp here; and in
78
* any case, there is no reason to pass it anyway.
79
*/
80
- bdrv_replace_child_noperm(&s->child, s->old_bs, true);
81
- /*
82
- * The child was pre-existing, so s->old_bs must be non-NULL, and
83
- * s->child thus must not have been freed
84
- */
85
- assert(s->child != NULL);
86
- if (!new_bs) {
87
- /* As described above, *s->childp was cleared, so restore it */
88
- assert(s->childp != NULL);
89
- *s->childp = s->child;
90
- }
91
+ bdrv_replace_child_noperm(&s->child, s->old_bs);
92
bdrv_unref(new_bs);
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
96
*
97
* The function doesn't update permissions, caller is responsible for this.
98
*
99
- * (*childp)->bs must not be NULL.
100
- *
101
* Note that if new_bs == NULL, @childp is stored in a state object attached
102
* to @tran, so that the old child can be reinstated in the abort handler.
103
* Therefore, if @new_bs can be NULL, @childp must stay valid until the
104
* transaction is committed or aborted.
105
*
106
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
107
- * freed (on commit). @free_empty_child should only be false if the
108
- * caller will free the BDrvChild themselves (which may be important
109
- * if this is in turn called in another transactional context).
110
+ * (TODO: The reinstating does not happen yet, but it will once
111
+ * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
112
*/
113
static void bdrv_replace_child_tran(BdrvChild **childp,
114
BlockDriverState *new_bs,
115
- Transaction *tran,
116
- bool free_empty_child)
117
+ Transaction *tran)
118
{
119
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
120
*s = (BdrvReplaceChildState) {
121
.child = *childp,
122
.childp = new_bs == NULL ? childp : NULL,
123
.old_bs = (*childp)->bs,
124
- .free_empty_child = free_empty_child,
125
};
126
tran_add(tran, &bdrv_replace_child_drv, s);
127
128
- /* The abort handler relies on this */
129
- assert(s->old_bs != NULL);
130
-
131
if (new_bs) {
132
bdrv_ref(new_bs);
133
}
134
- /*
135
- * Pass free_empty_child=false, we will free the child (if
136
- * necessary) in bdrv_replace_child_commit() (if our
137
- * @free_empty_child parameter was true).
138
- */
139
- bdrv_replace_child_noperm(childp, new_bs, false);
140
+ bdrv_replace_child_noperm(childp, new_bs);
141
/* old_bs reference is transparently moved from *childp to @s */
142
}
143
144
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
145
return permissions[qapi_perm];
146
}
147
148
-/**
149
- * Replace (*childp)->bs by @new_bs.
150
- *
151
- * If @new_bs is NULL, *childp will be set to NULL, too: BDS parents
152
- * generally cannot handle a BdrvChild with .bs == NULL, so clearing
153
- * BdrvChild.bs should generally immediately be followed by the
154
- * BdrvChild pointer being cleared as well.
155
- *
156
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
157
- * freed. @free_empty_child should only be false if the caller will
158
- * free the BdrvChild themselves (this may be important in a
159
- * transactional context, where it may only be freed on commit).
160
- */
161
static void bdrv_replace_child_noperm(BdrvChild **childp,
162
- BlockDriverState *new_bs,
163
- bool free_empty_child)
164
+ BlockDriverState *new_bs)
165
{
166
BdrvChild *child = *childp;
167
BlockDriverState *old_bs = child->bs;
168
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
169
}
170
171
child->bs = new_bs;
172
- if (!new_bs) {
173
- *childp = NULL;
174
- }
175
176
if (new_bs) {
177
assert_bdrv_graph_writable(new_bs);
178
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
179
bdrv_parent_drained_end_single(child);
180
drain_saldo++;
181
}
182
-
183
- if (free_empty_child && !child->bs) {
184
- bdrv_child_free(child);
185
- }
186
}
187
188
/**
189
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
190
BlockDriverState *bs = child->bs;
191
192
GLOBAL_STATE_CODE();
193
- /*
194
- * Pass free_empty_child=false, because we still need the child
195
- * for the AioContext operations on the parent below; those
196
- * BdrvChildClass methods all work on a BdrvChild object, so we
197
- * need to keep it as an empty shell (after this function, it will
198
- * not be attached to any parent, and it will not have a .bs).
199
- */
200
- bdrv_replace_child_noperm(s->child, NULL, false);
201
+ bdrv_replace_child_noperm(s->child, NULL);
202
203
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
204
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
205
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
206
207
bdrv_unref(bs);
208
bdrv_child_free(child);
209
+ *s->child = NULL;
210
}
211
212
static TransactionActionDrv bdrv_attach_child_common_drv = {
213
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
214
}
215
216
bdrv_ref(child_bs);
217
- bdrv_replace_child_noperm(&new_child, child_bs, true);
218
- /* child_bs was non-NULL, so new_child must not have been freed */
219
- assert(new_child != NULL);
220
+ bdrv_replace_child_noperm(&new_child, child_bs);
221
222
*child = new_child;
223
224
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild **childp)
225
BlockDriverState *old_bs = (*childp)->bs;
226
227
GLOBAL_STATE_CODE();
228
- bdrv_replace_child_noperm(childp, NULL, true);
229
+ bdrv_replace_child_noperm(childp, NULL);
230
+ bdrv_child_free(*childp);
231
232
if (old_bs) {
233
/*
234
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
235
}
236
237
if (child->bs) {
238
- /*
239
- * Pass free_empty_child=false, we will free the child in
240
- * bdrv_remove_filter_or_cow_child_commit()
241
- */
242
- bdrv_replace_child_tran(childp, NULL, tran, false);
243
+ bdrv_replace_child_tran(childp, NULL, tran);
244
}
245
246
s = g_new(BdrvRemoveFilterOrCowChild, 1);
247
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
248
.is_backing = (childp == &bs->backing),
249
};
250
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
251
+
252
+ *childp = NULL;
253
}
254
255
/*
256
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
257
* Passing a pointer to the local variable @c is fine here, because
258
* @to is not NULL, and so &c will not be attached to the transaction.
259
*/
260
- bdrv_replace_child_tran(&c, to, tran, true);
261
+ bdrv_replace_child_tran(&c, to, tran);
262
}
263
264
return 0;
265
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
266
bdrv_drained_begin(old_bs);
267
bdrv_drained_begin(new_bs);
268
269
- bdrv_replace_child_tran(&child, new_bs, tran, true);
270
- /* @new_bs must have been non-NULL, so @child must not have been freed */
271
- assert(child != NULL);
272
+ bdrv_replace_child_tran(&child, new_bs, tran);
273
274
found = g_hash_table_new(NULL, NULL);
275
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
276
--
277
2.37.3
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
3
That's a preparation to previously reverted
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
need it for a new approach.
6
7
This reverts commit 82b54cf51656bf3cd5ed1ac549e8a1085a0e3290.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-11-vsementsov@yandex-team.ru>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block.c | 81 +++++++--------------------------------------------------
15
1 file changed, 10 insertions(+), 71 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm,
22
23
typedef struct BdrvReplaceChildState {
24
BdrvChild *child;
25
- BdrvChild **childp;
26
BlockDriverState *old_bs;
27
} BdrvReplaceChildState;
28
29
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
30
BlockDriverState *new_bs = s->child->bs;
31
32
GLOBAL_STATE_CODE();
33
- /*
34
- * old_bs reference is transparently moved from @s to s->child.
35
- *
36
- * Pass &s->child here instead of s->childp, because:
37
- * (1) s->old_bs must be non-NULL, so bdrv_replace_child_noperm() will not
38
- * modify the BdrvChild * pointer we indirectly pass to it, i.e. it
39
- * will not modify s->child. From that perspective, it does not matter
40
- * whether we pass s->childp or &s->child.
41
- * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
42
- * pointer anyway (though it will in the future), so at this point it
43
- * absolutely does not matter whether we pass s->childp or &s->child.)
44
- * (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
45
- * it here.
46
- * (3) If new_bs is NULL, *s->childp will have been NULLed by
47
- * bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
48
- * must not pass a NULL *s->childp here.
49
- * (TODO: In its current state, bdrv_replace_child_noperm() will not
50
- * have NULLed *s->childp, so this does not apply yet. It will in the
51
- * future.)
52
- *
53
- * So whether new_bs was NULL or not, we cannot pass s->childp here; and in
54
- * any case, there is no reason to pass it anyway.
55
- */
56
+ /* old_bs reference is transparently moved from @s to @s->child */
57
bdrv_replace_child_noperm(&s->child, s->old_bs);
58
bdrv_unref(new_bs);
59
}
60
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
61
* Note: real unref of old_bs is done only on commit.
62
*
63
* The function doesn't update permissions, caller is responsible for this.
64
- *
65
- * Note that if new_bs == NULL, @childp is stored in a state object attached
66
- * to @tran, so that the old child can be reinstated in the abort handler.
67
- * Therefore, if @new_bs can be NULL, @childp must stay valid until the
68
- * transaction is committed or aborted.
69
- *
70
- * (TODO: The reinstating does not happen yet, but it will once
71
- * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
72
*/
73
-static void bdrv_replace_child_tran(BdrvChild **childp,
74
- BlockDriverState *new_bs,
75
+static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
76
Transaction *tran)
77
{
78
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
79
*s = (BdrvReplaceChildState) {
80
- .child = *childp,
81
- .childp = new_bs == NULL ? childp : NULL,
82
- .old_bs = (*childp)->bs,
83
+ .child = child,
84
+ .old_bs = child->bs,
85
};
86
tran_add(tran, &bdrv_replace_child_drv, s);
87
88
if (new_bs) {
89
bdrv_ref(new_bs);
90
}
91
- bdrv_replace_child_noperm(childp, new_bs);
92
- /* old_bs reference is transparently moved from *childp to @s */
93
+ bdrv_replace_child_noperm(&child, new_bs);
94
+ /* old_bs reference is transparently moved from @child to @s */
95
}
96
97
/*
98
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
99
100
typedef struct BdrvRemoveFilterOrCowChild {
101
BdrvChild *child;
102
- BlockDriverState *bs;
103
bool is_backing;
104
} BdrvRemoveFilterOrCowChild;
105
106
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
107
bdrv_child_free(s->child);
108
}
109
110
-static void bdrv_remove_filter_or_cow_child_clean(void *opaque)
111
-{
112
- BdrvRemoveFilterOrCowChild *s = opaque;
113
-
114
- /* Drop the bs reference after the transaction is done */
115
- bdrv_unref(s->bs);
116
- g_free(s);
117
-}
118
-
119
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
120
.abort = bdrv_remove_filter_or_cow_child_abort,
121
.commit = bdrv_remove_filter_or_cow_child_commit,
122
- .clean = bdrv_remove_filter_or_cow_child_clean,
123
+ .clean = g_free,
124
};
125
126
/*
127
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
128
return;
129
}
130
131
- /*
132
- * Keep a reference to @bs so @childp will stay valid throughout the
133
- * transaction (required by bdrv_replace_child_tran())
134
- */
135
- bdrv_ref(bs);
136
if (child == bs->backing) {
137
childp = &bs->backing;
138
} else if (child == bs->file) {
139
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
140
}
141
142
if (child->bs) {
143
- bdrv_replace_child_tran(childp, NULL, tran);
144
+ bdrv_replace_child_tran(*childp, NULL, tran);
145
}
146
147
s = g_new(BdrvRemoveFilterOrCowChild, 1);
148
*s = (BdrvRemoveFilterOrCowChild) {
149
.child = child,
150
- .bs = bs,
151
.is_backing = (childp == &bs->backing),
152
};
153
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
154
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
155
{
156
BdrvChild *c, *next;
157
158
- assert(to != NULL);
159
GLOBAL_STATE_CODE();
160
161
QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
162
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
163
c->name, from->node_name);
164
return -EPERM;
165
}
166
-
167
- /*
168
- * Passing a pointer to the local variable @c is fine here, because
169
- * @to is not NULL, and so &c will not be attached to the transaction.
170
- */
171
- bdrv_replace_child_tran(&c, to, tran);
172
+ bdrv_replace_child_tran(c, to, tran);
173
}
174
175
return 0;
176
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
177
*
178
* With @detach_subchain=true @to must be in a backing chain of @from. In this
179
* case backing link of the cow-parent of @to is removed.
180
- *
181
- * @to must not be NULL.
182
*/
183
static int bdrv_replace_node_common(BlockDriverState *from,
184
BlockDriverState *to,
185
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_common(BlockDriverState *from,
186
int ret;
187
188
GLOBAL_STATE_CODE();
189
- assert(to != NULL);
190
191
if (detach_subchain) {
192
assert(bdrv_chain_contains(from, to));
193
@@ -XXX,XX +XXX,XX @@ out:
194
return ret;
195
}
196
197
-/**
198
- * Replace node @from by @to (where neither may be NULL).
199
- */
200
int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
201
Error **errp)
202
{
203
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
204
bdrv_drained_begin(old_bs);
205
bdrv_drained_begin(new_bs);
206
207
- bdrv_replace_child_tran(&child, new_bs, tran);
208
+ bdrv_replace_child_tran(child, new_bs, tran);
209
210
found = g_hash_table_new(NULL, NULL);
211
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
212
--
213
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Previously, the alloc command required that input parameters be
3
That's a preparation to previously reverted
4
sector-aligned and clamped to 32 bits, because the underlying
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
bdrv_is_allocated used a 32-bit parameter and asserted aligned
5
need it for a new approach.
6
inputs. But now that we have fixed block status to report a
7
64-bit bytes value, and to properly round requests on behalf of
8
guests, we can pass any values, and can use qemu-io to add
9
coverage that our rounding is correct regardless of the guest
10
alignment constraints.
11
6
12
Update iotest 177 to intentionally probe block status at
7
This reverts commit 562bda8bb41879eeda0bd484dd3d55134579b28e.
13
unaligned boundaries as well as with a bytes value that does not
14
map to 32-bit sectors, which also required tweaking the image
15
prep to leave an unallocated portion to the image under test.
16
8
17
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-12-vsementsov@yandex-team.ru>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
13
---
20
qemu-io-cmds.c | 13 -------------
14
block.c | 21 +++++++++------------
21
tests/qemu-iotests/177 | 12 ++++++++++--
15
1 file changed, 9 insertions(+), 12 deletions(-)
22
tests/qemu-iotests/177.out | 19 ++++++++++++++-----
23
3 files changed, 24 insertions(+), 20 deletions(-)
24
16
25
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
17
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-io-cmds.c
19
--- a/block.c
28
+++ b/qemu-io-cmds.c
20
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
21
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
30
if (offset < 0) {
22
BdrvChild *child,
31
print_cvtnum_err(offset, argv[1]);
23
Transaction *tran)
32
return 0;
24
{
33
- } else if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
25
- BdrvChild **childp;
34
- printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
26
BdrvRemoveFilterOrCowChild *s;
35
- offset);
27
36
- return 0;
28
+ assert(child == bs->backing || child == bs->file);
29
+
30
if (!child) {
31
return;
37
}
32
}
38
33
39
if (argc == 3) {
34
- if (child == bs->backing) {
40
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
35
- childp = &bs->backing;
41
if (count < 0) {
36
- } else if (child == bs->file) {
42
print_cvtnum_err(count, argv[2]);
37
- childp = &bs->file;
43
return 0;
38
- } else {
44
- } else if (count > INT_MAX * BDRV_SECTOR_SIZE) {
39
- g_assert_not_reached();
45
- printf("length argument cannot exceed %llu, given %s\n",
40
- }
46
- INT_MAX * BDRV_SECTOR_SIZE, argv[2]);
41
-
47
- return 0;
42
if (child->bs) {
48
}
43
- bdrv_replace_child_tran(*childp, NULL, tran);
49
} else {
44
+ bdrv_replace_child_tran(child, NULL, tran);
50
count = BDRV_SECTOR_SIZE;
51
}
45
}
52
- if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
46
53
- printf("%" PRId64 " is not a sector-aligned value for 'count'\n",
47
s = g_new(BdrvRemoveFilterOrCowChild, 1);
54
- count);
48
*s = (BdrvRemoveFilterOrCowChild) {
55
- return 0;
49
.child = child,
56
- }
50
- .is_backing = (childp == &bs->backing),
57
51
+ .is_backing = (child == bs->backing),
58
remaining = count;
52
};
59
sum_alloc = 0;
53
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
60
diff --git a/tests/qemu-iotests/177 b/tests/qemu-iotests/177
54
61
index XXXXXXX..XXXXXXX 100755
55
- *childp = NULL;
62
--- a/tests/qemu-iotests/177
56
+ if (s->is_backing) {
63
+++ b/tests/qemu-iotests/177
57
+ bs->backing = NULL;
64
@@ -XXX,XX +XXX,XX @@ echo "== setting up files =="
58
+ } else {
65
TEST_IMG="$TEST_IMG.base" _make_test_img $size
59
+ bs->file = NULL;
66
$QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io
60
+ }
67
_make_test_img -b "$TEST_IMG.base"
68
-$QEMU_IO -c "write -P 22 0 $size" "$TEST_IMG" | _filter_qemu_io
69
+$QEMU_IO -c "write -P 22 0 110M" "$TEST_IMG" | _filter_qemu_io
70
71
# Limited to 64k max-transfer
72
echo
73
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
74
-c "discard 80000001 30M" | _filter_qemu_io
75
76
echo
77
+echo "== block status smaller than alignment =="
78
+limits=align=4k
79
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
80
+     -c "alloc 1 1" -c "alloc 0x6dffff0 1000" -c "alloc 127m 5P" \
81
+     -c map | _filter_qemu_io
82
+
83
+echo
84
echo "== verify image content =="
85
86
function verify_io()
87
@@ -XXX,XX +XXX,XX @@ function verify_io()
88
echo read -P 0 32M 32M
89
echo read -P 22 64M 13M
90
echo read -P $discarded 77M 29M
91
- echo read -P 22 106M 22M
92
+ echo read -P 22 106M 4M
93
+ echo read -P 11 110M 18M
94
}
61
}
95
62
96
verify_io | $QEMU_IO -r "$TEST_IMG" | _filter_qemu_io
63
/*
97
diff --git a/tests/qemu-iotests/177.out b/tests/qemu-iotests/177.out
98
index XXXXXXX..XXXXXXX 100644
99
--- a/tests/qemu-iotests/177.out
100
+++ b/tests/qemu-iotests/177.out
101
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
102
wrote 134217728/134217728 bytes at offset 0
103
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
104
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
105
-wrote 134217728/134217728 bytes at offset 0
106
-128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
107
+wrote 115343360/115343360 bytes at offset 0
108
+110 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
109
110
== constrained alignment and max-transfer ==
111
wrote 131072/131072 bytes at offset 1000
112
@@ -XXX,XX +XXX,XX @@ wrote 33554432/33554432 bytes at offset 33554432
113
discard 31457280/31457280 bytes at offset 80000001
114
30 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
115
116
+== block status smaller than alignment ==
117
+1/1 bytes allocated at offset 1 bytes
118
+16/1000 bytes allocated at offset 110 MiB
119
+0/1048576 bytes allocated at offset 127 MiB
120
+110 MiB (0x6e00000) bytes allocated at offset 0 bytes (0x0)
121
+18 MiB (0x1200000) bytes not allocated at offset 110 MiB (0x6e00000)
122
+
123
== verify image content ==
124
read 1000/1000 bytes at offset 0
125
1000 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
126
@@ -XXX,XX +XXX,XX @@ read 13631488/13631488 bytes at offset 67108864
127
13 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
128
read 30408704/30408704 bytes at offset 80740352
129
29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
130
-read 23068672/23068672 bytes at offset 111149056
131
-22 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
132
+read 4194304/4194304 bytes at offset 111149056
133
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
134
+read 18874368/18874368 bytes at offset 115343360
135
+18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
136
Offset Length File
137
0 0x800000 TEST_DIR/t.IMGFMT
138
0x900000 0x2400000 TEST_DIR/t.IMGFMT
139
0x3c00000 0x1100000 TEST_DIR/t.IMGFMT
140
-0x6a00000 0x1600000 TEST_DIR/t.IMGFMT
141
+0x6a00000 0x400000 TEST_DIR/t.IMGFMT
142
No errors were found on the image.
143
*** done
144
--
64
--
145
2.13.6
65
2.37.3
146
147
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
That's a preparation to previously reverted
4
easier to reason about than sector-based. Convert another internal
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
type (no semantic change), and rename it to match the corresponding
5
need it for a new approach.
6
public function rename.
7
6
8
Signed-off-by: Eric Blake <eblake@redhat.com>
7
This reverts commit be64bbb0149748f3999c49b13976aafb8330ea86.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-13-vsementsov@yandex-team.ru>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
block/io.c | 56 ++++++++++++++++++++++++++++++++++++++------------------
14
block.c | 23 +++++++++++------------
12
1 file changed, 38 insertions(+), 18 deletions(-)
15
1 file changed, 11 insertions(+), 12 deletions(-)
13
16
14
diff --git a/block/io.c b/block/io.c
17
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/block/io.c
19
--- a/block.c
17
+++ b/block/io.c
20
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
21
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
22
static bool bdrv_recurse_has_child(BlockDriverState *bs,
23
BlockDriverState *child);
24
25
-static void bdrv_replace_child_noperm(BdrvChild **child,
26
+static void bdrv_replace_child_noperm(BdrvChild *child,
27
BlockDriverState *new_bs);
28
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
29
BdrvChild *child,
30
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
31
32
GLOBAL_STATE_CODE();
33
/* old_bs reference is transparently moved from @s to @s->child */
34
- bdrv_replace_child_noperm(&s->child, s->old_bs);
35
+ bdrv_replace_child_noperm(s->child, s->old_bs);
36
bdrv_unref(new_bs);
19
}
37
}
20
38
21
39
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
22
-typedef struct BdrvCoGetBlockStatusData {
40
if (new_bs) {
23
+typedef struct BdrvCoBlockStatusData {
41
bdrv_ref(new_bs);
24
BlockDriverState *bs;
42
}
25
BlockDriverState *base;
43
- bdrv_replace_child_noperm(&child, new_bs);
26
bool want_zero;
44
+ bdrv_replace_child_noperm(child, new_bs);
27
- int64_t sector_num;
45
/* old_bs reference is transparently moved from @child to @s */
28
- int nb_sectors;
46
}
29
- int *pnum;
47
30
+ int64_t offset;
48
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
31
+ int64_t bytes;
49
return permissions[qapi_perm];
32
+ int64_t *pnum;
50
}
33
+ int64_t *map;
51
34
BlockDriverState **file;
52
-static void bdrv_replace_child_noperm(BdrvChild **childp,
35
- int64_t ret;
53
+static void bdrv_replace_child_noperm(BdrvChild *child,
36
+ int ret;
54
BlockDriverState *new_bs)
37
bool done;
38
-} BdrvCoGetBlockStatusData;
39
+} BdrvCoBlockStatusData;
40
41
int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
42
int64_t sector_num,
43
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
44
/* Coroutine wrapper for bdrv_get_block_status_above() */
45
static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque)
46
{
55
{
47
- BdrvCoGetBlockStatusData *data = opaque;
56
- BdrvChild *child = *childp;
48
+ BdrvCoBlockStatusData *data = opaque;
57
BlockDriverState *old_bs = child->bs;
49
+ int n = 0;
58
int new_bs_quiesce_counter;
50
+ int64_t ret;
59
int drain_saldo;
51
60
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
52
- data->ret = bdrv_co_get_block_status_above(data->bs, data->base,
61
BlockDriverState *bs = child->bs;
53
- data->want_zero,
62
54
- data->sector_num,
63
GLOBAL_STATE_CODE();
55
- data->nb_sectors,
64
- bdrv_replace_child_noperm(s->child, NULL);
56
- data->pnum,
65
+ bdrv_replace_child_noperm(child, NULL);
57
- data->file);
66
58
+ ret = bdrv_co_get_block_status_above(data->bs, data->base,
67
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
59
+ data->want_zero,
68
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
60
+ data->offset >> BDRV_SECTOR_BITS,
69
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
61
+ data->bytes >> BDRV_SECTOR_BITS,
70
}
62
+ &n,
71
63
+ data->file);
72
bdrv_ref(child_bs);
64
+ if (ret < 0) {
73
- bdrv_replace_child_noperm(&new_child, child_bs);
65
+ assert(INT_MIN <= ret);
74
+ bdrv_replace_child_noperm(new_child, child_bs);
66
+ data->ret = ret;
75
67
+ } else {
76
*child = new_child;
68
+ *data->pnum = n * BDRV_SECTOR_SIZE;
77
69
+ *data->map = ret & BDRV_BLOCK_OFFSET_MASK;
78
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
70
+ data->ret = ret & ~BDRV_BLOCK_OFFSET_MASK;
79
return 0;
71
+ }
72
data->done = true;
73
}
80
}
74
81
75
@@ -XXX,XX +XXX,XX @@ static int64_t bdrv_common_block_status_above(BlockDriverState *bs,
82
-static void bdrv_detach_child(BdrvChild **childp)
76
BlockDriverState **file)
83
+static void bdrv_detach_child(BdrvChild *child)
77
{
84
{
78
Coroutine *co;
85
- BlockDriverState *old_bs = (*childp)->bs;
79
- BdrvCoGetBlockStatusData data = {
86
+ BlockDriverState *old_bs = child->bs;
80
+ int64_t n;
87
81
+ int64_t map;
88
GLOBAL_STATE_CODE();
82
+ BdrvCoBlockStatusData data = {
89
- bdrv_replace_child_noperm(childp, NULL);
83
.bs = bs,
90
- bdrv_child_free(*childp);
84
.base = base,
91
+ bdrv_replace_child_noperm(child, NULL);
85
.want_zero = want_zero,
92
+ bdrv_child_free(child);
86
- .sector_num = sector_num,
93
87
- .nb_sectors = nb_sectors,
94
if (old_bs) {
88
- .pnum = pnum,
95
/*
89
+ .offset = sector_num * BDRV_SECTOR_SIZE,
96
@@ -XXX,XX +XXX,XX @@ void bdrv_root_unref_child(BdrvChild *child)
90
+ .bytes = nb_sectors * BDRV_SECTOR_SIZE,
97
GLOBAL_STATE_CODE();
91
+ .pnum = &n,
98
92
+ .map = &map,
99
child_bs = child->bs;
93
.file = file,
100
- bdrv_detach_child(&child);
94
.done = false,
101
+ bdrv_detach_child(child);
95
};
102
bdrv_unref(child_bs);
96
@@ -XXX,XX +XXX,XX @@ static int64_t bdrv_common_block_status_above(BlockDriverState *bs,
97
bdrv_coroutine_enter(bs, co);
98
BDRV_POLL_WHILE(bs, !data.done);
99
}
100
- return data.ret;
101
+ if (data.ret < 0) {
102
+ *pnum = 0;
103
+ return data.ret;
104
+ }
105
+ assert(QEMU_IS_ALIGNED(n | map, BDRV_SECTOR_SIZE));
106
+ *pnum = n >> BDRV_SECTOR_BITS;
107
+ return data.ret | map;
108
}
103
}
109
104
110
int64_t bdrv_get_block_status_above(BlockDriverState *bs,
111
--
105
--
112
2.13.6
106
2.37.3
113
114
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Not all callers care about which BDS owns the mapping for a given
3
bs->file and bs->backing are a kind of duplication of part of
4
range of the file, or where the zeroes lie within that mapping. In
4
bs->children. But very useful diplication, so let's not drop them at
5
particular, bdrv_is_allocated() cares more about finding the
5
all:)
6
largest run of allocated data from the guest perspective, whether
6
7
or not that data is consecutive from the host perspective, and
7
We should manage bs->file and bs->backing in same place, where we
8
whether or not the data reads as zero. Therefore, doing subsequent
8
manage bs->children, to keep them in sync.
9
refinements such as checking how much of the format-layer
9
10
allocation also satisfies BDRV_BLOCK_ZERO at the protocol layer is
10
Moreover, generic io paths are unprepared to BdrvChild without a bs, so
11
wasted work - in the best case, it just costs extra CPU cycles
11
it's double good to clear bs->file / bs->backing when we detach the
12
during a single bdrv_is_allocated(), but in the worst case, it
12
child.
13
results in a smaller *pnum, and forces callers to iterate through
13
14
more status probes when visiting the entire file for even more
14
Detach is simple: if we detach bs->file or bs->backing child, just
15
extra CPU cycles.
15
set corresponding field to NULL.
16
16
17
This patch only optimizes the block layer (no behavior change when
17
Attach is a bit more complicated. But we still can precisely detect
18
want_zero is true, but skip unnecessary effort when it is false).
18
should we set one of bs->file / bs->backing or not:
19
Then when subsequent patches tweak the driver callback to be
19
20
byte-based, we can also pass this hint through to the driver.
20
- if role is BDRV_CHILD_COW, we definitely deal with bs->backing
21
21
- else, if role is BDRV_CHILD_FILTERED (it must be also
22
Tweak BdrvCoGetBlockStatusData to declare arguments in parameter
22
BDRV_CHILD_PRIMARY), it's a filtered child. Use
23
order, rather than mixing things up (minimizing padding is not
23
bs->drv->filtered_child_is_backing to chose the pointer field to
24
necessary here).
24
modify.
25
25
- else, if role is BDRV_CHILD_PRIMARY, we deal with bs->file
26
Signed-off-by: Eric Blake <eblake@redhat.com>
26
- in all other cases, it's neither bs->backing nor bs->file. It's some
27
other child and we shouldn't care
28
29
OK. This change brings one more good thing: we can (and should) get rid
30
of all indirect pointers in the block-graph-change transactions:
31
32
bdrv_attach_child_common() stores BdrvChild** into transaction to clear
33
it on abort.
34
35
bdrv_attach_child_common() has two callers: bdrv_attach_child_noperm()
36
just pass-through this feature, bdrv_root_attach_child() doesn't need
37
the feature.
38
39
Look at bdrv_attach_child_noperm() callers:
40
- bdrv_attach_child() doesn't need the feature
41
- bdrv_set_file_or_backing_noperm() uses the feature to manage
42
bs->file and bs->backing, we don't want it anymore
43
- bdrv_append() uses the feature to manage bs->backing, again we
44
don't want it anymore
45
46
So, we should drop this stuff! Great!
47
48
We could probably keep BdrvChild** argument to keep the int return
49
value, but it seems not worth the complexity.
50
51
Finally, we now set .file / .backing automatically in generic code and
52
want to restring setting them by hand outside of .attach/.detach.
53
So, this patch cleanups all remaining places where they were set.
54
To find such places I use:
55
56
git grep '\->file ='
57
git grep '\->backing ='
58
git grep '&.*\<backing\>'
59
git grep '&.*\<file\>'
60
61
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
62
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
63
Message-Id: <20220726201134.924743-14-vsementsov@yandex-team.ru>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
64
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
---
65
---
29
block/io.c | 57 +++++++++++++++++++++++++++++++++++++++++----------------
66
include/block/block_int-common.h | 15 +-
30
1 file changed, 41 insertions(+), 16 deletions(-)
67
block.c | 234 ++++++++++++++-----------------
31
68
block/raw-format.c | 4 +-
32
diff --git a/block/io.c b/block/io.c
69
block/snapshot-access.c | 6 +-
70
block/snapshot.c | 1 -
71
tests/unit/test-bdrv-drain.c | 10 +-
72
6 files changed, 126 insertions(+), 144 deletions(-)
73
74
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
33
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
34
--- a/block/io.c
76
--- a/include/block/block_int-common.h
35
+++ b/block/io.c
77
+++ b/include/block/block_int-common.h
36
@@ -XXX,XX +XXX,XX @@ int bdrv_flush_all(void)
78
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
37
typedef struct BdrvCoGetBlockStatusData {
79
QDict *full_open_options;
38
BlockDriverState *bs;
80
char exact_filename[PATH_MAX];
39
BlockDriverState *base;
81
40
- BlockDriverState **file;
82
- BdrvChild *backing;
41
+ bool want_zero;
83
- BdrvChild *file;
42
int64_t sector_num;
84
-
43
int nb_sectors;
85
/* I/O Limits */
44
int *pnum;
86
BlockLimits bl;
45
+ BlockDriverState **file;
87
46
int64_t ret;
88
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
47
bool done;
89
* parent node of this node.
48
} BdrvCoGetBlockStatusData;
90
*/
49
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
91
BlockDriverState *inherits_from;
50
* Drivers not implementing the functionality are assumed to not support
92
+
51
* backing files, hence all their sectors are reported as allocated.
93
+ /*
94
+ * @backing and @file are some of @children or NULL. All these three fields
95
+ * (@file, @backing and @children) are modified only in
96
+ * bdrv_child_cb_attach() and bdrv_child_cb_detach().
97
+ *
98
+ * See also comment in include/block/block.h, to learn how backing and file
99
+ * are connected with BdrvChildRole.
100
+ */
101
QLIST_HEAD(, BdrvChild) children;
102
+ BdrvChild *backing;
103
+ BdrvChild *file;
104
+
105
QLIST_HEAD(, BdrvChild) parents;
106
107
QDict *options;
108
diff --git a/block.c b/block.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/block.c
111
+++ b/block.c
112
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_attach(BdrvChild *child)
113
114
assert_bdrv_graph_writable(bs);
115
QLIST_INSERT_HEAD(&bs->children, child, next);
116
-
117
- if (child->role & BDRV_CHILD_COW) {
118
+ if (bs->drv->is_filter || (child->role & BDRV_CHILD_FILTERED)) {
119
+ /*
120
+ * Here we handle filters and block/raw-format.c when it behave like
121
+ * filter. They generally have a single PRIMARY child, which is also the
122
+ * FILTERED child, and that they may have multiple more children, which
123
+ * are neither PRIMARY nor FILTERED. And never we have a COW child here.
124
+ * So bs->file will be the PRIMARY child, unless the PRIMARY child goes
125
+ * into bs->backing on exceptional cases; and bs->backing will be
126
+ * nothing else.
127
+ */
128
+ assert(!(child->role & BDRV_CHILD_COW));
129
+ if (child->role & BDRV_CHILD_PRIMARY) {
130
+ assert(child->role & BDRV_CHILD_FILTERED);
131
+ assert(!bs->backing);
132
+ assert(!bs->file);
133
+
134
+ if (bs->drv->filtered_child_is_backing) {
135
+ bs->backing = child;
136
+ } else {
137
+ bs->file = child;
138
+ }
139
+ } else {
140
+ assert(!(child->role & BDRV_CHILD_FILTERED));
141
+ }
142
+ } else if (child->role & BDRV_CHILD_COW) {
143
+ assert(bs->drv->supports_backing);
144
+ assert(!(child->role & BDRV_CHILD_PRIMARY));
145
+ assert(!bs->backing);
146
+ bs->backing = child;
147
bdrv_backing_attach(child);
148
+ } else if (child->role & BDRV_CHILD_PRIMARY) {
149
+ assert(!bs->file);
150
+ bs->file = child;
151
}
152
153
bdrv_apply_subtree_drain(child, bs);
154
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_detach(BdrvChild *child)
155
156
assert_bdrv_graph_writable(bs);
157
QLIST_REMOVE(child, next);
158
+ if (child == bs->backing) {
159
+ assert(child != bs->file);
160
+ bs->backing = NULL;
161
+ } else if (child == bs->file) {
162
+ bs->file = NULL;
163
+ }
164
}
165
166
static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
167
@@ -XXX,XX +XXX,XX @@ open_failed:
168
bs->drv = NULL;
169
if (bs->file != NULL) {
170
bdrv_unref_child(bs, bs->file);
171
- bs->file = NULL;
172
+ assert(!bs->file);
173
}
174
g_free(bs->opaque);
175
bs->opaque = NULL;
176
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_free(BdrvChild *child)
177
}
178
179
typedef struct BdrvAttachChildCommonState {
180
- BdrvChild **child;
181
+ BdrvChild *child;
182
AioContext *old_parent_ctx;
183
AioContext *old_child_ctx;
184
} BdrvAttachChildCommonState;
185
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvAttachChildCommonState {
186
static void bdrv_attach_child_common_abort(void *opaque)
187
{
188
BdrvAttachChildCommonState *s = opaque;
189
- BdrvChild *child = *s->child;
190
- BlockDriverState *bs = child->bs;
191
+ BlockDriverState *bs = s->child->bs;
192
193
GLOBAL_STATE_CODE();
194
- bdrv_replace_child_noperm(child, NULL);
195
+ bdrv_replace_child_noperm(s->child, NULL);
196
197
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
198
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
199
}
200
201
- if (bdrv_child_get_parent_aio_context(child) != s->old_parent_ctx) {
202
+ if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
203
GSList *ignore;
204
205
/* No need to ignore `child`, because it has been detached already */
206
ignore = NULL;
207
- child->klass->can_set_aio_ctx(child, s->old_parent_ctx, &ignore,
208
- &error_abort);
209
+ s->child->klass->can_set_aio_ctx(s->child, s->old_parent_ctx, &ignore,
210
+ &error_abort);
211
g_slist_free(ignore);
212
213
ignore = NULL;
214
- child->klass->set_aio_ctx(child, s->old_parent_ctx, &ignore);
215
+ s->child->klass->set_aio_ctx(s->child, s->old_parent_ctx, &ignore);
216
g_slist_free(ignore);
217
}
218
219
bdrv_unref(bs);
220
- bdrv_child_free(child);
221
- *s->child = NULL;
222
+ bdrv_child_free(s->child);
223
}
224
225
static TransactionActionDrv bdrv_attach_child_common_drv = {
226
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_attach_child_common_drv = {
227
/*
228
* Common part of attaching bdrv child to bs or to blk or to job
52
*
229
*
53
+ * If 'want_zero' is true, the caller is querying for mapping purposes,
230
- * Resulting new child is returned through @child.
54
+ * and the result should include BDRV_BLOCK_OFFSET_VALID and
231
- * At start *@child must be NULL.
55
+ * BDRV_BLOCK_ZERO where possible; otherwise, the result may omit those
232
- * @child is saved to a new entry of @tran, so that *@child could be reverted to
56
+ * bits particularly if it allows for a larger value in 'pnum'.
233
- * NULL on abort(). So referenced variable must live at least until transaction
234
- * end.
235
- *
236
* Function doesn't update permissions, caller is responsible for this.
57
+ *
237
+ *
58
* If 'sector_num' is beyond the end of the disk image the return value is
238
+ * Returns new created child.
59
* BDRV_BLOCK_EOF and 'pnum' is set to 0.
60
*
61
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
62
* is allocated in.
63
*/
239
*/
64
static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
240
-static int bdrv_attach_child_common(BlockDriverState *child_bs,
65
+ bool want_zero,
241
- const char *child_name,
66
int64_t sector_num,
242
- const BdrvChildClass *child_class,
67
int nb_sectors, int *pnum,
243
- BdrvChildRole child_role,
68
BlockDriverState **file)
244
- uint64_t perm, uint64_t shared_perm,
69
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
245
- void *opaque, BdrvChild **child,
70
246
- Transaction *tran, Error **errp)
71
if (ret & BDRV_BLOCK_RAW) {
247
+static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
72
assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file);
248
+ const char *child_name,
73
- ret = bdrv_co_get_block_status(local_file, ret >> BDRV_SECTOR_BITS,
249
+ const BdrvChildClass *child_class,
74
+ ret = bdrv_co_get_block_status(local_file, want_zero,
250
+ BdrvChildRole child_role,
75
+ ret >> BDRV_SECTOR_BITS,
251
+ uint64_t perm, uint64_t shared_perm,
76
*pnum, pnum, &local_file);
252
+ void *opaque,
253
+ Transaction *tran, Error **errp)
254
{
255
BdrvChild *new_child;
256
AioContext *parent_ctx;
257
AioContext *child_ctx = bdrv_get_aio_context(child_bs);
258
259
- assert(child);
260
- assert(*child == NULL);
261
assert(child_class->get_parent_desc);
262
GLOBAL_STATE_CODE();
263
264
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
265
if (ret < 0) {
266
error_propagate(errp, local_err);
267
bdrv_child_free(new_child);
268
- return ret;
269
+ return NULL;
270
}
271
}
272
273
bdrv_ref(child_bs);
274
bdrv_replace_child_noperm(new_child, child_bs);
275
276
- *child = new_child;
277
-
278
BdrvAttachChildCommonState *s = g_new(BdrvAttachChildCommonState, 1);
279
*s = (BdrvAttachChildCommonState) {
280
- .child = child,
281
+ .child = new_child,
282
.old_parent_ctx = parent_ctx,
283
.old_child_ctx = child_ctx,
284
};
285
tran_add(tran, &bdrv_attach_child_common_drv, s);
286
287
- return 0;
288
+ return new_child;
289
}
290
291
/*
292
- * Variable referenced by @child must live at least until transaction end.
293
- * (see bdrv_attach_child_common() doc for details)
294
- *
295
* Function doesn't update permissions, caller is responsible for this.
296
*/
297
-static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
298
- BlockDriverState *child_bs,
299
- const char *child_name,
300
- const BdrvChildClass *child_class,
301
- BdrvChildRole child_role,
302
- BdrvChild **child,
303
- Transaction *tran,
304
- Error **errp)
305
+static BdrvChild *bdrv_attach_child_noperm(BlockDriverState *parent_bs,
306
+ BlockDriverState *child_bs,
307
+ const char *child_name,
308
+ const BdrvChildClass *child_class,
309
+ BdrvChildRole child_role,
310
+ Transaction *tran,
311
+ Error **errp)
312
{
313
- int ret;
314
uint64_t perm, shared_perm;
315
316
assert(parent_bs->drv);
317
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
318
if (bdrv_recurse_has_child(child_bs, parent_bs)) {
319
error_setg(errp, "Making '%s' a %s child of '%s' would create a cycle",
320
child_bs->node_name, child_name, parent_bs->node_name);
321
- return -EINVAL;
322
+ return NULL;
323
}
324
325
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
326
bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
327
perm, shared_perm, &perm, &shared_perm);
328
329
- ret = bdrv_attach_child_common(child_bs, child_name, child_class,
330
- child_role, perm, shared_perm, parent_bs,
331
- child, tran, errp);
332
- if (ret < 0) {
333
- return ret;
334
- }
335
-
336
- return 0;
337
+ return bdrv_attach_child_common(child_bs, child_name, child_class,
338
+ child_role, perm, shared_perm, parent_bs,
339
+ tran, errp);
340
}
341
342
static void bdrv_detach_child(BdrvChild *child)
343
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
344
void *opaque, Error **errp)
345
{
346
int ret;
347
- BdrvChild *child = NULL;
348
+ BdrvChild *child;
349
Transaction *tran = tran_new();
350
351
GLOBAL_STATE_CODE();
352
353
- ret = bdrv_attach_child_common(child_bs, child_name, child_class,
354
+ child = bdrv_attach_child_common(child_bs, child_name, child_class,
355
child_role, perm, shared_perm, opaque,
356
- &child, tran, errp);
357
- if (ret < 0) {
358
+ tran, errp);
359
+ if (!child) {
360
+ ret = -EINVAL;
77
goto out;
361
goto out;
78
}
362
}
79
363
80
if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
364
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
81
ret |= BDRV_BLOCK_ALLOCATED;
365
366
out:
367
tran_finalize(tran, ret);
368
- /* child is unset on failure by bdrv_attach_child_common_abort() */
369
- assert((ret < 0) == !child);
370
371
bdrv_unref(child_bs);
372
- return child;
373
+
374
+ return ret < 0 ? NULL : child;
375
}
376
377
/*
378
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
379
Error **errp)
380
{
381
int ret;
382
- BdrvChild *child = NULL;
383
+ BdrvChild *child;
384
Transaction *tran = tran_new();
385
386
GLOBAL_STATE_CODE();
387
388
- ret = bdrv_attach_child_noperm(parent_bs, child_bs, child_name, child_class,
389
- child_role, &child, tran, errp);
390
- if (ret < 0) {
391
+ child = bdrv_attach_child_noperm(parent_bs, child_bs, child_name,
392
+ child_class, child_role, tran, errp);
393
+ if (!child) {
394
+ ret = -EINVAL;
395
goto out;
396
}
397
398
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
399
400
out:
401
tran_finalize(tran, ret);
402
- /* child is unset on failure by bdrv_attach_child_common_abort() */
403
- assert((ret < 0) == !child);
404
405
bdrv_unref(child_bs);
406
407
- return child;
408
+ return ret < 0 ? NULL : child;
409
}
410
411
/* Callers must ensure that child->frozen is false. */
412
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
413
bool is_backing,
414
Transaction *tran, Error **errp)
415
{
416
- int ret = 0;
417
bool update_inherits_from =
418
bdrv_inherits_from_recursive(child_bs, parent_bs);
419
BdrvChild *child = is_backing ? parent_bs->backing : parent_bs->file;
420
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
421
goto out;
422
}
423
424
- ret = bdrv_attach_child_noperm(parent_bs, child_bs,
425
- is_backing ? "backing" : "file",
426
- &child_of_bds, role,
427
- is_backing ? &parent_bs->backing :
428
- &parent_bs->file,
429
- tran, errp);
430
- if (ret < 0) {
431
- return ret;
432
+ child = bdrv_attach_child_noperm(parent_bs, child_bs,
433
+ is_backing ? "backing" : "file",
434
+ &child_of_bds, role,
435
+ tran, errp);
436
+ if (!child) {
437
+ return -EINVAL;
438
}
439
440
441
@@ -XXX,XX +XXX,XX @@ int bdrv_open_file_child(const char *filename,
442
443
/* commit_top and mirror_top don't use this function */
444
assert(!parent->drv->filtered_child_is_backing);
445
-
446
role = parent->drv->is_filter ?
447
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
448
449
- parent->file = bdrv_open_child(filename, options, bdref_key, parent,
450
- &child_of_bds, role, false, errp);
451
+ if (!bdrv_open_child(filename, options, bdref_key, parent,
452
+ &child_of_bds, role, false, errp))
453
+ {
454
+ return -EINVAL;
455
+ }
456
457
- return parent->file ? 0 : -EINVAL;
458
+ return 0;
459
}
460
461
/*
462
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
463
bdrv_unref_child(bs, child);
464
}
465
466
- bs->backing = NULL;
467
- bs->file = NULL;
468
+ assert(!bs->backing);
469
+ assert(!bs->file);
470
g_free(bs->opaque);
471
bs->opaque = NULL;
472
qatomic_set(&bs->copy_on_read, 0);
473
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
474
return ret;
475
}
476
477
-typedef struct BdrvRemoveFilterOrCowChild {
478
- BdrvChild *child;
479
- bool is_backing;
480
-} BdrvRemoveFilterOrCowChild;
481
-
482
-static void bdrv_remove_filter_or_cow_child_abort(void *opaque)
483
-{
484
- BdrvRemoveFilterOrCowChild *s = opaque;
485
- BlockDriverState *parent_bs = s->child->opaque;
486
-
487
- if (s->is_backing) {
488
- parent_bs->backing = s->child;
82
- } else {
489
- } else {
83
+ } else if (want_zero) {
490
- parent_bs->file = s->child;
84
if (bdrv_unallocated_blocks_are_zero(bs)) {
491
- }
85
ret |= BDRV_BLOCK_ZERO;
492
-
86
} else if (bs->backing) {
493
- /*
87
BlockDriverState *bs2 = bs->backing->bs;
494
- * We don't have to restore child->bs here to undo bdrv_replace_child_tran()
88
int64_t nb_sectors2 = bdrv_nb_sectors(bs2);
495
- * because that function is transactionable and it registered own completion
89
+
496
- * entries in @tran, so .abort() for bdrv_replace_child_safe() will be
90
if (nb_sectors2 >= 0 && sector_num >= nb_sectors2) {
497
- * called automatically.
91
ret |= BDRV_BLOCK_ZERO;
498
- */
92
}
499
-}
500
-
501
static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
502
{
503
- BdrvRemoveFilterOrCowChild *s = opaque;
504
GLOBAL_STATE_CODE();
505
- bdrv_child_free(s->child);
506
+ bdrv_child_free(opaque);
507
}
508
509
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
510
- .abort = bdrv_remove_filter_or_cow_child_abort,
511
.commit = bdrv_remove_filter_or_cow_child_commit,
512
- .clean = g_free,
513
};
514
515
/*
516
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
517
BdrvChild *child,
518
Transaction *tran)
519
{
520
- BdrvRemoveFilterOrCowChild *s;
521
-
522
assert(child == bs->backing || child == bs->file);
523
524
if (!child) {
525
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
526
bdrv_replace_child_tran(child, NULL, tran);
527
}
528
529
- s = g_new(BdrvRemoveFilterOrCowChild, 1);
530
- *s = (BdrvRemoveFilterOrCowChild) {
531
- .child = child,
532
- .is_backing = (child == bs->backing),
533
- };
534
- tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
535
-
536
- if (s->is_backing) {
537
- bs->backing = NULL;
538
- } else {
539
- bs->file = NULL;
540
- }
541
+ tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, child);
542
}
543
544
/*
545
@@ -XXX,XX +XXX,XX @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
546
Error **errp)
547
{
548
int ret;
549
+ BdrvChild *child;
550
Transaction *tran = tran_new();
551
552
GLOBAL_STATE_CODE();
553
554
assert(!bs_new->backing);
555
556
- ret = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
557
- &child_of_bds, bdrv_backing_role(bs_new),
558
- &bs_new->backing, tran, errp);
559
- if (ret < 0) {
560
+ child = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
561
+ &child_of_bds, bdrv_backing_role(bs_new),
562
+ tran, errp);
563
+ if (!child) {
564
+ ret = -EINVAL;
565
goto out;
566
}
567
568
diff --git a/block/raw-format.c b/block/raw-format.c
569
index XXXXXXX..XXXXXXX 100644
570
--- a/block/raw-format.c
571
+++ b/block/raw-format.c
572
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
573
file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
574
}
575
576
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
577
- file_role, false, errp);
578
+ bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
579
+ file_role, false, errp);
580
if (!bs->file) {
581
return -EINVAL;
582
}
583
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
584
index XXXXXXX..XXXXXXX 100644
585
--- a/block/snapshot-access.c
586
+++ b/block/snapshot-access.c
587
@@ -XXX,XX +XXX,XX @@ static void snapshot_access_refresh_filename(BlockDriverState *bs)
588
static int snapshot_access_open(BlockDriverState *bs, QDict *options, int flags,
589
Error **errp)
590
{
591
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
592
- BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
593
- false, errp);
594
+ bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
595
+ BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
596
+ false, errp);
597
if (!bs->file) {
598
return -EINVAL;
599
}
600
diff --git a/block/snapshot.c b/block/snapshot.c
601
index XXXXXXX..XXXXXXX 100644
602
--- a/block/snapshot.c
603
+++ b/block/snapshot.c
604
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
605
606
/* .bdrv_open() will re-attach it */
607
bdrv_unref_child(bs, *fallback_ptr);
608
- *fallback_ptr = NULL;
609
610
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
611
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
612
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
613
index XXXXXXX..XXXXXXX 100644
614
--- a/tests/unit/test-bdrv-drain.c
615
+++ b/tests/unit/test-bdrv-drain.c
616
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
617
for (i = 0; i < 3; i++) {
618
if (i) {
619
/* Takes the reference to chain[i - 1] */
620
- chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
621
- "chain", &chain_child_class,
622
- BDRV_CHILD_COW, &error_abort);
623
+ bdrv_attach_child(chain[i], chain[i - 1], "chain",
624
+ &chain_child_class, BDRV_CHILD_COW, &error_abort);
93
}
625
}
94
}
626
}
95
627
96
- if (local_file && local_file != bs &&
628
@@ -XXX,XX +XXX,XX @@ static void do_test_replace_child_mid_drain(int old_drain_count,
97
+ if (want_zero && local_file && local_file != bs &&
629
new_child_bs->total_sectors = 1;
98
(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
630
99
(ret & BDRV_BLOCK_OFFSET_VALID)) {
631
bdrv_ref(old_child_bs);
100
int file_pnum;
632
- parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
101
633
- &child_of_bds, BDRV_CHILD_COW,
102
- ret2 = bdrv_co_get_block_status(local_file, ret >> BDRV_SECTOR_BITS,
634
- &error_abort);
103
+ ret2 = bdrv_co_get_block_status(local_file, want_zero,
635
+ bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds,
104
+ ret >> BDRV_SECTOR_BITS,
636
+ BDRV_CHILD_COW, &error_abort);
105
*pnum, &file_pnum, NULL);
637
106
if (ret2 >= 0) {
638
for (i = 0; i < old_drain_count; i++) {
107
/* Ignore errors. This is just providing extra information, it
639
bdrv_drained_begin(old_child_bs);
108
@@ -XXX,XX +XXX,XX @@ early_out:
109
110
static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
111
BlockDriverState *base,
112
+ bool want_zero,
113
int64_t sector_num,
114
int nb_sectors,
115
int *pnum,
116
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
117
118
assert(bs != base);
119
for (p = bs; p != base; p = backing_bs(p)) {
120
- ret = bdrv_co_get_block_status(p, sector_num, nb_sectors, pnum, file);
121
+ ret = bdrv_co_get_block_status(p, want_zero, sector_num, nb_sectors,
122
+ pnum, file);
123
if (ret < 0) {
124
break;
125
}
126
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque)
127
BdrvCoGetBlockStatusData *data = opaque;
128
129
data->ret = bdrv_co_get_block_status_above(data->bs, data->base,
130
+ data->want_zero,
131
data->sector_num,
132
data->nb_sectors,
133
data->pnum,
134
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque)
135
*
136
* See bdrv_co_get_block_status_above() for details.
137
*/
138
-int64_t bdrv_get_block_status_above(BlockDriverState *bs,
139
- BlockDriverState *base,
140
- int64_t sector_num,
141
- int nb_sectors, int *pnum,
142
- BlockDriverState **file)
143
+static int64_t bdrv_common_block_status_above(BlockDriverState *bs,
144
+ BlockDriverState *base,
145
+ bool want_zero,
146
+ int64_t sector_num,
147
+ int nb_sectors, int *pnum,
148
+ BlockDriverState **file)
149
{
150
Coroutine *co;
151
BdrvCoGetBlockStatusData data = {
152
.bs = bs,
153
.base = base,
154
- .file = file,
155
+ .want_zero = want_zero,
156
.sector_num = sector_num,
157
.nb_sectors = nb_sectors,
158
.pnum = pnum,
159
+ .file = file,
160
.done = false,
161
};
162
163
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status_above(BlockDriverState *bs,
164
return data.ret;
165
}
166
167
+int64_t bdrv_get_block_status_above(BlockDriverState *bs,
168
+ BlockDriverState *base,
169
+ int64_t sector_num,
170
+ int nb_sectors, int *pnum,
171
+ BlockDriverState **file)
172
+{
173
+ return bdrv_common_block_status_above(bs, base, true, sector_num,
174
+ nb_sectors, pnum, file);
175
+}
176
+
177
int64_t bdrv_get_block_status(BlockDriverState *bs,
178
int64_t sector_num,
179
int nb_sectors, int *pnum,
180
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status(BlockDriverState *bs,
181
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
182
int64_t bytes, int64_t *pnum)
183
{
184
- int64_t sector_num = offset >> BDRV_SECTOR_BITS;
185
- int nb_sectors = bytes >> BDRV_SECTOR_BITS;
186
int64_t ret;
187
int psectors;
188
189
assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
190
assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE) && bytes < INT_MAX);
191
- ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &psectors,
192
- NULL);
193
+ ret = bdrv_common_block_status_above(bs, backing_bs(bs), false,
194
+ offset >> BDRV_SECTOR_BITS,
195
+ bytes >> BDRV_SECTOR_BITS, &psectors,
196
+ NULL);
197
if (ret < 0) {
198
return ret;
199
}
200
--
640
--
201
2.13.6
641
2.37.3
202
203
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Now the indirection is not actually used, we can safely reduce it to
4
easier to reason about than sector-based. Convert another internal
4
simple pointer. For consistency do a bit of refactoring to get rid of
5
function (no semantic change).
5
_ptr suffixes that become meaningless.
6
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20220726201134.924743-15-vsementsov@yandex-team.ru>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
11
---
10
block/io.c | 61 ++++++++++++++++++++++++++++++-------------------------------
12
block/snapshot.c | 38 ++++++++++++++++----------------------
11
1 file changed, 30 insertions(+), 31 deletions(-)
13
1 file changed, 16 insertions(+), 22 deletions(-)
12
14
13
diff --git a/block/io.c b/block/io.c
15
diff --git a/block/snapshot.c b/block/snapshot.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/block/io.c
17
--- a/block/snapshot.c
16
+++ b/block/io.c
18
+++ b/block/snapshot.c
17
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque)
19
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
18
*
20
}
19
* See bdrv_co_get_block_status_above() for details.
21
22
/**
23
- * Return a pointer to the child BDS pointer to which we can fall
24
+ * Return a pointer to child of given BDS to which we can fall
25
* back if the given BDS does not support snapshots.
26
* Return NULL if there is no BDS to (safely) fall back to.
27
- *
28
- * We need to return an indirect pointer because bdrv_snapshot_goto()
29
- * has to modify the BdrvChild pointer.
20
*/
30
*/
21
-static int64_t bdrv_common_block_status_above(BlockDriverState *bs,
31
-static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
22
- BlockDriverState *base,
32
+static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
23
- bool want_zero,
24
- int64_t sector_num,
25
- int nb_sectors, int *pnum,
26
- BlockDriverState **file)
27
+static int bdrv_common_block_status_above(BlockDriverState *bs,
28
+ BlockDriverState *base,
29
+ bool want_zero, int64_t offset,
30
+ int64_t bytes, int64_t *pnum,
31
+ int64_t *map,
32
+ BlockDriverState **file)
33
{
33
{
34
Coroutine *co;
34
- BdrvChild **fallback;
35
- int64_t n;
35
- BdrvChild *child = bdrv_primary_child(bs);
36
- int64_t map;
36
+ BdrvChild *fallback = bdrv_primary_child(bs);
37
BdrvCoBlockStatusData data = {
37
+ BdrvChild *child;
38
.bs = bs,
38
39
.base = base,
39
/* We allow fallback only to primary child */
40
.want_zero = want_zero,
40
- if (!child) {
41
- .offset = sector_num * BDRV_SECTOR_SIZE,
41
+ if (!fallback) {
42
- .bytes = nb_sectors * BDRV_SECTOR_SIZE,
42
return NULL;
43
- .pnum = &n,
44
- .map = &map,
45
+ .offset = offset,
46
+ .bytes = bytes,
47
+ .pnum = pnum,
48
+ .map = map,
49
.file = file,
50
.done = false,
51
};
52
@@ -XXX,XX +XXX,XX @@ static int64_t bdrv_common_block_status_above(BlockDriverState *bs,
53
bdrv_coroutine_enter(bs, co);
54
BDRV_POLL_WHILE(bs, !data.done);
55
}
43
}
56
- if (data.ret < 0) {
44
- fallback = (child == bs->file ? &bs->file : &bs->backing);
57
- *pnum = 0;
45
- assert(*fallback == child);
58
- return data.ret;
46
59
- }
47
/*
60
- assert(QEMU_IS_ALIGNED(n | map, BDRV_SECTOR_SIZE));
48
* Check that there are no other children that would need to be
61
- *pnum = n >> BDRV_SECTOR_BITS;
49
* snapshotted. If there are, it is not safe to fall back to
62
- return data.ret | map;
50
- * *fallback.
63
+ return data.ret;
51
+ * fallback.
52
*/
53
QLIST_FOREACH(child, &bs->children, next) {
54
if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
55
BDRV_CHILD_FILTERED) &&
56
- child != *fallback)
57
+ child != fallback)
58
{
59
return NULL;
60
}
61
@@ -XXX,XX +XXX,XX @@ static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
62
63
static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
64
{
65
- BdrvChild **child_ptr = bdrv_snapshot_fallback_ptr(bs);
66
- return child_ptr ? (*child_ptr)->bs : NULL;
67
+ return child_bs(bdrv_snapshot_fallback_child(bs));
64
}
68
}
65
69
66
int64_t bdrv_get_block_status_above(BlockDriverState *bs,
70
int bdrv_can_snapshot(BlockDriverState *bs)
67
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status_above(BlockDriverState *bs,
71
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
68
int nb_sectors, int *pnum,
72
Error **errp)
69
BlockDriverState **file)
70
{
73
{
71
- return bdrv_common_block_status_above(bs, base, true, sector_num,
74
BlockDriver *drv = bs->drv;
72
- nb_sectors, pnum, file);
75
- BdrvChild **fallback_ptr;
73
+ int64_t ret;
76
+ BdrvChild *fallback;
74
+ int64_t n;
77
int ret, open_ret;
75
+ int64_t map;
78
76
+
79
GLOBAL_STATE_CODE();
77
+ ret = bdrv_common_block_status_above(bs, base, true,
80
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
78
+ sector_num * BDRV_SECTOR_SIZE,
79
+ nb_sectors * BDRV_SECTOR_SIZE,
80
+ &n, &map, file);
81
+ if (ret < 0) {
82
+ *pnum = 0;
83
+ return ret;
84
+ }
85
+ assert(QEMU_IS_ALIGNED(n | map, BDRV_SECTOR_SIZE));
86
+ *pnum = n >> BDRV_SECTOR_BITS;
87
+ return ret | map;
88
}
89
90
int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
91
@@ -XXX,XX +XXX,XX @@ int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
92
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
93
int64_t bytes, int64_t *pnum)
94
{
95
- int64_t ret;
96
- int psectors;
97
+ int ret;
98
+ int64_t dummy;
99
100
- assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
101
- assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE) && bytes < INT_MAX);
102
- ret = bdrv_common_block_status_above(bs, backing_bs(bs), false,
103
- offset >> BDRV_SECTOR_BITS,
104
- bytes >> BDRV_SECTOR_BITS, &psectors,
105
+ ret = bdrv_common_block_status_above(bs, backing_bs(bs), false, offset,
106
+ bytes, pnum ? pnum : &dummy, NULL,
107
NULL);
108
if (ret < 0) {
109
return ret;
81
return ret;
110
}
82
}
111
- if (pnum) {
83
112
- *pnum = psectors * BDRV_SECTOR_SIZE;
84
- fallback_ptr = bdrv_snapshot_fallback_ptr(bs);
113
- }
85
- if (fallback_ptr) {
114
return !!(ret & BDRV_BLOCK_ALLOCATED);
86
+ fallback = bdrv_snapshot_fallback_child(bs);
115
}
87
+ if (fallback) {
116
88
QDict *options;
89
QDict *file_options;
90
Error *local_err = NULL;
91
- BlockDriverState *fallback_bs = (*fallback_ptr)->bs;
92
- char *subqdict_prefix = g_strdup_printf("%s.", (*fallback_ptr)->name);
93
+ BlockDriverState *fallback_bs = fallback->bs;
94
+ char *subqdict_prefix = g_strdup_printf("%s.", fallback->name);
95
96
options = qdict_clone_shallow(bs->options);
97
98
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
99
qobject_unref(file_options);
100
g_free(subqdict_prefix);
101
102
- /* Force .bdrv_open() below to re-attach fallback_bs on *fallback_ptr */
103
- qdict_put_str(options, (*fallback_ptr)->name,
104
+ /* Force .bdrv_open() below to re-attach fallback_bs on fallback */
105
+ qdict_put_str(options, fallback->name,
106
bdrv_get_node_name(fallback_bs));
107
108
/* Now close bs, apply the snapshot on fallback_bs, and re-open bs */
109
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
110
}
111
112
/* .bdrv_open() will re-attach it */
113
- bdrv_unref_child(bs, *fallback_ptr);
114
+ bdrv_unref_child(bs, fallback);
115
116
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
117
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
117
--
118
--
118
2.13.6
119
2.37.3
119
120
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Now the function can remove any child, so give it more common name.
4
byte-based. In the common case, allocation is unlikely to ever use
4
Drop assertions and drop bs argument which becomes unused. Function
5
values that are not naturally sector-aligned, but it is possible
5
would be reused in a further commit.
6
that byte-based values will let us be more precise about allocation
7
at the end of an unaligned file that can do byte-based access.
8
6
9
Changing the name of the function from bdrv_get_block_status_above()
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
to bdrv_block_status_above() ensures that the compiler enforces that
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
all callers are updated. Likewise, since it a byte interface allows
9
Message-Id: <20220726201134.924743-16-vsementsov@yandex-team.ru>
12
an offset mapping that might not be sector aligned, split the mapping
13
out of the return value and into a pass-by-reference parameter. For
14
now, the io.c layer still assert()s that all uses are sector-aligned,
15
but that can be relaxed when a later patch implements byte-based
16
block status in the drivers.
17
18
For the most part this patch is just the addition of scaling at the
19
callers followed by inverse scaling at bdrv_block_status(), plus
20
updates for the new split return interface. But some code,
21
particularly bdrv_block_status(), gets a lot simpler because it no
22
longer has to mess with sectors. Likewise, mirror code no longer
23
computes s->granularity >> BDRV_SECTOR_BITS, and can therefore drop
24
an assertion about alignment because the loop no longer depends on
25
alignment (never mind that we don't really have a driver that
26
reports sub-sector alignments, so it's not really possible to test
27
the effect of sub-sector mirroring). Fix a neighboring assertion to
28
use is_power_of_2 while there.
29
30
For ease of review, bdrv_get_block_status() was tackled separately.
31
32
Signed-off-by: Eric Blake <eblake@redhat.com>
33
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
---
11
---
35
include/block/block.h | 8 +++-----
12
block.c | 27 +++++++++------------------
36
block/io.c | 55 ++++++++-------------------------------------------
13
1 file changed, 9 insertions(+), 18 deletions(-)
37
block/mirror.c | 18 ++++++-----------
38
block/qcow2.c | 30 +++++++++++-----------------
39
qemu-img.c | 49 +++++++++++++++++++++++++--------------------
40
5 files changed, 57 insertions(+), 103 deletions(-)
41
14
42
diff --git a/include/block/block.h b/include/block/block.h
15
diff --git a/block.c b/block.c
43
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
44
--- a/include/block/block.h
17
--- a/block.c
45
+++ b/include/block/block.h
18
+++ b/block.c
46
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
19
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
47
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
20
48
int64_t bytes, int64_t *pnum, int64_t *map,
21
static void bdrv_replace_child_noperm(BdrvChild *child,
49
BlockDriverState **file);
22
BlockDriverState *new_bs);
50
-int64_t bdrv_get_block_status_above(BlockDriverState *bs,
23
-static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
51
- BlockDriverState *base,
24
- BdrvChild *child,
52
- int64_t sector_num,
25
- Transaction *tran);
53
- int nb_sectors, int *pnum,
26
+static void bdrv_remove_child(BdrvChild *child, Transaction *tran);
54
- BlockDriverState **file);
27
static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
55
+int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
28
Transaction *tran);
56
+ int64_t offset, int64_t bytes, int64_t *pnum,
29
57
+ int64_t *map, BlockDriverState **file);
30
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
58
int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
31
59
int64_t *pnum);
32
if (child) {
60
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
33
bdrv_unset_inherits_from(parent_bs, child, tran);
61
diff --git a/block/io.c b/block/io.c
34
- bdrv_remove_file_or_backing_child(parent_bs, child, tran);
62
index XXXXXXX..XXXXXXX 100644
35
+ bdrv_remove_child(child, tran);
63
--- a/block/io.c
36
}
64
+++ b/block/io.c
37
65
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status_above(BlockDriverState *bs,
38
if (!child_bs) {
39
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
66
return ret;
40
return ret;
67
}
41
}
68
42
69
-/* Coroutine wrapper for bdrv_get_block_status_above() */
43
-static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
70
+/* Coroutine wrapper for bdrv_block_status_above() */
44
+static void bdrv_remove_child_commit(void *opaque)
71
static void coroutine_fn bdrv_block_status_above_co_entry(void *opaque)
72
{
45
{
73
BdrvCoBlockStatusData *data = opaque;
46
GLOBAL_STATE_CODE();
74
@@ -XXX,XX +XXX,XX @@ static int bdrv_common_block_status_above(BlockDriverState *bs,
47
bdrv_child_free(opaque);
75
return data.ret;
76
}
48
}
77
49
78
-int64_t bdrv_get_block_status_above(BlockDriverState *bs,
50
-static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
79
- BlockDriverState *base,
51
- .commit = bdrv_remove_filter_or_cow_child_commit,
80
- int64_t sector_num,
52
+static TransactionActionDrv bdrv_remove_child_drv = {
81
- int nb_sectors, int *pnum,
53
+ .commit = bdrv_remove_child_commit,
82
- BlockDriverState **file)
54
};
83
+int bdrv_block_status_above(BlockDriverState *bs, BlockDriverState *base,
55
84
+ int64_t offset, int64_t bytes, int64_t *pnum,
56
-/*
85
+ int64_t *map, BlockDriverState **file)
57
- * A function to remove backing or file child of @bs.
58
- * Function doesn't update permissions, caller is responsible for this.
59
- */
60
-static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
61
- BdrvChild *child,
62
- Transaction *tran)
63
+/* Function doesn't update permissions, caller is responsible for this. */
64
+static void bdrv_remove_child(BdrvChild *child, Transaction *tran)
86
{
65
{
87
- int64_t ret;
66
- assert(child == bs->backing || child == bs->file);
88
- int64_t n;
89
- int64_t map;
90
-
67
-
91
- ret = bdrv_common_block_status_above(bs, base, true,
68
if (!child) {
92
- sector_num * BDRV_SECTOR_SIZE,
69
return;
93
- nb_sectors * BDRV_SECTOR_SIZE,
70
}
94
- &n, &map, file);
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
95
- if (ret < 0) {
72
bdrv_replace_child_tran(child, NULL, tran);
96
- *pnum = 0;
73
}
97
- return ret;
74
98
- }
75
- tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, child);
99
- assert(QEMU_IS_ALIGNED(n | map, BDRV_SECTOR_SIZE));
76
+ tran_add(tran, &bdrv_remove_child_drv, child);
100
- *pnum = n >> BDRV_SECTOR_BITS;
101
- return ret | map;
102
+ return bdrv_common_block_status_above(bs, base, true, offset, bytes,
103
+ pnum, map, file);
104
}
77
}
105
78
106
int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
79
/*
107
int64_t *pnum, int64_t *map, BlockDriverState **file)
80
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
81
static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
82
Transaction *tran)
108
{
83
{
109
- int64_t ret;
84
- bdrv_remove_file_or_backing_child(bs, bdrv_filter_or_cow_child(bs), tran);
110
- int n;
85
+ bdrv_remove_child(bdrv_filter_or_cow_child(bs), tran);
111
-
112
- assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
113
- assert(pnum);
114
- /*
115
- * The contract allows us to return pnum smaller than bytes, even
116
- * if the next query would see the same status; we truncate the
117
- * request to avoid overflowing the driver's 32-bit interface.
118
- */
119
- bytes = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
120
- ret = bdrv_get_block_status_above(bs, backing_bs(bs),
121
- offset >> BDRV_SECTOR_BITS,
122
- bytes >> BDRV_SECTOR_BITS, &n, file);
123
- if (ret < 0) {
124
- assert(INT_MIN <= ret);
125
- *pnum = 0;
126
- return ret;
127
- }
128
- *pnum = n * BDRV_SECTOR_SIZE;
129
- if (map) {
130
- *map = ret & BDRV_BLOCK_OFFSET_MASK;
131
- } else {
132
- ret &= ~BDRV_BLOCK_OFFSET_VALID;
133
- }
134
- return ret & ~BDRV_BLOCK_OFFSET_MASK;
135
+ return bdrv_block_status_above(bs, backing_bs(bs),
136
+ offset, bytes, pnum, map, file);
137
}
86
}
138
87
139
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
88
static int bdrv_replace_node_noperm(BlockDriverState *from,
140
diff --git a/block/mirror.c b/block/mirror.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/mirror.c
143
+++ b/block/mirror.c
144
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
145
uint64_t delay_ns = 0;
146
/* At least the first dirty chunk is mirrored in one iteration. */
147
int nb_chunks = 1;
148
- int sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
149
bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target));
150
int max_io_bytes = MAX(s->buf_size / MAX_IN_FLIGHT, MAX_IO_BYTES);
151
152
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
153
}
154
155
/* Clear dirty bits before querying the block status, because
156
- * calling bdrv_get_block_status_above could yield - if some blocks are
157
+ * calling bdrv_block_status_above could yield - if some blocks are
158
* marked dirty in this window, we need to know.
159
*/
160
bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, offset,
161
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
162
163
bitmap_set(s->in_flight_bitmap, offset / s->granularity, nb_chunks);
164
while (nb_chunks > 0 && offset < s->bdev_length) {
165
- int64_t ret;
166
- int io_sectors;
167
+ int ret;
168
int64_t io_bytes;
169
int64_t io_bytes_acct;
170
enum MirrorMethod {
171
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
172
} mirror_method = MIRROR_METHOD_COPY;
173
174
assert(!(offset % s->granularity));
175
- ret = bdrv_get_block_status_above(source, NULL,
176
- offset >> BDRV_SECTOR_BITS,
177
- nb_chunks * sectors_per_chunk,
178
- &io_sectors, NULL);
179
- io_bytes = io_sectors * BDRV_SECTOR_SIZE;
180
+ ret = bdrv_block_status_above(source, NULL, offset,
181
+ nb_chunks * s->granularity,
182
+ &io_bytes, NULL, NULL);
183
if (ret < 0) {
184
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
185
} else if (ret & BDRV_BLOCK_DATA) {
186
@@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
187
granularity = bdrv_get_default_bitmap_granularity(target);
188
}
189
190
- assert ((granularity & (granularity - 1)) == 0);
191
- /* Granularity must be large enough for sector-based dirty bitmap */
192
- assert(granularity >= BDRV_SECTOR_SIZE);
193
+ assert(is_power_of_2(granularity));
194
195
if (buf_size < 0) {
196
error_setg(errp, "Invalid parameter 'buf-size'");
197
diff --git a/block/qcow2.c b/block/qcow2.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/block/qcow2.c
200
+++ b/block/qcow2.c
201
@@ -XXX,XX +XXX,XX @@ finish:
202
203
static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
204
{
205
- int nr;
206
- int64_t res;
207
+ int64_t nr;
208
+ int res;
209
int64_t start;
210
211
/* TODO: Widening to sector boundaries should only be needed as
212
@@ -XXX,XX +XXX,XX @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
213
if (!bytes) {
214
return true;
215
}
216
- res = bdrv_get_block_status_above(bs, NULL, start >> BDRV_SECTOR_BITS,
217
- bytes >> BDRV_SECTOR_BITS, &nr, NULL);
218
- return res >= 0 && (res & BDRV_BLOCK_ZERO) &&
219
- nr * BDRV_SECTOR_SIZE == bytes;
220
+ res = bdrv_block_status_above(bs, NULL, start, bytes, &nr, NULL, NULL);
221
+ return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == bytes;
222
}
223
224
static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
225
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
226
required = virtual_size;
227
} else {
228
int64_t offset;
229
- int pnum = 0;
230
+ int64_t pnum = 0;
231
232
- for (offset = 0; offset < ssize;
233
- offset += pnum * BDRV_SECTOR_SIZE) {
234
- int nb_sectors = MIN(ssize - offset,
235
- BDRV_REQUEST_MAX_BYTES) / BDRV_SECTOR_SIZE;
236
- int64_t ret;
237
+ for (offset = 0; offset < ssize; offset += pnum) {
238
+ int ret;
239
240
- ret = bdrv_get_block_status_above(in_bs, NULL,
241
- offset >> BDRV_SECTOR_BITS,
242
- nb_sectors, &pnum, NULL);
243
+ ret = bdrv_block_status_above(in_bs, NULL, offset,
244
+ ssize - offset, &pnum, NULL,
245
+ NULL);
246
if (ret < 0) {
247
error_setg_errno(&local_err, -ret,
248
"Unable to get block status");
249
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
250
} else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) ==
251
(BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) {
252
/* Extend pnum to end of cluster for next iteration */
253
- pnum = (ROUND_UP(offset + pnum * BDRV_SECTOR_SIZE,
254
- cluster_size) - offset) >> BDRV_SECTOR_BITS;
255
+ pnum = ROUND_UP(offset + pnum, cluster_size) - offset;
256
257
/* Count clusters we've seen */
258
- required += offset % cluster_size + pnum * BDRV_SECTOR_SIZE;
259
+ required += offset % cluster_size + pnum;
260
}
261
}
262
}
263
diff --git a/qemu-img.c b/qemu-img.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/qemu-img.c
266
+++ b/qemu-img.c
267
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
268
BlockDriverState *bs1, *bs2;
269
int64_t total_sectors1, total_sectors2;
270
uint8_t *buf1 = NULL, *buf2 = NULL;
271
- int pnum1, pnum2;
272
+ int64_t pnum1, pnum2;
273
int allocated1, allocated2;
274
int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
275
bool progress = false, quiet = false, strict = false;
276
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
277
}
278
279
for (;;) {
280
- int64_t status1, status2;
281
+ int status1, status2;
282
283
nb_sectors = sectors_to_process(total_sectors, sector_num);
284
if (nb_sectors <= 0) {
285
break;
286
}
287
- status1 = bdrv_get_block_status_above(bs1, NULL, sector_num,
288
- total_sectors1 - sector_num,
289
- &pnum1, NULL);
290
+ status1 = bdrv_block_status_above(bs1, NULL,
291
+ sector_num * BDRV_SECTOR_SIZE,
292
+ (total_sectors1 - sector_num) *
293
+ BDRV_SECTOR_SIZE,
294
+ &pnum1, NULL, NULL);
295
if (status1 < 0) {
296
ret = 3;
297
error_report("Sector allocation test failed for %s", filename1);
298
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
299
}
300
allocated1 = status1 & BDRV_BLOCK_ALLOCATED;
301
302
- status2 = bdrv_get_block_status_above(bs2, NULL, sector_num,
303
- total_sectors2 - sector_num,
304
- &pnum2, NULL);
305
+ status2 = bdrv_block_status_above(bs2, NULL,
306
+ sector_num * BDRV_SECTOR_SIZE,
307
+ (total_sectors2 - sector_num) *
308
+ BDRV_SECTOR_SIZE,
309
+ &pnum2, NULL, NULL);
310
if (status2 < 0) {
311
ret = 3;
312
error_report("Sector allocation test failed for %s", filename2);
313
goto out;
314
}
315
allocated2 = status2 & BDRV_BLOCK_ALLOCATED;
316
+ /* TODO: Relax this once comparison is byte-based, and we no longer
317
+ * have to worry about sector alignment */
318
+ assert(QEMU_IS_ALIGNED(pnum1 | pnum2, BDRV_SECTOR_SIZE));
319
if (pnum1) {
320
- nb_sectors = MIN(nb_sectors, pnum1);
321
+ nb_sectors = MIN(nb_sectors, pnum1 >> BDRV_SECTOR_BITS);
322
}
323
if (pnum2) {
324
- nb_sectors = MIN(nb_sectors, pnum2);
325
+ nb_sectors = MIN(nb_sectors, pnum2 >> BDRV_SECTOR_BITS);
326
}
327
328
if (strict) {
329
- if ((status1 & ~BDRV_BLOCK_OFFSET_MASK) !=
330
- (status2 & ~BDRV_BLOCK_OFFSET_MASK)) {
331
+ if (status1 != status2) {
332
ret = 1;
333
qprintf(quiet, "Strict mode: Offset %" PRId64
334
" block status mismatch!\n",
335
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
336
}
337
}
338
if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) {
339
- nb_sectors = MIN(pnum1, pnum2);
340
+ nb_sectors = DIV_ROUND_UP(MIN(pnum1, pnum2), BDRV_SECTOR_SIZE);
341
} else if (allocated1 == allocated2) {
342
if (allocated1) {
343
ret = blk_pread(blk1, sector_num << BDRV_SECTOR_BITS, buf1,
344
@@ -XXX,XX +XXX,XX @@ static void convert_select_part(ImgConvertState *s, int64_t sector_num,
345
346
static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
347
{
348
- int64_t ret, src_cur_offset;
349
- int n, src_cur;
350
+ int64_t src_cur_offset;
351
+ int ret, n, src_cur;
352
353
convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
354
355
@@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
356
n = MIN(s->total_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS);
357
358
if (s->sector_next_status <= sector_num) {
359
+ int64_t count = n * BDRV_SECTOR_SIZE;
360
+
361
if (s->target_has_backing) {
362
- int64_t count = n * BDRV_SECTOR_SIZE;
363
364
ret = bdrv_block_status(blk_bs(s->src[src_cur]),
365
(sector_num - src_cur_offset) *
366
BDRV_SECTOR_SIZE,
367
count, &count, NULL, NULL);
368
- assert(ret < 0 || QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
369
- n = count >> BDRV_SECTOR_BITS;
370
} else {
371
- ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
372
- sector_num - src_cur_offset,
373
- n, &n, NULL);
374
+ ret = bdrv_block_status_above(blk_bs(s->src[src_cur]), NULL,
375
+ (sector_num - src_cur_offset) *
376
+ BDRV_SECTOR_SIZE,
377
+ count, &count, NULL, NULL);
378
}
379
if (ret < 0) {
380
return ret;
381
}
382
+ n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE);
383
384
if (ret & BDRV_BLOCK_ZERO) {
385
s->status = BLK_ZERO;
386
--
89
--
387
2.13.6
90
2.37.3
388
389
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
In the continuing quest to make more things byte-based, change
3
Also here ->aio_context is read by I/O threads and written
4
compare_sectors(), renaming it to compare_buffers() in the
4
under BQL.
5
process. Note that one caller (qemu-img compare) only cares
6
about the first difference, while the other (qemu-img rebase)
7
cares about how many consecutive sectors have the same
8
equal/different status; however, this patch does not bother to
9
micro-optimize the compare case to avoid the comparisons of
10
sectors beyond the first mismatch. Both callers are always
11
passing valid buffers in, so the initial check for buffer size
12
can be turned into an assertion.
13
5
14
Signed-off-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Reviewed-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20221025084952.2139888-2-eesposit@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
11
---
18
qemu-img.c | 55 +++++++++++++++++++++++++++----------------------------
12
block.c | 2 ++
19
1 file changed, 27 insertions(+), 28 deletions(-)
13
1 file changed, 2 insertions(+)
20
14
21
diff --git a/qemu-img.c b/qemu-img.c
15
diff --git a/block.c b/block.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/qemu-img.c
17
--- a/block.c
24
+++ b/qemu-img.c
18
+++ b/block.c
25
@@ -XXX,XX +XXX,XX @@ static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
19
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_aio_context(BlockDriverState *bs)
20
if (bs->quiesce_counter) {
21
aio_enable_external(bs->aio_context);
22
}
23
+ assert_bdrv_graph_writable(bs);
24
bs->aio_context = NULL;
26
}
25
}
27
26
28
/*
27
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
29
- * Compares two buffers sector by sector. Returns 0 if the first sector of both
28
aio_disable_external(new_context);
30
- * buffers matches, non-zero otherwise.
31
+ * Compares two buffers sector by sector. Returns 0 if the first
32
+ * sector of each buffer matches, non-zero otherwise.
33
*
34
- * pnum is set to the number of sectors (including and immediately following
35
- * the first one) that are known to have the same comparison result
36
+ * pnum is set to the sector-aligned size of the buffer prefix that
37
+ * has the same matching status as the first sector.
38
*/
39
-static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
40
- int *pnum)
41
+static int compare_buffers(const uint8_t *buf1, const uint8_t *buf2,
42
+ int64_t bytes, int64_t *pnum)
43
{
44
bool res;
45
- int i;
46
+ int64_t i = MIN(bytes, BDRV_SECTOR_SIZE);
47
48
- if (n <= 0) {
49
- *pnum = 0;
50
- return 0;
51
- }
52
+ assert(bytes > 0);
53
54
- res = !!memcmp(buf1, buf2, 512);
55
- for(i = 1; i < n; i++) {
56
- buf1 += 512;
57
- buf2 += 512;
58
+ res = !!memcmp(buf1, buf2, i);
59
+ while (i < bytes) {
60
+ int64_t len = MIN(bytes - i, BDRV_SECTOR_SIZE);
61
62
- if (!!memcmp(buf1, buf2, 512) != res) {
63
+ if (!!memcmp(buf1 + i, buf2 + i, len) != res) {
64
break;
65
}
66
+ i += len;
67
}
29
}
68
30
69
*pnum = i;
31
+ assert_bdrv_graph_writable(bs);
70
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
32
bs->aio_context = new_context;
71
int64_t total_sectors;
33
72
int64_t sector_num = 0;
34
if (bs->drv && bs->drv->bdrv_attach_aio_context) {
73
int64_t nb_sectors;
74
- int c, pnum;
75
+ int c;
76
uint64_t progress_base;
77
bool image_opts = false;
78
bool force_share = false;
79
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
80
/* nothing to do */
81
} else if (allocated1 == allocated2) {
82
if (allocated1) {
83
+ int64_t pnum;
84
+
85
nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
86
ret = blk_pread(blk1, sector_num << BDRV_SECTOR_BITS, buf1,
87
nb_sectors << BDRV_SECTOR_BITS);
88
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
89
ret = 4;
90
goto out;
91
}
92
- ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
93
- if (ret || pnum != nb_sectors) {
94
+ ret = compare_buffers(buf1, buf2,
95
+ nb_sectors * BDRV_SECTOR_SIZE, &pnum);
96
+ if (ret || pnum != nb_sectors * BDRV_SECTOR_SIZE) {
97
qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
98
- sectors_to_bytes(
99
- ret ? sector_num : sector_num + pnum));
100
+ sectors_to_bytes(sector_num) + (ret ? 0 : pnum));
101
ret = 1;
102
goto out;
103
}
104
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
105
/* If they differ, we need to write to the COW file */
106
uint64_t written = 0;
107
108
- while (written < n) {
109
- int pnum;
110
+ while (written < n * BDRV_SECTOR_SIZE) {
111
+ int64_t pnum;
112
113
- if (compare_sectors(buf_old + written * 512,
114
- buf_new + written * 512, n - written, &pnum))
115
+ if (compare_buffers(buf_old + written,
116
+ buf_new + written,
117
+ n * BDRV_SECTOR_SIZE - written, &pnum))
118
{
119
ret = blk_pwrite(blk,
120
- (sector + written) << BDRV_SECTOR_BITS,
121
- buf_old + written * 512,
122
- pnum << BDRV_SECTOR_BITS, 0);
123
+ (sector << BDRV_SECTOR_BITS) + written,
124
+ buf_old + written, pnum, 0);
125
if (ret < 0) {
126
error_report("Error while writing to COW image: %s",
127
strerror(-ret));
128
--
35
--
129
2.13.6
36
2.37.3
130
131
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Tests 067 and 087 filter the actual image size because it depends on the
3
Simplify the way the aiocontext can be changed in a BDS graph.
4
host filesystem (and is not part of the respective test). Since this is
4
There are currently two problems in bdrv_try_set_aio_context:
5
generally true, we should have a common filter function for this, so
5
- There is a confusion of AioContext locks taken and released, because
6
let's pull out the sed line from both tests into such a function.
6
we assume that old aiocontext is always taken and new one is
7
7
taken inside.
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
9
Message-id: 20171009163456.485-2-mreitz@redhat.com
9
- It doesn't look very safe to call bdrv_drained_begin while some
10
Reviewed-by: Eric Blake <eblake@redhat.com>
10
nodes have already switched to the new aiocontext and others haven't.
11
Reviewed-by: Jeff Cody <jcody@redhat.com>
11
This could be especially dangerous because bdrv_drained_begin polls, so
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
something else could be executed while graph is in an inconsistent
13
state.
14
15
Additional minor nitpick: can_set and set_ callbacks both traverse the
16
graph, both using the ignored list of visited nodes in a different way.
17
18
Therefore, get rid of all of this and introduce a new callback,
19
change_aio_context, that uses transactions to efficiently, cleanly
20
and most importantly safely change the aiocontext of a graph.
21
22
This new callback is a "merge" of the two previous ones:
23
- Just like can_set_aio_context, recursively traverses the graph.
24
Marks all nodes that are visited using a GList, and checks if
25
they *could* change the aio_context.
26
- For each node that passes the above check, drain it and add a new transaction
27
that implements a callback that effectively changes the aiocontext.
28
- Once done, the recursive function returns if *all* nodes can change
29
the AioContext. If so, commit the above transactions.
30
Regardless of the outcome, call transaction.clean() to undo all drains
31
done in the recursion.
32
- The transaction list is scanned only after all nodes are being drained, so
33
we are sure that they all are in the same context, and then
34
we switch their AioContext, concluding the drain only after all nodes
35
switched to the new AioContext. In this way we make sure that
36
bdrv_drained_begin() is always called under the old AioContext, and
37
bdrv_drained_end() under the new one.
38
- Because of the above, we don't need to release and re-acquire the
39
old AioContext every time, as everything is done once (and not
40
per-node drain and aiocontext change).
41
42
Note that the "change" API is not yet invoked anywhere.
43
44
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
45
Message-Id: <20221025084952.2139888-3-eesposit@redhat.com>
46
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
47
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
48
---
14
tests/qemu-iotests/067 | 2 +-
49
include/block/block-global-state.h | 6 +
15
tests/qemu-iotests/087 | 2 +-
50
include/block/block_int-common.h | 3 +
16
tests/qemu-iotests/common.filter | 6 ++++++
51
block.c | 220 ++++++++++++++++++++++++++++-
17
3 files changed, 8 insertions(+), 2 deletions(-)
52
3 files changed, 228 insertions(+), 1 deletion(-)
18
53
19
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
54
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
20
index XXXXXXX..XXXXXXX 100755
55
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/067
56
--- a/include/block/block-global-state.h
22
+++ b/tests/qemu-iotests/067
57
+++ b/include/block/block-global-state.h
23
@@ -XXX,XX +XXX,XX @@ _filter_qmp_events()
58
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
24
function run_qemu()
59
GSList **ignore, Error **errp);
60
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
61
62
+bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
63
+ GSList **visited, Transaction *tran,
64
+ Error **errp);
65
+int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
66
+ BdrvChild *ignore_child, Error **errp);
67
+
68
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
69
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
70
71
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/block/block_int-common.h
74
+++ b/include/block/block_int-common.h
75
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
76
GSList **ignore, Error **errp);
77
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
78
79
+ bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
80
+ GSList **visited, Transaction *tran, Error **errp);
81
+
82
AioContext *(*get_parent_aio_context)(BdrvChild *child);
83
84
/*
85
diff --git a/block.c b/block.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/block.c
88
+++ b/block.c
89
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
90
91
static bool bdrv_backing_overridden(BlockDriverState *bs);
92
93
+static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
94
+ GSList **visited, Transaction *tran,
95
+ Error **errp);
96
+
97
/* If non-zero, use only whitelisted block drivers */
98
static int use_bdrv_whitelist;
99
100
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
101
* must not own the AioContext lock for new_context (unless new_context is the
102
* same as the current context of bs).
103
*
104
- * @ignore will accumulate all visited BdrvChild object. The caller is
105
+ * @ignore will accumulate all visited BdrvChild objects. The caller is
106
* responsible for freeing the list afterwards.
107
*/
108
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
109
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
110
return true;
111
}
112
113
+typedef struct BdrvStateSetAioContext {
114
+ AioContext *new_ctx;
115
+ BlockDriverState *bs;
116
+} BdrvStateSetAioContext;
117
+
118
+static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
119
+ GSList **visited, Transaction *tran,
120
+ Error **errp)
121
+{
122
+ GLOBAL_STATE_CODE();
123
+ if (g_slist_find(*visited, c)) {
124
+ return true;
125
+ }
126
+ *visited = g_slist_prepend(*visited, c);
127
+
128
+ /*
129
+ * A BdrvChildClass that doesn't handle AioContext changes cannot
130
+ * tolerate any AioContext changes
131
+ */
132
+ if (!c->klass->change_aio_ctx) {
133
+ char *user = bdrv_child_user_desc(c);
134
+ error_setg(errp, "Changing iothreads is not supported by %s", user);
135
+ g_free(user);
136
+ return false;
137
+ }
138
+ if (!c->klass->change_aio_ctx(c, ctx, visited, tran, errp)) {
139
+ assert(!errp || *errp);
140
+ return false;
141
+ }
142
+ return true;
143
+}
144
+
145
bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
146
GSList **ignore, Error **errp)
25
{
147
{
26
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu \
148
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
27
- | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' \
149
return bdrv_can_set_aio_context(c->bs, ctx, ignore, errp);
28
+ | _filter_actual_image_size \
29
| _filter_generated_node_ids | _filter_qmp_events
30
}
150
}
31
151
32
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
152
+bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
33
index XXXXXXX..XXXXXXX 100755
153
+ GSList **visited, Transaction *tran,
34
--- a/tests/qemu-iotests/087
154
+ Error **errp)
35
+++ b/tests/qemu-iotests/087
155
+{
36
@@ -XXX,XX +XXX,XX @@ function run_qemu()
156
+ GLOBAL_STATE_CODE();
157
+ if (g_slist_find(*visited, c)) {
158
+ return true;
159
+ }
160
+ *visited = g_slist_prepend(*visited, c);
161
+ return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
162
+}
163
+
164
/* @ignore will accumulate all visited BdrvChild object. The caller is
165
* responsible for freeing the list afterwards. */
166
bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
167
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
168
return true;
169
}
170
171
+static void bdrv_set_aio_context_clean(void *opaque)
172
+{
173
+ BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
174
+ BlockDriverState *bs = (BlockDriverState *) state->bs;
175
+
176
+ /* Paired with bdrv_drained_begin in bdrv_change_aio_context() */
177
+ bdrv_drained_end(bs);
178
+
179
+ g_free(state);
180
+}
181
+
182
+static void bdrv_set_aio_context_commit(void *opaque)
183
+{
184
+ BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
185
+ BlockDriverState *bs = (BlockDriverState *) state->bs;
186
+ AioContext *new_context = state->new_ctx;
187
+ AioContext *old_context = bdrv_get_aio_context(bs);
188
+ assert_bdrv_graph_writable(bs);
189
+
190
+ /*
191
+ * Take the old AioContex when detaching it from bs.
192
+ * At this point, new_context lock is already acquired, and we are now
193
+ * also taking old_context. This is safe as long as bdrv_detach_aio_context
194
+ * does not call AIO_POLL_WHILE().
195
+ */
196
+ if (old_context != qemu_get_aio_context()) {
197
+ aio_context_acquire(old_context);
198
+ }
199
+ bdrv_detach_aio_context(bs);
200
+ if (old_context != qemu_get_aio_context()) {
201
+ aio_context_release(old_context);
202
+ }
203
+ bdrv_attach_aio_context(bs, new_context);
204
+}
205
+
206
+static TransactionActionDrv set_aio_context = {
207
+ .commit = bdrv_set_aio_context_commit,
208
+ .clean = bdrv_set_aio_context_clean,
209
+};
210
+
211
+/*
212
+ * Changes the AioContext used for fd handlers, timers, and BHs by this
213
+ * BlockDriverState and all its children and parents.
214
+ *
215
+ * Must be called from the main AioContext.
216
+ *
217
+ * The caller must own the AioContext lock for the old AioContext of bs, but it
218
+ * must not own the AioContext lock for new_context (unless new_context is the
219
+ * same as the current context of bs).
220
+ *
221
+ * @visited will accumulate all visited BdrvChild objects. The caller is
222
+ * responsible for freeing the list afterwards.
223
+ */
224
+static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
225
+ GSList **visited, Transaction *tran,
226
+ Error **errp)
227
+{
228
+ BdrvChild *c;
229
+ BdrvStateSetAioContext *state;
230
+
231
+ GLOBAL_STATE_CODE();
232
+
233
+ if (bdrv_get_aio_context(bs) == ctx) {
234
+ return true;
235
+ }
236
+
237
+ QLIST_FOREACH(c, &bs->parents, next_parent) {
238
+ if (!bdrv_parent_change_aio_context(c, ctx, visited, tran, errp)) {
239
+ return false;
240
+ }
241
+ }
242
+
243
+ QLIST_FOREACH(c, &bs->children, next) {
244
+ if (!bdrv_child_change_aio_context(c, ctx, visited, tran, errp)) {
245
+ return false;
246
+ }
247
+ }
248
+
249
+ state = g_new(BdrvStateSetAioContext, 1);
250
+ *state = (BdrvStateSetAioContext) {
251
+ .new_ctx = ctx,
252
+ .bs = bs,
253
+ };
254
+
255
+ /* Paired with bdrv_drained_end in bdrv_set_aio_context_clean() */
256
+ bdrv_drained_begin(bs);
257
+
258
+ tran_add(tran, &set_aio_context, state);
259
+
260
+ return true;
261
+}
262
+
263
int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
264
BdrvChild *ignore_child, Error **errp)
37
{
265
{
38
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
266
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
39
| _filter_qemu | _filter_imgfmt \
267
return 0;
40
- | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g'
41
+ | _filter_actual_image_size
42
}
268
}
43
269
44
size=128M
270
+/*
45
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
271
+ * Change bs's and recursively all of its parents' and children's AioContext
46
index XXXXXXX..XXXXXXX 100644
272
+ * to the given new context, returning an error if that isn't possible.
47
--- a/tests/qemu-iotests/common.filter
273
+ *
48
+++ b/tests/qemu-iotests/common.filter
274
+ * If ignore_child is not NULL, that child (and its subgraph) will not
49
@@ -XXX,XX +XXX,XX @@ _filter_block_job_len()
275
+ * be touched.
50
sed -e 's/, "len": [0-9]\+,/, "len": LEN,/g'
276
+ *
51
}
277
+ * This function still requires the caller to take the bs current
52
278
+ * AioContext lock, otherwise draining will fail since AIO_WAIT_WHILE
53
+# replace actual image size (depends on the host filesystem)
279
+ * assumes the lock is always held if bs is in another AioContext.
54
+_filter_actual_image_size()
280
+ * For the same reason, it temporarily also holds the new AioContext, since
55
+{
281
+ * bdrv_drained_end calls BDRV_POLL_WHILE that assumes the lock is taken too.
56
+ sed -s 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g'
282
+ * Therefore the new AioContext lock must not be taken by the caller.
57
+}
283
+ */
58
+
284
+int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
59
# replace driver-specific options in the "Formatting..." line
285
+ BdrvChild *ignore_child, Error **errp)
60
_filter_img_create()
286
+{
287
+ Transaction *tran;
288
+ GSList *visited;
289
+ int ret;
290
+ AioContext *old_context = bdrv_get_aio_context(bs);
291
+ GLOBAL_STATE_CODE();
292
+
293
+ /*
294
+ * Recursion phase: go through all nodes of the graph.
295
+ * Take care of checking that all nodes support changing AioContext
296
+ * and drain them, builing a linear list of callbacks to run if everything
297
+ * is successful (the transaction itself).
298
+ */
299
+ tran = tran_new();
300
+ visited = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
301
+ ret = bdrv_change_aio_context(bs, ctx, &visited, tran, errp);
302
+ g_slist_free(visited);
303
+
304
+ /*
305
+ * Linear phase: go through all callbacks collected in the transaction.
306
+ * Run all callbacks collected in the recursion to switch all nodes
307
+ * AioContext lock (transaction commit), or undo all changes done in the
308
+ * recursion (transaction abort).
309
+ */
310
+
311
+ if (!ret) {
312
+ /* Just run clean() callbacks. No AioContext changed. */
313
+ tran_abort(tran);
314
+ return -EPERM;
315
+ }
316
+
317
+ /*
318
+ * Release old AioContext, it won't be needed anymore, as all
319
+ * bdrv_drained_begin() have been called already.
320
+ */
321
+ if (qemu_get_aio_context() != old_context) {
322
+ aio_context_release(old_context);
323
+ }
324
+
325
+ /*
326
+ * Acquire new AioContext since bdrv_drained_end() is going to be called
327
+ * after we switched all nodes in the new AioContext, and the function
328
+ * assumes that the lock of the bs is always taken.
329
+ */
330
+ if (qemu_get_aio_context() != ctx) {
331
+ aio_context_acquire(ctx);
332
+ }
333
+
334
+ tran_commit(tran);
335
+
336
+ if (qemu_get_aio_context() != ctx) {
337
+ aio_context_release(ctx);
338
+ }
339
+
340
+ /* Re-acquire the old AioContext, since the caller takes and releases it. */
341
+ if (qemu_get_aio_context() != old_context) {
342
+ aio_context_acquire(old_context);
343
+ }
344
+
345
+ return 0;
346
+}
347
+
348
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
349
Error **errp)
61
{
350
{
62
--
351
--
63
2.13.6
352
2.37.3
64
65
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
Minor performance improvement, but given that we have hash tables
4
available, avoid iterating in the visited nodes list every time just
5
to check if a node has been already visited.
6
7
The data structure is not actually a proper hash map, but an hash set,
8
as we are just adding nodes and not key,value pairs.
9
10
Suggested-by: Hanna Reitz <hreitz@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20221025084952.2139888-4-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
include/block/block-global-state.h | 2 +-
17
include/block/block_int-common.h | 3 ++-
18
block.c | 28 ++++++++++++++++------------
19
3 files changed, 19 insertions(+), 14 deletions(-)
20
21
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block-global-state.h
24
+++ b/include/block/block-global-state.h
25
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
26
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
27
28
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
29
- GSList **visited, Transaction *tran,
30
+ GHashTable *visited, Transaction *tran,
31
Error **errp);
32
int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
33
BdrvChild *ignore_child, Error **errp);
34
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block_int-common.h
37
+++ b/include/block/block_int-common.h
38
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
39
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
40
41
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
42
- GSList **visited, Transaction *tran, Error **errp);
43
+ GHashTable *visited, Transaction *tran,
44
+ Error **errp);
45
46
AioContext *(*get_parent_aio_context)(BdrvChild *child);
47
48
diff --git a/block.c b/block.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block.c
51
+++ b/block.c
52
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
53
static bool bdrv_backing_overridden(BlockDriverState *bs);
54
55
static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
56
- GSList **visited, Transaction *tran,
57
+ GHashTable *visited, Transaction *tran,
58
Error **errp);
59
60
/* If non-zero, use only whitelisted block drivers */
61
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvStateSetAioContext {
62
} BdrvStateSetAioContext;
63
64
static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
65
- GSList **visited, Transaction *tran,
66
+ GHashTable *visited,
67
+ Transaction *tran,
68
Error **errp)
69
{
70
GLOBAL_STATE_CODE();
71
- if (g_slist_find(*visited, c)) {
72
+ if (g_hash_table_contains(visited, c)) {
73
return true;
74
}
75
- *visited = g_slist_prepend(*visited, c);
76
+ g_hash_table_add(visited, c);
77
78
/*
79
* A BdrvChildClass that doesn't handle AioContext changes cannot
80
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
81
}
82
83
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
84
- GSList **visited, Transaction *tran,
85
+ GHashTable *visited, Transaction *tran,
86
Error **errp)
87
{
88
GLOBAL_STATE_CODE();
89
- if (g_slist_find(*visited, c)) {
90
+ if (g_hash_table_contains(visited, c)) {
91
return true;
92
}
93
- *visited = g_slist_prepend(*visited, c);
94
+ g_hash_table_add(visited, c);
95
return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
96
}
97
98
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv set_aio_context = {
99
* responsible for freeing the list afterwards.
100
*/
101
static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
102
- GSList **visited, Transaction *tran,
103
+ GHashTable *visited, Transaction *tran,
104
Error **errp)
105
{
106
BdrvChild *c;
107
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
108
BdrvChild *ignore_child, Error **errp)
109
{
110
Transaction *tran;
111
- GSList *visited;
112
+ GHashTable *visited;
113
int ret;
114
AioContext *old_context = bdrv_get_aio_context(bs);
115
GLOBAL_STATE_CODE();
116
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
117
* is successful (the transaction itself).
118
*/
119
tran = tran_new();
120
- visited = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
121
- ret = bdrv_change_aio_context(bs, ctx, &visited, tran, errp);
122
- g_slist_free(visited);
123
+ visited = g_hash_table_new(NULL, NULL);
124
+ if (ignore_child) {
125
+ g_hash_table_add(visited, ignore_child);
126
+ }
127
+ ret = bdrv_change_aio_context(bs, ctx, visited, tran, errp);
128
+ g_hash_table_destroy(visited);
129
130
/*
131
* Linear phase: go through all callbacks collected in the transaction.
132
--
133
2.37.3
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Some qcow2 functions (at least perform_cow()) expect s->lock to be
3
child_job_change_aio_ctx() is very similar to
4
taken. Therefore, if we want to make use of them, we should execute
4
child_job_can_set_aio_ctx(), but it implements a new transaction
5
preallocate() (as "preallocate_co") in a coroutine so that we can use
5
so that if all check pass, the new transaction's .commit()
6
the qemu_co_mutex_* functions.
6
will take care of changin the BlockJob AioContext.
7
child_job_set_aio_ctx_commit() is similar to child_job_set_aio_ctx(),
8
but it doesn't need to invoke the recursion, as this is already
9
taken care by child_job_change_aio_ctx().
7
10
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Note: bdrv_child_try_change_aio_context() is not called by
9
Message-id: 20171009215533.12530-3-mreitz@redhat.com
12
anyone at this point.
10
Cc: qemu-stable@nongnu.org
13
11
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Message-Id: <20221025084952.2139888-5-eesposit@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
19
---
16
block/qcow2.c | 41 ++++++++++++++++++++++++++++++++++-------
20
blockjob.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
17
1 file changed, 34 insertions(+), 7 deletions(-)
21
1 file changed, 45 insertions(+)
18
22
19
diff --git a/block/qcow2.c b/block/qcow2.c
23
diff --git a/blockjob.c b/blockjob.c
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
25
--- a/blockjob.c
22
+++ b/block/qcow2.c
26
+++ b/blockjob.c
23
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
27
@@ -XXX,XX +XXX,XX @@ static void child_job_drained_end(BdrvChild *c, int *drained_end_counter)
28
job_resume(&job->job);
24
}
29
}
25
30
26
31
+typedef struct BdrvStateChildJobContext {
27
+typedef struct PreallocCo {
32
+ AioContext *new_ctx;
28
+ BlockDriverState *bs;
33
+ BlockJob *job;
29
+ uint64_t offset;
34
+} BdrvStateChildJobContext;
30
+ uint64_t new_length;
31
+
35
+
32
+ int ret;
36
+static void child_job_set_aio_ctx_commit(void *opaque)
33
+} PreallocCo;
37
+{
38
+ BdrvStateChildJobContext *s = opaque;
39
+ BlockJob *job = s->job;
34
+
40
+
35
/**
41
+ job_set_aio_context(&job->job, s->new_ctx);
36
* Preallocates metadata structures for data clusters between @offset (in the
37
* guest disk) and @new_length (which is thus generally the new guest disk
38
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
39
*
40
* Returns: 0 on success, -errno on failure.
41
*/
42
-static int preallocate(BlockDriverState *bs,
43
- uint64_t offset, uint64_t new_length)
44
+static void coroutine_fn preallocate_co(void *opaque)
45
{
46
+ PreallocCo *params = opaque;
47
+ BlockDriverState *bs = params->bs;
48
+ uint64_t offset = params->offset;
49
+ uint64_t new_length = params->new_length;
50
BDRVQcow2State *s = bs->opaque;
51
uint64_t bytes;
52
uint64_t host_offset = 0;
53
@@ -XXX,XX +XXX,XX @@ static int preallocate(BlockDriverState *bs,
54
int ret;
55
QCowL2Meta *meta;
56
57
- if (qemu_in_coroutine()) {
58
- qemu_co_mutex_lock(&s->lock);
59
- }
60
+ qemu_co_mutex_lock(&s->lock);
61
62
assert(offset <= new_length);
63
bytes = new_length - offset;
64
@@ -XXX,XX +XXX,XX @@ static int preallocate(BlockDriverState *bs,
65
ret = 0;
66
67
done:
68
+ qemu_co_mutex_unlock(&s->lock);
69
+ params->ret = ret;
70
+}
42
+}
71
+
43
+
72
+static int preallocate(BlockDriverState *bs,
44
+static TransactionActionDrv change_child_job_context = {
73
+ uint64_t offset, uint64_t new_length)
45
+ .commit = child_job_set_aio_ctx_commit,
46
+ .clean = g_free,
47
+};
48
+
49
+static bool child_job_change_aio_ctx(BdrvChild *c, AioContext *ctx,
50
+ GHashTable *visited, Transaction *tran,
51
+ Error **errp)
74
+{
52
+{
75
+ PreallocCo params = {
53
+ BlockJob *job = c->opaque;
76
+ .bs = bs,
54
+ BdrvStateChildJobContext *s;
77
+ .offset = offset,
55
+ GSList *l;
78
+ .new_length = new_length,
56
+
79
+ .ret = -EINPROGRESS,
57
+ for (l = job->nodes; l; l = l->next) {
58
+ BdrvChild *sibling = l->data;
59
+ if (!bdrv_child_change_aio_context(sibling, ctx, visited,
60
+ tran, errp)) {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ s = g_new(BdrvStateChildJobContext, 1);
66
+ *s = (BdrvStateChildJobContext) {
67
+ .new_ctx = ctx,
68
+ .job = job,
80
+ };
69
+ };
81
+
70
+
82
if (qemu_in_coroutine()) {
71
+ tran_add(tran, &change_child_job_context, s);
83
- qemu_co_mutex_unlock(&s->lock);
72
+ return true;
84
+ preallocate_co(&params);
73
+}
85
+ } else {
74
+
86
+ Coroutine *co = qemu_coroutine_create(preallocate_co, &params);
75
static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
87
+ bdrv_coroutine_enter(bs, co);
76
GSList **ignore, Error **errp)
88
+ BDRV_POLL_WHILE(bs, params.ret == -EINPROGRESS);
77
{
89
}
78
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_job = {
90
- return ret;
79
.drained_end = child_job_drained_end,
91
+ return params.ret;
80
.can_set_aio_ctx = child_job_can_set_aio_ctx,
92
}
81
.set_aio_ctx = child_job_set_aio_ctx,
93
82
+ .change_aio_ctx = child_job_change_aio_ctx,
94
/* qcow2_refcount_metadata_size:
83
.stay_at_node = true,
84
.get_parent_aio_context = child_job_get_parent_aio_context,
85
};
95
--
86
--
96
2.13.6
87
2.37.3
97
98
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
bdrv_child_cb_change_aio_ctx() is identical to
4
bdrv_child_cb_can_set_aio_ctx(), as we only need
5
to recursively go on the parent bs.
6
7
Note: bdrv_child_try_change_aio_context() is not called by
8
anyone at this point.
9
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20221025084952.2139888-6-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block.c | 9 +++++++++
17
1 file changed, 9 insertions(+)
18
19
diff --git a/block.c b/block.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block.c
22
+++ b/block.c
23
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_cb_inactivate(BdrvChild *child)
24
return 0;
25
}
26
27
+static bool bdrv_child_cb_change_aio_ctx(BdrvChild *child, AioContext *ctx,
28
+ GHashTable *visited, Transaction *tran,
29
+ Error **errp)
30
+{
31
+ BlockDriverState *bs = child->opaque;
32
+ return bdrv_change_aio_context(bs, ctx, visited, tran, errp);
33
+}
34
+
35
static bool bdrv_child_cb_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
36
GSList **ignore, Error **errp)
37
{
38
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_of_bds = {
39
.inactivate = bdrv_child_cb_inactivate,
40
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
41
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
42
+ .change_aio_ctx = bdrv_child_cb_change_aio_ctx,
43
.update_filename = bdrv_child_cb_update_filename,
44
.get_parent_aio_context = child_of_bds_get_parent_aio_context,
45
};
46
--
47
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
During 'qemu-img compare', when we are checking that an allocated
3
blk_root_change_aio_ctx() is very similar to blk_root_can_set_aio_ctx(),
4
portion of one file is all zeros, we don't need to waste time
4
but implements a new transaction so that if all check pass, the new
5
computing how many additional sectors after the first non-zero
5
transaction's .commit will take care of changing the BlockBackend
6
byte are also non-zero. Create a new helper find_nonzero() to do
6
AioContext. blk_root_set_aio_ctx_commit() is the same as
7
the check for a first non-zero sector, and rebase
7
blk_root_set_aio_ctx().
8
check_empty_sectors() to use it.
9
8
10
The new interface intentionally uses bytes in its interface, even
9
Note: bdrv_child_try_change_aio_context() is not called by
11
though it still crawls the buffer a sector at a time; it is robust
10
anyone at this point.
12
to a partial sector at the end of the buffer.
13
11
14
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Reviewed-by: John Snow <jsnow@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20221025084952.2139888-7-eesposit@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
16
---
18
qemu-img.c | 32 ++++++++++++++++++++++++++++----
17
block/block-backend.c | 52 +++++++++++++++++++++++++++++++++++++++++++
19
1 file changed, 28 insertions(+), 4 deletions(-)
18
1 file changed, 52 insertions(+)
20
19
21
diff --git a/qemu-img.c b/qemu-img.c
20
diff --git a/block/block-backend.c b/block/block-backend.c
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/qemu-img.c
22
--- a/block/block-backend.c
24
+++ b/qemu-img.c
23
+++ b/block/block-backend.c
25
@@ -XXX,XX +XXX,XX @@ done:
24
@@ -XXX,XX +XXX,XX @@ static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
25
GSList **ignore, Error **errp);
26
static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
27
GSList **ignore);
28
+static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
29
+ GHashTable *visited, Transaction *tran,
30
+ Error **errp);
31
32
static char *blk_root_get_parent_desc(BdrvChild *child)
33
{
34
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_root = {
35
36
.can_set_aio_ctx = blk_root_can_set_aio_ctx,
37
.set_aio_ctx = blk_root_set_aio_ctx,
38
+ .change_aio_ctx = blk_root_change_aio_ctx,
39
40
.get_parent_aio_context = blk_root_get_parent_aio_context,
41
};
42
@@ -XXX,XX +XXX,XX @@ int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
43
return blk_do_set_aio_context(blk, new_context, true, errp);
26
}
44
}
27
45
28
/*
46
+typedef struct BdrvStateBlkRootContext {
29
+ * Returns -1 if 'buf' contains only zeroes, otherwise the byte index
47
+ AioContext *new_ctx;
30
+ * of the first sector boundary within buf where the sector contains a
48
+ BlockBackend *blk;
31
+ * non-zero byte. This function is robust to a buffer that is not
49
+} BdrvStateBlkRootContext;
32
+ * sector-aligned.
50
+
33
+ */
51
+static void blk_root_set_aio_ctx_commit(void *opaque)
34
+static int64_t find_nonzero(const uint8_t *buf, int64_t n)
35
+{
52
+{
36
+ int64_t i;
53
+ BdrvStateBlkRootContext *s = opaque;
37
+ int64_t end = QEMU_ALIGN_DOWN(n, BDRV_SECTOR_SIZE);
54
+ BlockBackend *blk = s->blk;
38
+
55
+
39
+ for (i = 0; i < end; i += BDRV_SECTOR_SIZE) {
56
+ blk_do_set_aio_context(blk, s->new_ctx, false, &error_abort);
40
+ if (!buffer_is_zero(buf + i, BDRV_SECTOR_SIZE)) {
57
+}
41
+ return i;
58
+
59
+static TransactionActionDrv set_blk_root_context = {
60
+ .commit = blk_root_set_aio_ctx_commit,
61
+ .clean = g_free,
62
+};
63
+
64
+static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
65
+ GHashTable *visited, Transaction *tran,
66
+ Error **errp)
67
+{
68
+ BlockBackend *blk = child->opaque;
69
+ BdrvStateBlkRootContext *s;
70
+
71
+ if (!blk->allow_aio_context_change) {
72
+ /*
73
+ * Manually created BlockBackends (those with a name) that are not
74
+ * attached to anything can change their AioContext without updating
75
+ * their user; return an error for others.
76
+ */
77
+ if (!blk->name || blk->dev) {
78
+ /* TODO Add BB name/QOM path */
79
+ error_setg(errp, "Cannot change iothread of active block backend");
80
+ return false;
42
+ }
81
+ }
43
+ }
82
+ }
44
+ if (i < n && !buffer_is_zero(buf + i, n - end)) {
83
+
45
+ return i;
84
+ s = g_new(BdrvStateBlkRootContext, 1);
46
+ }
85
+ *s = (BdrvStateBlkRootContext) {
47
+ return -1;
86
+ .new_ctx = ctx,
87
+ .blk = blk,
88
+ };
89
+
90
+ tran_add(tran, &set_blk_root_context, s);
91
+ return true;
48
+}
92
+}
49
+
93
+
50
+/*
94
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
51
* Returns true iff the first sector pointed to by 'buf' contains at least
95
GSList **ignore, Error **errp)
52
* a non-NUL byte.
53
*
54
@@ -XXX,XX +XXX,XX @@ static int check_empty_sectors(BlockBackend *blk, int64_t sect_num,
55
int sect_count, const char *filename,
56
uint8_t *buffer, bool quiet)
57
{
96
{
58
- int pnum, ret = 0;
59
+ int ret = 0;
60
+ int64_t idx;
61
+
62
ret = blk_pread(blk, sect_num << BDRV_SECTOR_BITS, buffer,
63
sect_count << BDRV_SECTOR_BITS);
64
if (ret < 0) {
65
@@ -XXX,XX +XXX,XX @@ static int check_empty_sectors(BlockBackend *blk, int64_t sect_num,
66
sectors_to_bytes(sect_num), filename, strerror(-ret));
67
return ret;
68
}
69
- ret = is_allocated_sectors(buffer, sect_count, &pnum);
70
- if (ret || pnum != sect_count) {
71
+ idx = find_nonzero(buffer, sect_count * BDRV_SECTOR_SIZE);
72
+ if (idx >= 0) {
73
qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
74
- sectors_to_bytes(ret ? sect_num : sect_num + pnum));
75
+ sectors_to_bytes(sect_num) + idx);
76
return 1;
77
}
78
79
--
97
--
80
2.13.6
98
2.37.3
81
82
diff view generated by jsdifflib
1
From: Peter Krempa <pkrempa@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
When referring to a backing file of an image via node name
3
Replace all direct usage of ->can_set_aio_ctx and ->set_aio_ctx,
4
bdrv_open_backing_file would add the 'driver' option to the option list
4
and call bdrv_child_try_change_aio_context() in
5
filling it with the backing format driver. This breaks construction of
5
bdrv_try_set_aio_context(), the main function called through
6
the backing chain via -blockdev, as bdrv_open_inherit reports an error
6
the whole block layer.
7
if both 'reference' and 'options' are provided.
8
7
9
$ qemu-img create -f raw /tmp/backing.raw 64M
8
From this point onwards, ->can_set_aio_ctx and ->set_aio_ctx
10
$ qemu-img create -f qcow2 -F raw -b /tmp/backing.raw /tmp/test.qcow2
9
won't be used anymore.
11
$ qemu-system-x86_64 \
12
-blockdev driver=file,filename=/tmp/backing.raw,node-name=backing \
13
-blockdev driver=qcow2,file.driver=file,file.filename=/tmp/test.qcow2,node-name=root,backing=backing
14
qemu-system-x86_64: -blockdev driver=qcow2,file.driver=file,file.filename=/tmp/test.qcow2,node-name=root,backing=backing: Could not open backing file: Cannot reference an existing block device with additional options or a new filename
15
10
16
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20221025084952.2139888-8-eesposit@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
15
---
19
block.c | 3 ++-
16
block.c | 44 ++++++++++++++++++++++++-------------------
20
1 file changed, 2 insertions(+), 1 deletion(-)
17
block/block-backend.c | 8 ++++++--
18
2 files changed, 31 insertions(+), 21 deletions(-)
21
19
22
diff --git a/block.c b/block.c
20
diff --git a/block.c b/block.c
23
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
24
--- a/block.c
22
--- a/block.c
25
+++ b/block.c
23
+++ b/block.c
26
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
24
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
27
goto free_exit;
28
}
25
}
29
26
30
- if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
27
if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
31
+ if (!reference &&
28
- GSList *ignore;
32
+ bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
29
+ Transaction *tran;
33
qdict_put_str(options, "driver", bs->backing_format);
30
+ GHashTable *visited;
31
+ bool ret;
32
33
- /* No need to ignore `child`, because it has been detached already */
34
- ignore = NULL;
35
- s->child->klass->can_set_aio_ctx(s->child, s->old_parent_ctx, &ignore,
36
- &error_abort);
37
- g_slist_free(ignore);
38
+ tran = tran_new();
39
40
- ignore = NULL;
41
- s->child->klass->set_aio_ctx(s->child, s->old_parent_ctx, &ignore);
42
- g_slist_free(ignore);
43
+ /* No need to visit `child`, because it has been detached already */
44
+ visited = g_hash_table_new(NULL, NULL);
45
+ ret = s->child->klass->change_aio_ctx(s->child, s->old_parent_ctx,
46
+ visited, tran, &error_abort);
47
+ g_hash_table_destroy(visited);
48
+
49
+ /* transaction is supposed to always succeed */
50
+ assert(ret == true);
51
+ tran_commit(tran);
34
}
52
}
35
53
54
bdrv_unref(bs);
55
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
56
Error *local_err = NULL;
57
int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
58
59
- if (ret < 0 && child_class->can_set_aio_ctx) {
60
- GSList *ignore = g_slist_prepend(NULL, new_child);
61
- if (child_class->can_set_aio_ctx(new_child, child_ctx, &ignore,
62
- NULL))
63
- {
64
+ if (ret < 0 && child_class->change_aio_ctx) {
65
+ Transaction *tran = tran_new();
66
+ GHashTable *visited = g_hash_table_new(NULL, NULL);
67
+ bool ret_child;
68
+
69
+ g_hash_table_add(visited, new_child);
70
+ ret_child = child_class->change_aio_ctx(new_child, child_ctx,
71
+ visited, tran, NULL);
72
+ if (ret_child == true) {
73
error_free(local_err);
74
ret = 0;
75
- g_slist_free(ignore);
76
- ignore = g_slist_prepend(NULL, new_child);
77
- child_class->set_aio_ctx(new_child, child_ctx, &ignore);
78
}
79
- g_slist_free(ignore);
80
+ tran_finalize(tran, ret_child == true ? 0 : -1);
81
+ g_hash_table_destroy(visited);
82
}
83
84
if (ret < 0) {
85
@@ -XXX,XX +XXX,XX @@ int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
86
Error **errp)
87
{
88
GLOBAL_STATE_CODE();
89
- return bdrv_child_try_set_aio_context(bs, ctx, NULL, errp);
90
+ return bdrv_child_try_change_aio_context(bs, ctx, NULL, errp);
91
}
92
93
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
94
diff --git a/block/block-backend.c b/block/block-backend.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/block-backend.c
97
+++ b/block/block-backend.c
98
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
99
bdrv_ref(bs);
100
101
if (update_root_node) {
102
- ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
103
- errp);
104
+ /*
105
+ * update_root_node MUST be false for blk_root_set_aio_ctx_commit(),
106
+ * as we are already in the commit function of a transaction.
107
+ */
108
+ ret = bdrv_child_try_change_aio_context(bs, new_context, blk->root,
109
+ errp);
110
if (ret < 0) {
111
bdrv_unref(bs);
112
return ret;
36
--
113
--
37
2.13.6
114
2.37.3
38
39
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
Together with all _can_set_ and _set_ APIs, as they are not needed
4
anymore.
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20221025084952.2139888-9-eesposit@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-global-state.h | 9 --
12
include/block/block_int-common.h | 4 -
13
block.c | 196 -----------------------------
14
block/block-backend.c | 33 -----
15
blockjob.c | 35 ------
16
5 files changed, 277 deletions(-)
17
18
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/block-global-state.h
21
+++ b/include/block/block-global-state.h
22
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
23
*/
24
void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
25
26
-void bdrv_set_aio_context_ignore(BlockDriverState *bs,
27
- AioContext *new_context, GSList **ignore);
28
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
29
Error **errp);
30
-int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
31
- BdrvChild *ignore_child, Error **errp);
32
-bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
33
- GSList **ignore, Error **errp);
34
-bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
35
- GSList **ignore, Error **errp);
36
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
37
-
38
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
39
GHashTable *visited, Transaction *tran,
40
Error **errp);
41
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/block/block_int-common.h
44
+++ b/include/block/block_int-common.h
45
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
46
int (*update_filename)(BdrvChild *child, BlockDriverState *new_base,
47
const char *filename, Error **errp);
48
49
- bool (*can_set_aio_ctx)(BdrvChild *child, AioContext *ctx,
50
- GSList **ignore, Error **errp);
51
- void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
52
-
53
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
54
GHashTable *visited, Transaction *tran,
55
Error **errp);
56
diff --git a/block.c b/block.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block.c
59
+++ b/block.c
60
@@ -XXX,XX +XXX,XX @@ static bool bdrv_child_cb_change_aio_ctx(BdrvChild *child, AioContext *ctx,
61
return bdrv_change_aio_context(bs, ctx, visited, tran, errp);
62
}
63
64
-static bool bdrv_child_cb_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
65
- GSList **ignore, Error **errp)
66
-{
67
- BlockDriverState *bs = child->opaque;
68
- return bdrv_can_set_aio_context(bs, ctx, ignore, errp);
69
-}
70
-
71
-static void bdrv_child_cb_set_aio_ctx(BdrvChild *child, AioContext *ctx,
72
- GSList **ignore)
73
-{
74
- BlockDriverState *bs = child->opaque;
75
- return bdrv_set_aio_context_ignore(bs, ctx, ignore);
76
-}
77
-
78
/*
79
* Returns the options and flags that a temporary snapshot should get, based on
80
* the originally requested flags (the originally requested image will have
81
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_of_bds = {
82
.attach = bdrv_child_cb_attach,
83
.detach = bdrv_child_cb_detach,
84
.inactivate = bdrv_child_cb_inactivate,
85
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
86
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
87
.change_aio_ctx = bdrv_child_cb_change_aio_ctx,
88
.update_filename = bdrv_child_cb_update_filename,
89
.get_parent_aio_context = child_of_bds_get_parent_aio_context,
90
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
91
bs->walking_aio_notifiers = false;
92
}
93
94
-/*
95
- * Changes the AioContext used for fd handlers, timers, and BHs by this
96
- * BlockDriverState and all its children and parents.
97
- *
98
- * Must be called from the main AioContext.
99
- *
100
- * The caller must own the AioContext lock for the old AioContext of bs, but it
101
- * must not own the AioContext lock for new_context (unless new_context is the
102
- * same as the current context of bs).
103
- *
104
- * @ignore will accumulate all visited BdrvChild objects. The caller is
105
- * responsible for freeing the list afterwards.
106
- */
107
-void bdrv_set_aio_context_ignore(BlockDriverState *bs,
108
- AioContext *new_context, GSList **ignore)
109
-{
110
- AioContext *old_context = bdrv_get_aio_context(bs);
111
- GSList *children_to_process = NULL;
112
- GSList *parents_to_process = NULL;
113
- GSList *entry;
114
- BdrvChild *child, *parent;
115
-
116
- g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
117
- GLOBAL_STATE_CODE();
118
-
119
- if (old_context == new_context) {
120
- return;
121
- }
122
-
123
- bdrv_drained_begin(bs);
124
-
125
- QLIST_FOREACH(child, &bs->children, next) {
126
- if (g_slist_find(*ignore, child)) {
127
- continue;
128
- }
129
- *ignore = g_slist_prepend(*ignore, child);
130
- children_to_process = g_slist_prepend(children_to_process, child);
131
- }
132
-
133
- QLIST_FOREACH(parent, &bs->parents, next_parent) {
134
- if (g_slist_find(*ignore, parent)) {
135
- continue;
136
- }
137
- *ignore = g_slist_prepend(*ignore, parent);
138
- parents_to_process = g_slist_prepend(parents_to_process, parent);
139
- }
140
-
141
- for (entry = children_to_process;
142
- entry != NULL;
143
- entry = g_slist_next(entry)) {
144
- child = entry->data;
145
- bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
146
- }
147
- g_slist_free(children_to_process);
148
-
149
- for (entry = parents_to_process;
150
- entry != NULL;
151
- entry = g_slist_next(entry)) {
152
- parent = entry->data;
153
- assert(parent->klass->set_aio_ctx);
154
- parent->klass->set_aio_ctx(parent, new_context, ignore);
155
- }
156
- g_slist_free(parents_to_process);
157
-
158
- bdrv_detach_aio_context(bs);
159
-
160
- /* Acquire the new context, if necessary */
161
- if (qemu_get_aio_context() != new_context) {
162
- aio_context_acquire(new_context);
163
- }
164
-
165
- bdrv_attach_aio_context(bs, new_context);
166
-
167
- /*
168
- * If this function was recursively called from
169
- * bdrv_set_aio_context_ignore(), there may be nodes in the
170
- * subtree that have not yet been moved to the new AioContext.
171
- * Release the old one so bdrv_drained_end() can poll them.
172
- */
173
- if (qemu_get_aio_context() != old_context) {
174
- aio_context_release(old_context);
175
- }
176
-
177
- bdrv_drained_end(bs);
178
-
179
- if (qemu_get_aio_context() != old_context) {
180
- aio_context_acquire(old_context);
181
- }
182
- if (qemu_get_aio_context() != new_context) {
183
- aio_context_release(new_context);
184
- }
185
-}
186
-
187
-static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
188
- GSList **ignore, Error **errp)
189
-{
190
- GLOBAL_STATE_CODE();
191
- if (g_slist_find(*ignore, c)) {
192
- return true;
193
- }
194
- *ignore = g_slist_prepend(*ignore, c);
195
-
196
- /*
197
- * A BdrvChildClass that doesn't handle AioContext changes cannot
198
- * tolerate any AioContext changes
199
- */
200
- if (!c->klass->can_set_aio_ctx) {
201
- char *user = bdrv_child_user_desc(c);
202
- error_setg(errp, "Changing iothreads is not supported by %s", user);
203
- g_free(user);
204
- return false;
205
- }
206
- if (!c->klass->can_set_aio_ctx(c, ctx, ignore, errp)) {
207
- assert(!errp || *errp);
208
- return false;
209
- }
210
- return true;
211
-}
212
-
213
typedef struct BdrvStateSetAioContext {
214
AioContext *new_ctx;
215
BlockDriverState *bs;
216
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
217
return true;
218
}
219
220
-bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
221
- GSList **ignore, Error **errp)
222
-{
223
- GLOBAL_STATE_CODE();
224
- if (g_slist_find(*ignore, c)) {
225
- return true;
226
- }
227
- *ignore = g_slist_prepend(*ignore, c);
228
- return bdrv_can_set_aio_context(c->bs, ctx, ignore, errp);
229
-}
230
-
231
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
232
GHashTable *visited, Transaction *tran,
233
Error **errp)
234
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
235
return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
236
}
237
238
-/* @ignore will accumulate all visited BdrvChild object. The caller is
239
- * responsible for freeing the list afterwards. */
240
-bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
241
- GSList **ignore, Error **errp)
242
-{
243
- BdrvChild *c;
244
-
245
- if (bdrv_get_aio_context(bs) == ctx) {
246
- return true;
247
- }
248
-
249
- GLOBAL_STATE_CODE();
250
-
251
- QLIST_FOREACH(c, &bs->parents, next_parent) {
252
- if (!bdrv_parent_can_set_aio_context(c, ctx, ignore, errp)) {
253
- return false;
254
- }
255
- }
256
- QLIST_FOREACH(c, &bs->children, next) {
257
- if (!bdrv_child_can_set_aio_context(c, ctx, ignore, errp)) {
258
- return false;
259
- }
260
- }
261
-
262
- return true;
263
-}
264
-
265
static void bdrv_set_aio_context_clean(void *opaque)
266
{
267
BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
268
@@ -XXX,XX +XXX,XX @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
269
return true;
270
}
271
272
-int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
273
- BdrvChild *ignore_child, Error **errp)
274
-{
275
- GSList *ignore;
276
- bool ret;
277
-
278
- GLOBAL_STATE_CODE();
279
-
280
- ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
281
- ret = bdrv_can_set_aio_context(bs, ctx, &ignore, errp);
282
- g_slist_free(ignore);
283
-
284
- if (!ret) {
285
- return -EPERM;
286
- }
287
-
288
- ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
289
- bdrv_set_aio_context_ignore(bs, ctx, &ignore);
290
- g_slist_free(ignore);
291
-
292
- return 0;
293
-}
294
-
295
/*
296
* Change bs's and recursively all of its parents' and children's AioContext
297
* to the given new context, returning an error if that isn't possible.
298
diff --git a/block/block-backend.c b/block/block-backend.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/block/block-backend.c
301
+++ b/block/block-backend.c
302
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter);
303
static void blk_root_change_media(BdrvChild *child, bool load);
304
static void blk_root_resize(BdrvChild *child);
305
306
-static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
307
- GSList **ignore, Error **errp);
308
-static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
309
- GSList **ignore);
310
static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
311
GHashTable *visited, Transaction *tran,
312
Error **errp);
313
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_root = {
314
.attach = blk_root_attach,
315
.detach = blk_root_detach,
316
317
- .can_set_aio_ctx = blk_root_can_set_aio_ctx,
318
- .set_aio_ctx = blk_root_set_aio_ctx,
319
.change_aio_ctx = blk_root_change_aio_ctx,
320
321
.get_parent_aio_context = blk_root_get_parent_aio_context,
322
@@ -XXX,XX +XXX,XX @@ static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
323
return true;
324
}
325
326
-static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
327
- GSList **ignore, Error **errp)
328
-{
329
- BlockBackend *blk = child->opaque;
330
-
331
- if (blk->allow_aio_context_change) {
332
- return true;
333
- }
334
-
335
- /* Only manually created BlockBackends that are not attached to anything
336
- * can change their AioContext without updating their user. */
337
- if (!blk->name || blk->dev) {
338
- /* TODO Add BB name/QOM path */
339
- error_setg(errp, "Cannot change iothread of active block backend");
340
- return false;
341
- }
342
-
343
- return true;
344
-}
345
-
346
-static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
347
- GSList **ignore)
348
-{
349
- BlockBackend *blk = child->opaque;
350
- blk_do_set_aio_context(blk, ctx, false, &error_abort);
351
-}
352
-
353
void blk_add_aio_context_notifier(BlockBackend *blk,
354
void (*attached_aio_context)(AioContext *new_context, void *opaque),
355
void (*detach_aio_context)(void *opaque), void *opaque)
356
diff --git a/blockjob.c b/blockjob.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/blockjob.c
359
+++ b/blockjob.c
360
@@ -XXX,XX +XXX,XX @@ static bool child_job_change_aio_ctx(BdrvChild *c, AioContext *ctx,
361
return true;
362
}
363
364
-static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
365
- GSList **ignore, Error **errp)
366
-{
367
- BlockJob *job = c->opaque;
368
- GSList *l;
369
-
370
- for (l = job->nodes; l; l = l->next) {
371
- BdrvChild *sibling = l->data;
372
- if (!bdrv_child_can_set_aio_context(sibling, ctx, ignore, errp)) {
373
- return false;
374
- }
375
- }
376
- return true;
377
-}
378
-
379
-static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
380
- GSList **ignore)
381
-{
382
- BlockJob *job = c->opaque;
383
- GSList *l;
384
-
385
- for (l = job->nodes; l; l = l->next) {
386
- BdrvChild *sibling = l->data;
387
- if (g_slist_find(*ignore, sibling)) {
388
- continue;
389
- }
390
- *ignore = g_slist_prepend(*ignore, sibling);
391
- bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
392
- }
393
-
394
- job_set_aio_context(&job->job, ctx);
395
-}
396
-
397
static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
398
{
399
BlockJob *job = c->opaque;
400
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_job = {
401
.drained_begin = child_job_drained_begin,
402
.drained_poll = child_job_drained_poll,
403
.drained_end = child_job_drained_end,
404
- .can_set_aio_ctx = child_job_can_set_aio_ctx,
405
- .set_aio_ctx = child_job_set_aio_ctx,
406
.change_aio_ctx = child_job_change_aio_ctx,
407
.stay_at_node = true,
408
.get_parent_aio_context = child_job_get_parent_aio_context,
409
--
410
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
No functional changes intended.
4
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Message-Id: <20221025084952.2139888-10-eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block-global-state.h | 4 ++--
11
block.c | 6 +++---
12
block/block-backend.c | 3 +--
13
3 files changed, 6 insertions(+), 7 deletions(-)
14
15
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/block-global-state.h
18
+++ b/include/block/block-global-state.h
19
@@ -XXX,XX +XXX,XX @@ AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
20
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
21
GHashTable *visited, Transaction *tran,
22
Error **errp);
23
-int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
24
- BdrvChild *ignore_child, Error **errp);
25
+int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
26
+ BdrvChild *ignore_child, Error **errp);
27
28
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
29
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
30
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
33
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
35
* bdrv_drained_end calls BDRV_POLL_WHILE that assumes the lock is taken too.
36
* Therefore the new AioContext lock must not be taken by the caller.
37
*/
38
-int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
39
- BdrvChild *ignore_child, Error **errp)
40
+int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
41
+ BdrvChild *ignore_child, Error **errp)
42
{
43
Transaction *tran;
44
GHashTable *visited;
45
@@ -XXX,XX +XXX,XX @@ int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
46
Error **errp)
47
{
48
GLOBAL_STATE_CODE();
49
- return bdrv_child_try_change_aio_context(bs, ctx, NULL, errp);
50
+ return bdrv_try_change_aio_context(bs, ctx, NULL, errp);
51
}
52
53
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
54
diff --git a/block/block-backend.c b/block/block-backend.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block/block-backend.c
57
+++ b/block/block-backend.c
58
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
59
* update_root_node MUST be false for blk_root_set_aio_ctx_commit(),
60
* as we are already in the commit function of a transaction.
61
*/
62
- ret = bdrv_child_try_change_aio_context(bs, new_context, blk->root,
63
- errp);
64
+ ret = bdrv_try_change_aio_context(bs, new_context, blk->root, errp);
65
if (ret < 0) {
66
bdrv_unref(bs);
67
return ret;
68
--
69
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
As long as we are querying the status for a chunk smaller than
3
No functional change intended.
4
the known image size, we are guaranteed that a successful return
5
will have set pnum to a non-zero size (pnum is zero only for
6
queries beyond the end of the file). Use that to slightly
7
simplify the calculation of the current chunk size being compared.
8
Likewise, we don't have to shrink the amount of data operated on
9
until we know we have to read the file, and therefore have to fit
10
in the bounds of our buffer. Also, note that 'total_sectors_over'
11
is equivalent to 'progress_base'.
12
4
13
With these changes in place, sectors_to_process() is now dead code,
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
and can be removed.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
7
Message-Id: <20221025084952.2139888-11-eesposit@redhat.com>
16
Signed-off-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
9
---
19
qemu-img.c | 38 +++++++++++---------------------------
10
docs/devel/multiple-iothreads.txt | 4 ++--
20
1 file changed, 11 insertions(+), 27 deletions(-)
11
include/block/block-global-state.h | 2 --
12
block.c | 14 ++++----------
13
block/export/export.c | 2 +-
14
blockdev.c | 22 +++++++++++-----------
15
job.c | 2 +-
16
tests/unit/test-bdrv-drain.c | 6 +++---
17
tests/unit/test-block-iothread.c | 10 +++++-----
18
8 files changed, 27 insertions(+), 35 deletions(-)
21
19
22
diff --git a/qemu-img.c b/qemu-img.c
20
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
23
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
24
--- a/qemu-img.c
22
--- a/docs/devel/multiple-iothreads.txt
25
+++ b/qemu-img.c
23
+++ b/docs/devel/multiple-iothreads.txt
26
@@ -XXX,XX +XXX,XX @@ static int64_t sectors_to_bytes(int64_t sectors)
24
@@ -XXX,XX +XXX,XX @@ The AioContext originates from the QEMU block layer, even though nowadays
27
return sectors << BDRV_SECTOR_BITS;
25
AioContext is a generic event loop that can be used by any QEMU subsystem.
26
27
The block layer has support for AioContext integrated. Each BlockDriverState
28
-is associated with an AioContext using bdrv_try_set_aio_context() and
29
+is associated with an AioContext using bdrv_try_change_aio_context() and
30
bdrv_get_aio_context(). This allows block layer code to process I/O inside the
31
right AioContext. Other subsystems may wish to follow a similar approach.
32
33
@@ -XXX,XX +XXX,XX @@ Long-running jobs (usually in the form of coroutines) are best scheduled in
34
the BlockDriverState's AioContext to avoid the need to acquire/release around
35
each bdrv_*() call. The functions bdrv_add/remove_aio_context_notifier,
36
or alternatively blk_add/remove_aio_context_notifier if you use BlockBackends,
37
-can be used to get a notification whenever bdrv_try_set_aio_context() moves a
38
+can be used to get a notification whenever bdrv_try_change_aio_context() moves a
39
BlockDriverState to a different AioContext.
40
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block-global-state.h
43
+++ b/include/block/block-global-state.h
44
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
45
*/
46
void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
47
48
-int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
49
- Error **errp);
50
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
51
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
52
GHashTable *visited, Transaction *tran,
53
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
56
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
58
bdrv_replace_child_noperm(s->child, NULL);
59
60
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
61
- bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
62
+ bdrv_try_change_aio_context(bs, s->old_child_ctx, NULL, &error_abort);
63
}
64
65
if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
66
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
67
parent_ctx = bdrv_child_get_parent_aio_context(new_child);
68
if (child_ctx != parent_ctx) {
69
Error *local_err = NULL;
70
- int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
71
+ int ret = bdrv_try_change_aio_context(child_bs, parent_ctx, NULL,
72
+ &local_err);
73
74
if (ret < 0 && child_class->change_aio_ctx) {
75
Transaction *tran = tran_new();
76
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild *child)
77
* When the parent requiring a non-default AioContext is removed, the
78
* node moves back to the main AioContext
79
*/
80
- bdrv_try_set_aio_context(old_bs, qemu_get_aio_context(), NULL);
81
+ bdrv_try_change_aio_context(old_bs, qemu_get_aio_context(), NULL, NULL);
82
}
28
}
83
}
29
84
30
-static int64_t sectors_to_process(int64_t total, int64_t from)
85
@@ -XXX,XX +XXX,XX @@ int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
86
return 0;
87
}
88
89
-int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
90
- Error **errp)
31
-{
91
-{
32
- return MIN(total - from, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
92
- GLOBAL_STATE_CODE();
93
- return bdrv_try_change_aio_context(bs, ctx, NULL, errp);
33
-}
94
-}
34
-
95
-
35
/*
96
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
36
* Check if passed sectors are empty (not allocated or contain only 0 bytes)
97
void (*attached_aio_context)(AioContext *new_context, void *opaque),
37
*
98
void (*detach_aio_context)(void *opaque), void *opaque)
38
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
99
diff --git a/block/export/export.c b/block/export/export.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/export/export.c
102
+++ b/block/export/export.c
103
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
104
105
/* Ignore errors with fixed-iothread=false */
106
set_context_errp = fixed_iothread ? errp : NULL;
107
- ret = bdrv_try_set_aio_context(bs, new_ctx, set_context_errp);
108
+ ret = bdrv_try_change_aio_context(bs, new_ctx, NULL, set_context_errp);
109
if (ret == 0) {
110
aio_context_release(ctx);
111
aio_context_acquire(new_ctx);
112
diff --git a/blockdev.c b/blockdev.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/blockdev.c
115
+++ b/blockdev.c
116
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
117
aio_context_release(aio_context);
118
aio_context_acquire(tmp_context);
119
120
- ret = bdrv_try_set_aio_context(state->old_bs,
121
- aio_context, NULL);
122
+ ret = bdrv_try_change_aio_context(state->old_bs,
123
+ aio_context, NULL, NULL);
124
assert(ret == 0);
125
126
aio_context_release(tmp_context);
127
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
39
goto out;
128
goto out;
40
}
129
}
41
130
42
- for (;;) {
131
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
43
+ while (sector_num < total_sectors) {
132
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
44
int status1, status2;
133
old_context = bdrv_get_aio_context(target_bs);
45
134
aio_context_release(aio_context);
46
- nb_sectors = sectors_to_process(total_sectors, sector_num);
135
aio_context_acquire(old_context);
47
- if (nb_sectors <= 0) {
136
48
- break;
137
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
49
- }
138
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
50
status1 = bdrv_block_status_above(bs1, NULL,
139
if (ret < 0) {
51
sector_num * BDRV_SECTOR_SIZE,
140
bdrv_unref(target_bs);
52
(total_sectors1 - sector_num) *
141
aio_context_release(old_context);
53
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
142
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
54
/* TODO: Relax this once comparison is byte-based, and we no longer
143
return;
55
* have to worry about sector alignment */
144
}
56
assert(QEMU_IS_ALIGNED(pnum1 | pnum2, BDRV_SECTOR_SIZE));
145
57
- if (pnum1) {
146
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
58
- nb_sectors = MIN(nb_sectors, pnum1 >> BDRV_SECTOR_BITS);
147
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
59
- }
148
aio_context = bdrv_get_aio_context(bs);
60
- if (pnum2) {
149
old_context = bdrv_get_aio_context(target_bs);
61
- nb_sectors = MIN(nb_sectors, pnum2 >> BDRV_SECTOR_BITS);
150
aio_context_acquire(old_context);
62
- }
151
63
+
152
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
64
+ assert(pnum1 && pnum2);
153
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
65
+ nb_sectors = MIN(pnum1, pnum2) >> BDRV_SECTOR_BITS;
154
if (ret < 0) {
66
155
aio_context_release(old_context);
67
if (strict) {
156
return;
68
if (status1 != status2) {
157
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
69
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
158
!bdrv_has_zero_init(target_bs)));
70
}
159
71
}
160
72
if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) {
161
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
73
- nb_sectors = DIV_ROUND_UP(MIN(pnum1, pnum2), BDRV_SECTOR_SIZE);
162
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
74
+ /* nothing to do */
163
old_context = bdrv_get_aio_context(target_bs);
75
} else if (allocated1 == allocated2) {
164
aio_context_release(aio_context);
76
if (allocated1) {
165
aio_context_acquire(old_context);
77
+ nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
166
78
ret = blk_pread(blk1, sector_num << BDRV_SECTOR_BITS, buf1,
167
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
79
nb_sectors << BDRV_SECTOR_BITS);
168
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
80
if (ret < 0) {
169
if (ret < 0) {
81
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
170
bdrv_unref(target_bs);
82
}
171
aio_context_release(old_context);
83
}
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
84
} else {
173
85
-
174
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
86
+ nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
175
87
if (allocated1) {
176
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
88
ret = check_empty_sectors(blk1, sector_num, nb_sectors,
177
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
89
filename1, buf1, quiet);
178
old_context = bdrv_get_aio_context(target_bs);
90
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
179
aio_context = bdrv_get_aio_context(bs);
91
180
aio_context_acquire(old_context);
92
if (total_sectors1 != total_sectors2) {
181
93
BlockBackend *blk_over;
182
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
94
- int64_t total_sectors_over;
183
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
95
const char *filename_over;
184
96
185
aio_context_release(old_context);
97
qprintf(quiet, "Warning: Image size mismatch!\n");
186
aio_context_acquire(aio_context);
98
if (total_sectors1 > total_sectors2) {
187
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
99
- total_sectors_over = total_sectors1;
188
old_context = bdrv_get_aio_context(bs);
100
blk_over = blk1;
189
aio_context_acquire(old_context);
101
filename_over = filename1;
190
102
} else {
191
- bdrv_try_set_aio_context(bs, new_context, errp);
103
- total_sectors_over = total_sectors2;
192
+ bdrv_try_change_aio_context(bs, new_context, NULL, errp);
104
blk_over = blk2;
193
105
filename_over = filename2;
194
aio_context_release(old_context);
106
}
195
}
107
196
diff --git a/job.c b/job.c
108
- for (;;) {
197
index XXXXXXX..XXXXXXX 100644
109
+ while (sector_num < progress_base) {
198
--- a/job.c
110
int64_t count;
199
+++ b/job.c
111
200
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
112
- nb_sectors = sectors_to_process(total_sectors_over, sector_num);
201
next_aio_context = job->aio_context;
113
- if (nb_sectors <= 0) {
202
/*
114
- break;
203
* Coroutine has resumed, but in the meanwhile the job AioContext
115
- }
204
- * might have changed via bdrv_try_set_aio_context(), so we need to move
116
ret = bdrv_is_allocated_above(blk_bs(blk_over), NULL,
205
+ * might have changed via bdrv_try_change_aio_context(), so we need to move
117
sector_num * BDRV_SECTOR_SIZE,
206
* the coroutine too in the new aiocontext.
118
- nb_sectors * BDRV_SECTOR_SIZE,
207
*/
119
+ (progress_base - sector_num) *
208
while (qemu_get_current_aio_context() != next_aio_context) {
120
+ BDRV_SECTOR_SIZE,
209
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
121
&count);
210
index XXXXXXX..XXXXXXX 100644
122
if (ret < 0) {
211
--- a/tests/unit/test-bdrv-drain.c
123
ret = 3;
212
+++ b/tests/unit/test-bdrv-drain.c
124
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
213
@@ -XXX,XX +XXX,XX @@ static void test_set_aio_context(void)
125
assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
214
&error_abort);
126
nb_sectors = count >> BDRV_SECTOR_BITS;
215
127
if (ret) {
216
bdrv_drained_begin(bs);
128
+ nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
217
- bdrv_try_set_aio_context(bs, ctx_a, &error_abort);
129
ret = check_empty_sectors(blk_over, sector_num, nb_sectors,
218
+ bdrv_try_change_aio_context(bs, ctx_a, NULL, &error_abort);
130
filename_over, buf1, quiet);
219
131
if (ret) {
220
aio_context_acquire(ctx_a);
221
bdrv_drained_end(bs);
222
223
bdrv_drained_begin(bs);
224
- bdrv_try_set_aio_context(bs, ctx_b, &error_abort);
225
+ bdrv_try_change_aio_context(bs, ctx_b, NULL, &error_abort);
226
aio_context_release(ctx_a);
227
aio_context_acquire(ctx_b);
228
- bdrv_try_set_aio_context(bs, qemu_get_aio_context(), &error_abort);
229
+ bdrv_try_change_aio_context(bs, qemu_get_aio_context(), NULL, &error_abort);
230
aio_context_release(ctx_b);
231
bdrv_drained_end(bs);
232
233
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/tests/unit/test-block-iothread.c
236
+++ b/tests/unit/test-block-iothread.c
237
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
238
filter = bdrv_find_node("filter_node");
239
240
/* Change the AioContext of src */
241
- bdrv_try_set_aio_context(src, ctx, &error_abort);
242
+ bdrv_try_change_aio_context(src, ctx, NULL, &error_abort);
243
g_assert(bdrv_get_aio_context(src) == ctx);
244
g_assert(bdrv_get_aio_context(target) == ctx);
245
g_assert(bdrv_get_aio_context(filter) == ctx);
246
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
247
248
/* Change the AioContext of target */
249
aio_context_acquire(ctx);
250
- bdrv_try_set_aio_context(target, main_ctx, &error_abort);
251
+ bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
252
aio_context_release(ctx);
253
g_assert(bdrv_get_aio_context(src) == main_ctx);
254
g_assert(bdrv_get_aio_context(target) == main_ctx);
255
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
256
blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
257
blk_insert_bs(blk, src, &error_abort);
258
259
- bdrv_try_set_aio_context(target, ctx, &local_err);
260
+ bdrv_try_change_aio_context(target, ctx, NULL, &local_err);
261
error_free_or_abort(&local_err);
262
263
g_assert(blk_get_aio_context(blk) == main_ctx);
264
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
265
/* ...unless we explicitly allow it */
266
aio_context_acquire(ctx);
267
blk_set_allow_aio_context_change(blk, true);
268
- bdrv_try_set_aio_context(target, ctx, &error_abort);
269
+ bdrv_try_change_aio_context(target, ctx, NULL, &error_abort);
270
aio_context_release(ctx);
271
272
g_assert(blk_get_aio_context(blk) == ctx);
273
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
274
275
aio_context_acquire(ctx);
276
blk_set_aio_context(blk, main_ctx, &error_abort);
277
- bdrv_try_set_aio_context(target, main_ctx, &error_abort);
278
+ bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
279
aio_context_release(ctx);
280
281
blk_unref(blk);
132
--
282
--
133
2.13.6
283
2.37.3
134
135
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bin.meng@windriver.com>
1
2
3
libnfs.h declares nfs_fstat() as the following for win32:
4
5
int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh,
6
struct __stat64 *st);
7
8
The 'st' parameter should be of type 'struct __stat64'. The
9
codes happen to build successfully for 64-bit Windows, but it
10
does not build for 32-bit Windows.
11
12
Fixes: 6542aa9c75bc ("block: add native support for NFS")
13
Fixes: 18a8056e0bc7 ("block/nfs: cache allocated filesize for read-only files")
14
Signed-off-by: Bin Meng <bin.meng@windriver.com>
15
Message-Id: <20220908132817.1831008-6-bmeng.cn@gmail.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
block/nfs.c | 8 ++++++++
20
1 file changed, 8 insertions(+)
21
22
diff --git a/block/nfs.c b/block/nfs.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/nfs.c
25
+++ b/block/nfs.c
26
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts,
27
int flags, int open_flags, Error **errp)
28
{
29
int64_t ret = -EINVAL;
30
+#ifdef _WIN32
31
+ struct __stat64 st;
32
+#else
33
struct stat st;
34
+#endif
35
char *file = NULL, *strp = NULL;
36
37
qemu_mutex_init(&client->mutex);
38
@@ -XXX,XX +XXX,XX @@ static int nfs_reopen_prepare(BDRVReopenState *state,
39
BlockReopenQueue *queue, Error **errp)
40
{
41
NFSClient *client = state->bs->opaque;
42
+#ifdef _WIN32
43
+ struct __stat64 st;
44
+#else
45
struct stat st;
46
+#endif
47
int ret = 0;
48
49
if (state->flags & BDRV_O_RDWR && bdrv_is_read_only(state->bs)) {
50
--
51
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
The .set_speed callback is not called from coroutine.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-2-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/backup.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/block/backup.c b/block/backup.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/backup.c
17
+++ b/block/backup.c
18
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_pause(Job *job)
19
}
20
}
21
22
-static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
23
+static void backup_set_speed(BlockJob *job, int64_t speed)
24
{
25
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
26
27
--
28
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
easier to reason about than sector-based. Convert another internal
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
function (no semantic change); and as with its public counterpart,
5
Message-Id: <20221013123711.620631-3-pbonzini@redhat.com>
6
rename to bdrv_co_block_status() and split the offset return, to
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
make the compiler enforce that we catch all uses. For now, we
8
assert that callers and the return value still use aligned data,
9
but ultimately, this will be the function where we hand off to a
10
byte-based driver callback, and will eventually need to add logic
11
to ensure we round calls according to the driver's
12
request_alignment then touch up the result handed back to the
13
caller, to start permitting a caller to pass unaligned offsets.
14
15
Note that we are now prepared to accepts 'bytes' larger than INT_MAX;
16
this is okay as long as we clamp things internally before violating
17
any 32-bit limits, and makes no difference to how a client will
18
use the information (clients looping over the entire file must
19
already be prepared for consecutive calls to return the same status,
20
as drivers are already free to return shorter-than-maximal status
21
due to any other convenient split points, such as when the L2 table
22
crosses cluster boundaries in qcow2).
23
24
Signed-off-by: Eric Blake <eblake@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
---
8
---
27
block/io.c | 124 ++++++++++++++++++++++++++++++++++++++++---------------------
9
block/io.c | 4 ++--
28
1 file changed, 81 insertions(+), 43 deletions(-)
10
1 file changed, 2 insertions(+), 2 deletions(-)
29
11
30
diff --git a/block/io.c b/block/io.c
12
diff --git a/block/io.c b/block/io.c
31
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
32
--- a/block/io.c
14
--- a/block/io.c
33
+++ b/block/io.c
15
+++ b/block/io.c
34
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
16
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
35
* BDRV_BLOCK_ZERO where possible; otherwise, the result may omit those
17
return (pnum == bytes) && (ret & BDRV_BLOCK_ZERO);
36
* bits particularly if it allows for a larger value in 'pnum'.
37
*
38
- * If 'sector_num' is beyond the end of the disk image the return value is
39
+ * If 'offset' is beyond the end of the disk image the return value is
40
* BDRV_BLOCK_EOF and 'pnum' is set to 0.
41
*
42
- * 'pnum' is set to the number of sectors (including and immediately following
43
- * the specified sector) that are known to be in the same
44
- * allocated/unallocated state.
45
- *
46
- * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
47
+ * 'bytes' is the max value 'pnum' should be set to. If bytes goes
48
* beyond the end of the disk image it will be clamped; if 'pnum' is set to
49
* the end of the image, then the returned value will include BDRV_BLOCK_EOF.
50
*
51
- * If returned value is positive, BDRV_BLOCK_OFFSET_VALID bit is set, and
52
- * 'file' is non-NULL, then '*file' points to the BDS which the sector range
53
- * is allocated in.
54
+ * 'pnum' is set to the number of bytes (including and immediately
55
+ * following the specified offset) that are easily known to be in the
56
+ * same allocated/unallocated state. Note that a second call starting
57
+ * at the original offset plus returned pnum may have the same status.
58
+ * The returned value is non-zero on success except at end-of-file.
59
+ *
60
+ * Returns negative errno on failure. Otherwise, if the
61
+ * BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are
62
+ * set to the host mapping and BDS corresponding to the guest offset.
63
*/
64
-static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
65
- bool want_zero,
66
- int64_t sector_num,
67
- int nb_sectors, int *pnum,
68
- BlockDriverState **file)
69
-{
70
- int64_t total_sectors;
71
- int64_t n;
72
- int64_t ret, ret2;
73
+static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
74
+ bool want_zero,
75
+ int64_t offset, int64_t bytes,
76
+ int64_t *pnum, int64_t *map,
77
+ BlockDriverState **file)
78
+{
79
+ int64_t total_size;
80
+ int64_t n; /* bytes */
81
+ int64_t ret;
82
+ int64_t local_map = 0;
83
BlockDriverState *local_file = NULL;
84
+ int count; /* sectors */
85
86
assert(pnum);
87
*pnum = 0;
88
- total_sectors = bdrv_nb_sectors(bs);
89
- if (total_sectors < 0) {
90
- ret = total_sectors;
91
+ total_size = bdrv_getlength(bs);
92
+ if (total_size < 0) {
93
+ ret = total_size;
94
goto early_out;
95
}
96
97
- if (sector_num >= total_sectors) {
98
+ if (offset >= total_size) {
99
ret = BDRV_BLOCK_EOF;
100
goto early_out;
101
}
102
- if (!nb_sectors) {
103
+ if (!bytes) {
104
ret = 0;
105
goto early_out;
106
}
107
108
- n = total_sectors - sector_num;
109
- if (n < nb_sectors) {
110
- nb_sectors = n;
111
+ n = total_size - offset;
112
+ if (n < bytes) {
113
+ bytes = n;
114
}
115
116
if (!bs->drv->bdrv_co_get_block_status) {
117
- *pnum = nb_sectors;
118
+ *pnum = bytes;
119
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
120
- if (sector_num + nb_sectors == total_sectors) {
121
+ if (offset + bytes == total_size) {
122
ret |= BDRV_BLOCK_EOF;
123
}
124
if (bs->drv->protocol_name) {
125
- ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
126
+ ret |= BDRV_BLOCK_OFFSET_VALID;
127
+ local_map = offset;
128
local_file = bs;
129
}
130
goto early_out;
131
}
132
133
bdrv_inc_in_flight(bs);
134
- ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum,
135
+ /*
136
+ * TODO: Rather than require aligned offsets, we could instead
137
+ * round to the driver's request_alignment here, then touch up
138
+ * count afterwards back to the caller's expectations.
139
+ */
140
+ assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
141
+ /*
142
+ * The contract allows us to return pnum smaller than bytes, even
143
+ * if the next query would see the same status; we truncate the
144
+ * request to avoid overflowing the driver's 32-bit interface.
145
+ */
146
+ bytes = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
147
+ ret = bs->drv->bdrv_co_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
148
+ bytes >> BDRV_SECTOR_BITS, &count,
149
&local_file);
150
if (ret < 0) {
151
- *pnum = 0;
152
goto out;
153
}
154
+ if (ret & BDRV_BLOCK_OFFSET_VALID) {
155
+ local_map = ret & BDRV_BLOCK_OFFSET_MASK;
156
+ }
157
+ *pnum = count * BDRV_SECTOR_SIZE;
158
159
if (ret & BDRV_BLOCK_RAW) {
160
assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file);
161
- ret = bdrv_co_get_block_status(local_file, want_zero,
162
- ret >> BDRV_SECTOR_BITS,
163
- *pnum, pnum, &local_file);
164
+ ret = bdrv_co_block_status(local_file, want_zero, local_map,
165
+ *pnum, pnum, &local_map, &local_file);
166
+ assert(ret < 0 ||
167
+ QEMU_IS_ALIGNED(*pnum | local_map, BDRV_SECTOR_SIZE));
168
goto out;
169
}
170
171
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
172
ret |= BDRV_BLOCK_ZERO;
173
} else if (bs->backing) {
174
BlockDriverState *bs2 = bs->backing->bs;
175
- int64_t nb_sectors2 = bdrv_nb_sectors(bs2);
176
+ int64_t size2 = bdrv_getlength(bs2);
177
178
- if (nb_sectors2 >= 0 && sector_num >= nb_sectors2) {
179
+ if (size2 >= 0 && offset >= size2) {
180
ret |= BDRV_BLOCK_ZERO;
181
}
182
}
183
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
184
if (want_zero && local_file && local_file != bs &&
185
(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
186
(ret & BDRV_BLOCK_OFFSET_VALID)) {
187
- int file_pnum;
188
+ int64_t file_pnum;
189
+ int ret2;
190
191
- ret2 = bdrv_co_get_block_status(local_file, want_zero,
192
- ret >> BDRV_SECTOR_BITS,
193
- *pnum, &file_pnum, NULL);
194
+ ret2 = bdrv_co_block_status(local_file, want_zero, local_map,
195
+ *pnum, &file_pnum, NULL, NULL);
196
if (ret2 >= 0) {
197
/* Ignore errors. This is just providing extra information, it
198
* is useful but not necessary.
199
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
200
201
out:
202
bdrv_dec_in_flight(bs);
203
- if (ret >= 0 && sector_num + *pnum == total_sectors) {
204
+ if (ret >= 0 && offset + *pnum == total_size) {
205
ret |= BDRV_BLOCK_EOF;
206
}
207
early_out:
208
if (file) {
209
*file = local_file;
210
}
211
+ if (map) {
212
+ *map = local_map;
213
+ }
214
+ if (ret >= 0) {
215
+ ret &= ~BDRV_BLOCK_OFFSET_MASK;
216
+ } else {
217
+ assert(INT_MIN <= ret);
218
+ }
219
return ret;
220
}
18
}
221
19
222
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
20
-int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
223
BlockDriverState *p;
21
- int64_t bytes, int64_t *pnum)
224
int64_t ret = 0;
22
+int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
225
bool first = true;
23
+ int64_t *pnum)
226
+ int64_t map = 0;
24
{
227
25
int ret;
228
assert(bs != base);
26
int64_t dummy;
229
for (p = bs; p != base; p = backing_bs(p)) {
230
- ret = bdrv_co_get_block_status(p, want_zero, sector_num, nb_sectors,
231
- pnum, file);
232
+ int64_t count;
233
+
234
+ ret = bdrv_co_block_status(p, want_zero,
235
+ sector_num * BDRV_SECTOR_SIZE,
236
+ nb_sectors * BDRV_SECTOR_SIZE, &count,
237
+ &map, file);
238
if (ret < 0) {
239
break;
240
}
241
+ assert(QEMU_IS_ALIGNED(count | map, BDRV_SECTOR_SIZE));
242
+ ret |= map;
243
+ *pnum = count >> BDRV_SECTOR_BITS;
244
if (ret & BDRV_BLOCK_ZERO && ret & BDRV_BLOCK_EOF && !first) {
245
/*
246
* Reading beyond the end of the file continues to read
247
--
27
--
248
2.13.6
28
2.37.3
249
250
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
hmp_block_resize and hmp_screendump are defined as a ".coroutine = true" command,
4
so they must be coroutine_fn.
5
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-Id: <20221013123711.620631-4-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/block-hmp-cmds.h | 2 +-
13
include/monitor/hmp.h | 3 ++-
14
block/monitor/block-hmp-cmds.c | 2 +-
15
3 files changed, 4 insertions(+), 3 deletions(-)
16
17
diff --git a/include/block/block-hmp-cmds.h b/include/block/block-hmp-cmds.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block-hmp-cmds.h
20
+++ b/include/block/block-hmp-cmds.h
21
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
22
void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict);
23
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
24
25
-void hmp_block_resize(Monitor *mon, const QDict *qdict);
26
+void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict);
27
void hmp_block_stream(Monitor *mon, const QDict *qdict);
28
void hmp_block_passwd(Monitor *mon, const QDict *qdict);
29
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
30
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/monitor/hmp.h
33
+++ b/include/monitor/hmp.h
34
@@ -XXX,XX +XXX,XX @@
35
#define HMP_H
36
37
#include "qemu/readline.h"
38
+#include "qemu/coroutine.h"
39
#include "qapi/qapi-types-common.h"
40
41
bool hmp_handle_error(Monitor *mon, Error *err);
42
@@ -XXX,XX +XXX,XX @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict);
43
void hmp_getfd(Monitor *mon, const QDict *qdict);
44
void hmp_closefd(Monitor *mon, const QDict *qdict);
45
void hmp_sendkey(Monitor *mon, const QDict *qdict);
46
-void hmp_screendump(Monitor *mon, const QDict *qdict);
47
+void coroutine_fn hmp_screendump(Monitor *mon, const QDict *qdict);
48
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
49
void hmp_chardev_change(Monitor *mon, const QDict *qdict);
50
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
51
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/monitor/block-hmp-cmds.c
54
+++ b/block/monitor/block-hmp-cmds.c
55
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
56
hmp_handle_error(mon, err);
57
}
58
59
-void hmp_block_resize(Monitor *mon, const QDict *qdict)
60
+void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict)
61
{
62
const char *device = qdict_get_str(qdict, "device");
63
int64_t size = qdict_get_int(qdict, "size");
64
--
65
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
ssh_write is only called from ssh_co_writev.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-5-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/ssh.c | 6 +++---
12
1 file changed, 3 insertions(+), 3 deletions(-)
13
14
diff --git a/block/ssh.c b/block/ssh.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/ssh.c
17
+++ b/block/ssh.c
18
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
19
return ret;
20
}
21
22
-static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
23
- int64_t offset, size_t size,
24
- QEMUIOVector *qiov)
25
+static coroutine_fn int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
26
+ int64_t offset, size_t size,
27
+ QEMUIOVector *qiov)
28
{
29
ssize_t r;
30
size_t written;
31
--
32
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
The functions are marked coroutine_fn in the definition.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-6-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-io.h | 5 +++--
12
1 file changed, 3 insertions(+), 2 deletions(-)
13
14
diff --git a/include/block/block-io.h b/include/block/block-io.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block-io.h
17
+++ b/include/block/block-io.h
18
@@ -XXX,XX +XXX,XX @@ void bdrv_aio_cancel(BlockAIOCB *acb);
19
void bdrv_aio_cancel_async(BlockAIOCB *acb);
20
21
/* sg packet commands */
22
-int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
23
+int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
24
25
/* Ensure contents are flushed to disk. */
26
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
27
28
-int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
29
+int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
30
+ int64_t bytes);
31
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
32
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
33
int64_t bytes, int64_t *pnum, int64_t *map,
34
--
35
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
The functions are marked coroutine_fn in the definition.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-7-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/qemu/coroutine.h | 10 +++++-----
12
1 file changed, 5 insertions(+), 5 deletions(-)
13
14
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu/coroutine.h
17
+++ b/include/qemu/coroutine.h
18
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_init(CoRwlock *lock);
19
* of a parallel writer, control is transferred to the caller of the current
20
* coroutine.
21
*/
22
-void qemu_co_rwlock_rdlock(CoRwlock *lock);
23
+void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock);
24
25
/**
26
* Write Locks the CoRwlock from a reader. This is a bit more efficient than
27
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_rdlock(CoRwlock *lock);
28
* to the caller of the current coroutine; another writer might run while
29
* @qemu_co_rwlock_upgrade blocks.
30
*/
31
-void qemu_co_rwlock_upgrade(CoRwlock *lock);
32
+void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock);
33
34
/**
35
* Downgrades a write-side critical section to a reader. Downgrading with
36
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_upgrade(CoRwlock *lock);
37
* followed by @qemu_co_rwlock_rdlock. This makes it more efficient, but
38
* may also sometimes be necessary for correctness.
39
*/
40
-void qemu_co_rwlock_downgrade(CoRwlock *lock);
41
+void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock);
42
43
/**
44
* Write Locks the mutex. If the lock cannot be taken immediately because
45
* of a parallel reader, control is transferred to the caller of the current
46
* coroutine.
47
*/
48
-void qemu_co_rwlock_wrlock(CoRwlock *lock);
49
+void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock);
50
51
/**
52
* Unlocks the read/write lock and schedules the next coroutine that was
53
* waiting for this lock to be run.
54
*/
55
-void qemu_co_rwlock_unlock(CoRwlock *lock);
56
+void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock);
57
58
typedef struct QemuCoSleep {
59
Coroutine *to_wake;
60
--
61
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-8-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/qemu/coroutine.h | 8 +++++---
10
1 file changed, 5 insertions(+), 3 deletions(-)
11
12
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/qemu/coroutine.h
15
+++ b/include/qemu/coroutine.h
16
@@ -XXX,XX +XXX,XX @@ void qemu_coroutine_dec_pool_size(unsigned int additional_pool_size);
17
* The same interface as qemu_sendv_recvv(), with added yielding.
18
* XXX should mark these as coroutine_fn
19
*/
20
-ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
21
- size_t offset, size_t bytes, bool do_send);
22
+ssize_t coroutine_fn qemu_co_sendv_recvv(int sockfd, struct iovec *iov,
23
+ unsigned iov_cnt, size_t offset,
24
+ size_t bytes, bool do_send);
25
#define qemu_co_recvv(sockfd, iov, iov_cnt, offset, bytes) \
26
qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, false)
27
#define qemu_co_sendv(sockfd, iov, iov_cnt, offset, bytes) \
28
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
29
/**
30
* The same as above, but with just a single buffer
31
*/
32
-ssize_t qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send);
33
+ssize_t coroutine_fn qemu_co_send_recv(int sockfd, void *buf, size_t bytes,
34
+ bool do_send);
35
#define qemu_co_recv(sockfd, buf, bytes) \
36
qemu_co_send_recv(sockfd, buf, bytes, false)
37
#define qemu_co_send(sockfd, buf, bytes) \
38
--
39
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-9-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2.h | 14 +++++++-------
10
include/block/block_int-common.h | 12 +++++-------
11
2 files changed, 12 insertions(+), 14 deletions(-)
12
13
diff --git a/block/qcow2.h b/block/qcow2.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2.h
16
+++ b/block/qcow2.h
17
@@ -XXX,XX +XXX,XX @@ int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
18
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
19
bool release_stored, Error **errp);
20
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
21
-bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
22
- const char *name,
23
- uint32_t granularity,
24
- Error **errp);
25
-int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
26
- const char *name,
27
- Error **errp);
28
+bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
29
+ const char *name,
30
+ uint32_t granularity,
31
+ Error **errp);
32
+int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
33
+ const char *name,
34
+ Error **errp);
35
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
36
uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
37
uint32_t cluster_size);
38
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/block_int-common.h
41
+++ b/include/block/block_int-common.h
42
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
43
void coroutine_fn (*bdrv_co_drain_end)(BlockDriverState *bs);
44
45
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
46
- bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
47
- const char *name,
48
- uint32_t granularity,
49
- Error **errp);
50
- int (*bdrv_co_remove_persistent_dirty_bitmap)(BlockDriverState *bs,
51
- const char *name,
52
- Error **errp);
53
+ bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
54
+ BlockDriverState *bs, const char *name, uint32_t granularity,
55
+ Error **errp);
56
+ int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)(
57
+ BlockDriverState *bs, const char *name, Error **errp);
58
};
59
60
static inline bool block_driver_can_compress(BlockDriver *drv)
61
--
62
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
easier to reason about than sector-based. Convert another internal
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
function (no semantic change), and rename it to is_zero() in the
5
Message-Id: <20221013123711.620631-10-pbonzini@redhat.com>
6
process.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
8
---
13
block/qcow2.c | 33 +++++++++++++++++++--------------
9
block/qcow2.c | 8 ++++----
14
1 file changed, 19 insertions(+), 14 deletions(-)
10
1 file changed, 4 insertions(+), 4 deletions(-)
15
11
16
diff --git a/block/qcow2.c b/block/qcow2.c
12
diff --git a/block/qcow2.c b/block/qcow2.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.c
14
--- a/block/qcow2.c
19
+++ b/block/qcow2.c
15
+++ b/block/qcow2.c
20
@@ -XXX,XX +XXX,XX @@ finish:
16
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
17
return pos;
21
}
18
}
22
19
23
20
-static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
24
-static bool is_zero_sectors(BlockDriverState *bs, int64_t start,
21
- int64_t pos)
25
- uint32_t count)
22
+static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
26
+static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
23
+ QEMUIOVector *qiov, int64_t pos)
27
{
24
{
28
int nr;
25
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
29
int64_t res;
26
if (offset < 0) {
30
+ int64_t start;
27
@@ -XXX,XX +XXX,XX @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
31
28
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
32
- if (start + count > bs->total_sectors) {
33
- count = bs->total_sectors - start;
34
+ /* TODO: Widening to sector boundaries should only be needed as
35
+ * long as we can't query finer granularity. */
36
+ start = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
37
+ bytes = QEMU_ALIGN_UP(offset + bytes, BDRV_SECTOR_SIZE) - start;
38
+
39
+ /* Clamp to image length, before checking status of underlying sectors */
40
+ if (start + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) {
41
+ bytes = bs->total_sectors * BDRV_SECTOR_SIZE - start;
42
}
43
44
- if (!count) {
45
+ if (!bytes) {
46
return true;
47
}
48
- res = bdrv_get_block_status_above(bs, NULL, start, count, &nr, NULL);
49
- return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == count;
50
+ res = bdrv_get_block_status_above(bs, NULL, start >> BDRV_SECTOR_BITS,
51
+ bytes >> BDRV_SECTOR_BITS, &nr, NULL);
52
+ return res >= 0 && (res & BDRV_BLOCK_ZERO) &&
53
+ nr * BDRV_SECTOR_SIZE == bytes;
54
}
29
}
55
30
56
static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
31
-static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
57
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
32
- int64_t pos)
58
}
33
+static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs,
59
34
+ QEMUIOVector *qiov, int64_t pos)
60
if (head || tail) {
35
{
61
- int64_t cl_start = (offset - head) >> BDRV_SECTOR_BITS;
36
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
62
uint64_t off;
37
if (offset < 0) {
63
unsigned int nr;
64
65
assert(head + bytes <= s->cluster_size);
66
67
/* check whether remainder of cluster already reads as zero */
68
- if (!(is_zero_sectors(bs, cl_start,
69
- DIV_ROUND_UP(head, BDRV_SECTOR_SIZE)) &&
70
- is_zero_sectors(bs, (offset + bytes) >> BDRV_SECTOR_BITS,
71
- DIV_ROUND_UP(-tail & (s->cluster_size - 1),
72
- BDRV_SECTOR_SIZE)))) {
73
+ if (!(is_zero(bs, offset - head, head) &&
74
+ is_zero(bs, offset + bytes,
75
+ tail ? s->cluster_size - tail : 0))) {
76
return -ENOTSUP;
77
}
78
79
qemu_co_mutex_lock(&s->lock);
80
/* We can have new write after previous check */
81
- offset = cl_start << BDRV_SECTOR_BITS;
82
+ offset = QEMU_ALIGN_DOWN(offset, s->cluster_size);
83
bytes = s->cluster_size;
84
nr = s->cluster_size;
85
ret = qcow2_get_cluster_offset(bs, offset, &nr, &off);
86
--
38
--
87
2.13.6
39
2.37.3
88
89
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Any device that has request_alignment greater than 512 should be
3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
unable to report status at a finer granularity; it may also be
4
Message-Id: <20221013123711.620631-11-pbonzini@redhat.com>
5
simpler for such devices to be guaranteed that the block layer
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
has rounded things out to the granularity boundary (the way the
7
block layer already rounds all other I/O out). Besides, getting
8
the code correct for super-sector alignment also benefits us
9
for the fact that our public interface now has byte granularity,
10
even though none of our drivers have byte-level callbacks.
11
12
Add an assertion in blkdebug that proves that the block layer
13
never requests status of unaligned sections, similar to what it
14
does on other requests (while still keeping the generic helper
15
in place for when future patches add a throttle driver). Note
16
that iotest 177 already covers this (it would fail if you use
17
just the blkdebug.c hunk without the io.c changes). Meanwhile,
18
we can drop assertions in callers that no longer have to pass
19
in sector-aligned addresses.
20
21
There is a mid-function scope added for 'count' and 'longret',
22
for a couple of reasons: first, an upcoming patch will add an
23
'if' statement that checks whether a driver has an old- or
24
new-style callback, and can conveniently use the same scope for
25
less indentation churn at that time. Second, since we are
26
trying to get rid of sector-based computations, wrapping things
27
in a scope makes it easier to group and see what will be
28
deleted in a final cleanup patch once all drivers have been
29
converted to the new-style callback.
30
31
Signed-off-by: Eric Blake <eblake@redhat.com>
32
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
33
---
7
---
34
include/block/block_int.h | 3 +-
8
block/blkdebug.c | 2 +-
35
block/blkdebug.c | 13 ++++++++-
9
1 file changed, 1 insertion(+), 1 deletion(-)
36
block/io.c | 71 ++++++++++++++++++++++++++++++-----------------
37
3 files changed, 59 insertions(+), 28 deletions(-)
38
10
39
diff --git a/include/block/block_int.h b/include/block/block_int.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/include/block/block_int.h
42
+++ b/include/block/block_int.h
43
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
44
* according to the current layer, and should not set
45
* BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
46
* for the meaning of _DATA, _ZERO, and _OFFSET_VALID. The block
47
- * layer guarantees non-NULL pnum and file.
48
+ * layer guarantees input aligned to request_alignment, as well as
49
+ * non-NULL pnum and file.
50
*/
51
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
52
int64_t sector_num, int nb_sectors, int *pnum,
53
diff --git a/block/blkdebug.c b/block/blkdebug.c
11
diff --git a/block/blkdebug.c b/block/blkdebug.c
54
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
55
--- a/block/blkdebug.c
13
--- a/block/blkdebug.c
56
+++ b/block/blkdebug.c
14
+++ b/block/blkdebug.c
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
15
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
58
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
16
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
59
}
17
}
60
18
61
+static int64_t coroutine_fn blkdebug_co_get_block_status(
19
-static int blkdebug_co_flush(BlockDriverState *bs)
62
+ BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
20
+static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
63
+ BlockDriverState **file)
64
+{
65
+ assert(QEMU_IS_ALIGNED(sector_num | nb_sectors,
66
+ DIV_ROUND_UP(bs->bl.request_alignment,
67
+ BDRV_SECTOR_SIZE)));
68
+ return bdrv_co_get_block_status_from_file(bs, sector_num, nb_sectors,
69
+ pnum, file);
70
+}
71
+
72
static void blkdebug_close(BlockDriverState *bs)
73
{
21
{
74
BDRVBlkdebugState *s = bs->opaque;
22
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
75
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
76
.bdrv_co_flush_to_disk = blkdebug_co_flush,
77
.bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
78
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
79
- .bdrv_co_get_block_status = bdrv_co_get_block_status_from_file,
80
+ .bdrv_co_get_block_status = blkdebug_co_get_block_status,
81
82
.bdrv_debug_event = blkdebug_debug_event,
83
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
84
diff --git a/block/io.c b/block/io.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block/io.c
87
+++ b/block/io.c
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
89
{
90
int64_t total_size;
91
int64_t n; /* bytes */
92
- int64_t ret;
93
+ int ret;
94
int64_t local_map = 0;
95
BlockDriverState *local_file = NULL;
96
- int count; /* sectors */
97
+ int64_t aligned_offset, aligned_bytes;
98
+ uint32_t align;
99
100
assert(pnum);
101
*pnum = 0;
102
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
103
}
104
105
bdrv_inc_in_flight(bs);
106
+
107
+ /* Round out to request_alignment boundaries */
108
+ /* TODO: until we have a byte-based driver callback, we also have to
109
+ * round out to sectors, even if that is bigger than request_alignment */
110
+ align = MAX(bs->bl.request_alignment, BDRV_SECTOR_SIZE);
111
+ aligned_offset = QEMU_ALIGN_DOWN(offset, align);
112
+ aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset;
113
+
114
+ {
115
+ int count; /* sectors */
116
+ int64_t longret;
117
+
118
+ assert(QEMU_IS_ALIGNED(aligned_offset | aligned_bytes,
119
+ BDRV_SECTOR_SIZE));
120
+ /*
121
+ * The contract allows us to return pnum smaller than bytes, even
122
+ * if the next query would see the same status; we truncate the
123
+ * request to avoid overflowing the driver's 32-bit interface.
124
+ */
125
+ longret = bs->drv->bdrv_co_get_block_status(
126
+ bs, aligned_offset >> BDRV_SECTOR_BITS,
127
+ MIN(INT_MAX, aligned_bytes) >> BDRV_SECTOR_BITS, &count,
128
+ &local_file);
129
+ if (longret < 0) {
130
+ assert(INT_MIN <= longret);
131
+ ret = longret;
132
+ goto out;
133
+ }
134
+ if (longret & BDRV_BLOCK_OFFSET_VALID) {
135
+ local_map = longret & BDRV_BLOCK_OFFSET_MASK;
136
+ }
137
+ ret = longret & ~BDRV_BLOCK_OFFSET_MASK;
138
+ *pnum = count * BDRV_SECTOR_SIZE;
139
+ }
140
+
141
/*
142
- * TODO: Rather than require aligned offsets, we could instead
143
- * round to the driver's request_alignment here, then touch up
144
- * count afterwards back to the caller's expectations.
145
- */
146
- assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
147
- /*
148
- * The contract allows us to return pnum smaller than bytes, even
149
- * if the next query would see the same status; we truncate the
150
- * request to avoid overflowing the driver's 32-bit interface.
151
+ * The driver's result must be a multiple of request_alignment.
152
+ * Clamp pnum and adjust map to original request.
153
*/
154
- bytes = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
155
- ret = bs->drv->bdrv_co_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
156
- bytes >> BDRV_SECTOR_BITS, &count,
157
- &local_file);
158
- if (ret < 0) {
159
- goto out;
160
+ assert(QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset);
161
+ *pnum -= offset - aligned_offset;
162
+ if (*pnum > bytes) {
163
+ *pnum = bytes;
164
}
165
if (ret & BDRV_BLOCK_OFFSET_VALID) {
166
- local_map = ret & BDRV_BLOCK_OFFSET_MASK;
167
+ local_map += offset - aligned_offset;
168
}
169
- *pnum = count * BDRV_SECTOR_SIZE;
170
171
if (ret & BDRV_BLOCK_RAW) {
172
assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file);
173
ret = bdrv_co_block_status(local_file, want_zero, local_map,
174
*pnum, pnum, &local_map, &local_file);
175
- assert(ret < 0 ||
176
- QEMU_IS_ALIGNED(*pnum | local_map, BDRV_SECTOR_SIZE));
177
goto out;
178
}
179
180
@@ -XXX,XX +XXX,XX @@ early_out:
181
if (map) {
182
*map = local_map;
183
}
184
- if (ret >= 0) {
185
- ret &= ~BDRV_BLOCK_OFFSET_MASK;
186
- } else {
187
- assert(INT_MIN <= ret);
188
- }
189
return ret;
190
}
191
23
192
--
24
--
193
2.13.6
25
2.37.3
194
195
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
get_cluster_offset() and decompress_cluster() are only called from
4
the read and write paths.
5
6
The validity of these was double-checked with Alberto Faria's static analyzer.
7
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20221013123711.620631-12-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/qcow.c | 15 +++++++++------
14
1 file changed, 9 insertions(+), 6 deletions(-)
15
16
diff --git a/block/qcow.c b/block/qcow.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow.c
19
+++ b/block/qcow.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcowState {
21
22
static QemuOptsList qcow_create_opts;
23
24
-static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
25
+static int coroutine_fn decompress_cluster(BlockDriverState *bs,
26
+ uint64_t cluster_offset);
27
28
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
29
{
30
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
31
* return 0 if not allocated, 1 if *result is assigned, and negative
32
* errno on failure.
33
*/
34
-static int get_cluster_offset(BlockDriverState *bs,
35
- uint64_t offset, int allocate,
36
- int compressed_size,
37
- int n_start, int n_end, uint64_t *result)
38
+static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
39
+ uint64_t offset, int allocate,
40
+ int compressed_size,
41
+ int n_start, int n_end,
42
+ uint64_t *result)
43
{
44
BDRVQcowState *s = bs->opaque;
45
int min_index, i, j, l1_index, l2_index, ret;
46
@@ -XXX,XX +XXX,XX @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
47
return 0;
48
}
49
50
-static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
51
+static int coroutine_fn decompress_cluster(BlockDriverState *bs,
52
+ uint64_t cluster_offset)
53
{
54
BDRVQcowState *s = bs->opaque;
55
int ret, csize;
56
--
57
2.37.3
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
The validity of these was double-checked with Alberto Faria's static
4
byte-based. In the common case, allocation is unlikely to ever use
4
analyzer.
5
values that are not naturally sector-aligned, but it is possible
6
that byte-based values will let us be more precise about allocation
7
at the end of an unaligned file that can do byte-based access.
8
5
9
Changing the name of the function from bdrv_get_block_status() to
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
bdrv_block_status() ensures that the compiler enforces that all
7
Message-Id: <20221013123711.620631-13-pbonzini@redhat.com>
11
callers are updated. For now, the io.c layer still assert()s that
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
all callers are sector-aligned, but that can be relaxed when a later
13
patch implements byte-based block status in the drivers.
14
15
There was an inherent limitation in returning the offset via the
16
return value: we only have room for BDRV_BLOCK_OFFSET_MASK bits, which
17
means an offset can only be mapped for sector-aligned queries (or,
18
if we declare that non-aligned input is at the same relative position
19
modulo 512 of the answer), so the new interface also changes things to
20
return the offset via output through a parameter by reference rather
21
than mashed into the return value. We'll have some glue code that
22
munges between the two styles until we finish converting all uses.
23
24
For the most part this patch is just the addition of scaling at the
25
callers followed by inverse scaling at bdrv_block_status(), coupled
26
with the tweak in calling convention. But some code, particularly
27
bdrv_is_allocated(), gets a lot simpler because it no longer has to
28
mess with sectors.
29
30
For ease of review, bdrv_get_block_status_above() will be tackled
31
separately.
32
33
Signed-off-by: Eric Blake <eblake@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
10
---
36
include/block/block.h | 17 +++++++++--------
11
block/qcow2.h | 18 +++++++++---------
37
block/io.c | 47 ++++++++++++++++++++++++++++++++++-------------
12
block/qcow2-bitmap.c | 4 ++--
38
block/qcow2-cluster.c | 2 +-
13
block/qcow2-cluster.c | 21 ++++++++++++---------
39
qemu-img.c | 25 ++++++++++++++-----------
14
block/qcow2-refcount.c | 8 ++++----
40
4 files changed, 58 insertions(+), 33 deletions(-)
15
4 files changed, 27 insertions(+), 24 deletions(-)
41
16
42
diff --git a/include/block/block.h b/include/block/block.h
17
diff --git a/block/qcow2.h b/block/qcow2.h
43
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
44
--- a/include/block/block.h
19
--- a/block/qcow2.h
45
+++ b/include/block/block.h
20
+++ b/block/qcow2.h
46
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
21
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
47
#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
22
Error **errp);
48
23
49
/*
24
/* qcow2-refcount.c functions */
50
- * Allocation status flags for bdrv_get_block_status() and friends.
25
-int qcow2_refcount_init(BlockDriverState *bs);
51
+ * Allocation status flags for bdrv_block_status() and friends.
26
+int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
52
*
27
void qcow2_refcount_close(BlockDriverState *bs);
53
* Public flags:
28
54
* BDRV_BLOCK_DATA: allocation for data at offset is tied to this layer
29
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
55
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
30
@@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
56
* that the block layer recompute the answer from the returned
31
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
57
* BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID.
32
BlockDriverAmendStatusCB *status_cb,
58
*
33
void *cb_opaque, Error **errp);
59
- * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK)
34
-int qcow2_shrink_reftable(BlockDriverState *bs);
60
- * represent the offset in the returned BDS that is allocated for the
35
+int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs);
61
- * corresponding raw data; however, whether that offset actually contains
36
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
62
- * data also depends on BDRV_BLOCK_DATA and BDRV_BLOCK_ZERO, as follows:
37
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
63
+ * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK) of
38
64
+ * the return value (old interface) or the entire map parameter (new
39
/* qcow2-cluster.c functions */
65
+ * interface) represent the offset in the returned BDS that is allocated for
40
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
66
+ * the corresponding raw data. However, whether that offset actually
41
bool exact_size);
67
+ * contains data also depends on BDRV_BLOCK_DATA, as follows:
42
-int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
68
*
43
+int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
69
* DATA ZERO OFFSET_VALID
44
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
70
* t t t sectors read as zero, returned file is zero at offset
45
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
71
@@ -XXX,XX +XXX,XX @@ int bdrv_has_zero_init_1(BlockDriverState *bs);
46
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
72
int bdrv_has_zero_init(BlockDriverState *bs);
47
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
73
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
48
int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
74
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
49
unsigned int *bytes,
75
-int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
50
uint64_t *host_offset, QCowL2Meta **m);
76
- int nb_sectors, int *pnum,
51
-int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
77
- BlockDriverState **file);
52
- uint64_t offset,
78
+int bdrv_block_status(BlockDriverState *bs, int64_t offset,
53
- int compressed_size,
79
+ int64_t bytes, int64_t *pnum, int64_t *map,
54
- uint64_t *host_offset);
80
+ BlockDriverState **file);
55
+int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
81
int64_t bdrv_get_block_status_above(BlockDriverState *bs,
56
+ uint64_t offset,
82
BlockDriverState *base,
57
+ int compressed_size,
83
int64_t sector_num,
58
+ uint64_t *host_offset);
84
diff --git a/block/io.c b/block/io.c
59
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
60
uint64_t *coffset, int *csize);
61
62
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_discard(Qcow2Cache *c, void *table);
63
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
64
void **refcount_table,
65
int64_t *refcount_table_size);
66
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
67
- Error **errp);
68
+bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
69
+ bool *header_updated, Error **errp);
70
bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
71
Qcow2BitmapInfoList **info_list, Error **errp);
72
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
73
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
85
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
86
--- a/block/io.c
75
--- a/block/qcow2-bitmap.c
87
+++ b/block/io.c
76
+++ b/block/qcow2-bitmap.c
88
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
77
@@ -XXX,XX +XXX,XX @@ static void set_readonly_helper(gpointer bitmap, gpointer value)
78
* If header_updated is not NULL then it is set appropriately regardless of
79
* the return value.
89
*/
80
*/
90
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
81
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
82
- Error **errp)
83
+bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
84
+ bool *header_updated, Error **errp)
91
{
85
{
92
- int64_t target_size, ret, bytes, offset = 0;
86
BDRVQcow2State *s = bs->opaque;
93
+ int ret;
87
Qcow2BitmapList *bm_list;
94
+ int64_t target_size, bytes, offset = 0;
95
BlockDriverState *bs = child->bs;
96
- int n; /* sectors */
97
98
target_size = bdrv_getlength(bs);
99
if (target_size < 0) {
100
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
101
if (bytes <= 0) {
102
return 0;
103
}
104
- ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS,
105
- bytes >> BDRV_SECTOR_BITS, &n, NULL);
106
+ ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL);
107
if (ret < 0) {
108
error_report("error getting block status at offset %" PRId64 ": %s",
109
offset, strerror(-ret));
110
return ret;
111
}
112
if (ret & BDRV_BLOCK_ZERO) {
113
- offset += n * BDRV_SECTOR_BITS;
114
+ offset += bytes;
115
continue;
116
}
117
- ret = bdrv_pwrite_zeroes(child, offset, n * BDRV_SECTOR_SIZE, flags);
118
+ ret = bdrv_pwrite_zeroes(child, offset, bytes, flags);
119
if (ret < 0) {
120
error_report("error writing zeroes at offset %" PRId64 ": %s",
121
offset, strerror(-ret));
122
return ret;
123
}
124
- offset += n * BDRV_SECTOR_SIZE;
125
+ offset += bytes;
126
}
127
}
128
129
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status_above(BlockDriverState *bs,
130
nb_sectors, pnum, file);
131
}
132
133
-int64_t bdrv_get_block_status(BlockDriverState *bs,
134
- int64_t sector_num,
135
- int nb_sectors, int *pnum,
136
- BlockDriverState **file)
137
+int bdrv_block_status(BlockDriverState *bs, int64_t offset, int64_t bytes,
138
+ int64_t *pnum, int64_t *map, BlockDriverState **file)
139
{
140
- return bdrv_get_block_status_above(bs, backing_bs(bs),
141
- sector_num, nb_sectors, pnum, file);
142
+ int64_t ret;
143
+ int n;
144
+
145
+ assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
146
+ assert(pnum);
147
+ /*
148
+ * The contract allows us to return pnum smaller than bytes, even
149
+ * if the next query would see the same status; we truncate the
150
+ * request to avoid overflowing the driver's 32-bit interface.
151
+ */
152
+ bytes = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
153
+ ret = bdrv_get_block_status_above(bs, backing_bs(bs),
154
+ offset >> BDRV_SECTOR_BITS,
155
+ bytes >> BDRV_SECTOR_BITS, &n, file);
156
+ if (ret < 0) {
157
+ assert(INT_MIN <= ret);
158
+ *pnum = 0;
159
+ return ret;
160
+ }
161
+ *pnum = n * BDRV_SECTOR_SIZE;
162
+ if (map) {
163
+ *map = ret & BDRV_BLOCK_OFFSET_MASK;
164
+ } else {
165
+ ret &= ~BDRV_BLOCK_OFFSET_VALID;
166
+ }
167
+ return ret & ~BDRV_BLOCK_OFFSET_MASK;
168
}
169
170
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
171
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
88
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
172
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
173
--- a/block/qcow2-cluster.c
90
--- a/block/qcow2-cluster.c
174
+++ b/block/qcow2-cluster.c
91
+++ b/block/qcow2-cluster.c
175
@@ -XXX,XX +XXX,XX @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
92
@@ -XXX,XX +XXX,XX @@
176
* cluster is already marked as zero, or if it's unallocated and we
93
#include "qemu/memalign.h"
177
* don't have a backing file.
94
#include "trace.h"
178
*
95
179
- * TODO We might want to use bdrv_get_block_status(bs) here, but we're
96
-int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
180
+ * TODO We might want to use bdrv_block_status(bs) here, but we're
97
+int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs,
181
* holding s->lock, so that doesn't work today.
98
+ uint64_t exact_size)
182
*
99
{
183
* If full_discard is true, the sector should not read back as zeroes,
100
BDRVQcow2State *s = bs->opaque;
184
diff --git a/qemu-img.c b/qemu-img.c
101
int new_l1_size, i, ret;
102
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
103
*
104
* Return 0 on success and -errno in error cases
105
*/
106
-int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
107
- uint64_t offset,
108
- int compressed_size,
109
- uint64_t *host_offset)
110
+int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
111
+ uint64_t offset,
112
+ int compressed_size,
113
+ uint64_t *host_offset)
114
{
115
BDRVQcow2State *s = bs->opaque;
116
int l2_index, ret;
117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_dependencies(BlockDriverState *bs,
118
*
119
* -errno: in error cases
120
*/
121
-static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
122
- uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
123
+static int coroutine_fn handle_copied(BlockDriverState *bs,
124
+ uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
125
+ QCowL2Meta **m)
126
{
127
BDRVQcow2State *s = bs->opaque;
128
int l2_index;
129
@@ -XXX,XX +XXX,XX @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
130
*
131
* -errno: in error cases
132
*/
133
-static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
134
- uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
135
+static int coroutine_fn handle_alloc(BlockDriverState *bs,
136
+ uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
137
+ QCowL2Meta **m)
138
{
139
BDRVQcow2State *s = bs->opaque;
140
int l2_index;
141
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
185
index XXXXXXX..XXXXXXX 100644
142
index XXXXXXX..XXXXXXX 100644
186
--- a/qemu-img.c
143
--- a/block/qcow2-refcount.c
187
+++ b/qemu-img.c
144
+++ b/block/qcow2-refcount.c
188
@@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
145
@@ -XXX,XX +XXX,XX @@ static void update_max_refcount_table_index(BDRVQcow2State *s)
189
146
s->max_refcount_table_index = i;
190
if (s->sector_next_status <= sector_num) {
147
}
191
if (s->target_has_backing) {
148
192
- ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
149
-int qcow2_refcount_init(BlockDriverState *bs)
193
- sector_num - src_cur_offset,
150
+int coroutine_fn qcow2_refcount_init(BlockDriverState *bs)
194
- n, &n, NULL);
195
+ int64_t count = n * BDRV_SECTOR_SIZE;
196
+
197
+ ret = bdrv_block_status(blk_bs(s->src[src_cur]),
198
+ (sector_num - src_cur_offset) *
199
+ BDRV_SECTOR_SIZE,
200
+ count, &count, NULL, NULL);
201
+ assert(ret < 0 || QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
202
+ n = count >> BDRV_SECTOR_BITS;
203
} else {
204
ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
205
sector_num - src_cur_offset,
206
@@ -XXX,XX +XXX,XX @@ static void dump_map_entry(OutputFormat output_format, MapEntry *e,
207
static int get_block_status(BlockDriverState *bs, int64_t offset,
208
int64_t bytes, MapEntry *e)
209
{
151
{
210
- int64_t ret;
152
BDRVQcow2State *s = bs->opaque;
211
+ int ret;
153
unsigned int refcount_table_size2, i;
212
int depth;
154
@@ -XXX,XX +XXX,XX @@ static int64_t get_refblock_offset(BlockDriverState *bs, uint64_t offset)
213
BlockDriverState *file;
155
return covering_refblock_offset;
214
bool has_offset;
156
}
215
- int nb_sectors = bytes >> BDRV_SECTOR_BITS;
157
216
+ int64_t map;
158
-static int qcow2_discard_refcount_block(BlockDriverState *bs,
217
159
- uint64_t discard_block_offs)
218
- assert(bytes < INT_MAX);
160
+static int coroutine_fn
219
/* As an optimization, we could cache the current range of unallocated
161
+qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
220
* clusters in each file of the chain, and avoid querying the same
162
{
221
* range repeatedly.
163
BDRVQcow2State *s = bs->opaque;
222
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
164
int64_t refblock_offs;
223
165
@@ -XXX,XX +XXX,XX @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
224
depth = 0;
166
return 0;
225
for (;;) {
167
}
226
- ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS, nb_sectors,
168
227
- &nb_sectors, &file);
169
-int qcow2_shrink_reftable(BlockDriverState *bs)
228
+ ret = bdrv_block_status(bs, offset, bytes, &bytes, &map, &file);
170
+int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs)
229
if (ret < 0) {
171
{
230
return ret;
172
BDRVQcow2State *s = bs->opaque;
231
}
173
uint64_t *reftable_tmp =
232
- assert(nb_sectors);
233
+ assert(bytes);
234
if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {
235
break;
236
}
237
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
238
239
*e = (MapEntry) {
240
.start = offset,
241
- .length = nb_sectors * BDRV_SECTOR_SIZE,
242
+ .length = bytes,
243
.data = !!(ret & BDRV_BLOCK_DATA),
244
.zero = !!(ret & BDRV_BLOCK_ZERO),
245
- .offset = ret & BDRV_BLOCK_OFFSET_MASK,
246
+ .offset = map,
247
.has_offset = has_offset,
248
.depth = depth,
249
.has_filename = file && has_offset,
250
--
174
--
251
2.13.6
175
2.37.3
252
253
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Whenever the actual image size is not part of the test, it should be
3
The validity of these was double-checked with Alberto Faria's static analyzer.
4
filtered as it depends on the host filesystem.
5
4
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-id: 20171009163456.485-3-mreitz@redhat.com
6
Message-Id: <20221013123711.620631-14-pbonzini@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
9
---
12
tests/qemu-iotests/184 | 3 ++-
10
block/vmdk.c | 34 +++++++++++++++++-----------------
13
tests/qemu-iotests/184.out | 6 +++---
11
1 file changed, 17 insertions(+), 17 deletions(-)
14
tests/qemu-iotests/191 | 4 ++--
15
tests/qemu-iotests/191.out | 46 +++++++++++++++++++++++-----------------------
16
4 files changed, 30 insertions(+), 29 deletions(-)
17
12
18
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
13
diff --git a/block/vmdk.c b/block/vmdk.c
19
index XXXXXXX..XXXXXXX 100755
14
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/184
15
--- a/block/vmdk.c
21
+++ b/tests/qemu-iotests/184
16
+++ b/block/vmdk.c
22
@@ -XXX,XX +XXX,XX @@ function do_run_qemu()
17
@@ -XXX,XX +XXX,XX @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
23
function run_qemu()
18
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
19
* it for call to write user data in the request.
20
*/
21
-static int get_whole_cluster(BlockDriverState *bs,
22
- VmdkExtent *extent,
23
- uint64_t cluster_offset,
24
- uint64_t offset,
25
- uint64_t skip_start_bytes,
26
- uint64_t skip_end_bytes,
27
- bool zeroed)
28
+static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
29
+ VmdkExtent *extent,
30
+ uint64_t cluster_offset,
31
+ uint64_t offset,
32
+ uint64_t skip_start_bytes,
33
+ uint64_t skip_end_bytes,
34
+ bool zeroed)
24
{
35
{
25
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
36
int ret = VMDK_OK;
26
- | _filter_qemu_io | _filter_generated_node_ids
37
int64_t cluster_bytes;
27
+ | _filter_qemu_io | _filter_generated_node_ids \
38
@@ -XXX,XX +XXX,XX @@ exit:
28
+ | _filter_actual_image_size
39
return ret;
29
}
40
}
30
41
31
_make_test_img 64M
42
-static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
32
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
43
- uint32_t offset)
33
index XXXXXXX..XXXXXXX 100644
44
+static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
34
--- a/tests/qemu-iotests/184.out
45
+ uint32_t offset)
35
+++ b/tests/qemu-iotests/184.out
46
{
36
@@ -XXX,XX +XXX,XX @@ Testing:
47
offset = cpu_to_le32(offset);
37
"filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"qcow2\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/t.qcow2\"}}}",
48
/* update L2 table */
38
"cluster-size": 65536,
49
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
39
"format": "throttle",
50
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
40
- "actual-size": 200704,
51
* VMDK_ERROR if failed.
41
+ "actual-size": SIZE,
52
*/
42
"dirty-flag": false
53
-static int get_cluster_offset(BlockDriverState *bs,
43
},
54
- VmdkExtent *extent,
44
"iops_wr": 0,
55
- VmdkMetaData *m_data,
45
@@ -XXX,XX +XXX,XX @@ Testing:
56
- uint64_t offset,
46
"filename": "TEST_DIR/t.qcow2",
57
- bool allocate,
47
"cluster-size": 65536,
58
- uint64_t *cluster_offset,
48
"format": "qcow2",
59
- uint64_t skip_start_bytes,
49
- "actual-size": 200704,
60
- uint64_t skip_end_bytes)
50
+ "actual-size": SIZE,
61
+static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
51
"format-specific": {
62
+ VmdkExtent *extent,
52
"type": "qcow2",
63
+ VmdkMetaData *m_data,
53
"data": {
64
+ uint64_t offset,
54
@@ -XXX,XX +XXX,XX @@ Testing:
65
+ bool allocate,
55
"virtual-size": 197120,
66
+ uint64_t *cluster_offset,
56
"filename": "TEST_DIR/t.qcow2",
67
+ uint64_t skip_start_bytes,
57
"format": "file",
68
+ uint64_t skip_end_bytes)
58
- "actual-size": 200704,
69
{
59
+ "actual-size": SIZE,
70
unsigned int l1_index, l2_offset, l2_index;
60
"dirty-flag": false
71
int min_index, i, j;
61
},
62
"iops_wr": 0,
63
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
64
index XXXXXXX..XXXXXXX 100755
65
--- a/tests/qemu-iotests/191
66
+++ b/tests/qemu-iotests/191
67
@@ -XXX,XX +XXX,XX @@ echo === Check that both top and top2 point to base now ===
68
echo
69
70
_send_qemu_cmd $h "{ 'execute': 'query-named-block-nodes' }" "^}" |
71
- _filter_generated_node_ids
72
+ _filter_generated_node_ids | _filter_actual_image_size
73
74
_send_qemu_cmd $h "{ 'execute': 'quit' }" "^}"
75
wait=1 _cleanup_qemu
76
@@ -XXX,XX +XXX,XX @@ echo === Check that both top and top2 point to base now ===
77
echo
78
79
_send_qemu_cmd $h "{ 'execute': 'query-named-block-nodes' }" "^}" |
80
- _filter_generated_node_ids
81
+ _filter_generated_node_ids | _filter_actual_image_size
82
83
_send_qemu_cmd $h "{ 'execute': 'quit' }" "^}"
84
wait=1 _cleanup_qemu
85
diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
86
index XXXXXXX..XXXXXXX 100644
87
--- a/tests/qemu-iotests/191.out
88
+++ b/tests/qemu-iotests/191.out
89
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
90
"filename": "TEST_DIR/t.qcow2.base",
91
"cluster-size": 65536,
92
"format": "qcow2",
93
- "actual-size": 397312,
94
+ "actual-size": SIZE,
95
"format-specific": {
96
"type": "qcow2",
97
"data": {
98
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
99
"filename": "TEST_DIR/t.qcow2.ovl2",
100
"cluster-size": 65536,
101
"format": "qcow2",
102
- "actual-size": 200704,
103
+ "actual-size": SIZE,
104
"format-specific": {
105
"type": "qcow2",
106
"data": {
107
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
108
"virtual-size": 197120,
109
"filename": "TEST_DIR/t.qcow2.ovl2",
110
"format": "file",
111
- "actual-size": 200704,
112
+ "actual-size": SIZE,
113
"dirty-flag": false
114
},
115
"iops_wr": 0,
116
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
117
"filename": "TEST_DIR/t.qcow2.base",
118
"cluster-size": 65536,
119
"format": "qcow2",
120
- "actual-size": 397312,
121
+ "actual-size": SIZE,
122
"format-specific": {
123
"type": "qcow2",
124
"data": {
125
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
126
"filename": "TEST_DIR/t.qcow2",
127
"cluster-size": 65536,
128
"format": "qcow2",
129
- "actual-size": 200704,
130
+ "actual-size": SIZE,
131
"format-specific": {
132
"type": "qcow2",
133
"data": {
134
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
135
"virtual-size": 197120,
136
"filename": "TEST_DIR/t.qcow2",
137
"format": "file",
138
- "actual-size": 200704,
139
+ "actual-size": SIZE,
140
"dirty-flag": false
141
},
142
"iops_wr": 0,
143
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
144
"filename": "TEST_DIR/t.qcow2.base",
145
"cluster-size": 65536,
146
"format": "qcow2",
147
- "actual-size": 397312,
148
+ "actual-size": SIZE,
149
"format-specific": {
150
"type": "qcow2",
151
"data": {
152
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
153
"filename": "TEST_DIR/t.qcow2.mid",
154
"cluster-size": 65536,
155
"format": "qcow2",
156
- "actual-size": 397312,
157
+ "actual-size": SIZE,
158
"format-specific": {
159
"type": "qcow2",
160
"data": {
161
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
162
"virtual-size": 393216,
163
"filename": "TEST_DIR/t.qcow2.mid",
164
"format": "file",
165
- "actual-size": 397312,
166
+ "actual-size": SIZE,
167
"dirty-flag": false
168
},
169
"iops_wr": 0,
170
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
171
"filename": "TEST_DIR/t.qcow2.base",
172
"cluster-size": 65536,
173
"format": "qcow2",
174
- "actual-size": 397312,
175
+ "actual-size": SIZE,
176
"format-specific": {
177
"type": "qcow2",
178
"data": {
179
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
180
"virtual-size": 393216,
181
"filename": "TEST_DIR/t.qcow2.base",
182
"format": "file",
183
- "actual-size": 397312,
184
+ "actual-size": SIZE,
185
"dirty-flag": false
186
},
187
"iops_wr": 0,
188
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
189
"filename": "TEST_DIR/t.qcow2.base",
190
"cluster-size": 65536,
191
"format": "qcow2",
192
- "actual-size": 397312,
193
+ "actual-size": SIZE,
194
"format-specific": {
195
"type": "qcow2",
196
"data": {
197
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
198
"filename": "TEST_DIR/t.qcow2.ovl2",
199
"cluster-size": 65536,
200
"format": "qcow2",
201
- "actual-size": 200704,
202
+ "actual-size": SIZE,
203
"format-specific": {
204
"type": "qcow2",
205
"data": {
206
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
207
"virtual-size": 197120,
208
"filename": "TEST_DIR/t.qcow2.ovl2",
209
"format": "file",
210
- "actual-size": 200704,
211
+ "actual-size": SIZE,
212
"dirty-flag": false
213
},
214
"iops_wr": 0,
215
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
216
"filename": "TEST_DIR/t.qcow2.base",
217
"cluster-size": 65536,
218
"format": "qcow2",
219
- "actual-size": 397312,
220
+ "actual-size": SIZE,
221
"format-specific": {
222
"type": "qcow2",
223
"data": {
224
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
225
"filename": "TEST_DIR/t.qcow2.ovl2",
226
"cluster-size": 65536,
227
"format": "qcow2",
228
- "actual-size": 200704,
229
+ "actual-size": SIZE,
230
"format-specific": {
231
"type": "qcow2",
232
"data": {
233
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
234
"filename": "TEST_DIR/t.qcow2.ovl3",
235
"cluster-size": 65536,
236
"format": "qcow2",
237
- "actual-size": 200704,
238
+ "actual-size": SIZE,
239
"format-specific": {
240
"type": "qcow2",
241
"data": {
242
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
243
"virtual-size": 197120,
244
"filename": "TEST_DIR/t.qcow2.ovl3",
245
"format": "file",
246
- "actual-size": 200704,
247
+ "actual-size": SIZE,
248
"dirty-flag": false
249
},
250
"iops_wr": 0,
251
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
252
"filename": "TEST_DIR/t.qcow2.base",
253
"cluster-size": 65536,
254
"format": "qcow2",
255
- "actual-size": 397312,
256
+ "actual-size": SIZE,
257
"format-specific": {
258
"type": "qcow2",
259
"data": {
260
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
261
"virtual-size": 393216,
262
"filename": "TEST_DIR/t.qcow2.base",
263
"format": "file",
264
- "actual-size": 397312,
265
+ "actual-size": SIZE,
266
"dirty-flag": false
267
},
268
"iops_wr": 0,
269
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
270
"filename": "TEST_DIR/t.qcow2.base",
271
"cluster-size": 65536,
272
"format": "qcow2",
273
- "actual-size": 397312,
274
+ "actual-size": SIZE,
275
"format-specific": {
276
"type": "qcow2",
277
"data": {
278
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
279
"filename": "TEST_DIR/t.qcow2",
280
"cluster-size": 65536,
281
"format": "qcow2",
282
- "actual-size": 200704,
283
+ "actual-size": SIZE,
284
"format-specific": {
285
"type": "qcow2",
286
"data": {
287
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
288
"virtual-size": 197120,
289
"filename": "TEST_DIR/t.qcow2",
290
"format": "file",
291
- "actual-size": 200704,
292
+ "actual-size": SIZE,
293
"dirty-flag": false
294
},
295
"iops_wr": 0,
296
--
72
--
297
2.13.6
73
2.37.3
298
299
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Now that bdrv_is_allocated accepts non-aligned inputs, we can
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
remove the TODO added in commit d6a644bb.
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
5
Message-Id: <20221013123711.620631-15-pbonzini@redhat.com>
6
Signed-off-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
8
---
10
block/io.c | 8 ++------
9
block/commit.c | 2 +-
11
1 file changed, 2 insertions(+), 6 deletions(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
12
11
13
diff --git a/block/io.c b/block/io.c
12
diff --git a/block/commit.c b/block/commit.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/block/io.c
14
--- a/block/commit.c
16
+++ b/block/io.c
15
+++ b/block/commit.c
17
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
18
}
17
}
19
18
20
if (flags & BDRV_REQ_COPY_ON_READ) {
19
if (base_len < len) {
21
- /* TODO: Simplify further once bdrv_is_allocated no longer
20
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
22
- * requires sector alignment */
21
+ ret = blk_co_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
23
- int64_t start = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
22
if (ret) {
24
- int64_t end = QEMU_ALIGN_UP(offset + bytes, BDRV_SECTOR_SIZE);
23
return ret;
25
int64_t pnum;
26
27
- ret = bdrv_is_allocated(bs, start, end - start, &pnum);
28
+ ret = bdrv_is_allocated(bs, offset, bytes, &pnum);
29
if (ret < 0) {
30
goto out;
31
}
32
33
- if (!ret || pnum != end - start) {
34
+ if (!ret || pnum != bytes) {
35
ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov);
36
goto out;
37
}
24
}
38
--
25
--
39
2.13.6
26
2.37.3
40
41
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Not all callers care about which BDS owns the mapping for a given
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
range of the file. This patch merely simplifies the callers by
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
consolidating the logic in the common call point, while guaranteeing
5
Message-Id: <20221013123711.620631-16-pbonzini@redhat.com>
6
a non-NULL file to all the driver callbacks, for no semantic change.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
The only caller that does not care about pnum is bdrv_is_allocated,
8
as invoked by vvfat; we can likewise add assertions that the rest
9
of the stack does not have to worry about a NULL pnum.
10
11
Furthermore, this will also set the stage for a future cleanup: when
12
a caller does not care about which BDS owns an offset, it would be
13
nice to allow the driver to optimize things to not have to return
14
BDRV_BLOCK_OFFSET_VALID in the first place. In the case of fragmented
15
allocation (for example, it's fairly easy to create a qcow2 image
16
where consecutive guest addresses are not at consecutive host
17
addresses), the current contract requires bdrv_get_block_status()
18
to clamp *pnum to the limit where host addresses are no longer
19
consecutive, but allowing a NULL file means that *pnum could be
20
set to the full length of known-allocated data.
21
22
Signed-off-by: Eric Blake <eblake@redhat.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
---
8
---
25
include/block/block_int.h | 10 ++++++----
9
block.c | 2 +-
26
block/io.c | 49 ++++++++++++++++++++++++++---------------------
10
block/io.c | 4 ++--
27
block/mirror.c | 3 +--
11
2 files changed, 3 insertions(+), 3 deletions(-)
28
block/qcow2.c | 8 ++------
29
qemu-img.c | 10 ++++------
30
5 files changed, 40 insertions(+), 40 deletions(-)
31
12
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
13
diff --git a/block.c b/block.c
33
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
15
--- a/block.c
35
+++ b/include/block/block_int.h
16
+++ b/block.c
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
17
@@ -XXX,XX +XXX,XX @@ create_file_fallback_zero_first_sector(BlockBackend *blk,
37
int64_t offset, int bytes);
18
38
19
bytes_to_clear = MIN(current_size, BDRV_SECTOR_SIZE);
39
/*
20
if (bytes_to_clear) {
40
- * Building block for bdrv_block_status[_above]. The driver should
21
- ret = blk_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
41
- * answer only according to the current layer, and should not
22
+ ret = blk_co_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
42
- * set BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
23
if (ret < 0) {
43
- * for the meaning of _DATA, _ZERO, and _OFFSET_VALID.
24
error_setg_errno(errp, -ret,
44
+ * Building block for bdrv_block_status[_above] and
25
"Failed to clear the new image's first sector");
45
+ * bdrv_is_allocated[_above]. The driver should answer only
46
+ * according to the current layer, and should not set
47
+ * BDRV_BLOCK_ALLOCATED, but may set BDRV_BLOCK_RAW. See block.h
48
+ * for the meaning of _DATA, _ZERO, and _OFFSET_VALID. The block
49
+ * layer guarantees non-NULL pnum and file.
50
*/
51
int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs,
52
int64_t sector_num, int nb_sectors, int *pnum,
53
diff --git a/block/io.c b/block/io.c
26
diff --git a/block/io.c b/block/io.c
54
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
55
--- a/block/io.c
28
--- a/block/io.c
56
+++ b/block/io.c
29
+++ b/block/io.c
57
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
30
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
58
{
31
return 1;
59
int64_t target_sectors, ret, nb_sectors, sector_num = 0;
60
BlockDriverState *bs = child->bs;
61
- BlockDriverState *file;
62
int n;
63
64
target_sectors = bdrv_nb_sectors(bs);
65
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
66
if (nb_sectors <= 0) {
67
return 0;
68
}
69
- ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n, &file);
70
+ ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n, NULL);
71
if (ret < 0) {
72
error_report("error getting block status at sector %" PRId64 ": %s",
73
sector_num, strerror(-ret));
74
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
75
* beyond the end of the disk image it will be clamped; if 'pnum' is set to
76
* the end of the image, then the returned value will include BDRV_BLOCK_EOF.
77
*
78
- * If returned value is positive and BDRV_BLOCK_OFFSET_VALID bit is set, 'file'
79
- * points to the BDS which the sector range is allocated in.
80
+ * If returned value is positive, BDRV_BLOCK_OFFSET_VALID bit is set, and
81
+ * 'file' is non-NULL, then '*file' points to the BDS which the sector range
82
+ * is allocated in.
83
*/
84
static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
85
int64_t sector_num,
86
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
87
int64_t total_sectors;
88
int64_t n;
89
int64_t ret, ret2;
90
+ BlockDriverState *local_file = NULL;
91
92
- *file = NULL;
93
+ assert(pnum);
94
+ *pnum = 0;
95
total_sectors = bdrv_nb_sectors(bs);
96
if (total_sectors < 0) {
97
- return total_sectors;
98
+ ret = total_sectors;
99
+ goto early_out;
100
}
32
}
101
33
102
if (sector_num >= total_sectors) {
34
- ret = bdrv_common_block_status_above(bs, NULL, false, false, offset,
103
- *pnum = 0;
35
- bytes, &pnum, NULL, NULL, NULL);
104
- return BDRV_BLOCK_EOF;
36
+ ret = bdrv_co_common_block_status_above(bs, NULL, false, false, offset,
105
+ ret = BDRV_BLOCK_EOF;
37
+ bytes, &pnum, NULL, NULL, NULL);
106
+ goto early_out;
38
107
}
108
if (!nb_sectors) {
109
- *pnum = 0;
110
- return 0;
111
+ ret = 0;
112
+ goto early_out;
113
}
114
115
n = total_sectors - sector_num;
116
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
117
}
118
if (bs->drv->protocol_name) {
119
ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
120
- *file = bs;
121
+ local_file = bs;
122
}
123
- return ret;
124
+ goto early_out;
125
}
126
127
bdrv_inc_in_flight(bs);
128
ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum,
129
- file);
130
+ &local_file);
131
if (ret < 0) {
132
*pnum = 0;
133
goto out;
134
}
135
136
if (ret & BDRV_BLOCK_RAW) {
137
- assert(ret & BDRV_BLOCK_OFFSET_VALID && *file);
138
- ret = bdrv_co_get_block_status(*file, ret >> BDRV_SECTOR_BITS,
139
- *pnum, pnum, file);
140
+ assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file);
141
+ ret = bdrv_co_get_block_status(local_file, ret >> BDRV_SECTOR_BITS,
142
+ *pnum, pnum, &local_file);
143
goto out;
144
}
145
146
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
147
}
148
}
149
150
- if (*file && *file != bs &&
151
+ if (local_file && local_file != bs &&
152
(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
153
(ret & BDRV_BLOCK_OFFSET_VALID)) {
154
- BlockDriverState *file2;
155
int file_pnum;
156
157
- ret2 = bdrv_co_get_block_status(*file, ret >> BDRV_SECTOR_BITS,
158
- *pnum, &file_pnum, &file2);
159
+ ret2 = bdrv_co_get_block_status(local_file, ret >> BDRV_SECTOR_BITS,
160
+ *pnum, &file_pnum, NULL);
161
if (ret2 >= 0) {
162
/* Ignore errors. This is just providing extra information, it
163
* is useful but not necessary.
164
@@ -XXX,XX +XXX,XX @@ out:
165
if (ret >= 0 && sector_num + *pnum == total_sectors) {
166
ret |= BDRV_BLOCK_EOF;
167
}
168
+early_out:
169
+ if (file) {
170
+ *file = local_file;
171
+ }
172
return ret;
173
}
174
175
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status(BlockDriverState *bs,
176
int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
177
int64_t bytes, int64_t *pnum)
178
{
179
- BlockDriverState *file;
180
int64_t sector_num = offset >> BDRV_SECTOR_BITS;
181
int nb_sectors = bytes >> BDRV_SECTOR_BITS;
182
int64_t ret;
183
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
184
assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
185
assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE) && bytes < INT_MAX);
186
ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &psectors,
187
- &file);
188
+ NULL);
189
if (ret < 0) {
39
if (ret < 0) {
190
return ret;
40
return ret;
191
}
192
diff --git a/block/mirror.c b/block/mirror.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/mirror.c
195
+++ b/block/mirror.c
196
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
197
int io_sectors;
198
unsigned int io_bytes;
199
int64_t io_bytes_acct;
200
- BlockDriverState *file;
201
enum MirrorMethod {
202
MIRROR_METHOD_COPY,
203
MIRROR_METHOD_ZERO,
204
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
205
ret = bdrv_get_block_status_above(source, NULL,
206
offset >> BDRV_SECTOR_BITS,
207
nb_chunks * sectors_per_chunk,
208
- &io_sectors, &file);
209
+ &io_sectors, NULL);
210
io_bytes = io_sectors * BDRV_SECTOR_SIZE;
211
if (ret < 0) {
212
io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
213
diff --git a/block/qcow2.c b/block/qcow2.c
214
index XXXXXXX..XXXXXXX 100644
215
--- a/block/qcow2.c
216
+++ b/block/qcow2.c
217
@@ -XXX,XX +XXX,XX @@ static bool is_zero_sectors(BlockDriverState *bs, int64_t start,
218
uint32_t count)
219
{
220
int nr;
221
- BlockDriverState *file;
222
int64_t res;
223
224
if (start + count > bs->total_sectors) {
225
@@ -XXX,XX +XXX,XX @@ static bool is_zero_sectors(BlockDriverState *bs, int64_t start,
226
if (!count) {
227
return true;
228
}
229
- res = bdrv_get_block_status_above(bs, NULL, start, count,
230
- &nr, &file);
231
+ res = bdrv_get_block_status_above(bs, NULL, start, count, &nr, NULL);
232
return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == count;
233
}
234
235
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
236
offset += pnum * BDRV_SECTOR_SIZE) {
237
int nb_sectors = MIN(ssize - offset,
238
BDRV_REQUEST_MAX_BYTES) / BDRV_SECTOR_SIZE;
239
- BlockDriverState *file;
240
int64_t ret;
241
242
ret = bdrv_get_block_status_above(in_bs, NULL,
243
offset >> BDRV_SECTOR_BITS,
244
- nb_sectors,
245
- &pnum, &file);
246
+ nb_sectors, &pnum, NULL);
247
if (ret < 0) {
248
error_setg_errno(&local_err, -ret,
249
"Unable to get block status");
250
diff --git a/qemu-img.c b/qemu-img.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/qemu-img.c
253
+++ b/qemu-img.c
254
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
255
256
for (;;) {
257
int64_t status1, status2;
258
- BlockDriverState *file;
259
260
nb_sectors = sectors_to_process(total_sectors, sector_num);
261
if (nb_sectors <= 0) {
262
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
263
}
264
status1 = bdrv_get_block_status_above(bs1, NULL, sector_num,
265
total_sectors1 - sector_num,
266
- &pnum1, &file);
267
+ &pnum1, NULL);
268
if (status1 < 0) {
269
ret = 3;
270
error_report("Sector allocation test failed for %s", filename1);
271
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
272
273
status2 = bdrv_get_block_status_above(bs2, NULL, sector_num,
274
total_sectors2 - sector_num,
275
- &pnum2, &file);
276
+ &pnum2, NULL);
277
if (status2 < 0) {
278
ret = 3;
279
error_report("Sector allocation test failed for %s", filename2);
280
@@ -XXX,XX +XXX,XX @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
281
n = MIN(s->total_sectors - sector_num, BDRV_REQUEST_MAX_SECTORS);
282
283
if (s->sector_next_status <= sector_num) {
284
- BlockDriverState *file;
285
if (s->target_has_backing) {
286
ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
287
sector_num - src_cur_offset,
288
- n, &n, &file);
289
+ n, &n, NULL);
290
} else {
291
ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
292
sector_num - src_cur_offset,
293
- n, &n, &file);
294
+ n, &n, NULL);
295
}
296
if (ret < 0) {
297
return ret;
298
--
41
--
299
2.13.6
42
2.37.3
300
301
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
In the process of converting sector-based interfaces to bytes,
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
I'm finding it easier to represent a byte count as a 64-bit
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
integer at the block layer (even if we are internally capped
5
Message-Id: <20221013123711.620631-17-pbonzini@redhat.com>
6
by SIZE_MAX or even INT_MAX for individual transactions, it's
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
still nicer to not have to worry about truncation/overflow
8
issues on as many variables). Update the signature of
9
bdrv_round_to_clusters() to uniformly use int64_t, matching
10
the signature already chosen for bdrv_is_allocated and the
11
fact that off_t is also a signed type, then adjust clients
12
according to the required fallout (even where the result could
13
now exceed 32 bits, no client is directly assigning the result
14
into a 32-bit value without breaking things into a loop first).
15
16
Signed-off-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
8
---
19
include/block/block.h | 4 ++--
9
block/mirror.c | 4 ++--
20
block/io.c | 6 +++---
10
1 file changed, 2 insertions(+), 2 deletions(-)
21
block/mirror.c | 7 +++----
22
block/trace-events | 2 +-
23
4 files changed, 9 insertions(+), 10 deletions(-)
24
11
25
diff --git a/include/block/block.h b/include/block/block.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block.h
28
+++ b/include/block/block.h
29
@@ -XXX,XX +XXX,XX @@ int bdrv_get_flags(BlockDriverState *bs);
30
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
31
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
32
void bdrv_round_to_clusters(BlockDriverState *bs,
33
- int64_t offset, unsigned int bytes,
34
+ int64_t offset, int64_t bytes,
35
int64_t *cluster_offset,
36
- unsigned int *cluster_bytes);
37
+ int64_t *cluster_bytes);
38
39
const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
40
void bdrv_get_backing_filename(BlockDriverState *bs,
41
diff --git a/block/io.c b/block/io.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block/io.c
44
+++ b/block/io.c
45
@@ -XXX,XX +XXX,XX @@ static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
46
* Round a region to cluster boundaries
47
*/
48
void bdrv_round_to_clusters(BlockDriverState *bs,
49
- int64_t offset, unsigned int bytes,
50
+ int64_t offset, int64_t bytes,
51
int64_t *cluster_offset,
52
- unsigned int *cluster_bytes)
53
+ int64_t *cluster_bytes)
54
{
55
BlockDriverInfo bdi;
56
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
58
struct iovec iov;
59
QEMUIOVector local_qiov;
60
int64_t cluster_offset;
61
- unsigned int cluster_bytes;
62
+ int64_t cluster_bytes;
63
size_t skip_bytes;
64
int ret;
65
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
66
diff --git a/block/mirror.c b/block/mirror.c
12
diff --git a/block/mirror.c b/block/mirror.c
67
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
68
--- a/block/mirror.c
14
--- a/block/mirror.c
69
+++ b/block/mirror.c
15
+++ b/block/mirror.c
70
@@ -XXX,XX +XXX,XX @@ static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
71
bool need_cow;
17
* active layer. */
72
int ret = 0;
18
if (s->base == blk_bs(s->target)) {
73
int64_t align_offset = *offset;
19
if (s->bdev_length > target_length) {
74
- unsigned int align_bytes = *bytes;
20
- ret = blk_truncate(s->target, s->bdev_length, false,
75
+ int64_t align_bytes = *bytes;
21
- PREALLOC_MODE_OFF, 0, NULL);
76
int max_bytes = s->granularity * s->max_iov;
22
+ ret = blk_co_truncate(s->target, s->bdev_length, false,
77
23
+ PREALLOC_MODE_OFF, 0, NULL);
78
- assert(*bytes < INT_MAX);
24
if (ret < 0) {
79
need_cow = !test_bit(*offset / s->granularity, s->cow_bitmap);
25
goto immediate_exit;
80
need_cow |= !test_bit((*offset + *bytes - 1) / s->granularity,
26
}
81
s->cow_bitmap);
82
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
83
while (nb_chunks > 0 && offset < s->bdev_length) {
84
int64_t ret;
85
int io_sectors;
86
- unsigned int io_bytes;
87
+ int64_t io_bytes;
88
int64_t io_bytes_acct;
89
enum MirrorMethod {
90
MIRROR_METHOD_COPY,
91
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
92
io_bytes = s->granularity;
93
} else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) {
94
int64_t target_offset;
95
- unsigned int target_bytes;
96
+ int64_t target_bytes;
97
bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
98
&target_offset, &target_bytes);
99
if (target_offset == offset &&
100
diff --git a/block/trace-events b/block/trace-events
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/trace-events
103
+++ b/block/trace-events
104
@@ -XXX,XX +XXX,XX @@ blk_co_pwritev(void *blk, void *bs, int64_t offset, unsigned int bytes, int flag
105
bdrv_co_preadv(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
106
bdrv_co_pwritev(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
107
bdrv_co_pwrite_zeroes(void *bs, int64_t offset, int count, int flags) "bs %p offset %"PRId64" count %d flags 0x%x"
108
-bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, unsigned int cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %u"
109
+bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, int64_t cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %"PRId64
110
111
# block/stream.c
112
stream_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d"
113
--
27
--
114
2.13.6
28
2.37.3
115
116
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
If a read error is encountered during 'qemu-img compare', we
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
were printing the "Error while reading offset ..." message twice;
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
this was because our helper function was awkward, printing output
5
Message-Id: <20221013123711.620631-18-pbonzini@redhat.com>
6
on some but not all paths. Fix it to consistently report errors
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
on all paths, so that the callers do not risk a redundant message,
8
and update the testsuite for the improved output.
9
10
Further simplify the code by hoisting the conversion from an error
11
message to an exit code into the helper function, rather than
12
repeating that logic at all callers (yes, the helper function is
13
now less generic, but it's a net win in lines of code).
14
15
Signed-off-by: Eric Blake <eblake@redhat.com>
16
Reviewed-by: John Snow <jsnow@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
8
---
19
qemu-img.c | 19 +++++--------------
9
block/parallels.c | 28 ++++++++++++++--------------
20
tests/qemu-iotests/074.out | 2 --
10
1 file changed, 14 insertions(+), 14 deletions(-)
21
2 files changed, 5 insertions(+), 16 deletions(-)
22
11
23
diff --git a/qemu-img.c b/qemu-img.c
12
diff --git a/block/parallels.c b/block/parallels.c
24
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
25
--- a/qemu-img.c
14
--- a/block/parallels.c
26
+++ b/qemu-img.c
15
+++ b/block/parallels.c
27
@@ -XXX,XX +XXX,XX @@ static int64_t sectors_to_bytes(int64_t sectors)
16
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
28
/*
17
* force the safer-but-slower fallocate.
29
* Check if passed sectors are empty (not allocated or contain only 0 bytes)
18
*/
30
*
19
if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
31
- * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero
20
- ret = bdrv_truncate(bs->file,
32
- * data and negative value on error.
21
- (s->data_end + space) << BDRV_SECTOR_BITS,
33
+ * Intended for use by 'qemu-img compare': Returns 0 in case sectors are
22
- false, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE,
34
+ * filled with 0, 1 if sectors contain non-zero data (this is a comparison
23
- NULL);
35
+ * failure), and 4 on error (the exit status for read errors), after emitting
24
+ ret = bdrv_co_truncate(bs->file,
36
+ * an error message.
25
+ (s->data_end + space) << BDRV_SECTOR_BITS,
37
*
26
+ false, PREALLOC_MODE_OFF,
38
* @param blk: BlockBackend for the image
27
+ BDRV_REQ_ZERO_WRITE, NULL);
39
* @param sect_num: Number of first sector to check
28
if (ret == -ENOTSUP) {
40
@@ -XXX,XX +XXX,XX @@ static int check_empty_sectors(BlockBackend *blk, int64_t sect_num,
29
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
41
if (ret < 0) {
42
error_report("Error while reading offset %" PRId64 " of %s: %s",
43
sectors_to_bytes(sect_num), filename, strerror(-ret));
44
- return ret;
45
+ return 4;
46
}
47
idx = find_nonzero(buffer, sect_count * BDRV_SECTOR_SIZE);
48
if (idx >= 0) {
49
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
50
filename2, buf1, quiet);
51
}
52
if (ret) {
53
- if (ret < 0) {
54
- error_report("Error while reading offset %" PRId64 ": %s",
55
- sectors_to_bytes(sector_num), strerror(-ret));
56
- ret = 4;
57
- }
58
goto out;
59
}
30
}
60
}
31
}
61
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
32
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
62
ret = check_empty_sectors(blk_over, sector_num, nb_sectors,
33
- ret = bdrv_pwrite_zeroes(bs->file,
63
filename_over, buf1, quiet);
34
- s->data_end << BDRV_SECTOR_BITS,
64
if (ret) {
35
- space << BDRV_SECTOR_BITS, 0);
65
- if (ret < 0) {
36
+ ret = bdrv_co_pwrite_zeroes(bs->file,
66
- error_report("Error while reading offset %" PRId64
37
+ s->data_end << BDRV_SECTOR_BITS,
67
- " of %s: %s", sectors_to_bytes(sector_num),
38
+ space << BDRV_SECTOR_BITS, 0);
68
- filename_over, strerror(-ret));
39
}
69
- ret = 4;
40
if (ret < 0) {
70
- }
41
return ret;
71
goto out;
42
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
72
}
43
if (off + to_write > s->header_size) {
73
}
44
to_write = s->header_size - off;
74
diff --git a/tests/qemu-iotests/074.out b/tests/qemu-iotests/074.out
45
}
75
index XXXXXXX..XXXXXXX 100644
46
- ret = bdrv_pwrite(bs->file, off, to_write, (uint8_t *)s->header + off,
76
--- a/tests/qemu-iotests/074.out
47
- 0);
77
+++ b/tests/qemu-iotests/074.out
48
+ ret = bdrv_co_pwrite(bs->file, off, to_write,
78
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
49
+ (uint8_t *)s->header + off, 0);
79
wrote 512/512 bytes at offset 512
50
if (ret < 0) {
80
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
51
qemu_co_mutex_unlock(&s->lock);
81
qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
52
return ret;
82
-qemu-img: Error while reading offset 0: Input/output error
53
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
83
4
54
* In order to really repair the image, we must shrink it.
84
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
55
* That means we have to pass exact=true.
85
Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0
56
*/
86
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0
57
- ret = bdrv_truncate(bs->file, res->image_end_offset, true,
87
wrote 512/512 bytes at offset 512
58
- PREALLOC_MODE_OFF, 0, &local_err);
88
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
59
+ ret = bdrv_co_truncate(bs->file, res->image_end_offset, true,
89
qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
60
+ PREALLOC_MODE_OFF, 0, &local_err);
90
-qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
61
if (ret < 0) {
91
Warning: Image size mismatch!
62
error_report_err(local_err);
92
4
63
res->check_errors++;
93
Cleanup
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
65
memset(tmp, 0, sizeof(tmp));
66
memcpy(tmp, &header, sizeof(header));
67
68
- ret = blk_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
69
+ ret = blk_co_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
70
if (ret < 0) {
71
goto exit;
72
}
73
- ret = blk_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
74
- (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
75
+ ret = blk_co_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
76
+ (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
77
if (ret < 0) {
78
goto exit;
79
}
94
--
80
--
95
2.13.6
81
2.37.3
96
97
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
bdrv_truncate() has an errp parameter which is always set when an error
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
occurs. Let's use that instead of a plain strerror().
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-19-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow.c | 45 +++++++++++++++++++++++----------------------
10
1 file changed, 23 insertions(+), 22 deletions(-)
5
11
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
diff --git a/block/qcow.c b/block/qcow.c
7
Message-id: 20171009155431.14093-1-mreitz@redhat.com
8
Reviewed-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/qcow2.c | 13 +++++++------
13
1 file changed, 7 insertions(+), 6 deletions(-)
14
15
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
14
--- a/block/qcow.c
18
+++ b/block/qcow2.c
15
+++ b/block/qcow.c
19
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
20
return last_cluster;
17
s->l1_table[l1_index] = l2_offset;
18
tmp = cpu_to_be64(l2_offset);
19
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
20
- ret = bdrv_pwrite_sync(bs->file,
21
- s->l1_table_offset + l1_index * sizeof(tmp),
22
- sizeof(tmp), &tmp, 0);
23
+ ret = bdrv_co_pwrite_sync(bs->file,
24
+ s->l1_table_offset + l1_index * sizeof(tmp),
25
+ sizeof(tmp), &tmp, 0);
26
if (ret < 0) {
27
return ret;
21
}
28
}
22
if ((last_cluster + 1) * s->cluster_size < old_file_size) {
29
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
23
- ret = bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
30
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
24
- PREALLOC_MODE_OFF, NULL);
31
if (new_l2_table) {
25
- if (ret < 0) {
32
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
26
- warn_report("Failed to truncate the tail of the image: %s",
33
- ret = bdrv_pwrite_sync(bs->file, l2_offset,
27
- strerror(-ret));
34
- s->l2_size * sizeof(uint64_t), l2_table, 0);
28
- ret = 0;
35
+ ret = bdrv_co_pwrite_sync(bs->file, l2_offset,
29
+ Error *local_err = NULL;
36
+ s->l2_size * sizeof(uint64_t), l2_table, 0);
30
+
37
if (ret < 0) {
31
+ bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
38
return ret;
32
+ PREALLOC_MODE_OFF, &local_err);
33
+ if (local_err) {
34
+ warn_reportf_err(local_err,
35
+ "Failed to truncate the tail of the image: ");
36
}
37
}
39
}
38
} else {
40
} else {
41
- ret = bdrv_pread(bs->file, l2_offset, s->l2_size * sizeof(uint64_t),
42
- l2_table, 0);
43
+ ret = bdrv_co_pread(bs->file, l2_offset,
44
+ s->l2_size * sizeof(uint64_t), l2_table, 0);
45
if (ret < 0) {
46
return ret;
47
}
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
49
cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
50
/* write the cluster content */
51
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
52
- ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_size,
53
- s->cluster_cache, 0);
54
+ ret = bdrv_co_pwrite(bs->file, cluster_offset, s->cluster_size,
55
+ s->cluster_cache, 0);
56
if (ret < 0) {
57
return ret;
58
}
59
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
60
if (cluster_offset + s->cluster_size > INT64_MAX) {
61
return -E2BIG;
62
}
63
- ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
64
- false, PREALLOC_MODE_OFF, 0, NULL);
65
+ ret = bdrv_co_truncate(bs->file,
66
+ cluster_offset + s->cluster_size,
67
+ false, PREALLOC_MODE_OFF, 0, NULL);
68
if (ret < 0) {
69
return ret;
70
}
71
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
72
return -EIO;
73
}
74
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
75
- ret = bdrv_pwrite(bs->file, cluster_offset + i,
76
- BDRV_SECTOR_SIZE,
77
- s->cluster_data, 0);
78
+ ret = bdrv_co_pwrite(bs->file, cluster_offset + i,
79
+ BDRV_SECTOR_SIZE,
80
+ s->cluster_data, 0);
81
if (ret < 0) {
82
return ret;
83
}
84
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
85
} else {
86
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
87
}
88
- ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
89
- sizeof(tmp), &tmp, 0);
90
+ ret = bdrv_co_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
91
+ sizeof(tmp), &tmp, 0);
92
if (ret < 0) {
93
return ret;
94
}
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn decompress_cluster(BlockDriverState *bs,
96
csize = cluster_offset >> (63 - s->cluster_bits);
97
csize &= (s->cluster_size - 1);
98
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
99
- ret = bdrv_pread(bs->file, coffset, csize, s->cluster_data, 0);
100
+ ret = bdrv_co_pread(bs->file, coffset, csize, s->cluster_data, 0);
101
if (ret < 0)
102
return -1;
103
if (decompress_buffer(s->cluster_cache, s->cluster_size,
104
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
105
}
106
107
/* write all the data */
108
- ret = blk_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
109
+ ret = blk_co_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
110
if (ret < 0) {
111
goto exit;
112
}
113
114
if (qcow_opts->has_backing_file) {
115
- ret = blk_pwrite(qcow_blk, sizeof(header), backing_filename_len,
116
- qcow_opts->backing_file, 0);
117
+ ret = blk_co_pwrite(qcow_blk, sizeof(header), backing_filename_len,
118
+ qcow_opts->backing_file, 0);
119
if (ret < 0) {
120
goto exit;
121
}
122
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
123
tmp = g_malloc0(BDRV_SECTOR_SIZE);
124
for (i = 0; i < DIV_ROUND_UP(sizeof(uint64_t) * l1_size, BDRV_SECTOR_SIZE);
125
i++) {
126
- ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
127
- BDRV_SECTOR_SIZE, tmp, 0);
128
+ ret = blk_co_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
129
+ BDRV_SECTOR_SIZE, tmp, 0);
130
if (ret < 0) {
131
g_free(tmp);
132
goto exit;
39
--
133
--
40
2.13.6
134
2.37.3
41
42
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
BDRV_SECTOR_BITS is defined to be 9 in block.h (and BDRV_SECTOR_SIZE
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
is calculated from that), but there are still a couple of places where
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
we are using the literal value instead of the macro.
5
Message-Id: <20221013123711.620631-20-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2-cluster.c | 8 ++++----
10
block/qcow2-refcount.c | 10 +++++-----
11
block/qcow2-snapshot.c | 6 +++---
12
block/qcow2.c | 24 ++++++++++++------------
13
4 files changed, 24 insertions(+), 24 deletions(-)
6
14
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
8
Message-id: 20171009153856.20387-1-berto@igalia.com
16
index XXXXXXX..XXXXXXX 100644
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
--- a/block/qcow2-cluster.c
10
---
18
+++ b/block/qcow2-cluster.c
11
block/qcow2.c | 4 ++--
19
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs,
12
1 file changed, 2 insertions(+), 2 deletions(-)
20
#endif
13
21
22
BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE);
23
- ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset +
24
- new_l1_size * L1E_SIZE,
25
- (s->l1_size - new_l1_size) * L1E_SIZE, 0);
26
+ ret = bdrv_co_pwrite_zeroes(bs->file,
27
+ s->l1_table_offset + new_l1_size * L1E_SIZE,
28
+ (s->l1_size - new_l1_size) * L1E_SIZE, 0);
29
if (ret < 0) {
30
goto fail;
31
}
32
33
- ret = bdrv_flush(bs->file->bs);
34
+ ret = bdrv_co_flush(bs->file->bs);
35
if (ret < 0) {
36
goto fail;
37
}
38
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/qcow2-refcount.c
41
+++ b/block/qcow2-refcount.c
42
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_refcount_init(BlockDriverState *bs)
43
goto fail;
44
}
45
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
46
- ret = bdrv_pread(bs->file, s->refcount_table_offset,
47
- refcount_table_size2, s->refcount_table, 0);
48
+ ret = bdrv_co_pread(bs->file, s->refcount_table_offset,
49
+ refcount_table_size2, s->refcount_table, 0);
50
if (ret < 0) {
51
goto fail;
52
}
53
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs)
54
reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]);
55
}
56
57
- ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset,
58
- s->refcount_table_size * REFTABLE_ENTRY_SIZE,
59
- reftable_tmp, 0);
60
+ ret = bdrv_co_pwrite_sync(bs->file, s->refcount_table_offset,
61
+ s->refcount_table_size * REFTABLE_ENTRY_SIZE,
62
+ reftable_tmp, 0);
63
/*
64
* If the write in the reftable failed the image may contain a partially
65
* overwritten reftable. In this case it would be better to clear the
66
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/qcow2-snapshot.c
69
+++ b/block/qcow2-snapshot.c
70
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
71
} QEMU_PACKED snapshot_table_pointer;
72
73
/* qcow2_do_open() discards this information in check mode */
74
- ret = bdrv_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
75
- sizeof(snapshot_table_pointer), &snapshot_table_pointer,
76
- 0);
77
+ ret = bdrv_co_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
78
+ sizeof(snapshot_table_pointer), &snapshot_table_pointer,
79
+ 0);
80
if (ret < 0) {
81
result->check_errors++;
82
fprintf(stderr, "ERROR failed to read the snapshot table pointer from "
14
diff --git a/block/qcow2.c b/block/qcow2.c
83
diff --git a/block/qcow2.c b/block/qcow2.c
15
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2.c
85
--- a/block/qcow2.c
17
+++ b/block/qcow2.c
86
+++ b/block/qcow2.c
18
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
19
88
uint64_t l1_vm_state_index;
20
s->cluster_bits = header.cluster_bits;
89
bool update_header = false;
21
s->cluster_size = 1 << s->cluster_bits;
90
22
- s->cluster_sectors = 1 << (s->cluster_bits - 9);
91
- ret = bdrv_pread(bs->file, 0, sizeof(header), &header, 0);
23
+ s->cluster_sectors = 1 << (s->cluster_bits - BDRV_SECTOR_BITS);
92
+ ret = bdrv_co_pread(bs->file, 0, sizeof(header), &header, 0);
24
25
/* Initialise version 3 header fields */
26
if (header.version == 2) {
27
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
28
29
bytes = MIN(INT_MAX, nb_sectors * BDRV_SECTOR_SIZE);
30
qemu_co_mutex_lock(&s->lock);
31
- ret = qcow2_get_cluster_offset(bs, sector_num << 9, &bytes,
32
+ ret = qcow2_get_cluster_offset(bs, sector_num << BDRV_SECTOR_BITS, &bytes,
33
&cluster_offset);
34
qemu_co_mutex_unlock(&s->lock);
35
if (ret < 0) {
93
if (ret < 0) {
94
error_setg_errno(errp, -ret, "Could not read qcow2 header");
95
goto fail;
96
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
97
if (header.header_length > sizeof(header)) {
98
s->unknown_header_fields_size = header.header_length - sizeof(header);
99
s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
100
- ret = bdrv_pread(bs->file, sizeof(header),
101
- s->unknown_header_fields_size,
102
- s->unknown_header_fields, 0);
103
+ ret = bdrv_co_pread(bs->file, sizeof(header),
104
+ s->unknown_header_fields_size,
105
+ s->unknown_header_fields, 0);
106
if (ret < 0) {
107
error_setg_errno(errp, -ret, "Could not read unknown qcow2 header "
108
"fields");
109
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
110
ret = -ENOMEM;
111
goto fail;
112
}
113
- ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
114
- s->l1_table, 0);
115
+ ret = bdrv_co_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
116
+ s->l1_table, 0);
117
if (ret < 0) {
118
error_setg_errno(errp, -ret, "Could not read L1 table");
119
goto fail;
120
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
121
}
122
123
s->image_backing_file = g_malloc(len + 1);
124
- ret = bdrv_pread(bs->file, header.backing_file_offset, len,
125
- s->image_backing_file, 0);
126
+ ret = bdrv_co_pread(bs->file, header.backing_file_offset, len,
127
+ s->image_backing_file, 0);
128
if (ret < 0) {
129
error_setg_errno(errp, -ret, "Could not read backing file name");
130
goto fail;
131
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
132
cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
133
}
134
135
- ret = blk_pwrite(blk, 0, cluster_size, header, 0);
136
+ ret = blk_co_pwrite(blk, 0, cluster_size, header, 0);
137
g_free(header);
138
if (ret < 0) {
139
error_setg_errno(errp, -ret, "Could not write qcow2 header");
140
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
141
/* Write a refcount table with one refcount block */
142
refcount_table = g_malloc0(2 * cluster_size);
143
refcount_table[0] = cpu_to_be64(2 * cluster_size);
144
- ret = blk_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
145
+ ret = blk_co_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
146
g_free(refcount_table);
147
148
if (ret < 0) {
149
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
150
}
151
152
/* Okay, now that we have a valid image, let's give it the right size */
153
- ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
154
- 0, errp);
155
+ ret = blk_co_truncate(blk, qcow2_opts->size, false,
156
+ qcow2_opts->preallocation, 0, errp);
157
if (ret < 0) {
158
error_prepend(errp, "Could not resize image: ");
159
goto out;
36
--
160
--
37
2.13.6
161
2.37.3
38
39
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
In the continuing quest to make more things byte-based, change
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
the internal iteration of img_compare(). We can finally drop the
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
TODO assertions added earlier, now that the entire algorithm is
5
Message-Id: <20221013123711.620631-21-pbonzini@redhat.com>
6
byte-based and no longer has to shift from bytes to sectors.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
8
Most of the change is mechanical ('total_sectors' becomes
9
'total_size', 'sector_num' becomes 'offset', 'nb_sectors' becomes
10
'chunk', 'progress_base' goes from sectors to bytes); some of it
11
is also a cleanup (sectors_to_bytes() is now unused, loss of
12
variable 'count' added earlier in commit 51b0a488).
13
14
Signed-off-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: John Snow <jsnow@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
8
---
18
qemu-img.c | 124 ++++++++++++++++++++++++-------------------------------------
9
block/qed-table.c | 2 +-
19
1 file changed, 48 insertions(+), 76 deletions(-)
10
block/qed.c | 12 ++++++------
11
2 files changed, 7 insertions(+), 7 deletions(-)
20
12
21
diff --git a/qemu-img.c b/qemu-img.c
13
diff --git a/block/qed-table.c b/block/qed-table.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/qemu-img.c
15
--- a/block/qed-table.c
24
+++ b/qemu-img.c
16
+++ b/block/qed-table.c
25
@@ -XXX,XX +XXX,XX @@ static int compare_buffers(const uint8_t *buf1, const uint8_t *buf2,
17
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
26
18
}
27
#define IO_BUF_SIZE (2 * 1024 * 1024)
19
28
20
if (flush) {
29
-static int64_t sectors_to_bytes(int64_t sectors)
21
- ret = bdrv_flush(s->bs);
30
-{
22
+ ret = bdrv_co_flush(s->bs);
31
- return sectors << BDRV_SECTOR_BITS;
23
if (ret < 0) {
32
-}
24
goto out;
33
-
25
}
34
/*
26
diff --git a/block/qed.c b/block/qed.c
35
* Check if passed sectors are empty (not allocated or contain only 0 bytes)
27
index XXXXXXX..XXXXXXX 100644
36
*
28
--- a/block/qed.c
37
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
29
+++ b/block/qed.c
38
const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
39
BlockBackend *blk1, *blk2;
31
int64_t file_size;
40
BlockDriverState *bs1, *bs2;
32
int ret;
41
- int64_t total_sectors1, total_sectors2;
33
42
+ int64_t total_size1, total_size2;
34
- ret = bdrv_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
43
uint8_t *buf1 = NULL, *buf2 = NULL;
35
+ ret = bdrv_co_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
44
int64_t pnum1, pnum2;
36
if (ret < 0) {
45
int allocated1, allocated2;
37
error_setg(errp, "Failed to read QED header");
46
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
38
return ret;
47
bool progress = false, quiet = false, strict = false;
39
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
48
int flags;
40
}
49
bool writethrough;
41
50
- int64_t total_sectors;
42
/* From here on only known autoclear feature bits are valid */
51
- int64_t sector_num = 0;
43
- bdrv_flush(bs->file->bs);
52
- int64_t nb_sectors;
44
+ bdrv_co_flush(bs->file->bs);
53
+ int64_t total_size;
45
}
54
+ int64_t offset = 0;
46
55
+ int64_t chunk;
47
s->l1_table = qed_alloc_table(s);
56
int c;
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
57
uint64_t progress_base;
49
* The QED format associates file length with allocation status,
58
bool image_opts = false;
50
* so a new file (which is empty) must have a length of 0.
59
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
51
*/
60
52
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
61
buf1 = blk_blockalign(blk1, IO_BUF_SIZE);
53
+ ret = blk_co_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
62
buf2 = blk_blockalign(blk2, IO_BUF_SIZE);
54
if (ret < 0) {
63
- total_sectors1 = blk_nb_sectors(blk1);
64
- if (total_sectors1 < 0) {
65
+ total_size1 = blk_getlength(blk1);
66
+ if (total_size1 < 0) {
67
error_report("Can't get size of %s: %s",
68
- filename1, strerror(-total_sectors1));
69
+ filename1, strerror(-total_size1));
70
ret = 4;
71
goto out;
55
goto out;
72
}
56
}
73
- total_sectors2 = blk_nb_sectors(blk2);
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
74
- if (total_sectors2 < 0) {
58
}
75
+ total_size2 = blk_getlength(blk2);
59
76
+ if (total_size2 < 0) {
60
qed_header_cpu_to_le(&header, &le_header);
77
error_report("Can't get size of %s: %s",
61
- ret = blk_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
78
- filename2, strerror(-total_sectors2));
62
+ ret = blk_co_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
79
+ filename2, strerror(-total_size2));
63
if (ret < 0) {
80
ret = 4;
81
goto out;
64
goto out;
82
}
65
}
83
- total_sectors = MIN(total_sectors1, total_sectors2);
66
- ret = blk_pwrite(blk, sizeof(le_header), header.backing_filename_size,
84
- progress_base = MAX(total_sectors1, total_sectors2);
67
+ ret = blk_co_pwrite(blk, sizeof(le_header), header.backing_filename_size,
85
+ total_size = MIN(total_size1, total_size2);
68
qed_opts->backing_file, 0);
86
+ progress_base = MAX(total_size1, total_size2);
69
if (ret < 0) {
87
88
qemu_progress_print(0, 100);
89
90
- if (strict && total_sectors1 != total_sectors2) {
91
+ if (strict && total_size1 != total_size2) {
92
ret = 1;
93
qprintf(quiet, "Strict mode: Image size mismatch!\n");
94
goto out;
70
goto out;
95
}
71
}
96
72
97
- while (sector_num < total_sectors) {
73
l1_table = g_malloc0(l1_size);
98
+ while (offset < total_size) {
74
- ret = blk_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
99
int status1, status2;
75
+ ret = blk_co_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
100
76
if (ret < 0) {
101
- status1 = bdrv_block_status_above(bs1, NULL,
77
goto out;
102
- sector_num * BDRV_SECTOR_SIZE,
103
- (total_sectors1 - sector_num) *
104
- BDRV_SECTOR_SIZE,
105
- &pnum1, NULL, NULL);
106
+ status1 = bdrv_block_status_above(bs1, NULL, offset,
107
+ total_size1 - offset, &pnum1, NULL,
108
+ NULL);
109
if (status1 < 0) {
110
ret = 3;
111
error_report("Sector allocation test failed for %s", filename1);
112
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
113
}
114
allocated1 = status1 & BDRV_BLOCK_ALLOCATED;
115
116
- status2 = bdrv_block_status_above(bs2, NULL,
117
- sector_num * BDRV_SECTOR_SIZE,
118
- (total_sectors2 - sector_num) *
119
- BDRV_SECTOR_SIZE,
120
- &pnum2, NULL, NULL);
121
+ status2 = bdrv_block_status_above(bs2, NULL, offset,
122
+ total_size2 - offset, &pnum2, NULL,
123
+ NULL);
124
if (status2 < 0) {
125
ret = 3;
126
error_report("Sector allocation test failed for %s", filename2);
127
goto out;
128
}
129
allocated2 = status2 & BDRV_BLOCK_ALLOCATED;
130
- /* TODO: Relax this once comparison is byte-based, and we no longer
131
- * have to worry about sector alignment */
132
- assert(QEMU_IS_ALIGNED(pnum1 | pnum2, BDRV_SECTOR_SIZE));
133
134
assert(pnum1 && pnum2);
135
- nb_sectors = MIN(pnum1, pnum2) >> BDRV_SECTOR_BITS;
136
+ chunk = MIN(pnum1, pnum2);
137
138
if (strict) {
139
if (status1 != status2) {
140
ret = 1;
141
qprintf(quiet, "Strict mode: Offset %" PRId64
142
- " block status mismatch!\n",
143
- sectors_to_bytes(sector_num));
144
+ " block status mismatch!\n", offset);
145
goto out;
146
}
147
}
148
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
149
if (allocated1) {
150
int64_t pnum;
151
152
- nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
153
- ret = blk_pread(blk1, sector_num << BDRV_SECTOR_BITS, buf1,
154
- nb_sectors << BDRV_SECTOR_BITS);
155
+ chunk = MIN(chunk, IO_BUF_SIZE);
156
+ ret = blk_pread(blk1, offset, buf1, chunk);
157
if (ret < 0) {
158
- error_report("Error while reading offset %" PRId64 " of %s:"
159
- " %s", sectors_to_bytes(sector_num), filename1,
160
- strerror(-ret));
161
+ error_report("Error while reading offset %" PRId64
162
+ " of %s: %s",
163
+ offset, filename1, strerror(-ret));
164
ret = 4;
165
goto out;
166
}
167
- ret = blk_pread(blk2, sector_num << BDRV_SECTOR_BITS, buf2,
168
- nb_sectors << BDRV_SECTOR_BITS);
169
+ ret = blk_pread(blk2, offset, buf2, chunk);
170
if (ret < 0) {
171
error_report("Error while reading offset %" PRId64
172
- " of %s: %s", sectors_to_bytes(sector_num),
173
- filename2, strerror(-ret));
174
+ " of %s: %s",
175
+ offset, filename2, strerror(-ret));
176
ret = 4;
177
goto out;
178
}
179
- ret = compare_buffers(buf1, buf2,
180
- nb_sectors * BDRV_SECTOR_SIZE, &pnum);
181
- if (ret || pnum != nb_sectors * BDRV_SECTOR_SIZE) {
182
+ ret = compare_buffers(buf1, buf2, chunk, &pnum);
183
+ if (ret || pnum != chunk) {
184
qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
185
- sectors_to_bytes(sector_num) + (ret ? 0 : pnum));
186
+ offset + (ret ? 0 : pnum));
187
ret = 1;
188
goto out;
189
}
190
}
191
} else {
192
- nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
193
+ chunk = MIN(chunk, IO_BUF_SIZE);
194
if (allocated1) {
195
- ret = check_empty_sectors(blk1, sector_num * BDRV_SECTOR_SIZE,
196
- nb_sectors * BDRV_SECTOR_SIZE,
197
+ ret = check_empty_sectors(blk1, offset, chunk,
198
filename1, buf1, quiet);
199
} else {
200
- ret = check_empty_sectors(blk2, sector_num * BDRV_SECTOR_SIZE,
201
- nb_sectors * BDRV_SECTOR_SIZE,
202
+ ret = check_empty_sectors(blk2, offset, chunk,
203
filename2, buf1, quiet);
204
}
205
if (ret) {
206
goto out;
207
}
208
}
209
- sector_num += nb_sectors;
210
- qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
211
+ offset += chunk;
212
+ qemu_progress_print(((float) chunk / progress_base) * 100, 100);
213
}
78
}
214
215
- if (total_sectors1 != total_sectors2) {
216
+ if (total_size1 != total_size2) {
217
BlockBackend *blk_over;
218
const char *filename_over;
219
220
qprintf(quiet, "Warning: Image size mismatch!\n");
221
- if (total_sectors1 > total_sectors2) {
222
+ if (total_size1 > total_size2) {
223
blk_over = blk1;
224
filename_over = filename1;
225
} else {
226
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
227
filename_over = filename2;
228
}
229
230
- while (sector_num < progress_base) {
231
- int64_t count;
232
-
233
- ret = bdrv_block_status_above(blk_bs(blk_over), NULL,
234
- sector_num * BDRV_SECTOR_SIZE,
235
- (progress_base - sector_num) *
236
- BDRV_SECTOR_SIZE,
237
- &count, NULL, NULL);
238
+ while (offset < progress_base) {
239
+ ret = bdrv_block_status_above(blk_bs(blk_over), NULL, offset,
240
+ progress_base - offset, &chunk,
241
+ NULL, NULL);
242
if (ret < 0) {
243
ret = 3;
244
error_report("Sector allocation test failed for %s",
245
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
246
goto out;
247
248
}
249
- /* TODO relax this once bdrv_block_status_above does not enforce
250
- * sector alignment */
251
- assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
252
- nb_sectors = count >> BDRV_SECTOR_BITS;
253
if (ret & BDRV_BLOCK_ALLOCATED && !(ret & BDRV_BLOCK_ZERO)) {
254
- nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
255
- ret = check_empty_sectors(blk_over,
256
- sector_num * BDRV_SECTOR_SIZE,
257
- nb_sectors * BDRV_SECTOR_SIZE,
258
+ chunk = MIN(chunk, IO_BUF_SIZE);
259
+ ret = check_empty_sectors(blk_over, offset, chunk,
260
filename_over, buf1, quiet);
261
if (ret) {
262
goto out;
263
}
264
}
265
- sector_num += nb_sectors;
266
- qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
267
+ offset += chunk;
268
+ qemu_progress_print(((float) chunk / progress_base) * 100, 100);
269
}
270
}
271
272
--
79
--
273
2.13.6
80
2.37.3
274
275
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
In the continuing quest to make more things byte-based, change
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
the internal iteration of img_rebase(). We can finally drop the
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
TODO assertion added earlier, now that the entire algorithm is
5
Message-Id: <20221013123711.620631-22-pbonzini@redhat.com>
6
byte-based and no longer has to shift from bytes to sectors.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
8
Most of the change is mechanical ('num_sectors' becomes 'size',
9
'sector' becomes 'offset', 'n' goes from sectors to bytes); some
10
of it is also a cleanup (use of MIN() instead of open-coding,
11
loss of variable 'count' added earlier in commit d6a644bb).
12
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: John Snow <jsnow@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
8
---
17
qemu-img.c | 84 +++++++++++++++++++++++++-------------------------------------
9
block/vdi.c | 17 +++++++++--------
18
1 file changed, 34 insertions(+), 50 deletions(-)
10
1 file changed, 9 insertions(+), 8 deletions(-)
19
11
20
diff --git a/qemu-img.c b/qemu-img.c
12
diff --git a/block/vdi.c b/block/vdi.c
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/qemu-img.c
14
--- a/block/vdi.c
23
+++ b/qemu-img.c
15
+++ b/block/vdi.c
24
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
16
@@ -XXX,XX +XXX,XX @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
25
* the image is the same as the original one at any time.
17
* so this full-cluster write does not overlap a partial write
26
*/
18
* of the same cluster, issued from the "else" branch.
27
if (!unsafe) {
19
*/
28
- int64_t num_sectors;
20
- ret = bdrv_pwrite(bs->file, data_offset, s->block_size, block, 0);
29
- int64_t old_backing_num_sectors;
21
+ ret = bdrv_co_pwrite(bs->file, data_offset, s->block_size, block,
30
- int64_t new_backing_num_sectors = 0;
22
+ 0);
31
- uint64_t sector;
23
qemu_co_rwlock_unlock(&s->bmap_lock);
32
- int n;
24
} else {
33
- int64_t count;
25
nonallocating_write:
34
+ int64_t size;
26
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
35
+ int64_t old_backing_size;
27
assert(VDI_IS_ALLOCATED(bmap_first));
36
+ int64_t new_backing_size = 0;
28
*header = s->header;
37
+ uint64_t offset;
29
vdi_header_to_le(header);
38
+ int64_t n;
30
- ret = bdrv_pwrite(bs->file, 0, sizeof(*header), header, 0);
39
float local_progress = 0;
31
+ ret = bdrv_co_pwrite(bs->file, 0, sizeof(*header), header, 0);
40
32
g_free(header);
41
buf_old = blk_blockalign(blk, IO_BUF_SIZE);
33
42
buf_new = blk_blockalign(blk, IO_BUF_SIZE);
34
if (ret < 0) {
43
35
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
44
- num_sectors = blk_nb_sectors(blk);
36
base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
45
- if (num_sectors < 0) {
37
logout("will write %u block map sectors starting from entry %u\n",
46
+ size = blk_getlength(blk);
38
n_sectors, bmap_first);
47
+ if (size < 0) {
39
- ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE,
48
error_report("Could not get size of '%s': %s",
40
- n_sectors * SECTOR_SIZE, base, 0);
49
- filename, strerror(-num_sectors));
41
+ ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE,
50
+ filename, strerror(-size));
42
+ n_sectors * SECTOR_SIZE, base, 0);
51
ret = -1;
43
}
52
goto out;
44
53
}
45
return ret;
54
- old_backing_num_sectors = blk_nb_sectors(blk_old_backing);
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
55
- if (old_backing_num_sectors < 0) {
47
vdi_header_print(&header);
56
+ old_backing_size = blk_getlength(blk_old_backing);
48
}
57
+ if (old_backing_size < 0) {
49
vdi_header_to_le(&header);
58
char backing_name[PATH_MAX];
50
- ret = blk_pwrite(blk, offset, sizeof(header), &header, 0);
59
51
+ ret = blk_co_pwrite(blk, offset, sizeof(header), &header, 0);
60
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
52
if (ret < 0) {
61
error_report("Could not get size of '%s': %s",
53
error_setg(errp, "Error writing header");
62
- backing_name, strerror(-old_backing_num_sectors));
54
goto exit;
63
+ backing_name, strerror(-old_backing_size));
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
64
ret = -1;
56
bmap[i] = VDI_UNALLOCATED;
65
goto out;
66
}
67
if (blk_new_backing) {
68
- new_backing_num_sectors = blk_nb_sectors(blk_new_backing);
69
- if (new_backing_num_sectors < 0) {
70
+ new_backing_size = blk_getlength(blk_new_backing);
71
+ if (new_backing_size < 0) {
72
error_report("Could not get size of '%s': %s",
73
- out_baseimg, strerror(-new_backing_num_sectors));
74
+ out_baseimg, strerror(-new_backing_size));
75
ret = -1;
76
goto out;
77
}
57
}
78
}
58
}
79
59
- ret = blk_pwrite(blk, offset, bmap_size, bmap, 0);
80
- if (num_sectors != 0) {
60
+ ret = blk_co_pwrite(blk, offset, bmap_size, bmap, 0);
81
- local_progress = (float)100 /
61
if (ret < 0) {
82
- (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
62
error_setg(errp, "Error writing bmap");
83
+ if (size != 0) {
63
goto exit;
84
+ local_progress = (float)100 / (size / MIN(size, IO_BUF_SIZE));
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
85
}
65
}
86
66
87
- for (sector = 0; sector < num_sectors; sector += n) {
67
if (image_type == VDI_TYPE_STATIC) {
88
-
68
- ret = blk_truncate(blk, offset + blocks * block_size, false,
89
- /* How many sectors can we handle with the next read? */
69
- PREALLOC_MODE_OFF, 0, errp);
90
- if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
70
+ ret = blk_co_truncate(blk, offset + blocks * block_size, false,
91
- n = (IO_BUF_SIZE / 512);
71
+ PREALLOC_MODE_OFF, 0, errp);
92
- } else {
72
if (ret < 0) {
93
- n = num_sectors - sector;
73
error_prepend(errp, "Failed to statically allocate file");
94
- }
74
goto exit;
95
+ for (offset = 0; offset < size; offset += n) {
96
+ /* How many bytes can we handle with the next read? */
97
+ n = MIN(IO_BUF_SIZE, size - offset);
98
99
/* If the cluster is allocated, we don't need to take action */
100
- ret = bdrv_is_allocated(bs, sector << BDRV_SECTOR_BITS,
101
- n << BDRV_SECTOR_BITS, &count);
102
+ ret = bdrv_is_allocated(bs, offset, n, &n);
103
if (ret < 0) {
104
error_report("error while reading image metadata: %s",
105
strerror(-ret));
106
goto out;
107
}
108
- /* TODO relax this once bdrv_is_allocated does not enforce
109
- * sector alignment */
110
- assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
111
- n = count >> BDRV_SECTOR_BITS;
112
if (ret) {
113
continue;
114
}
115
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
116
* Read old and new backing file and take into consideration that
117
* backing files may be smaller than the COW image.
118
*/
119
- if (sector >= old_backing_num_sectors) {
120
- memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
121
+ if (offset >= old_backing_size) {
122
+ memset(buf_old, 0, n);
123
} else {
124
- if (sector + n > old_backing_num_sectors) {
125
- n = old_backing_num_sectors - sector;
126
+ if (offset + n > old_backing_size) {
127
+ n = old_backing_size - offset;
128
}
129
130
- ret = blk_pread(blk_old_backing, sector << BDRV_SECTOR_BITS,
131
- buf_old, n << BDRV_SECTOR_BITS);
132
+ ret = blk_pread(blk_old_backing, offset, buf_old, n);
133
if (ret < 0) {
134
error_report("error while reading from old backing file");
135
goto out;
136
}
137
}
138
139
- if (sector >= new_backing_num_sectors || !blk_new_backing) {
140
- memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
141
+ if (offset >= new_backing_size || !blk_new_backing) {
142
+ memset(buf_new, 0, n);
143
} else {
144
- if (sector + n > new_backing_num_sectors) {
145
- n = new_backing_num_sectors - sector;
146
+ if (offset + n > new_backing_size) {
147
+ n = new_backing_size - offset;
148
}
149
150
- ret = blk_pread(blk_new_backing, sector << BDRV_SECTOR_BITS,
151
- buf_new, n << BDRV_SECTOR_BITS);
152
+ ret = blk_pread(blk_new_backing, offset, buf_new, n);
153
if (ret < 0) {
154
error_report("error while reading from new backing file");
155
goto out;
156
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
157
/* If they differ, we need to write to the COW file */
158
uint64_t written = 0;
159
160
- while (written < n * BDRV_SECTOR_SIZE) {
161
+ while (written < n) {
162
int64_t pnum;
163
164
- if (compare_buffers(buf_old + written,
165
- buf_new + written,
166
- n * BDRV_SECTOR_SIZE - written, &pnum))
167
+ if (compare_buffers(buf_old + written, buf_new + written,
168
+ n - written, &pnum))
169
{
170
- ret = blk_pwrite(blk,
171
- (sector << BDRV_SECTOR_BITS) + written,
172
+ ret = blk_pwrite(blk, offset + written,
173
buf_old + written, pnum, 0);
174
if (ret < 0) {
175
error_report("Error while writing to COW image: %s",
176
--
75
--
177
2.13.6
76
2.37.3
178
179
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Compare the following images with all-zero contents:
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
$ truncate --size 1M A
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
$ qemu-img create -f qcow2 -o preallocation=off B 1G
5
Message-Id: <20221013123711.620631-23-pbonzini@redhat.com>
6
$ qemu-img create -f qcow2 -o preallocation=metadata C 1G
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
8
On my machine, the difference is noticeable for pre-patch speeds,
9
with more than an order of magnitude in difference caused by the
10
choice of preallocation in the qcow2 file:
11
12
$ time ./qemu-img compare -f raw -F qcow2 A B
13
Warning: Image size mismatch!
14
Images are identical.
15
16
real    0m0.014s
17
user    0m0.007s
18
sys    0m0.007s
19
20
$ time ./qemu-img compare -f raw -F qcow2 A C
21
Warning: Image size mismatch!
22
Images are identical.
23
24
real    0m0.341s
25
user    0m0.144s
26
sys    0m0.188s
27
28
Why? Because bdrv_is_allocated() returns false for image B but
29
true for image C, throwing away the fact that both images know
30
via lseek(SEEK_HOLE) that the entire image still reads as zero.
31
From there, qemu-img ends up calling bdrv_pread() for every byte
32
of the tail, instead of quickly looking for the next allocation.
33
The solution: use block_status instead of is_allocated, giving:
34
35
$ time ./qemu-img compare -f raw -F qcow2 A C
36
Warning: Image size mismatch!
37
Images are identical.
38
39
real    0m0.014s
40
user    0m0.011s
41
sys    0m0.003s
42
43
which is on par with the speeds for no pre-allocation.
44
45
Signed-off-by: Eric Blake <eblake@redhat.com>
46
Reviewed-by: John Snow <jsnow@redhat.com>
47
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
48
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
49
---
8
---
50
qemu-img.c | 8 ++++----
9
block/vhdx.c | 8 ++++----
51
1 file changed, 4 insertions(+), 4 deletions(-)
10
1 file changed, 4 insertions(+), 4 deletions(-)
52
11
53
diff --git a/qemu-img.c b/qemu-img.c
12
diff --git a/block/vhdx.c b/block/vhdx.c
54
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
55
--- a/qemu-img.c
14
--- a/block/vhdx.c
56
+++ b/qemu-img.c
15
+++ b/block/vhdx.c
57
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
58
while (sector_num < progress_base) {
17
creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL,
59
int64_t count;
18
&creator_items, NULL);
60
19
signature = cpu_to_le64(VHDX_FILE_SIGNATURE);
61
- ret = bdrv_is_allocated_above(blk_bs(blk_over), NULL,
20
- ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
62
+ ret = bdrv_block_status_above(blk_bs(blk_over), NULL,
21
- 0);
63
sector_num * BDRV_SECTOR_SIZE,
22
+ ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
64
(progress_base - sector_num) *
23
+ 0);
65
BDRV_SECTOR_SIZE,
24
if (ret < 0) {
66
- &count);
25
error_setg_errno(errp, -ret, "Failed to write file signature");
67
+ &count, NULL, NULL);
26
goto delete_and_exit;
68
if (ret < 0) {
27
}
69
ret = 3;
28
if (creator) {
70
error_report("Sector allocation test failed for %s",
29
- ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
71
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
30
- creator_items * sizeof(gunichar2), creator, 0);
72
goto out;
31
+ ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
73
32
+ creator_items * sizeof(gunichar2), creator, 0);
74
}
33
if (ret < 0) {
75
- /* TODO relax this once bdrv_is_allocated_above does not enforce
34
error_setg_errno(errp, -ret, "Failed to write creator field");
76
+ /* TODO relax this once bdrv_block_status_above does not enforce
35
goto delete_and_exit;
77
* sector alignment */
78
assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
79
nb_sectors = count >> BDRV_SECTOR_BITS;
80
- if (ret) {
81
+ if (ret & BDRV_BLOCK_ALLOCATED && !(ret & BDRV_BLOCK_ZERO)) {
82
nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
83
ret = check_empty_sectors(blk_over, sector_num, nb_sectors,
84
filename_over, buf1, quiet);
85
--
36
--
86
2.13.6
37
2.37.3
87
88
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Continue on the quest to make more things byte-based instead of
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
sector-based.
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
5
Message-Id: <20221013123711.620631-24-pbonzini@redhat.com>
6
Signed-off-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
8
---
10
qemu-img.c | 27 +++++++++++++++------------
9
block/vmdk.c | 54 ++++++++++++++++++++++++++--------------------------
11
1 file changed, 15 insertions(+), 12 deletions(-)
10
1 file changed, 27 insertions(+), 27 deletions(-)
12
11
13
diff --git a/qemu-img.c b/qemu-img.c
12
diff --git a/block/vmdk.c b/block/vmdk.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/qemu-img.c
14
--- a/block/vmdk.c
16
+++ b/qemu-img.c
15
+++ b/block/vmdk.c
17
@@ -XXX,XX +XXX,XX @@ static int64_t sectors_to_bytes(int64_t sectors)
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
18
* an error message.
17
if (copy_from_backing) {
19
*
18
/* qcow2 emits this on bs->file instead of bs->backing */
20
* @param blk: BlockBackend for the image
19
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
21
- * @param sect_num: Number of first sector to check
20
- ret = bdrv_pread(bs->backing, offset, skip_start_bytes,
22
- * @param sect_count: Number of sectors to check
21
- whole_grain, 0);
23
+ * @param offset: Starting offset to check
22
+ ret = bdrv_co_pread(bs->backing, offset, skip_start_bytes,
24
+ * @param bytes: Number of bytes to check
23
+ whole_grain, 0);
25
* @param filename: Name of disk file we are checking (logging purpose)
24
if (ret < 0) {
26
* @param buffer: Allocated buffer for storing read data
25
ret = VMDK_ERROR;
27
* @param quiet: Flag for quiet mode
26
goto exit;
28
*/
27
}
29
-static int check_empty_sectors(BlockBackend *blk, int64_t sect_num,
28
}
30
- int sect_count, const char *filename,
29
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
31
+static int check_empty_sectors(BlockBackend *blk, int64_t offset,
30
- ret = bdrv_pwrite(extent->file, cluster_offset, skip_start_bytes,
32
+ int64_t bytes, const char *filename,
31
- whole_grain, 0);
33
uint8_t *buffer, bool quiet)
32
+ ret = bdrv_co_pwrite(extent->file, cluster_offset, skip_start_bytes,
34
{
33
+ whole_grain, 0);
35
int ret = 0;
34
if (ret < 0) {
36
int64_t idx;
35
ret = VMDK_ERROR;
37
36
goto exit;
38
- ret = blk_pread(blk, sect_num << BDRV_SECTOR_BITS, buffer,
37
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
39
- sect_count << BDRV_SECTOR_BITS);
38
if (copy_from_backing) {
40
+ ret = blk_pread(blk, offset, buffer, bytes);
39
/* qcow2 emits this on bs->file instead of bs->backing */
40
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
41
- ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
42
- cluster_bytes - skip_end_bytes,
43
- whole_grain + skip_end_bytes, 0);
44
+ ret = bdrv_co_pread(bs->backing, offset + skip_end_bytes,
45
+ cluster_bytes - skip_end_bytes,
46
+ whole_grain + skip_end_bytes, 0);
47
if (ret < 0) {
48
ret = VMDK_ERROR;
49
goto exit;
50
}
51
}
52
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
53
- ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
54
- cluster_bytes - skip_end_bytes,
55
- whole_grain + skip_end_bytes, 0);
56
+ ret = bdrv_co_pwrite(extent->file, cluster_offset + skip_end_bytes,
57
+ cluster_bytes - skip_end_bytes,
58
+ whole_grain + skip_end_bytes, 0);
59
if (ret < 0) {
60
ret = VMDK_ERROR;
61
goto exit;
62
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
63
offset = cpu_to_le32(offset);
64
/* update L2 table */
65
BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE);
66
- if (bdrv_pwrite(extent->file,
67
- ((int64_t)m_data->l2_offset * 512)
68
- + (m_data->l2_index * sizeof(offset)),
69
- sizeof(offset), &offset, 0) < 0) {
70
+ if (bdrv_co_pwrite(extent->file,
71
+ ((int64_t)m_data->l2_offset * 512)
72
+ + (m_data->l2_index * sizeof(offset)),
73
+ sizeof(offset), &offset, 0) < 0) {
74
return VMDK_ERROR;
75
}
76
/* update backup L2 table */
77
if (extent->l1_backup_table_offset != 0) {
78
m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
79
- if (bdrv_pwrite(extent->file,
80
- ((int64_t)m_data->l2_offset * 512)
81
- + (m_data->l2_index * sizeof(offset)),
82
- sizeof(offset), &offset, 0) < 0) {
83
+ if (bdrv_co_pwrite(extent->file,
84
+ ((int64_t)m_data->l2_offset * 512)
85
+ + (m_data->l2_index * sizeof(offset)),
86
+ sizeof(offset), &offset, 0) < 0) {
87
return VMDK_ERROR;
88
}
89
}
90
- if (bdrv_flush(extent->file->bs) < 0) {
91
+ if (bdrv_co_flush(extent->file->bs) < 0) {
92
return VMDK_ERROR;
93
}
94
if (m_data->l2_cache_entry) {
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
96
}
97
l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes);
98
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
99
- if (bdrv_pread(extent->file,
100
+ if (bdrv_co_pread(extent->file,
101
(int64_t)l2_offset * 512,
102
l2_size_bytes,
103
- l2_table,
104
- 0
105
+ l2_table, 0
106
) < 0) {
107
return VMDK_ERROR;
108
}
109
@@ -XXX,XX +XXX,XX @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
110
cluster_buf = g_malloc(buf_bytes);
111
uncomp_buf = g_malloc(cluster_bytes);
112
BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
113
- ret = bdrv_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, 0);
114
+ ret = bdrv_co_pread(extent->file, cluster_offset, buf_bytes, cluster_buf,
115
+ 0);
41
if (ret < 0) {
116
if (ret < 0) {
42
error_report("Error while reading offset %" PRId64 " of %s: %s",
117
goto out;
43
- sectors_to_bytes(sect_num), filename, strerror(-ret));
44
+ offset, filename, strerror(-ret));
45
return 4;
46
}
118
}
47
- idx = find_nonzero(buffer, sect_count * BDRV_SECTOR_SIZE);
119
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
48
+ idx = find_nonzero(buffer, bytes);
120
return length;
49
if (idx >= 0) {
121
}
50
qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
122
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
51
- sectors_to_bytes(sect_num) + idx);
123
- ret = bdrv_truncate(s->extents[i].file, length, false,
52
+ offset + idx);
124
- PREALLOC_MODE_OFF, 0, NULL);
53
return 1;
125
+ ret = bdrv_co_truncate(s->extents[i].file, length, false,
126
+ PREALLOC_MODE_OFF, 0, NULL);
127
if (ret < 0) {
128
return ret;
129
}
130
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
131
desc_offset = 0x200;
54
}
132
}
55
133
56
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
134
- ret = blk_pwrite(blk, desc_offset, desc_len, desc, 0);
57
} else {
135
+ ret = blk_co_pwrite(blk, desc_offset, desc_len, desc, 0);
58
nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
136
if (ret < 0) {
59
if (allocated1) {
137
error_setg_errno(errp, -ret, "Could not write description");
60
- ret = check_empty_sectors(blk1, sector_num, nb_sectors,
138
goto exit;
61
+ ret = check_empty_sectors(blk1, sector_num * BDRV_SECTOR_SIZE,
139
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
62
+ nb_sectors * BDRV_SECTOR_SIZE,
140
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
63
filename1, buf1, quiet);
141
* for description file */
64
} else {
142
if (desc_offset == 0) {
65
- ret = check_empty_sectors(blk2, sector_num, nb_sectors,
143
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
66
+ ret = check_empty_sectors(blk2, sector_num * BDRV_SECTOR_SIZE,
144
+ ret = blk_co_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
67
+ nb_sectors * BDRV_SECTOR_SIZE,
145
if (ret < 0) {
68
filename2, buf1, quiet);
146
goto exit;
69
}
147
}
70
if (ret) {
71
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
72
nb_sectors = count >> BDRV_SECTOR_BITS;
73
if (ret & BDRV_BLOCK_ALLOCATED && !(ret & BDRV_BLOCK_ZERO)) {
74
nb_sectors = MIN(nb_sectors, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
75
- ret = check_empty_sectors(blk_over, sector_num, nb_sectors,
76
+ ret = check_empty_sectors(blk_over,
77
+ sector_num * BDRV_SECTOR_SIZE,
78
+ nb_sectors * BDRV_SECTOR_SIZE,
79
filename_over, buf1, quiet);
80
if (ret) {
81
goto out;
82
--
148
--
83
2.13.6
149
2.37.3
84
85
diff view generated by jsdifflib
1
This changes test case 191 to include a backing image that has
1
From: Alberto Faria <afaria@redhat.com>
2
backing_fmt set in the image file, but is referenced by node name in the
3
qemu command line.
4
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-25-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
---
8
tests/qemu-iotests/191 | 3 ++-
9
blockdev.c | 2 +-
9
tests/qemu-iotests/191.out | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
11
12
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
12
diff --git a/blockdev.c b/blockdev.c
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/191
15
+++ b/tests/qemu-iotests/191
16
@@ -XXX,XX +XXX,XX @@ echo === Preparing and starting VM ===
17
echo
18
19
TEST_IMG="${TEST_IMG}.base" _make_test_img $size
20
-TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base"
21
+IMGOPTS=$(_optstr_add "$IMGOPTS" "backing_fmt=$IMGFMT") \
22
+ TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base"
23
_make_test_img -b "${TEST_IMG}.mid"
24
TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid"
25
26
diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/tests/qemu-iotests/191.out
14
--- a/blockdev.c
29
+++ b/tests/qemu-iotests/191.out
15
+++ b/blockdev.c
30
@@ -XXX,XX +XXX,XX @@ QA output created by 191
16
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(bool has_device, const char *device,
31
=== Preparing and starting VM ===
17
bdrv_co_unlock(bs);
32
18
33
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
19
old_ctx = bdrv_co_enter(bs);
34
-Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
20
- blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
35
+Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
21
+ blk_co_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
36
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid
22
bdrv_co_leave(bs, old_ctx);
37
Formatting 'TEST_DIR/t.IMGFMT.ovl2', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid
23
38
wrote 65536/65536 bytes at offset 1048576
24
bdrv_co_lock(bs);
39
--
25
--
40
2.13.6
26
2.37.3
41
42
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Now that bdrv_is_allocated accepts non-aligned inputs, we can
3
blk_set_enable_write_cache() is defined as GLOBAL_STATE_CODE
4
remove the TODO added in earlier refactoring.
4
but can be invoked from iothreads when handling scsi requests.
5
This triggers an assertion failure:
5
6
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
0x00007fd6c3515ce1 in raise () from /lib/x86_64-linux-gnu/libc.so.6
8
0x00007fd6c34ff537 in abort () from /lib/x86_64-linux-gnu/libc.so.6
9
0x00007fd6c34ff40f in ?? () from /lib/x86_64-linux-gnu/libc.so.6
10
0x00007fd6c350e662 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
11
0x000056149e2cea03 in blk_set_enable_write_cache (wce=true, blk=0x5614a01c27f0)
12
at ../src/block/block-backend.c:1949
13
0x000056149e2d0a67 in blk_set_enable_write_cache (blk=0x5614a01c27f0,
14
wce=<optimized out>) at ../src/block/block-backend.c:1951
15
0x000056149dfe9c59 in scsi_disk_apply_mode_select (p=0x7fd6b400c00e "\004",
16
page=<optimized out>, s=<optimized out>) at ../src/hw/scsi/scsi-disk.c:1520
17
mode_select_pages (change=true, len=18, p=0x7fd6b400c00e "\004", r=0x7fd6b4001ff0)
18
at ../src/hw/scsi/scsi-disk.c:1570
19
scsi_disk_emulate_mode_select (inbuf=<optimized out>, r=0x7fd6b4001ff0) at
20
../src/hw/scsi/scsi-disk.c:1640
21
scsi_disk_emulate_write_data (req=0x7fd6b4001ff0) at ../src/hw/scsi/scsi-disk.c:1934
22
0x000056149e18ff16 in virtio_scsi_handle_cmd_req_submit (req=<optimized out>,
23
req=<optimized out>, s=0x5614a12f16b0) at ../src/hw/scsi/virtio-scsi.c:719
24
virtio_scsi_handle_cmd_vq (vq=0x7fd6bab92140, s=0x5614a12f16b0) at
25
../src/hw/scsi/virtio-scsi.c:761
26
virtio_scsi_handle_cmd (vq=<optimized out>, vdev=<optimized out>) at
27
../src/hw/scsi/virtio-scsi.c:775
28
virtio_scsi_handle_cmd (vdev=0x5614a12f16b0, vq=0x7fd6bab92140) at
29
../src/hw/scsi/virtio-scsi.c:765
30
0x000056149e1a8aa6 in virtio_queue_notify_vq (vq=0x7fd6bab92140) at
31
../src/hw/virtio/virtio.c:2365
32
0x000056149e3ccea5 in aio_dispatch_handler (ctx=ctx@entry=0x5614a01babe0,
33
node=<optimized out>) at ../src/util/aio-posix.c:369
34
0x000056149e3cd868 in aio_dispatch_ready_handlers (ready_list=0x7fd6c09b2680,
35
ctx=0x5614a01babe0) at ../src/util/aio-posix.c:399
36
aio_poll (ctx=0x5614a01babe0, blocking=blocking@entry=true) at
37
../src/util/aio-posix.c:713
38
0x000056149e2a7796 in iothread_run (opaque=opaque@entry=0x56149ffde500) at
39
../src/iothread.c:67
40
0x000056149e3d0859 in qemu_thread_start (args=0x7fd6c09b26f0) at
41
../src/util/qemu-thread-posix.c:504
42
0x00007fd6c36b9ea7 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
43
0x00007fd6c35d9aef in clone () from /lib/x86_64-linux-gnu/libc.so.6
44
45
Changing GLOBAL_STATE_CODE in IO_CODE is allowed, since GSC callers are
46
allowed to call IO_CODE.
47
48
Resolves: #1272
49
50
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
51
Message-Id: <20221027072726.2681500-1-eesposit@redhat.com>
52
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
53
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
54
Tested-by: Antoine Damhet <antoine.damhet@shadow.tech>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
55
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
56
---
9
block/qcow2.c | 12 +++---------
57
block/block-backend.c | 2 +-
10
1 file changed, 3 insertions(+), 9 deletions(-)
58
1 file changed, 1 insertion(+), 1 deletion(-)
11
59
12
diff --git a/block/qcow2.c b/block/qcow2.c
60
diff --git a/block/block-backend.c b/block/block-backend.c
13
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
62
--- a/block/block-backend.c
15
+++ b/block/qcow2.c
63
+++ b/block/block-backend.c
16
@@ -XXX,XX +XXX,XX @@ static bool is_zero(BlockDriverState *bs, int64_t offset, int64_t bytes)
64
@@ -XXX,XX +XXX,XX @@ bool blk_enable_write_cache(BlockBackend *blk)
65
66
void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
17
{
67
{
18
int64_t nr;
68
- GLOBAL_STATE_CODE();
19
int res;
69
+ IO_CODE();
20
- int64_t start;
70
blk->enable_write_cache = wce;
21
-
22
- /* TODO: Widening to sector boundaries should only be needed as
23
- * long as we can't query finer granularity. */
24
- start = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
25
- bytes = QEMU_ALIGN_UP(offset + bytes, BDRV_SECTOR_SIZE) - start;
26
27
/* Clamp to image length, before checking status of underlying sectors */
28
- if (start + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) {
29
- bytes = bs->total_sectors * BDRV_SECTOR_SIZE - start;
30
+ if (offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) {
31
+ bytes = bs->total_sectors * BDRV_SECTOR_SIZE - offset;
32
}
33
34
if (!bytes) {
35
return true;
36
}
37
- res = bdrv_block_status_above(bs, NULL, start, bytes, &nr, NULL, NULL);
38
+ res = bdrv_block_status_above(bs, NULL, offset, bytes, &nr, NULL, NULL);
39
return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == bytes;
40
}
71
}
41
72
42
--
73
--
43
2.13.6
74
2.37.3
44
45
diff view generated by jsdifflib