1
The following changes since commit bfec359afba088aaacc7d316f43302f28c6e642a:
1
The following changes since commit ba29883206d92a29ad5a466e679ccfc2ee6132ef:
2
2
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qdev-2017-04-21' into staging (2017-04-21 11:42:03 +0100)
3
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20200310' into staging (2020-03-10 16:50:28 +0000)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-03-11
8
8
9
for you to fetch changes up to 1507631e438930bc07f776f303af127a9cdb4d41:
9
for you to fetch changes up to 397f4e9d83e9c0000905f0a988ba1aeda162571c:
10
10
11
qemu-iotests: _cleanup_qemu must be called on exit (2017-04-21 08:32:44 -0400)
11
block/block-copy: hide structure definitions (2020-03-11 12:42:30 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
Block patches for the 5.0 softfreeze:
15
Block patches for 2.10
15
- qemu-img measure for LUKS
16
- Improve block-copy's performance by reducing inter-request
17
dependencies
18
- Make curl's detection of accept-ranges more robust
19
- Memleak fixes
20
- iotest fix
16
21
17
----------------------------------------------------------------
22
----------------------------------------------------------------
23
David Edmondson (2):
24
block/curl: HTTP header fields allow whitespace around values
25
block/curl: HTTP header field names are case insensitive
18
26
19
Ashish Mittal (2):
27
Eric Blake (1):
20
block/vxhs.c: Add support for a new block device type called "vxhs"
28
iotests: Fix nonportable use of od --endian
21
block/vxhs.c: Add qemu-iotests for new block device type "vxhs"
22
29
23
Jeff Cody (10):
30
Pan Nengyuan (2):
24
qemu-iotests: exclude vxhs from image creation via protocol
31
block/qcow2: do free crypto_opts in qcow2_close()
25
block: add bdrv_set_read_only() helper function
32
qemu-img: free memory before re-assign
26
block: do not set BDS read_only if copy_on_read enabled
27
block: honor BDRV_O_ALLOW_RDWR when clearing bs->read_only
28
block: code movement
29
block: introduce bdrv_can_set_read_only()
30
block: use bdrv_can_set_read_only() during reopen
31
block/rbd - update variable names to more apt names
32
block/rbd: Add support for reopen()
33
qemu-iotests: _cleanup_qemu must be called on exit
34
33
35
block.c | 56 +++-
34
Stefan Hajnoczi (4):
36
block/Makefile.objs | 2 +
35
luks: extract qcrypto_block_calculate_payload_offset()
37
block/bochs.c | 5 +-
36
luks: implement .bdrv_measure()
38
block/cloop.c | 5 +-
37
qemu-img: allow qemu-img measure --object without a filename
39
block/dmg.c | 6 +-
38
iotests: add 288 luks qemu-img measure test
40
block/rbd.c | 65 +++--
39
41
block/trace-events | 17 ++
40
Vladimir Sementsov-Ogievskiy (10):
42
block/vvfat.c | 19 +-
41
block/qcow2-threads: fix qcow2_decompress
43
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++
42
job: refactor progress to separate object
44
configure | 39 +++
43
block/block-copy: fix progress calculation
45
include/block/block.h | 2 +
44
block/block-copy: specialcase first copy_range request
46
qapi/block-core.json | 23 +-
45
block/block-copy: use block_status
47
tests/qemu-iotests/017 | 1 +
46
block/block-copy: factor out find_conflicting_inflight_req
48
tests/qemu-iotests/020 | 1 +
47
block/block-copy: refactor interfaces to use bytes instead of end
49
tests/qemu-iotests/028 | 1 +
48
block/block-copy: rename start to offset in interfaces
50
tests/qemu-iotests/029 | 1 +
49
block/block-copy: reduce intersecting request lock
51
tests/qemu-iotests/073 | 1 +
50
block/block-copy: hide structure definitions
52
tests/qemu-iotests/094 | 11 +-
51
53
tests/qemu-iotests/102 | 5 +-
52
block/backup-top.c | 6 +-
54
tests/qemu-iotests/109 | 1 +
53
block/backup.c | 38 ++-
55
tests/qemu-iotests/114 | 1 +
54
block/block-copy.c | 405 ++++++++++++++++++++++++-------
56
tests/qemu-iotests/117 | 1 +
55
block/crypto.c | 62 +++++
57
tests/qemu-iotests/130 | 2 +
56
block/curl.c | 32 ++-
58
tests/qemu-iotests/134 | 1 +
57
block/qcow2-threads.c | 12 +-
59
tests/qemu-iotests/140 | 1 +
58
block/qcow2.c | 75 ++----
60
tests/qemu-iotests/141 | 1 +
59
block/trace-events | 1 +
61
tests/qemu-iotests/143 | 1 +
60
blockjob.c | 16 +-
62
tests/qemu-iotests/156 | 2 +
61
crypto/block.c | 36 +++
63
tests/qemu-iotests/158 | 1 +
62
include/block/block-copy.h | 65 +----
64
tests/qemu-iotests/common | 6 +
63
include/crypto/block.h | 22 ++
65
tests/qemu-iotests/common.config | 13 +
64
include/qemu/job.h | 11 +-
66
tests/qemu-iotests/common.filter | 1 +
65
include/qemu/progress_meter.h | 58 +++++
67
tests/qemu-iotests/common.rc | 19 ++
66
job-qmp.c | 4 +-
68
33 files changed, 844 insertions(+), 42 deletions(-)
67
job.c | 6 +-
69
create mode 100644 block/vxhs.c
68
qemu-img.c | 14 +-
69
tests/qemu-iotests/178 | 2 +-
70
tests/qemu-iotests/178.out.qcow2 | 8 +-
71
tests/qemu-iotests/178.out.raw | 8 +-
72
tests/qemu-iotests/288 | 93 +++++++
73
tests/qemu-iotests/288.out | 30 +++
74
tests/qemu-iotests/common.rc | 22 +-
75
tests/qemu-iotests/group | 1 +
76
24 files changed, 749 insertions(+), 278 deletions(-)
77
create mode 100644 include/qemu/progress_meter.h
78
create mode 100755 tests/qemu-iotests/288
79
create mode 100644 tests/qemu-iotests/288.out
70
80
71
--
81
--
72
2.9.3
82
2.24.1
73
83
74
84
diff view generated by jsdifflib
New patch
1
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
3
The qcow2 .bdrv_measure() code calculates the crypto payload offset.
4
This logic really belongs in crypto/block.c where it can be reused by
5
other image formats.
6
7
The "luks" block driver will need this same logic in order to implement
8
.bdrv_measure(), so extract the qcrypto_block_calculate_payload_offset()
9
function now.
10
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20200221112522.1497712-2-stefanha@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2.c | 74 +++++++++++-------------------------------
17
crypto/block.c | 36 ++++++++++++++++++++
18
include/crypto/block.h | 22 +++++++++++++
19
3 files changed, 77 insertions(+), 55 deletions(-)
20
21
diff --git a/block/qcow2.c b/block/qcow2.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2.c
24
+++ b/block/qcow2.c
25
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
26
return ret;
27
}
28
29
-static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
30
- size_t headerlen, void *opaque, Error **errp)
31
-{
32
- size_t *headerlenp = opaque;
33
-
34
- /* Stash away the payload size */
35
- *headerlenp = headerlen;
36
- return 0;
37
-}
38
-
39
-static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
40
- size_t offset, const uint8_t *buf, size_t buflen,
41
- void *opaque, Error **errp)
42
-{
43
- /* Discard the bytes, we're not actually writing to an image */
44
- return buflen;
45
-}
46
-
47
-/* Determine the number of bytes for the LUKS payload */
48
-static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len,
49
- Error **errp)
50
-{
51
- QDict *opts_qdict;
52
- QDict *cryptoopts_qdict;
53
- QCryptoBlockCreateOptions *cryptoopts;
54
- QCryptoBlock *crypto;
55
-
56
- /* Extract "encrypt." options into a qdict */
57
- opts_qdict = qemu_opts_to_qdict(opts, NULL);
58
- qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
59
- qobject_unref(opts_qdict);
60
-
61
- /* Build QCryptoBlockCreateOptions object from qdict */
62
- qdict_put_str(cryptoopts_qdict, "format", "luks");
63
- cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
64
- qobject_unref(cryptoopts_qdict);
65
- if (!cryptoopts) {
66
- return false;
67
- }
68
-
69
- /* Fake LUKS creation in order to determine the payload size */
70
- crypto = qcrypto_block_create(cryptoopts, "encrypt.",
71
- qcow2_measure_crypto_hdr_init_func,
72
- qcow2_measure_crypto_hdr_write_func,
73
- len, errp);
74
- qapi_free_QCryptoBlockCreateOptions(cryptoopts);
75
- if (!crypto) {
76
- return false;
77
- }
78
-
79
- qcrypto_block_free(crypto);
80
- return true;
81
-}
82
-
83
static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
84
Error **errp)
85
{
86
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
87
g_free(optstr);
88
89
if (has_luks) {
90
+ g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL;
91
+ QDict *opts_qdict;
92
+ QDict *cryptoopts;
93
size_t headerlen;
94
95
- if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
96
+ opts_qdict = qemu_opts_to_qdict(opts, NULL);
97
+ qdict_extract_subqdict(opts_qdict, &cryptoopts, "encrypt.");
98
+ qobject_unref(opts_qdict);
99
+
100
+ qdict_put_str(cryptoopts, "format", "luks");
101
+
102
+ create_opts = block_crypto_create_opts_init(cryptoopts, errp);
103
+ qobject_unref(cryptoopts);
104
+ if (!create_opts) {
105
+ goto err;
106
+ }
107
+
108
+ if (!qcrypto_block_calculate_payload_offset(create_opts,
109
+ "encrypt.",
110
+ &headerlen,
111
+ &local_err)) {
112
goto err;
113
}
114
115
diff --git a/crypto/block.c b/crypto/block.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/crypto/block.c
118
+++ b/crypto/block.c
119
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
120
}
121
122
123
+static ssize_t qcrypto_block_headerlen_hdr_init_func(QCryptoBlock *block,
124
+ size_t headerlen, void *opaque, Error **errp)
125
+{
126
+ size_t *headerlenp = opaque;
127
+
128
+ /* Stash away the payload size */
129
+ *headerlenp = headerlen;
130
+ return 0;
131
+}
132
+
133
+
134
+static ssize_t qcrypto_block_headerlen_hdr_write_func(QCryptoBlock *block,
135
+ size_t offset, const uint8_t *buf, size_t buflen,
136
+ void *opaque, Error **errp)
137
+{
138
+ /* Discard the bytes, we're not actually writing to an image */
139
+ return buflen;
140
+}
141
+
142
+
143
+bool
144
+qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
145
+ const char *optprefix,
146
+ size_t *len,
147
+ Error **errp)
148
+{
149
+ /* Fake LUKS creation in order to determine the payload size */
150
+ g_autoptr(QCryptoBlock) crypto =
151
+ qcrypto_block_create(create_opts, optprefix,
152
+ qcrypto_block_headerlen_hdr_init_func,
153
+ qcrypto_block_headerlen_hdr_write_func,
154
+ len, errp);
155
+ return crypto != NULL;
156
+}
157
+
158
+
159
QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
160
Error **errp)
161
{
162
diff --git a/include/crypto/block.h b/include/crypto/block.h
163
index XXXXXXX..XXXXXXX 100644
164
--- a/include/crypto/block.h
165
+++ b/include/crypto/block.h
166
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
167
Error **errp);
168
169
170
+/**
171
+ * qcrypto_block_calculate_payload_offset:
172
+ * @create_opts: the encryption options
173
+ * @optprefix: name prefix for options
174
+ * @len: output for number of header bytes before payload
175
+ * @errp: pointer to a NULL-initialized error object
176
+ *
177
+ * Calculate the number of header bytes before the payload in an encrypted
178
+ * storage volume. The header is an area before the payload that is reserved
179
+ * for encryption metadata.
180
+ *
181
+ * Returns: true on success, false on error
182
+ */
183
+bool
184
+qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
185
+ const char *optprefix,
186
+ size_t *len,
187
+ Error **errp);
188
+
189
+
190
/**
191
* qcrypto_block_get_info:
192
* @block: the block encryption object
193
@@ -XXX,XX +XXX,XX @@ uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block);
194
void qcrypto_block_free(QCryptoBlock *block);
195
196
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlock, qcrypto_block_free)
197
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlockCreateOptions,
198
+ qapi_free_QCryptoBlockCreateOptions)
199
200
#endif /* QCRYPTO_BLOCK_H */
201
--
202
2.24.1
203
204
diff view generated by jsdifflib
1
A few block drivers will set the BDS read_only flag from their
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
.bdrv_open() function. This means the bs->read_only flag could
3
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
4
flag check occurs prior to the call to bdrv->bdrv_open().
5
2
6
This adds an error return to bdrv_set_read_only(), and an error will be
3
Add qemu-img measure support in the "luks" block driver.
7
return if we try to set the BDS to read_only while copy_on_read is
8
enabled.
9
4
10
This patch also changes the behavior of vvfat. Before, vvfat could
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
override the drive 'readonly' flag with its own, internal 'rw' flag.
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20200221112522.1497712-3-stefanha@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
block/crypto.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 62 insertions(+)
12
12
13
For instance, this -drive parameter would result in a writable image:
13
diff --git a/block/crypto.c b/block/crypto.c
14
15
"-drive format=vvfat,dir=/tmp/vvfat,rw,if=virtio,readonly=on"
16
17
This is not correct. Now, attempting to use the above -drive parameter
18
will result in an error (i.e., 'rw' is incompatible with 'readonly=on').
19
20
Signed-off-by: Jeff Cody <jcody@redhat.com>
21
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
22
Reviewed-by: John Snow <jsnow@redhat.com>
23
Message-id: 0c5b4c1cc2c651471b131f21376dfd5ea24d2196.1491597120.git.jcody@redhat.com
24
---
25
block.c | 10 +++++++++-
26
block/bochs.c | 5 ++++-
27
block/cloop.c | 5 ++++-
28
block/dmg.c | 6 +++++-
29
block/rbd.c | 11 ++++++++++-
30
block/vvfat.c | 19 +++++++++++++++----
31
include/block/block.h | 2 +-
32
7 files changed, 48 insertions(+), 10 deletions(-)
33
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
15
--- a/block/crypto.c
37
+++ b/block.c
16
+++ b/block/crypto.c
38
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
17
@@ -XXX,XX +XXX,XX @@ static int64_t block_crypto_getlength(BlockDriverState *bs)
39
}
40
}
18
}
41
19
42
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
20
43
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
21
+static BlockMeasureInfo *block_crypto_measure(QemuOpts *opts,
44
{
22
+ BlockDriverState *in_bs,
45
+ /* Do not set read_only if copy_on_read is enabled */
23
+ Error **errp)
46
+ if (bs->copy_on_read && read_only) {
24
+{
47
+ error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
25
+ g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL;
48
+ bdrv_get_device_or_node_name(bs));
26
+ Error *local_err = NULL;
49
+ return -EINVAL;
27
+ BlockMeasureInfo *info;
28
+ uint64_t size;
29
+ size_t luks_payload_size;
30
+ QDict *cryptoopts;
31
+
32
+ /*
33
+ * Preallocation mode doesn't affect size requirements but we must consume
34
+ * the option.
35
+ */
36
+ g_free(qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC));
37
+
38
+ size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
39
+
40
+ if (in_bs) {
41
+ int64_t ssize = bdrv_getlength(in_bs);
42
+
43
+ if (ssize < 0) {
44
+ error_setg_errno(&local_err, -ssize,
45
+ "Unable to get image virtual_size");
46
+ goto err;
47
+ }
48
+
49
+ size = ssize;
50
+ }
50
+ }
51
+
51
+
52
bs->read_only = read_only;
52
+ cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
53
+ return 0;
53
+ &block_crypto_create_opts_luks, true);
54
}
54
+ qdict_put_str(cryptoopts, "format", "luks");
55
55
+ create_opts = block_crypto_create_opts_init(cryptoopts, &local_err);
56
void bdrv_get_full_backing_filename_from_filename(const char *backed,
56
+ qobject_unref(cryptoopts);
57
diff --git a/block/bochs.c b/block/bochs.c
57
+ if (!create_opts) {
58
index XXXXXXX..XXXXXXX 100644
58
+ goto err;
59
--- a/block/bochs.c
60
+++ b/block/bochs.c
61
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
62
return -EINVAL;
63
}
64
65
- bdrv_set_read_only(bs, true); /* no write support yet */
66
+ ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
67
+ if (ret < 0) {
68
+ return ret;
69
+ }
70
71
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
72
if (ret < 0) {
73
diff --git a/block/cloop.c b/block/cloop.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/cloop.c
76
+++ b/block/cloop.c
77
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
78
return -EINVAL;
79
}
80
81
- bdrv_set_read_only(bs, true);
82
+ ret = bdrv_set_read_only(bs, true, errp);
83
+ if (ret < 0) {
84
+ return ret;
85
+ }
86
87
/* read header */
88
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
89
diff --git a/block/dmg.c b/block/dmg.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/dmg.c
92
+++ b/block/dmg.c
93
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
94
return -EINVAL;
95
}
96
97
+ ret = bdrv_set_read_only(bs, true, errp);
98
+ if (ret < 0) {
99
+ return ret;
100
+ }
59
+ }
101
+
60
+
102
block_module_load_one("dmg-bz2");
61
+ if (!qcrypto_block_calculate_payload_offset(create_opts, NULL,
103
- bdrv_set_read_only(bs, true);
62
+ &luks_payload_size,
104
63
+ &local_err)) {
105
s->n_chunks = 0;
64
+ goto err;
106
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
107
diff --git a/block/rbd.c b/block/rbd.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/rbd.c
110
+++ b/block/rbd.c
111
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
112
goto failed_shutdown;
113
}
114
115
+ /* rbd_open is always r/w */
116
r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
117
if (r < 0) {
118
error_setg_errno(errp, -r, "error reading header from %s", s->name);
119
goto failed_open;
120
}
121
122
- bdrv_set_read_only(bs, (s->snap != NULL));
123
+ /* If we are using an rbd snapshot, we must be r/o, otherwise
124
+ * leave as-is */
125
+ if (s->snap != NULL) {
126
+ r = bdrv_set_read_only(bs, true, &local_err);
127
+ if (r < 0) {
128
+ error_propagate(errp, local_err);
129
+ goto failed_open;
130
+ }
131
+ }
65
+ }
132
66
+
133
qemu_opts_del(opts);
67
+ /*
134
return 0;
68
+ * Unallocated blocks are still encrypted so allocation status makes no
135
diff --git a/block/vvfat.c b/block/vvfat.c
69
+ * difference to the file size.
136
index XXXXXXX..XXXXXXX 100644
70
+ */
137
--- a/block/vvfat.c
71
+ info = g_new(BlockMeasureInfo, 1);
138
+++ b/block/vvfat.c
72
+ info->fully_allocated = luks_payload_size + size;
139
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
73
+ info->required = luks_payload_size + size;
140
74
+ return info;
141
s->current_cluster=0xffffffff;
75
+
142
76
+err:
143
- /* read only is the default for safety */
77
+ error_propagate(errp, local_err);
144
- bdrv_set_read_only(bs, true);
78
+ return NULL;
145
s->qcow = NULL;
79
+}
146
s->qcow_filename = NULL;
80
+
147
s->fat2 = NULL;
81
+
148
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
82
static int block_crypto_probe_luks(const uint8_t *buf,
149
s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
83
int buf_size,
150
84
const char *filename) {
151
if (qemu_opt_get_bool(opts, "rw", false)) {
85
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_crypto_luks = {
152
- ret = enable_write_target(bs, errp);
86
.bdrv_co_preadv = block_crypto_co_preadv,
153
+ if (!bdrv_is_read_only(bs)) {
87
.bdrv_co_pwritev = block_crypto_co_pwritev,
154
+ ret = enable_write_target(bs, errp);
88
.bdrv_getlength = block_crypto_getlength,
155
+ if (ret < 0) {
89
+ .bdrv_measure = block_crypto_measure,
156
+ goto fail;
90
.bdrv_get_info = block_crypto_get_info_luks,
157
+ }
91
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
158
+ } else {
92
159
+ ret = -EPERM;
160
+ error_setg(errp,
161
+ "Unable to set VVFAT to 'rw' when drive is read-only");
162
+ goto fail;
163
+ }
164
+ } else {
165
+ /* read only is the default for safety */
166
+ ret = bdrv_set_read_only(bs, true, &local_err);
167
if (ret < 0) {
168
+ error_propagate(errp, local_err);
169
goto fail;
170
}
171
- bdrv_set_read_only(bs, false);
172
}
173
174
bs->total_sectors = cyls * heads * secs;
175
diff --git a/include/block/block.h b/include/block/block.h
176
index XXXXXXX..XXXXXXX 100644
177
--- a/include/block/block.h
178
+++ b/include/block/block.h
179
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
180
int64_t sector_num, int nb_sectors, int *pnum);
181
182
bool bdrv_is_read_only(BlockDriverState *bs);
183
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
184
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
185
bool bdrv_is_sg(BlockDriverState *bs);
186
bool bdrv_is_inserted(BlockDriverState *bs);
187
int bdrv_media_changed(BlockDriverState *bs);
188
--
93
--
189
2.9.3
94
2.24.1
190
95
191
96
diff view generated by jsdifflib
1
Update 'clientname' to be 'user', which tracks better with both
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
the QAPI and rados variable naming.
3
2
4
Update 'name' to be 'image_name', as it indicates the rbd image.
3
In most qemu-img sub-commands the --object option only makes sense when
5
Naming it 'image' would have been ideal, but we are using that for
4
there is a filename. qemu-img measure is an exception because objects
6
the rados_image_t value returned by rbd_open().
5
may be referenced from the image creation options instead of an existing
6
image file. Allow --object without a filename.
7
7
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Jeff Cody <jcody@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
10
Message-Id: <20200221112522.1497712-4-stefanha@redhat.com>
11
Message-id: b7ec1fb2e1cf36f9b6911631447a5b0422590b7d.1491597120.git.jcody@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
12
---
13
block/rbd.c | 33 +++++++++++++++++----------------
13
qemu-img.c | 6 ++----
14
1 file changed, 17 insertions(+), 16 deletions(-)
14
tests/qemu-iotests/178 | 2 +-
15
tests/qemu-iotests/178.out.qcow2 | 8 ++++----
16
tests/qemu-iotests/178.out.raw | 8 ++++----
17
4 files changed, 11 insertions(+), 13 deletions(-)
15
18
16
diff --git a/block/rbd.c b/block/rbd.c
19
diff --git a/qemu-img.c b/qemu-img.c
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/block/rbd.c
21
--- a/qemu-img.c
19
+++ b/block/rbd.c
22
+++ b/qemu-img.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
23
@@ -XXX,XX +XXX,XX @@ static int img_measure(int argc, char **argv)
21
rados_t cluster;
24
filename = argv[optind];
22
rados_ioctx_t io_ctx;
23
rbd_image_t image;
24
- char *name;
25
+ char *image_name;
26
char *snap;
27
} BDRVRBDState;
28
29
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
30
int64_t bytes = 0;
31
int64_t objsize;
32
int obj_order = 0;
33
- const char *pool, *name, *conf, *clientname, *keypairs;
34
+ const char *pool, *image_name, *conf, *user, *keypairs;
35
const char *secretid;
36
rados_t cluster;
37
rados_ioctx_t io_ctx;
38
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
39
*/
40
pool = qdict_get_try_str(options, "pool");
41
conf = qdict_get_try_str(options, "conf");
42
- clientname = qdict_get_try_str(options, "user");
43
- name = qdict_get_try_str(options, "image");
44
+ user = qdict_get_try_str(options, "user");
45
+ image_name = qdict_get_try_str(options, "image");
46
keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
47
48
- ret = rados_create(&cluster, clientname);
49
+ ret = rados_create(&cluster, user);
50
if (ret < 0) {
51
error_setg_errno(errp, -ret, "error initializing");
52
goto exit;
53
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
54
goto shutdown;
55
}
25
}
56
26
57
- ret = rbd_create(io_ctx, name, bytes, &obj_order);
27
- if (!filename &&
58
+ ret = rbd_create(io_ctx, image_name, bytes, &obj_order);
28
- (object_opts || image_opts || fmt || snapshot_name || sn_opts)) {
59
if (ret < 0) {
29
- error_report("--object, --image-opts, -f, and -l "
60
error_setg_errno(errp, -ret, "error rbd create");
30
- "require a filename argument.");
31
+ if (!filename && (image_opts || fmt || snapshot_name || sn_opts)) {
32
+ error_report("--image-opts, -f, and -l require a filename argument.");
33
goto out;
61
}
34
}
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
35
if (filename && img_size != UINT64_MAX) {
63
Error **errp)
36
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
64
{
37
index XXXXXXX..XXXXXXX 100755
65
BDRVRBDState *s = bs->opaque;
38
--- a/tests/qemu-iotests/178
66
- const char *pool, *snap, *conf, *clientname, *name, *keypairs;
39
+++ b/tests/qemu-iotests/178
67
+ const char *pool, *snap, *conf, *user, *image_name, *keypairs;
40
@@ -XXX,XX +XXX,XX @@ _make_test_img 1G
68
const char *secretid;
41
$QEMU_IMG measure # missing arguments
69
QemuOpts *opts;
42
$QEMU_IMG measure --size 2G "$TEST_IMG" # only one allowed
70
Error *local_err = NULL;
43
$QEMU_IMG measure "$TEST_IMG" a # only one filename allowed
71
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
44
-$QEMU_IMG measure --object secret,id=sec0,data=MTIzNDU2,format=base64 # missing filename
72
pool = qemu_opt_get(opts, "pool");
45
+$QEMU_IMG measure --object secret,id=sec0,data=MTIzNDU2,format=base64 # size or filename needed
73
conf = qemu_opt_get(opts, "conf");
46
$QEMU_IMG measure --image-opts # missing filename
74
snap = qemu_opt_get(opts, "snapshot");
47
$QEMU_IMG measure -f qcow2 # missing filename
75
- clientname = qemu_opt_get(opts, "user");
48
$QEMU_IMG measure -l snap1 # missing filename
76
- name = qemu_opt_get(opts, "image");
49
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
77
+ user = qemu_opt_get(opts, "user");
50
index XXXXXXX..XXXXXXX 100644
78
+ image_name = qemu_opt_get(opts, "image");
51
--- a/tests/qemu-iotests/178.out.qcow2
79
keypairs = qemu_opt_get(opts, "=keyvalue-pairs");
52
+++ b/tests/qemu-iotests/178.out.qcow2
80
53
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
81
- if (!pool || !name) {
54
qemu-img: Either --size N or one filename must be specified.
82
+ if (!pool || !image_name) {
55
qemu-img: --size N cannot be used together with a filename.
83
error_setg(errp, "Parameters 'pool' and 'image' are required");
56
qemu-img: At most one filename argument is allowed.
84
r = -EINVAL;
57
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
85
goto failed_opts;
58
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
86
}
59
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
87
60
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
88
- r = rados_create(&s->cluster, clientname);
61
+qemu-img: Either --size N or one filename must be specified.
89
+ r = rados_create(&s->cluster, user);
62
+qemu-img: --image-opts, -f, and -l require a filename argument.
90
if (r < 0) {
63
+qemu-img: --image-opts, -f, and -l require a filename argument.
91
error_setg_errno(errp, -r, "error initializing");
64
+qemu-img: --image-opts, -f, and -l require a filename argument.
92
goto failed_opts;
65
qemu-img: Invalid option list: ,
93
}
66
qemu-img: Invalid parameter 'snapshot.foo'
94
67
qemu-img: Failed in parsing snapshot param 'snapshot.foo'
95
s->snap = g_strdup(snap);
68
diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw
96
- s->name = g_strdup(name);
69
index XXXXXXX..XXXXXXX 100644
97
+ s->image_name = g_strdup(image_name);
70
--- a/tests/qemu-iotests/178.out.raw
98
71
+++ b/tests/qemu-iotests/178.out.raw
99
/* try default location when conf=NULL, but ignore failure */
72
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
100
r = rados_conf_read_file(s->cluster, conf);
73
qemu-img: Either --size N or one filename must be specified.
101
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
74
qemu-img: --size N cannot be used together with a filename.
102
}
75
qemu-img: At most one filename argument is allowed.
103
76
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
104
/* rbd_open is always r/w */
77
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
105
- r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
78
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
106
+ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap);
79
-qemu-img: --object, --image-opts, -f, and -l require a filename argument.
107
if (r < 0) {
80
+qemu-img: Either --size N or one filename must be specified.
108
- error_setg_errno(errp, -r, "error reading header from %s", s->name);
81
+qemu-img: --image-opts, -f, and -l require a filename argument.
109
+ error_setg_errno(errp, -r, "error reading header from %s",
82
+qemu-img: --image-opts, -f, and -l require a filename argument.
110
+ s->image_name);
83
+qemu-img: --image-opts, -f, and -l require a filename argument.
111
goto failed_open;
84
qemu-img: Invalid option list: ,
112
}
85
qemu-img: Invalid parameter 'snapshot.foo'
113
86
qemu-img: Failed in parsing snapshot param 'snapshot.foo'
114
@@ -XXX,XX +XXX,XX @@ failed_open:
115
failed_shutdown:
116
rados_shutdown(s->cluster);
117
g_free(s->snap);
118
- g_free(s->name);
119
+ g_free(s->image_name);
120
failed_opts:
121
qemu_opts_del(opts);
122
g_free(mon_host);
123
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_close(BlockDriverState *bs)
124
rbd_close(s->image);
125
rados_ioctx_destroy(s->io_ctx);
126
g_free(s->snap);
127
- g_free(s->name);
128
+ g_free(s->image_name);
129
rados_shutdown(s->cluster);
130
}
131
132
--
87
--
133
2.9.3
88
2.24.1
134
89
135
90
diff view generated by jsdifflib
1
For the tests that use the common.qemu functions for running a QEMU
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
process, _cleanup_qemu must be called in the exit function.
3
2
4
If it is not, if the qemu process aborts, then not all of the droppings
3
This test exercises the block/crypto.c "luks" block driver
5
are cleaned up (e.g. pidfile, fifos).
4
.bdrv_measure() code.
6
5
7
This updates those tests that did not have a cleanup in qemu-iotests.
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200221112522.1497712-5-stefanha@redhat.com>
9
[mreitz: Renamed test from 282 to 288]
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/288 | 93 ++++++++++++++++++++++++++++++++++++++
13
tests/qemu-iotests/288.out | 30 ++++++++++++
14
tests/qemu-iotests/group | 1 +
15
3 files changed, 124 insertions(+)
16
create mode 100755 tests/qemu-iotests/288
17
create mode 100644 tests/qemu-iotests/288.out
8
18
9
(I swapped spaces for tabs in test 102 as well)
19
diff --git a/tests/qemu-iotests/288 b/tests/qemu-iotests/288
10
20
new file mode 100755
11
Reported-by: Eric Blake <eblake@redhat.com>
21
index XXXXXXX..XXXXXXX
12
Reviewed-by: Eric Blake <eblake@redhat.com>
22
--- /dev/null
13
Signed-off-by: Jeff Cody <jcody@redhat.com>
23
+++ b/tests/qemu-iotests/288
14
Message-id: d59c2f6ad6c1da8b9b3c7f357c94a7122ccfc55a.1492544096.git.jcody@redhat.com
24
@@ -XXX,XX +XXX,XX @@
15
---
25
+#!/usr/bin/env bash
16
tests/qemu-iotests/028 | 1 +
26
+#
17
tests/qemu-iotests/094 | 11 ++++++++---
27
+# qemu-img measure tests for LUKS images
18
tests/qemu-iotests/102 | 5 +++--
28
+#
19
tests/qemu-iotests/109 | 1 +
29
+# Copyright (C) 2020 Red Hat, Inc.
20
tests/qemu-iotests/117 | 1 +
30
+#
21
tests/qemu-iotests/130 | 1 +
31
+# This program is free software; you can redistribute it and/or modify
22
tests/qemu-iotests/140 | 1 +
32
+# it under the terms of the GNU General Public License as published by
23
tests/qemu-iotests/141 | 1 +
33
+# the Free Software Foundation; either version 2 of the License, or
24
tests/qemu-iotests/143 | 1 +
34
+# (at your option) any later version.
25
tests/qemu-iotests/156 | 1 +
35
+#
26
10 files changed, 19 insertions(+), 5 deletions(-)
36
+# This program is distributed in the hope that it will be useful,
27
37
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
28
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
38
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
index XXXXXXX..XXXXXXX 100755
39
+# GNU General Public License for more details.
30
--- a/tests/qemu-iotests/028
40
+#
31
+++ b/tests/qemu-iotests/028
41
+# You should have received a copy of the GNU General Public License
32
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
42
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
33
43
+#
34
_cleanup()
44
+
35
{
45
+# creator
36
+ _cleanup_qemu
46
+owner=stefanha@redhat.com
37
rm -f "${TEST_IMG}.copy"
47
+
38
_cleanup_test_img
48
+seq=`basename $0`
39
}
49
+echo "QA output created by $seq"
40
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
50
+
41
index XXXXXXX..XXXXXXX 100755
51
+status=1 # failure is the default!
42
--- a/tests/qemu-iotests/094
52
+
43
+++ b/tests/qemu-iotests/094
44
@@ -XXX,XX +XXX,XX @@ echo "QA output created by $seq"
45
here="$PWD"
46
status=1    # failure is the default!
47
48
-trap "exit \$status" 0 1 2 3 15
49
+_cleanup()
53
+_cleanup()
50
+{
54
+{
51
+ _cleanup_qemu
52
+ _cleanup_test_img
55
+ _cleanup_test_img
53
+ rm -f "$TEST_DIR/source.$IMGFMT"
56
+ rm -f "$TEST_IMG.converted"
54
+}
57
+}
58
+trap "_cleanup; exit \$status" 0 1 2 3 15
55
+
59
+
56
+trap "_cleanup; exit \$status" 0 1 2 3 15
60
+# get standard environment, filters and checks
57
61
+. ./common.rc
58
# get standard environment, filters and checks
62
+. ./common.filter
59
. ./common.rc
63
+. ./common.pattern
60
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
64
+
61
65
+_supported_fmt luks
62
wait=1 _cleanup_qemu
66
+_supported_proto file
63
67
+_supported_os Linux
64
-_cleanup_test_img
68
+
65
-rm -f "$TEST_DIR/source.$IMGFMT"
69
+SECRET=secret,id=sec0,data=passphrase
66
70
+
67
# success, all done
71
+echo "== measure 1G image file =="
68
echo '*** done'
72
+echo
69
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
73
+
70
index XXXXXXX..XXXXXXX 100755
74
+$QEMU_IMG measure --object "$SECRET" \
71
--- a/tests/qemu-iotests/102
75
+     -O "$IMGFMT" \
72
+++ b/tests/qemu-iotests/102
76
+         -o key-secret=sec0,iter-time=10 \
73
@@ -XXX,XX +XXX,XX @@ seq=$(basename $0)
77
+         --size 1G
74
echo "QA output created by $seq"
78
+
75
79
+echo
76
here=$PWD
80
+echo "== create 1G image file (size should be no greater than measured) =="
77
-status=1    # failure is the default!
81
+echo
78
+status=1 # failure is the default!
82
+
79
83
+_make_test_img 1G
80
_cleanup()
84
+stat -c "image file size in bytes: %s" "$TEST_IMG_FILE"
81
{
85
+
82
-    _cleanup_test_img
86
+echo
83
+ _cleanup_qemu
87
+echo "== modified 1G image file (size should be no greater than measured) =="
84
+ _cleanup_test_img
88
+echo
85
}
89
+
86
trap "_cleanup; exit \$status" 0 1 2 3 15
90
+$QEMU_IO --object "$SECRET" --image-opts "$TEST_IMG" -c "write -P 0x51 0x10000 0x400" | _filter_qemu_io | _filter_testdir
87
91
+stat -c "image file size in bytes: %s" "$TEST_IMG_FILE"
88
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
92
+
89
index XXXXXXX..XXXXXXX 100755
93
+echo
90
--- a/tests/qemu-iotests/109
94
+echo "== measure preallocation=falloc 1G image file =="
91
+++ b/tests/qemu-iotests/109
95
+echo
92
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
96
+
93
97
+$QEMU_IMG measure --object "$SECRET" \
94
_cleanup()
98
+     -O "$IMGFMT" \
95
{
99
+         -o key-secret=sec0,iter-time=10,preallocation=falloc \
96
+ _cleanup_qemu
100
+         --size 1G
97
rm -f $TEST_IMG.src
101
+
98
    _cleanup_test_img
102
+echo
99
}
103
+echo "== measure with input image file =="
100
diff --git a/tests/qemu-iotests/117 b/tests/qemu-iotests/117
104
+echo
101
index XXXXXXX..XXXXXXX 100755
105
+
102
--- a/tests/qemu-iotests/117
106
+IMGFMT=raw IMGKEYSECRET= IMGOPTS= _make_test_img 1G | _filter_imgfmt
103
+++ b/tests/qemu-iotests/117
107
+QEMU_IO_OPTIONS= IMGOPTSSYNTAX= $QEMU_IO -f raw -c "write -P 0x51 0x10000 0x400" "$TEST_IMG_FILE" | _filter_qemu_io | _filter_testdir
104
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
108
+$QEMU_IMG measure --object "$SECRET" \
105
109
+     -O "$IMGFMT" \
106
_cleanup()
110
+         -o key-secret=sec0,iter-time=10 \
107
{
111
+         -f raw \
108
+ _cleanup_qemu
112
+         "$TEST_IMG_FILE"
109
    _cleanup_test_img
113
+
110
}
114
+# success, all done
111
trap "_cleanup; exit \$status" 0 1 2 3 15
115
+echo "*** done"
112
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
116
+rm -f $seq.full
113
index XXXXXXX..XXXXXXX 100755
117
+status=0
114
--- a/tests/qemu-iotests/130
118
diff --git a/tests/qemu-iotests/288.out b/tests/qemu-iotests/288.out
115
+++ b/tests/qemu-iotests/130
119
new file mode 100644
116
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
120
index XXXXXXX..XXXXXXX
117
121
--- /dev/null
118
_cleanup()
122
+++ b/tests/qemu-iotests/288.out
119
{
123
@@ -XXX,XX +XXX,XX @@
120
+ _cleanup_qemu
124
+QA output created by 288
121
_cleanup_test_img
125
+== measure 1G image file ==
122
}
126
+
123
trap "_cleanup; exit \$status" 0 1 2 3 15
127
+required size: 1075810304
124
diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140
128
+fully allocated size: 1075810304
125
index XXXXXXX..XXXXXXX 100755
129
+
126
--- a/tests/qemu-iotests/140
130
+== create 1G image file (size should be no greater than measured) ==
127
+++ b/tests/qemu-iotests/140
131
+
128
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
132
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
129
133
+image file size in bytes: 1075810304
130
_cleanup()
134
+
131
{
135
+== modified 1G image file (size should be no greater than measured) ==
132
+ _cleanup_qemu
136
+
133
_cleanup_test_img
137
+wrote 1024/1024 bytes at offset 65536
134
rm -f "$TEST_DIR/nbd"
138
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
135
}
139
+image file size in bytes: 1075810304
136
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
140
+
137
index XXXXXXX..XXXXXXX 100755
141
+== measure preallocation=falloc 1G image file ==
138
--- a/tests/qemu-iotests/141
142
+
139
+++ b/tests/qemu-iotests/141
143
+required size: 1075810304
140
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
144
+fully allocated size: 1075810304
141
145
+
142
_cleanup()
146
+== measure with input image file ==
143
{
147
+
144
+ _cleanup_qemu
148
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
145
_cleanup_test_img
149
+wrote 1024/1024 bytes at offset 65536
146
rm -f "$TEST_DIR/{b,m,o}.$IMGFMT"
150
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
147
}
151
+required size: 1075810304
148
diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143
152
+fully allocated size: 1075810304
149
index XXXXXXX..XXXXXXX 100755
153
+*** done
150
--- a/tests/qemu-iotests/143
154
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
151
+++ b/tests/qemu-iotests/143
155
index XXXXXXX..XXXXXXX 100644
152
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
156
--- a/tests/qemu-iotests/group
153
157
+++ b/tests/qemu-iotests/group
154
_cleanup()
158
@@ -XXX,XX +XXX,XX @@
155
{
159
283 auto quick
156
+ _cleanup_qemu
160
284 rw
157
rm -f "$TEST_DIR/nbd"
161
286 rw quick
158
}
162
+288 quick
159
trap "_cleanup; exit \$status" 0 1 2 3 15
160
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
161
index XXXXXXX..XXXXXXX 100755
162
--- a/tests/qemu-iotests/156
163
+++ b/tests/qemu-iotests/156
164
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
165
166
_cleanup()
167
{
168
+ _cleanup_qemu
169
rm -f "$TEST_IMG{,.target}{,.backing,.overlay}"
170
}
171
trap "_cleanup; exit \$status" 0 1 2 3 15
172
--
163
--
173
2.9.3
164
2.24.1
174
165
175
166
diff view generated by jsdifflib
1
The BDRV_O_ALLOW_RDWR flag allows / prohibits the changing of
1
From: David Edmondson <david.edmondson@oracle.com>
2
the BDS 'read_only' state, but there are a few places where it
3
is ignored. In the bdrv_set_read_only() helper, make sure to
4
honor the flag.
5
2
6
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
RFC 7230 section 3.2 indicates that whitespace is permitted between
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
the field name and field value and after the field value.
8
Reviewed-by: John Snow <jsnow@redhat.com>
5
9
Message-id: be2e5fb2d285cbece2b6d06bed54a6f56520d251.1491597120.git.jcody@redhat.com
6
Signed-off-by: David Edmondson <david.edmondson@oracle.com>
7
Message-Id: <20200224101310.101169-2-david.edmondson@oracle.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
10
---
11
block.c | 7 +++++++
11
block/curl.c | 31 +++++++++++++++++++++++++++----
12
1 file changed, 7 insertions(+)
12
1 file changed, 27 insertions(+), 4 deletions(-)
13
13
14
diff --git a/block.c b/block.c
14
diff --git a/block/curl.c b/block/curl.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block.c
16
--- a/block/curl.c
17
+++ b/block.c
17
+++ b/block/curl.c
18
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
18
@@ -XXX,XX +XXX,XX @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
19
return -EINVAL;
19
{
20
BDRVCURLState *s = opaque;
21
size_t realsize = size * nmemb;
22
- const char *accept_line = "Accept-Ranges: bytes";
23
+ const char *header = (char *)ptr;
24
+ const char *end = header + realsize;
25
+ const char *accept_ranges = "Accept-Ranges:";
26
+ const char *bytes = "bytes";
27
28
- if (realsize >= strlen(accept_line)
29
- && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
30
- s->accept_range = true;
31
+ if (realsize >= strlen(accept_ranges)
32
+ && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) {
33
+
34
+ char *p = strchr(header, ':') + 1;
35
+
36
+ /* Skip whitespace between the header name and value. */
37
+ while (p < end && *p && g_ascii_isspace(*p)) {
38
+ p++;
39
+ }
40
+
41
+ if (end - p >= strlen(bytes)
42
+ && strncmp(p, bytes, strlen(bytes)) == 0) {
43
+
44
+ /* Check that there is nothing but whitespace after the value. */
45
+ p += strlen(bytes);
46
+ while (p < end && *p && g_ascii_isspace(*p)) {
47
+ p++;
48
+ }
49
+
50
+ if (p == end || !*p) {
51
+ s->accept_range = true;
52
+ }
53
+ }
20
}
54
}
21
55
22
+ /* Do not clear read_only if it is prohibited */
56
return realsize;
23
+ if (!read_only && !(bs->open_flags & BDRV_O_ALLOW_RDWR)) {
24
+ error_setg(errp, "Node '%s' is read only",
25
+ bdrv_get_device_or_node_name(bs));
26
+ return -EPERM;
27
+ }
28
+
29
bs->read_only = read_only;
30
return 0;
31
}
32
--
57
--
33
2.9.3
58
2.24.1
34
59
35
60
diff view generated by jsdifflib
1
The protocol VXHS does not support image creation. Some tests expect
1
From: David Edmondson <david.edmondson@oracle.com>
2
to be able to create images through the protocol. Exclude VXHS from
3
these tests.
4
2
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
RFC 7230 section 3.2 indicates that HTTP header field names are case
4
insensitive.
5
6
Signed-off-by: David Edmondson <david.edmondson@oracle.com>
7
Message-Id: <20200224101310.101169-3-david.edmondson@oracle.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
10
---
7
tests/qemu-iotests/017 | 1 +
11
block/curl.c | 5 +++--
8
tests/qemu-iotests/020 | 1 +
12
1 file changed, 3 insertions(+), 2 deletions(-)
9
tests/qemu-iotests/029 | 1 +
10
tests/qemu-iotests/073 | 1 +
11
tests/qemu-iotests/114 | 1 +
12
tests/qemu-iotests/130 | 1 +
13
tests/qemu-iotests/134 | 1 +
14
tests/qemu-iotests/156 | 1 +
15
tests/qemu-iotests/158 | 1 +
16
9 files changed, 9 insertions(+)
17
13
18
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
14
diff --git a/block/curl.c b/block/curl.c
19
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/017
16
--- a/block/curl.c
21
+++ b/tests/qemu-iotests/017
17
+++ b/block/curl.c
22
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
18
@@ -XXX,XX +XXX,XX @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
23
# Any format supporting backing files
19
size_t realsize = size * nmemb;
24
_supported_fmt qcow qcow2 vmdk qed
20
const char *header = (char *)ptr;
25
_supported_proto generic
21
const char *end = header + realsize;
26
+_unsupported_proto vxhs
22
- const char *accept_ranges = "Accept-Ranges:";
27
_supported_os Linux
23
+ const char *accept_ranges = "accept-ranges:";
28
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
24
const char *bytes = "bytes";
29
25
30
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
26
if (realsize >= strlen(accept_ranges)
31
index XXXXXXX..XXXXXXX 100755
27
- && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) {
32
--- a/tests/qemu-iotests/020
28
+ && g_ascii_strncasecmp(header, accept_ranges,
33
+++ b/tests/qemu-iotests/020
29
+ strlen(accept_ranges)) == 0) {
34
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
30
35
# Any format supporting backing files
31
char *p = strchr(header, ':') + 1;
36
_supported_fmt qcow qcow2 vmdk qed
37
_supported_proto generic
38
+_unsupported_proto vxhs
39
_supported_os Linux
40
_unsupported_imgopts "subformat=monolithicFlat" \
41
"subformat=twoGbMaxExtentFlat" \
42
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
43
index XXXXXXX..XXXXXXX 100755
44
--- a/tests/qemu-iotests/029
45
+++ b/tests/qemu-iotests/029
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
47
# Any format supporting intenal snapshots
48
_supported_fmt qcow2
49
_supported_proto generic
50
+_unsupported_proto vxhs
51
_supported_os Linux
52
# Internal snapshots are (currently) impossible with refcount_bits=1
53
_unsupported_imgopts 'refcount_bits=1[^0-9]'
54
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
55
index XXXXXXX..XXXXXXX 100755
56
--- a/tests/qemu-iotests/073
57
+++ b/tests/qemu-iotests/073
58
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
59
60
_supported_fmt qcow2
61
_supported_proto generic
62
+_unsupported_proto vxhs
63
_supported_os Linux
64
65
CLUSTER_SIZE=64k
66
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
67
index XXXXXXX..XXXXXXX 100755
68
--- a/tests/qemu-iotests/114
69
+++ b/tests/qemu-iotests/114
70
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
71
72
_supported_fmt qcow2
73
_supported_proto generic
74
+_unsupported_proto vxhs
75
_supported_os Linux
76
77
78
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
79
index XXXXXXX..XXXXXXX 100755
80
--- a/tests/qemu-iotests/130
81
+++ b/tests/qemu-iotests/130
82
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
83
84
_supported_fmt qcow2
85
_supported_proto generic
86
+_unsupported_proto vxhs
87
_supported_os Linux
88
89
qemu_comm_method="monitor"
90
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
91
index XXXXXXX..XXXXXXX 100755
92
--- a/tests/qemu-iotests/134
93
+++ b/tests/qemu-iotests/134
94
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
95
96
_supported_fmt qcow2
97
_supported_proto generic
98
+_unsupported_proto vxhs
99
_supported_os Linux
100
101
102
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
103
index XXXXXXX..XXXXXXX 100755
104
--- a/tests/qemu-iotests/156
105
+++ b/tests/qemu-iotests/156
106
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
107
108
_supported_fmt qcow2 qed
109
_supported_proto generic
110
+_unsupported_proto vxhs
111
_supported_os Linux
112
113
# Create source disk
114
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
115
index XXXXXXX..XXXXXXX 100755
116
--- a/tests/qemu-iotests/158
117
+++ b/tests/qemu-iotests/158
118
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
119
120
_supported_fmt qcow2
121
_supported_proto generic
122
+_unsupported_proto vxhs
123
_supported_os Linux
124
125
32
126
--
33
--
127
2.9.3
34
2.24.1
128
35
129
36
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
These changes use a vxhs test server that is a part of the following
3
Tests 261 and 272 fail on RHEL 7 with coreutils 8.22, since od
4
repository:
4
--endian was not added until coreutils 8.23. Fix this by manually
5
https://github.com/VeritasHyperScale/libqnio.git
5
constructing the final value one byte at a time.
6
6
7
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
7
Fixes: fc8ba423
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reported-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Jeff Cody <jcody@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 1491277689-24949-3-git-send-email-Ashish.Mittal@veritas.com
11
Message-Id: <20200226125424.481840-1-eblake@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
---
13
tests/qemu-iotests/common | 6 ++++++
14
tests/qemu-iotests/common.rc | 22 +++++++++++++++++-----
14
tests/qemu-iotests/common.config | 13 +++++++++++++
15
1 file changed, 17 insertions(+), 5 deletions(-)
15
tests/qemu-iotests/common.filter | 1 +
16
tests/qemu-iotests/common.rc | 19 +++++++++++++++++++
17
4 files changed, 39 insertions(+)
18
16
19
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/common
22
+++ b/tests/qemu-iotests/common
23
@@ -XXX,XX +XXX,XX @@ check options
24
-ssh test ssh
25
-nfs test nfs
26
-luks test luks
27
+ -vxhs test vxhs
28
-xdiff graphical mode diff
29
-nocache use O_DIRECT on backing file
30
-misalign misalign memory allocations
31
@@ -XXX,XX +XXX,XX @@ testlist options
32
xpand=false
33
;;
34
35
+ -vxhs)
36
+ IMGPROTO=vxhs
37
+ xpand=false
38
+ ;;
39
+
40
-ssh)
41
IMGPROTO=ssh
42
xpand=false
43
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
44
index XXXXXXX..XXXXXXX 100644
45
--- a/tests/qemu-iotests/common.config
46
+++ b/tests/qemu-iotests/common.config
47
@@ -XXX,XX +XXX,XX @@ if [ -z "$QEMU_NBD_PROG" ]; then
48
export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
49
fi
50
51
+if [ -z "$QEMU_VXHS_PROG" ]; then
52
+ export QEMU_VXHS_PROG="`set_prog_path qnio_server`"
53
+fi
54
+
55
_qemu_wrapper()
56
{
57
(
58
@@ -XXX,XX +XXX,XX @@ _qemu_nbd_wrapper()
59
)
60
}
61
62
+_qemu_vxhs_wrapper()
63
+{
64
+ (
65
+ echo $BASHPID > "${TEST_DIR}/qemu-vxhs.pid"
66
+ exec "$QEMU_VXHS_PROG" $QEMU_VXHS_OPTIONS "$@"
67
+ )
68
+}
69
+
70
export QEMU=_qemu_wrapper
71
export QEMU_IMG=_qemu_img_wrapper
72
export QEMU_IO=_qemu_io_wrapper
73
export QEMU_NBD=_qemu_nbd_wrapper
74
+export QEMU_VXHS=_qemu_vxhs_wrapper
75
76
QEMU_IMG_EXTRA_ARGS=
77
if [ "$IMGOPTSSYNTAX" = "true" ]; then
78
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
79
index XXXXXXX..XXXXXXX 100644
80
--- a/tests/qemu-iotests/common.filter
81
+++ b/tests/qemu-iotests/common.filter
82
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
83
-e "s#$TEST_DIR#TEST_DIR#g" \
84
-e "s#$IMGFMT#IMGFMT#g" \
85
-e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \
86
+ -e 's#json.*vdisk-id.*vxhs"}}#TEST_DIR/t.IMGFMT#' \
87
-e "/encrypted: yes/d" \
88
-e "/cluster_size: [0-9]\\+/d" \
89
-e "/table_size: [0-9]\\+/d" \
90
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
17
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
91
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
92
--- a/tests/qemu-iotests/common.rc
19
--- a/tests/qemu-iotests/common.rc
93
+++ b/tests/qemu-iotests/common.rc
20
+++ b/tests/qemu-iotests/common.rc
94
@@ -XXX,XX +XXX,XX @@ else
21
@@ -XXX,XX +XXX,XX @@ poke_file()
95
elif [ "$IMGPROTO" = "nfs" ]; then
22
# peek_file_le 'test.img' 512 2 => 65534
96
TEST_DIR="nfs://127.0.0.1/$TEST_DIR"
23
peek_file_le()
97
TEST_IMG=$TEST_DIR/t.$IMGFMT
24
{
98
+ elif [ "$IMGPROTO" = "vxhs" ]; then
25
- # Wrap in echo $() to strip spaces
99
+ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
26
- echo $(od -j"$2" -N"$3" --endian=little -An -vtu"$3" "$1")
100
+ TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT"
27
+ local val=0 shift=0 byte
101
else
102
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
103
fi
104
@@ -XXX,XX +XXX,XX @@ _make_test_img()
105
eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT $TEST_IMG_FILE >/dev/null &"
106
sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
107
fi
108
+
28
+
109
+ # Start QNIO server on image directory for vxhs protocol
29
+ # coreutils' od --endian is not portable, so manually assemble bytes.
110
+ if [ $IMGPROTO = "vxhs" ]; then
30
+ for byte in $(od -j"$2" -N"$3" -An -v -tu1 "$1"); do
111
+ eval "$QEMU_VXHS -d $TEST_DIR > /dev/null &"
31
+ val=$(( val | (byte << shift) ))
112
+ sleep 1 # Wait for server to come up.
32
+ shift=$((shift + 8))
113
+ fi
33
+ done
34
+ printf %llu $val
114
}
35
}
115
36
116
_rm_test_img()
37
# peek_file_be 'test.img' 512 2 => 65279
117
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img()
38
peek_file_be()
118
fi
39
{
119
rm -f "$TEST_IMG_FILE"
40
- # Wrap in echo $() to strip spaces
120
;;
41
- echo $(od -j"$2" -N"$3" --endian=big -An -vtu"$3" "$1")
121
+ vxhs)
42
+ local val=0 byte
122
+ if [ -f "${TEST_DIR}/qemu-vxhs.pid" ]; then
123
+ local QEMU_VXHS_PID
124
+ read QEMU_VXHS_PID < "${TEST_DIR}/qemu-vxhs.pid"
125
+ kill ${QEMU_VXHS_PID} >/dev/null 2>&1
126
+ rm -f "${TEST_DIR}/qemu-vxhs.pid"
127
+ fi
128
+ rm -f "$TEST_IMG_FILE"
129
+ ;;
130
+
43
+
131
file)
44
+ # coreutils' od --endian is not portable, so manually assemble bytes.
132
_rm_test_img "$TEST_DIR/t.$IMGFMT"
45
+ for byte in $(od -j"$2" -N"$3" -An -v -tu1 "$1"); do
133
_rm_test_img "$TEST_DIR/t.$IMGFMT.orig"
46
+ val=$(( (val << 8) | byte ))
47
+ done
48
+ printf %llu $val
49
}
50
51
-# peek_file_raw 'test.img' 512 2 => '\xff\xfe'
52
+# peek_file_raw 'test.img' 512 2 => '\xff\xfe'. Do not use if the raw data
53
+# is likely to contain \0 or trailing \n.
54
peek_file_raw()
55
{
56
dd if="$1" bs=1 skip="$2" count="$3" status=none
134
--
57
--
135
2.9.3
58
2.24.1
136
59
137
60
diff view generated by jsdifflib
New patch
1
From: Pan Nengyuan <pannengyuan@huawei.com>
1
2
3
'crypto_opts' forgot to free in qcow2_close(), this patch fix the bellow leak stack:
4
5
Direct leak of 24 byte(s) in 1 object(s) allocated from:
6
#0 0x7f0edd81f970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970)
7
#1 0x7f0edc6d149d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d)
8
#2 0x55d7eaede63d in qobject_input_start_struct /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qobject-input-visitor.c:295
9
#3 0x55d7eaed78b8 in visit_start_struct /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qapi-visit-core.c:49
10
#4 0x55d7eaf5140b in visit_type_QCryptoBlockOpenOptions qapi/qapi-visit-crypto.c:290
11
#5 0x55d7eae43af3 in block_crypto_open_opts_init /mnt/sdb/qemu-new/qemu_test/qemu/block/crypto.c:163
12
#6 0x55d7eacd2924 in qcow2_update_options_prepare /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1148
13
#7 0x55d7eacd33f7 in qcow2_update_options /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1232
14
#8 0x55d7eacd9680 in qcow2_do_open /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1512
15
#9 0x55d7eacdc55e in qcow2_open_entry /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1792
16
#10 0x55d7eacdc8fe in qcow2_open /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1819
17
#11 0x55d7eac3742d in bdrv_open_driver /mnt/sdb/qemu-new/qemu_test/qemu/block.c:1317
18
#12 0x55d7eac3e990 in bdrv_open_common /mnt/sdb/qemu-new/qemu_test/qemu/block.c:1575
19
#13 0x55d7eac4442c in bdrv_open_inherit /mnt/sdb/qemu-new/qemu_test/qemu/block.c:3126
20
#14 0x55d7eac45c3f in bdrv_open /mnt/sdb/qemu-new/qemu_test/qemu/block.c:3219
21
#15 0x55d7ead8e8a4 in blk_new_open /mnt/sdb/qemu-new/qemu_test/qemu/block/block-backend.c:397
22
#16 0x55d7eacde74c in qcow2_co_create /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:3534
23
#17 0x55d7eacdfa6d in qcow2_co_create_opts /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:3668
24
#18 0x55d7eac1c678 in bdrv_create_co_entry /mnt/sdb/qemu-new/qemu_test/qemu/block.c:485
25
#19 0x55d7eb0024d2 in coroutine_trampoline /mnt/sdb/qemu-new/qemu_test/qemu/util/coroutine-ucontext.c:115
26
27
Reported-by: Euler Robot <euler.robot@huawei.com>
28
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
29
Reviewed-by: Max Reitz <mreitz@redhat.com>
30
Message-Id: <20200227012950.12256-2-pannengyuan@huawei.com>
31
Signed-off-by: Max Reitz <mreitz@redhat.com>
32
---
33
block/qcow2.c | 1 +
34
1 file changed, 1 insertion(+)
35
36
diff --git a/block/qcow2.c b/block/qcow2.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/qcow2.c
39
+++ b/block/qcow2.c
40
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
41
42
qcrypto_block_free(s->crypto);
43
s->crypto = NULL;
44
+ qapi_free_QCryptoBlockOpenOptions(s->crypto_opts);
45
46
g_free(s->unknown_header_fields);
47
cleanup_unknown_header_ext(bs);
48
--
49
2.24.1
50
51
diff view generated by jsdifflib
New patch
1
From: Pan Nengyuan <pannengyuan@huawei.com>
1
2
3
collect_image_check() is called twice in img_check(), the filename/format will be alloced without free the original memory.
4
It is not a big deal since the process will exit anyway, but seems like a clean code and it will remove the warning spotted by asan.
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
8
Message-Id: <20200227012950.12256-3-pannengyuan@huawei.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
qemu-img.c | 2 ++
12
1 file changed, 2 insertions(+)
13
14
diff --git a/qemu-img.c b/qemu-img.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/qemu-img.c
17
+++ b/qemu-img.c
18
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
19
check->corruptions_fixed);
20
}
21
22
+ qapi_free_ImageCheck(check);
23
+ check = g_new0(ImageCheck, 1);
24
ret = collect_image_check(bs, check, filename, fmt, 0);
25
26
check->leaks_fixed = leaks_fixed;
27
--
28
2.24.1
29
30
diff view generated by jsdifflib
1
Signed-off-by: Jeff Cody <jcody@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2
3
Reviewed-by: John Snow <jsnow@redhat.com>
3
On success path we return what inflate() returns instead of 0. And it
4
Message-id: 00aed7ffdd7be4b9ed9ce1007d50028a72b34ebe.1491597120.git.jcody@redhat.com
4
most probably works for Z_STREAM_END as it is positive, but is
5
definitely broken for Z_BUF_ERROR.
6
7
While being here, switch to errno return code, to be closer to
8
qcow2_compress API (and usual expectations).
9
10
Revert condition in if to be more positive. Drop dead initialization of
11
ret.
12
13
Cc: qemu-stable@nongnu.org # v4.0
14
Fixes: 341926ab83e2b
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Message-Id: <20200302150930.16218-1-vsementsov@virtuozzo.com>
17
Reviewed-by: Alberto Garcia <berto@igalia.com>
18
Reviewed-by: Ján Tomko <jtomko@redhat.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
20
---
6
block.c | 14 ++++++++------
21
block/qcow2-threads.c | 12 +++++++-----
7
1 file changed, 8 insertions(+), 6 deletions(-)
22
1 file changed, 7 insertions(+), 5 deletions(-)
8
23
9
diff --git a/block.c b/block.c
24
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
10
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
26
--- a/block/qcow2-threads.c
12
+++ b/block.c
27
+++ b/block/qcow2-threads.c
13
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
28
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_compress(void *dest, size_t dest_size,
14
BlockDriver *drv;
29
* @src - source buffer, @src_size bytes
15
QemuOpts *opts;
30
*
16
const char *value;
31
* Returns: 0 on success
17
+ bool read_only;
32
- * -1 on fail
18
33
+ * -EIO on fail
19
assert(reopen_state != NULL);
34
*/
20
assert(reopen_state->bs->drv != NULL);
35
static ssize_t qcow2_decompress(void *dest, size_t dest_size,
21
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
36
const void *src, size_t src_size)
22
qdict_put(reopen_state->options, "driver", qstring_from_str(value));
37
{
38
- int ret = 0;
39
+ int ret;
40
z_stream strm;
41
42
memset(&strm, 0, sizeof(strm));
43
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_decompress(void *dest, size_t dest_size,
44
45
ret = inflateInit2(&strm, -12);
46
if (ret != Z_OK) {
47
- return -1;
48
+ return -EIO;
23
}
49
}
24
50
25
- /* if we are to stay read-only, do not allow permission change
51
ret = inflate(&strm, Z_FINISH);
26
- * to r/w */
52
- if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || strm.avail_out != 0) {
27
- if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
53
+ if ((ret == Z_STREAM_END || ret == Z_BUF_ERROR) && strm.avail_out == 0) {
28
- reopen_state->flags & BDRV_O_RDWR) {
54
/*
29
- error_setg(errp, "Node '%s' is read only",
55
* We approve Z_BUF_ERROR because we need @dest buffer to be filled, but
30
- bdrv_get_device_or_node_name(reopen_state->bs));
56
* @src buffer may be processed partly (because in qcow2 we know size of
31
+ /* If we are to stay read-only, do not allow permission change
57
* compressed data with precision of one sector)
32
+ * to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
58
*/
33
+ * not set, or if the BDS still has copy_on_read enabled */
59
- ret = -1;
34
+ read_only = !(reopen_state->flags & BDRV_O_RDWR);
60
+ ret = 0;
35
+ ret = bdrv_can_set_read_only(reopen_state->bs, read_only, &local_err);
61
+ } else {
36
+ if (local_err) {
62
+ ret = -EIO;
37
+ error_propagate(errp, local_err);
38
goto error;
39
}
63
}
40
64
65
inflateEnd(&strm);
41
--
66
--
42
2.9.3
67
2.24.1
43
68
44
69
diff view generated by jsdifflib
1
From: Ashish Mittal <ashmit602@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Source code for the qnio library that this code loads can be downloaded from:
3
We need it in separate to pass to the block-copy object in the next
4
https://github.com/VeritasHyperScale/libqnio.git
4
commit.
5
5
6
Sample command line using JSON syntax:
6
Cc: qemu-stable@nongnu.org
7
./x86_64-softmmu/qemu-system-x86_64 -name instance-00000008 -S -vnc 0.0.0.0:0
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
-k en-us -vga cirrus -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
8
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
9
-msg timestamp=on
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
'json:{"driver":"vxhs","vdisk-id":"c3e9095a-a5ee-4dce-afeb-2a59fb387410",
10
Message-Id: <20200311103004.7649-2-vsementsov@virtuozzo.com>
11
"server":{"host":"172.172.17.4","port":"9999"}}'
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
13
Sample command line using URI syntax:
14
qemu-img convert -f raw -O raw -n
15
/var/lib/nova/instances/_base/0c5eacd5ebea5ed914b6a3e7b18f1ce734c386ad
16
vxhs://192.168.0.1:9999/c6718f6b-0401-441d-a8c3-1f0064d75ee0
17
18
Sample command line using TLS credentials (run in secure mode):
19
./qemu-io --object
20
tls-creds-x509,id=tls0,dir=/etc/pki/qemu/vxhs,endpoint=client -c 'read
21
-v 66000 2.5k' 'json:{"server.host": "127.0.0.1", "server.port": "9999",
22
"vdisk-id": "/test.raw", "driver": "vxhs", "tls-creds":"tls0"}'
23
24
Signed-off-by: Ashish Mittal <Ashish.Mittal@veritas.com>
25
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Reviewed-by: Jeff Cody <jcody@redhat.com>
27
Signed-off-by: Jeff Cody <jcody@redhat.com>
28
Message-id: 1491277689-24949-2-git-send-email-Ashish.Mittal@veritas.com
29
---
12
---
30
block/Makefile.objs | 2 +
13
blockjob.c | 16 +++++-----
31
block/trace-events | 17 ++
14
include/qemu/job.h | 11 ++-----
32
block/vxhs.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++++++
15
include/qemu/progress_meter.h | 58 +++++++++++++++++++++++++++++++++++
33
configure | 39 ++++
16
job-qmp.c | 4 +--
34
qapi/block-core.json | 23 ++-
17
job.c | 6 ++--
35
5 files changed, 654 insertions(+), 2 deletions(-)
18
qemu-img.c | 6 ++--
36
create mode 100644 block/vxhs.c
19
6 files changed, 76 insertions(+), 25 deletions(-)
37
20
create mode 100644 include/qemu/progress_meter.h
38
diff --git a/block/Makefile.objs b/block/Makefile.objs
21
39
index XXXXXXX..XXXXXXX 100644
22
diff --git a/blockjob.c b/blockjob.c
40
--- a/block/Makefile.objs
23
index XXXXXXX..XXXXXXX 100644
41
+++ b/block/Makefile.objs
24
--- a/blockjob.c
42
@@ -XXX,XX +XXX,XX @@ block-obj-$(CONFIG_LIBNFS) += nfs.o
25
+++ b/blockjob.c
43
block-obj-$(CONFIG_CURL) += curl.o
26
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
44
block-obj-$(CONFIG_RBD) += rbd.o
27
info->device = g_strdup(job->job.id);
45
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
28
info->busy = atomic_read(&job->job.busy);
46
+block-obj-$(CONFIG_VXHS) += vxhs.o
29
info->paused = job->job.pause_count > 0;
47
block-obj-$(CONFIG_LIBSSH2) += ssh.o
30
- info->offset = job->job.progress_current;
48
block-obj-y += accounting.o dirty-bitmap.o
31
- info->len = job->job.progress_total;
49
block-obj-y += write-threshold.o
32
+ info->offset = job->job.progress.current;
50
@@ -XXX,XX +XXX,XX @@ rbd.o-cflags := $(RBD_CFLAGS)
33
+ info->len = job->job.progress.total;
51
rbd.o-libs := $(RBD_LIBS)
34
info->speed = job->speed;
52
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
35
info->io_status = job->iostatus;
53
gluster.o-libs := $(GLUSTERFS_LIBS)
36
info->ready = job_is_ready(&job->job),
54
+vxhs.o-libs := $(VXHS_LIBS)
37
@@ -XXX,XX +XXX,XX @@ static void block_job_event_cancelled(Notifier *n, void *opaque)
55
ssh.o-cflags := $(LIBSSH2_CFLAGS)
38
56
ssh.o-libs := $(LIBSSH2_LIBS)
39
qapi_event_send_block_job_cancelled(job_type(&job->job),
57
block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
40
job->job.id,
58
diff --git a/block/trace-events b/block/trace-events
41
- job->job.progress_total,
59
index XXXXXXX..XXXXXXX 100644
42
- job->job.progress_current,
60
--- a/block/trace-events
43
+ job->job.progress.total,
61
+++ b/block/trace-events
44
+ job->job.progress.current,
62
@@ -XXX,XX +XXX,XX @@ qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
45
job->speed);
63
qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64
46
}
64
qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64
47
65
qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
48
@@ -XXX,XX +XXX,XX @@ static void block_job_event_completed(Notifier *n, void *opaque)
66
+
49
67
+# block/vxhs.c
50
qapi_event_send_block_job_completed(job_type(&job->job),
68
+vxhs_iio_callback(int error) "ctx is NULL: error %d"
51
job->job.id,
69
+vxhs_iio_callback_chnfail(int err, int error) "QNIO channel failed, no i/o %d, %d"
52
- job->job.progress_total,
70
+vxhs_iio_callback_unknwn(int opcode, int err) "unexpected opcode %d, errno %d"
53
- job->job.progress_current,
71
+vxhs_aio_rw_invalid(int req) "Invalid I/O request iodir %d"
54
+ job->job.progress.total,
72
+vxhs_aio_rw_ioerr(char *guid, int iodir, uint64_t size, uint64_t off, void *acb, int ret, int err) "IO ERROR (vDisk %s) FOR : Read/Write = %d size = %lu offset = %lu ACB = %p. Error = %d, errno = %d"
55
+ job->job.progress.current,
73
+vxhs_get_vdisk_stat_err(char *guid, int ret, int err) "vDisk (%s) stat ioctl failed, ret = %d, errno = %d"
56
job->speed,
74
+vxhs_get_vdisk_stat(char *vdisk_guid, uint64_t vdisk_size) "vDisk %s stat ioctl returned size %lu"
57
!!msg,
75
+vxhs_complete_aio(void *acb, uint64_t ret) "aio failed acb %p ret %ld"
58
msg);
76
+vxhs_parse_uri_filename(const char *filename) "URI passed via bdrv_parse_filename %s"
59
@@ -XXX,XX +XXX,XX @@ static void block_job_event_ready(Notifier *n, void *opaque)
77
+vxhs_open_vdiskid(const char *vdisk_id) "Opening vdisk-id %s"
60
78
+vxhs_open_hostinfo(char *of_vsa_addr, int port) "Adding host %s:%d to BDRVVXHSState"
61
qapi_event_send_block_job_ready(job_type(&job->job),
79
+vxhs_open_iio_open(const char *host) "Failed to connect to storage agent on host %s"
62
job->job.id,
80
+vxhs_parse_uri_hostinfo(char *host, int port) "Host: IP %s, Port %d"
63
- job->job.progress_total,
81
+vxhs_close(char *vdisk_guid) "Closing vdisk %s"
64
- job->job.progress_current,
82
+vxhs_get_creds(const char *cacert, const char *client_key, const char *client_cert) "cacert %s, client_key %s, client_cert %s"
65
+ job->job.progress.total,
83
diff --git a/block/vxhs.c b/block/vxhs.c
66
+ job->job.progress.current,
67
job->speed);
68
}
69
70
diff --git a/include/qemu/job.h b/include/qemu/job.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/qemu/job.h
73
+++ b/include/qemu/job.h
74
@@ -XXX,XX +XXX,XX @@
75
76
#include "qapi/qapi-types-job.h"
77
#include "qemu/queue.h"
78
+#include "qemu/progress_meter.h"
79
#include "qemu/coroutine.h"
80
#include "block/aio.h"
81
82
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
83
/** True if this job should automatically dismiss itself */
84
bool auto_dismiss;
85
86
- /**
87
- * Current progress. The unit is arbitrary as long as the ratio between
88
- * progress_current and progress_total represents the estimated percentage
89
- * of work already done.
90
- */
91
- int64_t progress_current;
92
-
93
- /** Estimated progress_current value at the completion of the job */
94
- int64_t progress_total;
95
+ ProgressMeter progress;
96
97
/**
98
* Return code from @run and/or @prepare callback(s).
99
diff --git a/include/qemu/progress_meter.h b/include/qemu/progress_meter.h
84
new file mode 100644
100
new file mode 100644
85
index XXXXXXX..XXXXXXX
101
index XXXXXXX..XXXXXXX
86
--- /dev/null
102
--- /dev/null
87
+++ b/block/vxhs.c
103
+++ b/include/qemu/progress_meter.h
88
@@ -XXX,XX +XXX,XX @@
104
@@ -XXX,XX +XXX,XX @@
89
+/*
105
+/*
90
+ * QEMU Block driver for Veritas HyperScale (VxHS)
106
+ * Helper functionality for some process progress tracking.
91
+ *
107
+ *
92
+ * Copyright (c) 2017 Veritas Technologies LLC.
108
+ * Copyright (c) 2011 IBM Corp.
93
+ *
109
+ * Copyright (c) 2012, 2018 Red Hat, Inc.
94
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
110
+ * Copyright (c) 2020 Virtuozzo International GmbH
95
+ * See the COPYING file in the top-level directory.
111
+ *
96
+ *
112
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
113
+ * of this software and associated documentation files (the "Software"), to deal
114
+ * in the Software without restriction, including without limitation the rights
115
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
116
+ * copies of the Software, and to permit persons to whom the Software is
117
+ * furnished to do so, subject to the following conditions:
118
+ *
119
+ * The above copyright notice and this permission notice shall be included in
120
+ * all copies or substantial portions of the Software.
121
+ *
122
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
123
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
124
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
125
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
126
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
127
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
128
+ * THE SOFTWARE.
97
+ */
129
+ */
98
+
130
+
99
+#include "qemu/osdep.h"
131
+#ifndef QEMU_PROGRESS_METER_H
100
+#include <qnio/qnio_api.h>
132
+#define QEMU_PROGRESS_METER_H
101
+#include <sys/param.h>
133
+
102
+#include "block/block_int.h"
134
+typedef struct ProgressMeter {
103
+#include "qapi/qmp/qerror.h"
135
+ /**
104
+#include "qapi/qmp/qdict.h"
136
+ * Current progress. The unit is arbitrary as long as the ratio between
105
+#include "qapi/qmp/qstring.h"
137
+ * current and total represents the estimated percentage
106
+#include "trace.h"
138
+ * of work already done.
107
+#include "qemu/uri.h"
139
+ */
108
+#include "qapi/error.h"
140
+ uint64_t current;
109
+#include "qemu/uuid.h"
141
+
110
+#include "crypto/tlscredsx509.h"
142
+ /** Estimated current value at the completion of the process */
111
+
143
+ uint64_t total;
112
+#define VXHS_OPT_FILENAME "filename"
144
+} ProgressMeter;
113
+#define VXHS_OPT_VDISK_ID "vdisk-id"
145
+
114
+#define VXHS_OPT_SERVER "server"
146
+static inline void progress_work_done(ProgressMeter *pm, uint64_t done)
115
+#define VXHS_OPT_HOST "host"
116
+#define VXHS_OPT_PORT "port"
117
+
118
+/* Only accessed under QEMU global mutex */
119
+static uint32_t vxhs_ref;
120
+
121
+typedef enum {
122
+ VDISK_AIO_READ,
123
+ VDISK_AIO_WRITE,
124
+} VDISKAIOCmd;
125
+
126
+/*
127
+ * HyperScale AIO callbacks structure
128
+ */
129
+typedef struct VXHSAIOCB {
130
+ BlockAIOCB common;
131
+ int err;
132
+} VXHSAIOCB;
133
+
134
+typedef struct VXHSvDiskHostsInfo {
135
+ void *dev_handle; /* Device handle */
136
+ char *host; /* Host name or IP */
137
+ int port; /* Host's port number */
138
+} VXHSvDiskHostsInfo;
139
+
140
+/*
141
+ * Structure per vDisk maintained for state
142
+ */
143
+typedef struct BDRVVXHSState {
144
+ VXHSvDiskHostsInfo vdisk_hostinfo; /* Per host info */
145
+ char *vdisk_guid;
146
+ char *tlscredsid; /* tlscredsid */
147
+} BDRVVXHSState;
148
+
149
+static void vxhs_complete_aio_bh(void *opaque)
150
+{
147
+{
151
+ VXHSAIOCB *acb = opaque;
148
+ pm->current += done;
152
+ BlockCompletionFunc *cb = acb->common.cb;
153
+ void *cb_opaque = acb->common.opaque;
154
+ int ret = 0;
155
+
156
+ if (acb->err != 0) {
157
+ trace_vxhs_complete_aio(acb, acb->err);
158
+ ret = (-EIO);
159
+ }
160
+
161
+ qemu_aio_unref(acb);
162
+ cb(cb_opaque, ret);
163
+}
149
+}
164
+
150
+
165
+/*
151
+static inline void progress_set_remaining(ProgressMeter *pm, uint64_t remaining)
166
+ * Called from a libqnio thread
167
+ */
168
+static void vxhs_iio_callback(void *ctx, uint32_t opcode, uint32_t error)
169
+{
152
+{
170
+ VXHSAIOCB *acb = NULL;
153
+ pm->total = pm->current + remaining;
171
+
172
+ switch (opcode) {
173
+ case IRP_READ_REQUEST:
174
+ case IRP_WRITE_REQUEST:
175
+
176
+ /*
177
+ * ctx is VXHSAIOCB*
178
+ * ctx is NULL if error is QNIOERROR_CHANNEL_HUP
179
+ */
180
+ if (ctx) {
181
+ acb = ctx;
182
+ } else {
183
+ trace_vxhs_iio_callback(error);
184
+ goto out;
185
+ }
186
+
187
+ if (error) {
188
+ if (!acb->err) {
189
+ acb->err = error;
190
+ }
191
+ trace_vxhs_iio_callback(error);
192
+ }
193
+
194
+ aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
195
+ vxhs_complete_aio_bh, acb);
196
+ break;
197
+
198
+ default:
199
+ if (error == QNIOERROR_HUP) {
200
+ /*
201
+ * Channel failed, spontaneous notification,
202
+ * not in response to I/O
203
+ */
204
+ trace_vxhs_iio_callback_chnfail(error, errno);
205
+ } else {
206
+ trace_vxhs_iio_callback_unknwn(opcode, error);
207
+ }
208
+ break;
209
+ }
210
+out:
211
+ return;
212
+}
154
+}
213
+
155
+
214
+static QemuOptsList runtime_opts = {
156
+static inline void progress_increase_remaining(ProgressMeter *pm,
215
+ .name = "vxhs",
157
+ uint64_t delta)
216
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
217
+ .desc = {
218
+ {
219
+ .name = VXHS_OPT_FILENAME,
220
+ .type = QEMU_OPT_STRING,
221
+ .help = "URI to the Veritas HyperScale image",
222
+ },
223
+ {
224
+ .name = VXHS_OPT_VDISK_ID,
225
+ .type = QEMU_OPT_STRING,
226
+ .help = "UUID of the VxHS vdisk",
227
+ },
228
+ {
229
+ .name = "tls-creds",
230
+ .type = QEMU_OPT_STRING,
231
+ .help = "ID of the TLS/SSL credentials to use",
232
+ },
233
+ { /* end of list */ }
234
+ },
235
+};
236
+
237
+static QemuOptsList runtime_tcp_opts = {
238
+ .name = "vxhs_tcp",
239
+ .head = QTAILQ_HEAD_INITIALIZER(runtime_tcp_opts.head),
240
+ .desc = {
241
+ {
242
+ .name = VXHS_OPT_HOST,
243
+ .type = QEMU_OPT_STRING,
244
+ .help = "host address (ipv4 addresses)",
245
+ },
246
+ {
247
+ .name = VXHS_OPT_PORT,
248
+ .type = QEMU_OPT_NUMBER,
249
+ .help = "port number on which VxHSD is listening (default 9999)",
250
+ .def_value_str = "9999"
251
+ },
252
+ { /* end of list */ }
253
+ },
254
+};
255
+
256
+/*
257
+ * Parse incoming URI and populate *options with the host
258
+ * and device information
259
+ */
260
+static int vxhs_parse_uri(const char *filename, QDict *options)
261
+{
158
+{
262
+ URI *uri = NULL;
159
+ pm->total += delta;
263
+ char *port;
264
+ int ret = 0;
265
+
266
+ trace_vxhs_parse_uri_filename(filename);
267
+ uri = uri_parse(filename);
268
+ if (!uri || !uri->server || !uri->path) {
269
+ uri_free(uri);
270
+ return -EINVAL;
271
+ }
272
+
273
+ qdict_put(options, VXHS_OPT_SERVER".host", qstring_from_str(uri->server));
274
+
275
+ if (uri->port) {
276
+ port = g_strdup_printf("%d", uri->port);
277
+ qdict_put(options, VXHS_OPT_SERVER".port", qstring_from_str(port));
278
+ g_free(port);
279
+ }
280
+
281
+ qdict_put(options, "vdisk-id", qstring_from_str(uri->path));
282
+
283
+ trace_vxhs_parse_uri_hostinfo(uri->server, uri->port);
284
+ uri_free(uri);
285
+
286
+ return ret;
287
+}
160
+}
288
+
161
+
289
+static void vxhs_parse_filename(const char *filename, QDict *options,
162
+#endif /* QEMU_PROGRESS_METER_H */
290
+ Error **errp)
163
diff --git a/job-qmp.c b/job-qmp.c
291
+{
164
index XXXXXXX..XXXXXXX 100644
292
+ if (qdict_haskey(options, "vdisk-id") || qdict_haskey(options, "server")) {
165
--- a/job-qmp.c
293
+ error_setg(errp, "vdisk-id/server and a file name may not be specified "
166
+++ b/job-qmp.c
294
+ "at the same time");
167
@@ -XXX,XX +XXX,XX @@ static JobInfo *job_query_single(Job *job, Error **errp)
295
+ return;
168
.id = g_strdup(job->id),
296
+ }
169
.type = job_type(job),
297
+
170
.status = job->status,
298
+ if (strstr(filename, "://")) {
171
- .current_progress = job->progress_current,
299
+ int ret = vxhs_parse_uri(filename, options);
172
- .total_progress = job->progress_total,
300
+ if (ret < 0) {
173
+ .current_progress = job->progress.current,
301
+ error_setg(errp, "Invalid URI. URI should be of the form "
174
+ .total_progress = job->progress.total,
302
+ " vxhs://<host_ip>:<port>/<vdisk-id>");
175
.has_error = !!job->err,
303
+ }
176
.error = job->err ? \
304
+ }
177
g_strdup(error_get_pretty(job->err)) : NULL,
305
+}
178
diff --git a/job.c b/job.c
306
+
179
index XXXXXXX..XXXXXXX 100644
307
+static int vxhs_init_and_ref(void)
180
--- a/job.c
308
+{
181
+++ b/job.c
309
+ if (vxhs_ref++ == 0) {
182
@@ -XXX,XX +XXX,XX @@ void job_unref(Job *job)
310
+ if (iio_init(QNIO_VERSION, vxhs_iio_callback)) {
183
311
+ return -ENODEV;
184
void job_progress_update(Job *job, uint64_t done)
312
+ }
185
{
313
+ }
186
- job->progress_current += done;
314
+ return 0;
187
+ progress_work_done(&job->progress, done);
315
+}
188
}
316
+
189
317
+static void vxhs_unref(void)
190
void job_progress_set_remaining(Job *job, uint64_t remaining)
318
+{
191
{
319
+ if (--vxhs_ref == 0) {
192
- job->progress_total = job->progress_current + remaining;
320
+ iio_fini();
193
+ progress_set_remaining(&job->progress, remaining);
321
+ }
194
}
322
+}
195
323
+
196
void job_progress_increase_remaining(Job *job, uint64_t delta)
324
+static void vxhs_get_tls_creds(const char *id, char **cacert,
197
{
325
+ char **key, char **cert, Error **errp)
198
- job->progress_total += delta;
326
+{
199
+ progress_increase_remaining(&job->progress, delta);
327
+ Object *obj;
200
}
328
+ QCryptoTLSCreds *creds;
201
329
+ QCryptoTLSCredsX509 *creds_x509;
202
void job_event_cancelled(Job *job)
330
+
203
diff --git a/qemu-img.c b/qemu-img.c
331
+ obj = object_resolve_path_component(
204
index XXXXXXX..XXXXXXX 100644
332
+ object_get_objects_root(), id);
205
--- a/qemu-img.c
333
+
206
+++ b/qemu-img.c
334
+ if (!obj) {
207
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
335
+ error_setg(errp, "No TLS credentials with id '%s'",
208
do {
336
+ id);
209
float progress = 0.0f;
337
+ return;
210
aio_poll(aio_context, true);
338
+ }
211
- if (job->job.progress_total) {
339
+
212
- progress = (float)job->job.progress_current /
340
+ creds_x509 = (QCryptoTLSCredsX509 *)
213
- job->job.progress_total * 100.f;
341
+ object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS_X509);
214
+ if (job->job.progress.total) {
342
+
215
+ progress = (float)job->job.progress.current /
343
+ if (!creds_x509) {
216
+ job->job.progress.total * 100.f;
344
+ error_setg(errp, "Object with id '%s' is not TLS credentials",
217
}
345
+ id);
218
qemu_progress_print(progress, 0);
346
+ return;
219
} while (!job_is_ready(&job->job) && !job_is_completed(&job->job));
347
+ }
348
+
349
+ creds = &creds_x509->parent_obj;
350
+
351
+ if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
352
+ error_setg(errp,
353
+ "Expecting TLS credentials with a client endpoint");
354
+ return;
355
+ }
356
+
357
+ /*
358
+ * Get the cacert, client_cert and client_key file names.
359
+ */
360
+ if (!creds->dir) {
361
+ error_setg(errp, "TLS object missing 'dir' property value");
362
+ return;
363
+ }
364
+
365
+ *cacert = g_strdup_printf("%s/%s", creds->dir,
366
+ QCRYPTO_TLS_CREDS_X509_CA_CERT);
367
+ *cert = g_strdup_printf("%s/%s", creds->dir,
368
+ QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
369
+ *key = g_strdup_printf("%s/%s", creds->dir,
370
+ QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
371
+}
372
+
373
+static int vxhs_open(BlockDriverState *bs, QDict *options,
374
+ int bdrv_flags, Error **errp)
375
+{
376
+ BDRVVXHSState *s = bs->opaque;
377
+ void *dev_handlep;
378
+ QDict *backing_options = NULL;
379
+ QemuOpts *opts = NULL;
380
+ QemuOpts *tcp_opts = NULL;
381
+ char *of_vsa_addr = NULL;
382
+ Error *local_err = NULL;
383
+ const char *vdisk_id_opt;
384
+ const char *server_host_opt;
385
+ int ret = 0;
386
+ char *cacert = NULL;
387
+ char *client_key = NULL;
388
+ char *client_cert = NULL;
389
+
390
+ ret = vxhs_init_and_ref();
391
+ if (ret < 0) {
392
+ ret = -EINVAL;
393
+ goto out;
394
+ }
395
+
396
+ /* Create opts info from runtime_opts and runtime_tcp_opts list */
397
+ opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
398
+ tcp_opts = qemu_opts_create(&runtime_tcp_opts, NULL, 0, &error_abort);
399
+
400
+ qemu_opts_absorb_qdict(opts, options, &local_err);
401
+ if (local_err) {
402
+ ret = -EINVAL;
403
+ goto out;
404
+ }
405
+
406
+ /* vdisk-id is the disk UUID */
407
+ vdisk_id_opt = qemu_opt_get(opts, VXHS_OPT_VDISK_ID);
408
+ if (!vdisk_id_opt) {
409
+ error_setg(&local_err, QERR_MISSING_PARAMETER, VXHS_OPT_VDISK_ID);
410
+ ret = -EINVAL;
411
+ goto out;
412
+ }
413
+
414
+ /* vdisk-id may contain a leading '/' */
415
+ if (strlen(vdisk_id_opt) > UUID_FMT_LEN + 1) {
416
+ error_setg(&local_err, "vdisk-id cannot be more than %d characters",
417
+ UUID_FMT_LEN);
418
+ ret = -EINVAL;
419
+ goto out;
420
+ }
421
+
422
+ s->vdisk_guid = g_strdup(vdisk_id_opt);
423
+ trace_vxhs_open_vdiskid(vdisk_id_opt);
424
+
425
+ /* get the 'server.' arguments */
426
+ qdict_extract_subqdict(options, &backing_options, VXHS_OPT_SERVER".");
427
+
428
+ qemu_opts_absorb_qdict(tcp_opts, backing_options, &local_err);
429
+ if (local_err != NULL) {
430
+ ret = -EINVAL;
431
+ goto out;
432
+ }
433
+
434
+ server_host_opt = qemu_opt_get(tcp_opts, VXHS_OPT_HOST);
435
+ if (!server_host_opt) {
436
+ error_setg(&local_err, QERR_MISSING_PARAMETER,
437
+ VXHS_OPT_SERVER"."VXHS_OPT_HOST);
438
+ ret = -EINVAL;
439
+ goto out;
440
+ }
441
+
442
+ if (strlen(server_host_opt) > MAXHOSTNAMELEN) {
443
+ error_setg(&local_err, "server.host cannot be more than %d characters",
444
+ MAXHOSTNAMELEN);
445
+ ret = -EINVAL;
446
+ goto out;
447
+ }
448
+
449
+ /* check if we got tls-creds via the --object argument */
450
+ s->tlscredsid = g_strdup(qemu_opt_get(opts, "tls-creds"));
451
+ if (s->tlscredsid) {
452
+ vxhs_get_tls_creds(s->tlscredsid, &cacert, &client_key,
453
+ &client_cert, &local_err);
454
+ if (local_err != NULL) {
455
+ ret = -EINVAL;
456
+ goto out;
457
+ }
458
+ trace_vxhs_get_creds(cacert, client_key, client_cert);
459
+ }
460
+
461
+ s->vdisk_hostinfo.host = g_strdup(server_host_opt);
462
+ s->vdisk_hostinfo.port = g_ascii_strtoll(qemu_opt_get(tcp_opts,
463
+ VXHS_OPT_PORT),
464
+ NULL, 0);
465
+
466
+ trace_vxhs_open_hostinfo(s->vdisk_hostinfo.host,
467
+ s->vdisk_hostinfo.port);
468
+
469
+ of_vsa_addr = g_strdup_printf("of://%s:%d",
470
+ s->vdisk_hostinfo.host,
471
+ s->vdisk_hostinfo.port);
472
+
473
+ /*
474
+ * Open qnio channel to storage agent if not opened before
475
+ */
476
+ dev_handlep = iio_open(of_vsa_addr, s->vdisk_guid, 0,
477
+ cacert, client_key, client_cert);
478
+ if (dev_handlep == NULL) {
479
+ trace_vxhs_open_iio_open(of_vsa_addr);
480
+ ret = -ENODEV;
481
+ goto out;
482
+ }
483
+ s->vdisk_hostinfo.dev_handle = dev_handlep;
484
+
485
+out:
486
+ g_free(of_vsa_addr);
487
+ QDECREF(backing_options);
488
+ qemu_opts_del(tcp_opts);
489
+ qemu_opts_del(opts);
490
+ g_free(cacert);
491
+ g_free(client_key);
492
+ g_free(client_cert);
493
+
494
+ if (ret < 0) {
495
+ vxhs_unref();
496
+ error_propagate(errp, local_err);
497
+ g_free(s->vdisk_hostinfo.host);
498
+ g_free(s->vdisk_guid);
499
+ g_free(s->tlscredsid);
500
+ s->vdisk_guid = NULL;
501
+ }
502
+
503
+ return ret;
504
+}
505
+
506
+static const AIOCBInfo vxhs_aiocb_info = {
507
+ .aiocb_size = sizeof(VXHSAIOCB)
508
+};
509
+
510
+/*
511
+ * This allocates QEMU-VXHS callback for each IO
512
+ * and is passed to QNIO. When QNIO completes the work,
513
+ * it will be passed back through the callback.
514
+ */
515
+static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, int64_t sector_num,
516
+ QEMUIOVector *qiov, int nb_sectors,
517
+ BlockCompletionFunc *cb, void *opaque,
518
+ VDISKAIOCmd iodir)
519
+{
520
+ VXHSAIOCB *acb = NULL;
521
+ BDRVVXHSState *s = bs->opaque;
522
+ size_t size;
523
+ uint64_t offset;
524
+ int iio_flags = 0;
525
+ int ret = 0;
526
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
527
+
528
+ offset = sector_num * BDRV_SECTOR_SIZE;
529
+ size = nb_sectors * BDRV_SECTOR_SIZE;
530
+ acb = qemu_aio_get(&vxhs_aiocb_info, bs, cb, opaque);
531
+
532
+ /*
533
+ * Initialize VXHSAIOCB.
534
+ */
535
+ acb->err = 0;
536
+
537
+ iio_flags = IIO_FLAG_ASYNC;
538
+
539
+ switch (iodir) {
540
+ case VDISK_AIO_WRITE:
541
+ ret = iio_writev(dev_handle, acb, qiov->iov, qiov->niov,
542
+ offset, (uint64_t)size, iio_flags);
543
+ break;
544
+ case VDISK_AIO_READ:
545
+ ret = iio_readv(dev_handle, acb, qiov->iov, qiov->niov,
546
+ offset, (uint64_t)size, iio_flags);
547
+ break;
548
+ default:
549
+ trace_vxhs_aio_rw_invalid(iodir);
550
+ goto errout;
551
+ }
552
+
553
+ if (ret != 0) {
554
+ trace_vxhs_aio_rw_ioerr(s->vdisk_guid, iodir, size, offset,
555
+ acb, ret, errno);
556
+ goto errout;
557
+ }
558
+ return &acb->common;
559
+
560
+errout:
561
+ qemu_aio_unref(acb);
562
+ return NULL;
563
+}
564
+
565
+static BlockAIOCB *vxhs_aio_readv(BlockDriverState *bs,
566
+ int64_t sector_num, QEMUIOVector *qiov,
567
+ int nb_sectors,
568
+ BlockCompletionFunc *cb, void *opaque)
569
+{
570
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
571
+ opaque, VDISK_AIO_READ);
572
+}
573
+
574
+static BlockAIOCB *vxhs_aio_writev(BlockDriverState *bs,
575
+ int64_t sector_num, QEMUIOVector *qiov,
576
+ int nb_sectors,
577
+ BlockCompletionFunc *cb, void *opaque)
578
+{
579
+ return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors,
580
+ cb, opaque, VDISK_AIO_WRITE);
581
+}
582
+
583
+static void vxhs_close(BlockDriverState *bs)
584
+{
585
+ BDRVVXHSState *s = bs->opaque;
586
+
587
+ trace_vxhs_close(s->vdisk_guid);
588
+
589
+ g_free(s->vdisk_guid);
590
+ s->vdisk_guid = NULL;
591
+
592
+ /*
593
+ * Close vDisk device
594
+ */
595
+ if (s->vdisk_hostinfo.dev_handle) {
596
+ iio_close(s->vdisk_hostinfo.dev_handle);
597
+ s->vdisk_hostinfo.dev_handle = NULL;
598
+ }
599
+
600
+ vxhs_unref();
601
+
602
+ /*
603
+ * Free the dynamically allocated host string etc
604
+ */
605
+ g_free(s->vdisk_hostinfo.host);
606
+ g_free(s->tlscredsid);
607
+ s->tlscredsid = NULL;
608
+ s->vdisk_hostinfo.host = NULL;
609
+ s->vdisk_hostinfo.port = 0;
610
+}
611
+
612
+static int64_t vxhs_get_vdisk_stat(BDRVVXHSState *s)
613
+{
614
+ int64_t vdisk_size = -1;
615
+ int ret = 0;
616
+ void *dev_handle = s->vdisk_hostinfo.dev_handle;
617
+
618
+ ret = iio_ioctl(dev_handle, IOR_VDISK_STAT, &vdisk_size, 0);
619
+ if (ret < 0) {
620
+ trace_vxhs_get_vdisk_stat_err(s->vdisk_guid, ret, errno);
621
+ return -EIO;
622
+ }
623
+
624
+ trace_vxhs_get_vdisk_stat(s->vdisk_guid, vdisk_size);
625
+ return vdisk_size;
626
+}
627
+
628
+/*
629
+ * Returns the size of vDisk in bytes. This is required
630
+ * by QEMU block upper block layer so that it is visible
631
+ * to guest.
632
+ */
633
+static int64_t vxhs_getlength(BlockDriverState *bs)
634
+{
635
+ BDRVVXHSState *s = bs->opaque;
636
+ int64_t vdisk_size;
637
+
638
+ vdisk_size = vxhs_get_vdisk_stat(s);
639
+ if (vdisk_size < 0) {
640
+ return -EIO;
641
+ }
642
+
643
+ return vdisk_size;
644
+}
645
+
646
+static BlockDriver bdrv_vxhs = {
647
+ .format_name = "vxhs",
648
+ .protocol_name = "vxhs",
649
+ .instance_size = sizeof(BDRVVXHSState),
650
+ .bdrv_file_open = vxhs_open,
651
+ .bdrv_parse_filename = vxhs_parse_filename,
652
+ .bdrv_close = vxhs_close,
653
+ .bdrv_getlength = vxhs_getlength,
654
+ .bdrv_aio_readv = vxhs_aio_readv,
655
+ .bdrv_aio_writev = vxhs_aio_writev,
656
+};
657
+
658
+static void bdrv_vxhs_init(void)
659
+{
660
+ bdrv_register(&bdrv_vxhs);
661
+}
662
+
663
+block_init(bdrv_vxhs_init);
664
diff --git a/configure b/configure
665
index XXXXXXX..XXXXXXX 100755
666
--- a/configure
667
+++ b/configure
668
@@ -XXX,XX +XXX,XX @@ numa=""
669
tcmalloc="no"
670
jemalloc="no"
671
replication="yes"
672
+vxhs=""
673
674
supported_cpu="no"
675
supported_os="no"
676
@@ -XXX,XX +XXX,XX @@ for opt do
677
;;
678
--enable-replication) replication="yes"
679
;;
680
+ --disable-vxhs) vxhs="no"
681
+ ;;
682
+ --enable-vxhs) vxhs="yes"
683
+ ;;
684
*)
685
echo "ERROR: unknown option $opt"
686
echo "Try '$0 --help' for more information"
687
@@ -XXX,XX +XXX,XX @@ disabled with --disable-FEATURE, default is enabled if available:
688
xfsctl xfsctl support
689
qom-cast-debug cast debugging support
690
tools build qemu-io, qemu-nbd and qemu-image tools
691
+ vxhs Veritas HyperScale vDisk backend support
692
693
NOTE: The object files are built at the place where configure is launched
694
EOF
695
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
696
fi
697
698
##########################################
699
+# Veritas HyperScale block driver VxHS
700
+# Check if libvxhs is installed
701
+
702
+if test "$vxhs" != "no" ; then
703
+ cat > $TMPC <<EOF
704
+#include <stdint.h>
705
+#include <qnio/qnio_api.h>
706
+
707
+void *vxhs_callback;
708
+
709
+int main(void) {
710
+ iio_init(QNIO_VERSION, vxhs_callback);
711
+ return 0;
712
+}
713
+EOF
714
+ vxhs_libs="-lvxhs -lssl"
715
+ if compile_prog "" "$vxhs_libs" ; then
716
+ vxhs=yes
717
+ else
718
+ if test "$vxhs" = "yes" ; then
719
+ feature_not_found "vxhs block device" "Install libvxhs See github"
720
+ fi
721
+ vxhs=no
722
+ fi
723
+fi
724
+
725
+##########################################
726
# End of CC checks
727
# After here, no more $cc or $ld runs
728
729
@@ -XXX,XX +XXX,XX @@ echo "tcmalloc support $tcmalloc"
730
echo "jemalloc support $jemalloc"
731
echo "avx2 optimization $avx2_opt"
732
echo "replication support $replication"
733
+echo "VxHS block device $vxhs"
734
735
if test "$sdl_too_old" = "yes"; then
736
echo "-> Your SDL version is too old - please upgrade to have SDL support"
737
@@ -XXX,XX +XXX,XX @@ if test "$pthread_setname_np" = "yes" ; then
738
echo "CONFIG_PTHREAD_SETNAME_NP=y" >> $config_host_mak
739
fi
740
741
+if test "$vxhs" = "yes" ; then
742
+ echo "CONFIG_VXHS=y" >> $config_host_mak
743
+ echo "VXHS_LIBS=$vxhs_libs" >> $config_host_mak
744
+fi
745
+
746
if test "$tcg_interpreter" = "yes"; then
747
QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
748
elif test "$ARCH" = "sparc64" ; then
749
diff --git a/qapi/block-core.json b/qapi/block-core.json
750
index XXXXXXX..XXXXXXX 100644
751
--- a/qapi/block-core.json
752
+++ b/qapi/block-core.json
753
@@ -XXX,XX +XXX,XX @@
754
#
755
# Drivers that are supported in block device operations.
756
#
757
+# @vxhs: Since 2.10
758
+#
759
# Since: 2.9
760
##
761
{ 'enum': 'BlockdevDriver',
762
@@ -XXX,XX +XXX,XX @@
763
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
764
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
765
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
766
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
767
+ 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
768
769
##
770
# @BlockdevOptionsFile:
771
@@ -XXX,XX +XXX,XX @@
772
'data': { '*offset': 'int', '*size': 'int' } }
773
774
##
775
+# @BlockdevOptionsVxHS:
776
+#
777
+# Driver specific block device options for VxHS
778
+#
779
+# @vdisk-id: UUID of VxHS volume
780
+# @server: vxhs server IP, port
781
+# @tls-creds: TLS credentials ID
782
+#
783
+# Since: 2.10
784
+##
785
+{ 'struct': 'BlockdevOptionsVxHS',
786
+ 'data': { 'vdisk-id': 'str',
787
+ 'server': 'InetSocketAddressBase',
788
+ '*tls-creds': 'str' } }
789
+
790
+##
791
# @BlockdevOptions:
792
#
793
# Options for creating a block device. Many options are available for all
794
@@ -XXX,XX +XXX,XX @@
795
'vhdx': 'BlockdevOptionsGenericFormat',
796
'vmdk': 'BlockdevOptionsGenericCOWFormat',
797
'vpc': 'BlockdevOptionsGenericFormat',
798
- 'vvfat': 'BlockdevOptionsVVFAT'
799
+ 'vvfat': 'BlockdevOptionsVVFAT',
800
+ 'vxhs': 'BlockdevOptionsVxHS'
801
} }
802
803
##
804
--
220
--
805
2.9.3
221
2.24.1
806
222
807
223
diff view generated by jsdifflib
1
Introduce check function for setting read_only flags. Will return < 0 on
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
error, with appropriate Error value set. Does not alter any flags.
3
2
4
Signed-off-by: Jeff Cody <jcody@redhat.com>
3
Assume we have two regions, A and B, and region B is in-flight now,
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
region A is not yet touched, but it is unallocated and should be
6
Reviewed-by: John Snow <jsnow@redhat.com>
5
skipped.
7
Message-id: e2bba34ac3bc76a0c42adc390413f358ae0566e8.1491597120.git.jcody@redhat.com
6
7
Correspondingly, as progress we have
8
9
total = A + B
10
current = 0
11
12
If we reset unallocated region A and call progress_reset_callback,
13
it will calculate 0 bytes dirty in the bitmap and call
14
job_progress_set_remaining, which will set
15
16
total = current + 0 = 0 + 0 = 0
17
18
So, B bytes are actually removed from total accounting. When job
19
finishes we'll have
20
21
total = 0
22
current = B
23
24
, which doesn't sound good.
25
26
This is because we didn't considered in-flight bytes, actually when
27
calculating remaining, we should have set (in_flight + dirty_bytes)
28
as remaining, not only dirty_bytes.
29
30
To fix it, let's refactor progress calculation, moving it to block-copy
31
itself instead of fixing callback. And, of course, track in_flight
32
bytes count.
33
34
We still have to keep one callback, to maintain backup job bytes_read
35
calculation, but it will go on soon, when we turn the whole backup
36
process into one block_copy call.
37
38
Cc: qemu-stable@nongnu.org
39
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
40
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
41
Message-Id: <20200311103004.7649-3-vsementsov@virtuozzo.com>
42
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
43
---
9
block.c | 14 +++++++++++++-
44
block/backup.c | 13 ++-----------
10
include/block/block.h | 1 +
45
block/block-copy.c | 16 ++++++++++++----
11
2 files changed, 14 insertions(+), 1 deletion(-)
46
include/block/block-copy.h | 15 +++++----------
47
3 files changed, 19 insertions(+), 25 deletions(-)
12
48
13
diff --git a/block.c b/block.c
49
diff --git a/block/backup.c b/block/backup.c
14
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
51
--- a/block/backup.c
16
+++ b/block.c
52
+++ b/block/backup.c
17
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_read_only(BlockDriverState *bs)
53
@@ -XXX,XX +XXX,XX @@ static void backup_progress_bytes_callback(int64_t bytes, void *opaque)
18
return bs->read_only;
54
BackupBlockJob *s = opaque;
55
56
s->bytes_read += bytes;
57
- job_progress_update(&s->common.job, bytes);
58
-}
59
-
60
-static void backup_progress_reset_callback(void *opaque)
61
-{
62
- BackupBlockJob *s = opaque;
63
- uint64_t estimate = bdrv_get_dirty_count(s->bcs->copy_bitmap);
64
-
65
- job_progress_set_remaining(&s->common.job, estimate);
19
}
66
}
20
67
21
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
68
static int coroutine_fn backup_do_cow(BackupBlockJob *job,
22
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
69
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
70
job->cluster_size = cluster_size;
71
job->len = len;
72
73
- block_copy_set_callbacks(bcs, backup_progress_bytes_callback,
74
- backup_progress_reset_callback, job);
75
+ block_copy_set_progress_callback(bcs, backup_progress_bytes_callback, job);
76
+ block_copy_set_progress_meter(bcs, &job->common.job.progress);
77
78
/* Required permissions are already taken by backup-top target */
79
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
80
diff --git a/block/block-copy.c b/block/block-copy.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/block/block-copy.c
83
+++ b/block/block-copy.c
84
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
85
return s;
86
}
87
88
-void block_copy_set_callbacks(
89
+void block_copy_set_progress_callback(
90
BlockCopyState *s,
91
ProgressBytesCallbackFunc progress_bytes_callback,
92
- ProgressResetCallbackFunc progress_reset_callback,
93
void *progress_opaque)
23
{
94
{
24
/* Do not set read_only if copy_on_read is enabled */
95
s->progress_bytes_callback = progress_bytes_callback;
25
if (bs->copy_on_read && read_only) {
96
- s->progress_reset_callback = progress_reset_callback;
26
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
97
s->progress_opaque = progress_opaque;
27
return -EPERM;
98
}
28
}
99
29
100
+void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm)
30
+ return 0;
101
+{
102
+ s->progress = pm;
31
+}
103
+}
32
+
104
+
33
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
105
/*
34
+{
106
* block_copy_do_copy
35
+ int ret = 0;
107
*
108
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
109
110
if (!ret) {
111
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
112
- s->progress_reset_callback(s->progress_opaque);
113
+ progress_set_remaining(s->progress,
114
+ bdrv_get_dirty_count(s->copy_bitmap) +
115
+ s->in_flight_bytes);
116
}
117
118
*count = bytes;
119
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
120
trace_block_copy_process(s, start);
121
122
bdrv_reset_dirty_bitmap(s->copy_bitmap, start, chunk_end - start);
123
+ s->in_flight_bytes += chunk_end - start;
124
125
co_get_from_shres(s->mem, chunk_end - start);
126
ret = block_copy_do_copy(s, start, chunk_end, error_is_read);
127
co_put_to_shres(s->mem, chunk_end - start);
128
+ s->in_flight_bytes -= chunk_end - start;
129
if (ret < 0) {
130
bdrv_set_dirty_bitmap(s->copy_bitmap, start, chunk_end - start);
131
break;
132
}
133
134
+ progress_work_done(s->progress, chunk_end - start);
135
s->progress_bytes_callback(chunk_end - start, s->progress_opaque);
136
start = chunk_end;
137
ret = 0;
138
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
139
index XXXXXXX..XXXXXXX 100644
140
--- a/include/block/block-copy.h
141
+++ b/include/block/block-copy.h
142
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyInFlightReq {
143
} BlockCopyInFlightReq;
144
145
typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
146
-typedef void (*ProgressResetCallbackFunc)(void *opaque);
147
typedef struct BlockCopyState {
148
/*
149
* BdrvChild objects are not owned or managed by block-copy. They are
150
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
151
BdrvChild *source;
152
BdrvChild *target;
153
BdrvDirtyBitmap *copy_bitmap;
154
+ int64_t in_flight_bytes;
155
int64_t cluster_size;
156
bool use_copy_range;
157
int64_t copy_size;
158
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
159
*/
160
bool skip_unallocated;
161
162
+ ProgressMeter *progress;
163
/* progress_bytes_callback: called when some copying progress is done. */
164
ProgressBytesCallbackFunc progress_bytes_callback;
165
-
166
- /*
167
- * progress_reset_callback: called when some bytes reset from copy_bitmap
168
- * (see @skip_unallocated above). The callee is assumed to recalculate how
169
- * many bytes remain based on the dirty bit count of copy_bitmap.
170
- */
171
- ProgressResetCallbackFunc progress_reset_callback;
172
void *progress_opaque;
173
174
SharedResource *mem;
175
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
176
BdrvRequestFlags write_flags,
177
Error **errp);
178
179
-void block_copy_set_callbacks(
180
+void block_copy_set_progress_callback(
181
BlockCopyState *s,
182
ProgressBytesCallbackFunc progress_bytes_callback,
183
- ProgressResetCallbackFunc progress_reset_callback,
184
void *progress_opaque);
185
186
+void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
36
+
187
+
37
+ ret = bdrv_can_set_read_only(bs, read_only, errp);
188
void block_copy_state_free(BlockCopyState *s);
38
+ if (ret < 0) {
189
39
+ return ret;
190
int64_t block_copy_reset_unallocated(BlockCopyState *s,
40
+ }
41
+
42
bs->read_only = read_only;
43
return 0;
44
}
45
diff --git a/include/block/block.h b/include/block/block.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/block/block.h
48
+++ b/include/block/block.h
49
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
50
int64_t sector_num, int nb_sectors, int *pnum);
51
52
bool bdrv_is_read_only(BlockDriverState *bs);
53
+int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
54
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
55
bool bdrv_is_sg(BlockDriverState *bs);
56
bool bdrv_is_inserted(BlockDriverState *bs);
57
--
191
--
58
2.9.3
192
2.24.1
59
193
60
194
diff view generated by jsdifflib
1
We have a helper wrapper for checking for the BDS read_only flag,
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
add a helper wrapper to set the read_only flag as well.
3
2
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
In block_copy_do_copy we fallback to read+write if copy_range failed.
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
4
In this case copy_size is larger than defined for buffered IO, and
6
Reviewed-by: John Snow <jsnow@redhat.com>
5
there is corresponding commit. Still, backup copies data cluster by
7
Message-id: 9b18972d05f5fa2ac16c014f0af98d680553048d.1491597120.git.jcody@redhat.com
6
cluster, and most of requests are limited to one cluster anyway, so the
7
only source of this one bad-limited request is copy-before-write
8
operation.
9
10
Further patch will move backup to use block_copy directly, than for
11
cases where copy_range is not supported, first request will be
12
oversized in each backup. It's not good, let's change it now.
13
14
Fix is simple: just limit first copy_range request like buffer-based
15
request. If it succeed, set larger copy_range limit.
16
17
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
19
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
Message-Id: <20200311103004.7649-4-vsementsov@virtuozzo.com>
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
22
---
9
block.c | 5 +++++
23
block/block-copy.c | 41 +++++++++++++++++++++++++++++++----------
10
block/bochs.c | 2 +-
24
1 file changed, 31 insertions(+), 10 deletions(-)
11
block/cloop.c | 2 +-
12
block/dmg.c | 2 +-
13
block/rbd.c | 2 +-
14
block/vvfat.c | 4 ++--
15
include/block/block.h | 1 +
16
7 files changed, 12 insertions(+), 6 deletions(-)
17
25
18
diff --git a/block.c b/block.c
26
diff --git a/block/block-copy.c b/block/block-copy.c
19
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
28
--- a/block/block-copy.c
21
+++ b/block.c
29
+++ b/block/block-copy.c
22
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
30
@@ -XXX,XX +XXX,XX @@ void block_copy_state_free(BlockCopyState *s)
23
}
31
g_free(s);
24
}
32
}
25
33
26
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
34
+static uint32_t block_copy_max_transfer(BdrvChild *source, BdrvChild *target)
27
+{
35
+{
28
+ bs->read_only = read_only;
36
+ return MIN_NON_ZERO(INT_MAX,
37
+ MIN_NON_ZERO(source->bs->bl.max_transfer,
38
+ target->bs->bl.max_transfer));
29
+}
39
+}
30
+
40
+
31
void bdrv_get_full_backing_filename_from_filename(const char *backed,
41
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
32
const char *backing,
42
int64_t cluster_size,
33
char *dest, size_t sz,
43
BdrvRequestFlags write_flags, Error **errp)
34
diff --git a/block/bochs.c b/block/bochs.c
44
{
35
index XXXXXXX..XXXXXXX 100644
45
BlockCopyState *s;
36
--- a/block/bochs.c
46
BdrvDirtyBitmap *copy_bitmap;
37
+++ b/block/bochs.c
47
- uint32_t max_transfer =
38
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
48
- MIN_NON_ZERO(INT_MAX,
39
return -EINVAL;
49
- MIN_NON_ZERO(source->bs->bl.max_transfer,
50
- target->bs->bl.max_transfer));
51
52
copy_bitmap = bdrv_create_dirty_bitmap(source->bs, cluster_size, NULL,
53
errp);
54
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
55
.mem = shres_create(BLOCK_COPY_MAX_MEM),
56
};
57
58
- if (max_transfer < cluster_size) {
59
+ if (block_copy_max_transfer(source, target) < cluster_size) {
60
/*
61
* copy_range does not respect max_transfer. We don't want to bother
62
* with requests smaller than block-copy cluster size, so fallback to
63
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
64
s->copy_size = cluster_size;
65
} else {
66
/*
67
- * copy_range does not respect max_transfer (it's a TODO), so we factor
68
- * that in here.
69
+ * We enable copy-range, but keep small copy_size, until first
70
+ * successful copy_range (look at block_copy_do_copy).
71
*/
72
s->use_copy_range = true;
73
- s->copy_size = MIN(MAX(cluster_size, BLOCK_COPY_MAX_COPY_RANGE),
74
- QEMU_ALIGN_DOWN(max_transfer, cluster_size));
75
+ s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
40
}
76
}
41
77
42
- bs->read_only = true; /* no write support yet */
78
QLIST_INIT(&s->inflight_reqs);
43
+ bdrv_set_read_only(bs, true); /* no write support yet */
79
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
44
80
s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
45
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
81
/* Fallback to read+write with allocated buffer */
46
if (ret < 0) {
82
} else {
47
diff --git a/block/cloop.c b/block/cloop.c
83
+ if (s->use_copy_range) {
48
index XXXXXXX..XXXXXXX 100644
84
+ /*
49
--- a/block/cloop.c
85
+ * Successful copy-range. Now increase copy_size. copy_range
50
+++ b/block/cloop.c
86
+ * does not respect max_transfer (it's a TODO), so we factor
51
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
87
+ * that in here.
52
return -EINVAL;
88
+ *
89
+ * Note: we double-check s->use_copy_range for the case when
90
+ * parallel block-copy request unsets it during previous
91
+ * bdrv_co_copy_range call.
92
+ */
93
+ s->copy_size =
94
+ MIN(MAX(s->cluster_size, BLOCK_COPY_MAX_COPY_RANGE),
95
+ QEMU_ALIGN_DOWN(block_copy_max_transfer(s->source,
96
+ s->target),
97
+ s->cluster_size));
98
+ }
99
goto out;
100
}
53
}
101
}
54
102
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
55
- bs->read_only = true;
103
/*
56
+ bdrv_set_read_only(bs, true);
104
* In case of failed copy_range request above, we may proceed with buffered
57
105
* request larger than BLOCK_COPY_MAX_BUFFER. Still, further requests will
58
/* read header */
106
- * be properly limited, so don't care too much.
59
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
107
+ * be properly limited, so don't care too much. Moreover the most likely
60
diff --git a/block/dmg.c b/block/dmg.c
108
+ * case (copy_range is unsupported for the configuration, so the very first
61
index XXXXXXX..XXXXXXX 100644
109
+ * copy_range request fails) is handled by setting large copy_size only
62
--- a/block/dmg.c
110
+ * after first successful copy_range.
63
+++ b/block/dmg.c
111
*/
64
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
112
65
}
113
bounce_buffer = qemu_blockalign(s->source->bs, nbytes);
66
67
block_module_load_one("dmg-bz2");
68
- bs->read_only = true;
69
+ bdrv_set_read_only(bs, true);
70
71
s->n_chunks = 0;
72
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
73
diff --git a/block/rbd.c b/block/rbd.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/rbd.c
76
+++ b/block/rbd.c
77
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
78
goto failed_open;
79
}
80
81
- bs->read_only = (s->snap != NULL);
82
+ bdrv_set_read_only(bs, (s->snap != NULL));
83
84
qemu_opts_del(opts);
85
return 0;
86
diff --git a/block/vvfat.c b/block/vvfat.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/vvfat.c
89
+++ b/block/vvfat.c
90
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
91
s->current_cluster=0xffffffff;
92
93
/* read only is the default for safety */
94
- bs->read_only = true;
95
+ bdrv_set_read_only(bs, true);
96
s->qcow = NULL;
97
s->qcow_filename = NULL;
98
s->fat2 = NULL;
99
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
100
if (ret < 0) {
101
goto fail;
102
}
103
- bs->read_only = false;
104
+ bdrv_set_read_only(bs, false);
105
}
106
107
bs->total_sectors = cyls * heads * secs;
108
diff --git a/include/block/block.h b/include/block/block.h
109
index XXXXXXX..XXXXXXX 100644
110
--- a/include/block/block.h
111
+++ b/include/block/block.h
112
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
113
int64_t sector_num, int nb_sectors, int *pnum);
114
115
bool bdrv_is_read_only(BlockDriverState *bs);
116
+void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
117
bool bdrv_is_sg(BlockDriverState *bs);
118
bool bdrv_is_inserted(BlockDriverState *bs);
119
int bdrv_media_changed(BlockDriverState *bs);
120
--
114
--
121
2.9.3
115
2.24.1
122
116
123
117
diff view generated by jsdifflib
1
This adds support for reopen in rbd, for changing between r/w and r/o.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Note, that this is only a flag change, but we will block a change from
3
Use bdrv_block_status_above to chose effective chunk size and to handle
4
r/o to r/w if we are using an RBD internal snapshot.
4
zeroes effectively.
5
5
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
This substitutes checking for just being allocated or not, and drops
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
7
old code path for it. Assistance by backup job is dropped too, as
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
caching block-status information is more difficult than just caching
9
Message-id: d4e87539167ec6527d44c97b164eabcccf96e4f3.1491597120.git.jcody@redhat.com
9
is-allocated information in our dirty bitmap, and backup job is not
10
good place for this caching anyway.
11
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <20200311103004.7649-5-vsementsov@virtuozzo.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
17
---
11
block/rbd.c | 21 +++++++++++++++++++++
18
block/block-copy.c | 73 +++++++++++++++++++++++++++++++++++++---------
12
1 file changed, 21 insertions(+)
19
block/trace-events | 1 +
20
2 files changed, 61 insertions(+), 13 deletions(-)
13
21
14
diff --git a/block/rbd.c b/block/rbd.c
22
diff --git a/block/block-copy.c b/block/block-copy.c
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
24
--- a/block/block-copy.c
17
+++ b/block/rbd.c
25
+++ b/block/block-copy.c
18
@@ -XXX,XX +XXX,XX @@ failed_opts:
26
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm)
19
return r;
27
*/
20
}
28
static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
21
29
int64_t start, int64_t end,
22
+
30
- bool *error_is_read)
23
+/* Since RBD is currently always opened R/W via the API,
31
+ bool zeroes, bool *error_is_read)
24
+ * we just need to check if we are using a snapshot or not, in
32
{
25
+ * order to determine if we will allow it to be R/W */
33
int ret;
26
+static int qemu_rbd_reopen_prepare(BDRVReopenState *state,
34
int nbytes = MIN(end, s->len) - start;
27
+ BlockReopenQueue *queue, Error **errp)
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
28
+{
36
assert(QEMU_IS_ALIGNED(end, s->cluster_size));
29
+ BDRVRBDState *s = state->bs->opaque;
37
assert(end < s->len || end == QEMU_ALIGN_UP(s->len, s->cluster_size));
30
+ int ret = 0;
38
31
+
39
+ if (zeroes) {
32
+ if (s->snap && state->flags & BDRV_O_RDWR) {
40
+ ret = bdrv_co_pwrite_zeroes(s->target, start, nbytes, s->write_flags &
33
+ error_setg(errp,
41
+ ~BDRV_REQ_WRITE_COMPRESSED);
34
+ "Cannot change node '%s' to r/w when using RBD snapshot",
42
+ if (ret < 0) {
35
+ bdrv_get_device_or_node_name(state->bs));
43
+ trace_block_copy_write_zeroes_fail(s, start, ret);
36
+ ret = -EINVAL;
44
+ if (error_is_read) {
45
+ *error_is_read = false;
46
+ }
47
+ }
48
+ return ret;
37
+ }
49
+ }
38
+
50
+
51
if (s->use_copy_range) {
52
ret = bdrv_co_copy_range(s->source, start, s->target, start, nbytes,
53
0, s->write_flags);
54
@@ -XXX,XX +XXX,XX @@ out:
55
return ret;
56
}
57
58
+static int block_copy_block_status(BlockCopyState *s, int64_t offset,
59
+ int64_t bytes, int64_t *pnum)
60
+{
61
+ int64_t num;
62
+ BlockDriverState *base;
63
+ int ret;
64
+
65
+ if (s->skip_unallocated && s->source->bs->backing) {
66
+ base = s->source->bs->backing->bs;
67
+ } else {
68
+ base = NULL;
69
+ }
70
+
71
+ ret = bdrv_block_status_above(s->source->bs, base, offset, bytes, &num,
72
+ NULL, NULL);
73
+ if (ret < 0 || num < s->cluster_size) {
74
+ /*
75
+ * On error or if failed to obtain large enough chunk just fallback to
76
+ * copy one cluster.
77
+ */
78
+ num = s->cluster_size;
79
+ ret = BDRV_BLOCK_ALLOCATED | BDRV_BLOCK_DATA;
80
+ } else if (offset + num == s->len) {
81
+ num = QEMU_ALIGN_UP(num, s->cluster_size);
82
+ } else {
83
+ num = QEMU_ALIGN_DOWN(num, s->cluster_size);
84
+ }
85
+
86
+ *pnum = num;
39
+ return ret;
87
+ return ret;
40
+}
88
+}
41
+
89
+
42
static void qemu_rbd_close(BlockDriverState *bs)
90
/*
91
* Check if the cluster starting at offset is allocated or not.
92
* return via pnum the number of contiguous clusters sharing this allocation.
93
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
43
{
94
{
44
BDRVRBDState *s = bs->opaque;
95
int ret = 0;
45
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
96
int64_t end = bytes + start; /* bytes */
46
.bdrv_parse_filename = qemu_rbd_parse_filename,
97
- int64_t status_bytes;
47
.bdrv_file_open = qemu_rbd_open,
98
BlockCopyInFlightReq req;
48
.bdrv_close = qemu_rbd_close,
99
49
+ .bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
100
/*
50
.bdrv_create = qemu_rbd_create,
101
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
51
.bdrv_has_zero_init = bdrv_has_zero_init_1,
102
block_copy_inflight_req_begin(s, &req, start, end);
52
.bdrv_get_info = qemu_rbd_getinfo,
103
104
while (start < end) {
105
- int64_t next_zero, chunk_end;
106
+ int64_t next_zero, chunk_end, status_bytes;
107
108
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, start)) {
109
trace_block_copy_skip(s, start);
110
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
111
chunk_end = next_zero;
112
}
113
114
- if (s->skip_unallocated) {
115
- ret = block_copy_reset_unallocated(s, start, &status_bytes);
116
- if (ret == 0) {
117
- trace_block_copy_skip_range(s, start, status_bytes);
118
- start += status_bytes;
119
- continue;
120
- }
121
- /* Clamp to known allocated region */
122
- chunk_end = MIN(chunk_end, start + status_bytes);
123
+ ret = block_copy_block_status(s, start, chunk_end - start,
124
+ &status_bytes);
125
+ if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
126
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, start, status_bytes);
127
+ progress_set_remaining(s->progress,
128
+ bdrv_get_dirty_count(s->copy_bitmap) +
129
+ s->in_flight_bytes);
130
+ trace_block_copy_skip_range(s, start, status_bytes);
131
+ start += status_bytes;
132
+ continue;
133
}
134
135
+ chunk_end = MIN(chunk_end, start + status_bytes);
136
+
137
trace_block_copy_process(s, start);
138
139
bdrv_reset_dirty_bitmap(s->copy_bitmap, start, chunk_end - start);
140
s->in_flight_bytes += chunk_end - start;
141
142
co_get_from_shres(s->mem, chunk_end - start);
143
- ret = block_copy_do_copy(s, start, chunk_end, error_is_read);
144
+ ret = block_copy_do_copy(s, start, chunk_end, ret & BDRV_BLOCK_ZERO,
145
+ error_is_read);
146
co_put_to_shres(s->mem, chunk_end - start);
147
s->in_flight_bytes -= chunk_end - start;
148
if (ret < 0) {
149
diff --git a/block/trace-events b/block/trace-events
150
index XXXXXXX..XXXXXXX 100644
151
--- a/block/trace-events
152
+++ b/block/trace-events
153
@@ -XXX,XX +XXX,XX @@ block_copy_process(void *bcs, int64_t start) "bcs %p start %"PRId64
154
block_copy_copy_range_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
155
block_copy_read_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
156
block_copy_write_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
157
+block_copy_write_zeroes_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
158
159
# ../blockdev.c
160
qmp_block_job_cancel(void *job) "job %p"
53
--
161
--
54
2.9.3
162
2.24.1
55
163
56
164
diff view generated by jsdifflib
1
Move bdrv_is_read_only() up with its friends.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
Split find_conflicting_inflight_req to be used separately.
4
Reviewed-by: John Snow <jsnow@redhat.com>
4
5
Signed-off-by: Jeff Cody <jcody@redhat.com>
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-id: 73b2399459760c32506f9407efb9dddb3a2789de.1491597120.git.jcody@redhat.com
6
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200311103004.7649-6-vsementsov@virtuozzo.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
10
---
8
block.c | 10 +++++-----
11
block/block-copy.c | 31 +++++++++++++++++++------------
9
1 file changed, 5 insertions(+), 5 deletions(-)
12
1 file changed, 19 insertions(+), 12 deletions(-)
10
13
11
diff --git a/block.c b/block.c
14
diff --git a/block/block-copy.c b/block/block-copy.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
16
--- a/block/block-copy.c
14
+++ b/block.c
17
+++ b/block/block-copy.c
15
@@ -XXX,XX +XXX,XX @@ void path_combine(char *dest, int dest_size,
18
@@ -XXX,XX +XXX,XX @@
16
}
19
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
17
}
20
#define BLOCK_COPY_MAX_MEM (128 * MiB)
18
21
19
+bool bdrv_is_read_only(BlockDriverState *bs)
22
+static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
23
+ int64_t start,
24
+ int64_t end)
20
+{
25
+{
21
+ return bs->read_only;
26
+ BlockCopyInFlightReq *req;
27
+
28
+ QLIST_FOREACH(req, &s->inflight_reqs, list) {
29
+ if (end > req->start_byte && start < req->end_byte) {
30
+ return req;
31
+ }
32
+ }
33
+
34
+ return NULL;
22
+}
35
+}
23
+
36
+
24
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
37
static void coroutine_fn block_copy_wait_inflight_reqs(BlockCopyState *s,
38
int64_t start,
39
int64_t end)
25
{
40
{
26
/* Do not set read_only if copy_on_read is enabled */
41
BlockCopyInFlightReq *req;
27
@@ -XXX,XX +XXX,XX @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
42
- bool waited;
28
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
43
-
44
- do {
45
- waited = false;
46
- QLIST_FOREACH(req, &s->inflight_reqs, list) {
47
- if (end > req->start_byte && start < req->end_byte) {
48
- qemu_co_queue_wait(&req->wait_queue, NULL);
49
- waited = true;
50
- break;
51
- }
52
- }
53
- } while (waited);
54
+
55
+ while ((req = find_conflicting_inflight_req(s, start, end))) {
56
+ qemu_co_queue_wait(&req->wait_queue, NULL);
57
+ }
29
}
58
}
30
59
31
-bool bdrv_is_read_only(BlockDriverState *bs)
60
static void block_copy_inflight_req_begin(BlockCopyState *s,
32
-{
33
- return bs->read_only;
34
-}
35
-
36
bool bdrv_is_sg(BlockDriverState *bs)
37
{
38
return bs->sg;
39
--
61
--
40
2.9.3
62
2.24.1
41
63
42
64
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
We have a lot of "chunk_end - start" invocations, let's switch to
4
bytes/cur_bytes scheme instead.
5
6
While being here, improve check on block_copy_do_copy parameters to not
7
overflow when calculating nbytes and use int64_t for bytes in
8
block_copy for consistency.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20200311103004.7649-7-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/block-copy.c | 78 ++++++++++++++++++++------------------
17
include/block/block-copy.h | 6 +--
18
2 files changed, 44 insertions(+), 40 deletions(-)
19
20
diff --git a/block/block-copy.c b/block/block-copy.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/block-copy.c
23
+++ b/block/block-copy.c
24
@@ -XXX,XX +XXX,XX @@
25
26
static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
27
int64_t start,
28
- int64_t end)
29
+ int64_t bytes)
30
{
31
BlockCopyInFlightReq *req;
32
33
QLIST_FOREACH(req, &s->inflight_reqs, list) {
34
- if (end > req->start_byte && start < req->end_byte) {
35
+ if (start + bytes > req->start && start < req->start + req->bytes) {
36
return req;
37
}
38
}
39
@@ -XXX,XX +XXX,XX @@ static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
40
41
static void coroutine_fn block_copy_wait_inflight_reqs(BlockCopyState *s,
42
int64_t start,
43
- int64_t end)
44
+ int64_t bytes)
45
{
46
BlockCopyInFlightReq *req;
47
48
- while ((req = find_conflicting_inflight_req(s, start, end))) {
49
+ while ((req = find_conflicting_inflight_req(s, start, bytes))) {
50
qemu_co_queue_wait(&req->wait_queue, NULL);
51
}
52
}
53
54
static void block_copy_inflight_req_begin(BlockCopyState *s,
55
BlockCopyInFlightReq *req,
56
- int64_t start, int64_t end)
57
+ int64_t start, int64_t bytes)
58
{
59
- req->start_byte = start;
60
- req->end_byte = end;
61
+ req->start = start;
62
+ req->bytes = bytes;
63
qemu_co_queue_init(&req->wait_queue);
64
QLIST_INSERT_HEAD(&s->inflight_reqs, req, list);
65
}
66
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm)
67
/*
68
* block_copy_do_copy
69
*
70
- * Do copy of cluser-aligned chunk. @end is allowed to exceed s->len only to
71
- * cover last cluster when s->len is not aligned to clusters.
72
+ * Do copy of cluster-aligned chunk. Requested region is allowed to exceed
73
+ * s->len only to cover last cluster when s->len is not aligned to clusters.
74
*
75
* No sync here: nor bitmap neighter intersecting requests handling, only copy.
76
*
77
* Returns 0 on success.
78
*/
79
static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
80
- int64_t start, int64_t end,
81
+ int64_t start, int64_t bytes,
82
bool zeroes, bool *error_is_read)
83
{
84
int ret;
85
- int nbytes = MIN(end, s->len) - start;
86
+ int64_t nbytes = MIN(start + bytes, s->len) - start;
87
void *bounce_buffer = NULL;
88
89
+ assert(start >= 0 && bytes > 0 && INT64_MAX - start >= bytes);
90
assert(QEMU_IS_ALIGNED(start, s->cluster_size));
91
- assert(QEMU_IS_ALIGNED(end, s->cluster_size));
92
- assert(end < s->len || end == QEMU_ALIGN_UP(s->len, s->cluster_size));
93
+ assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
94
+ assert(start < s->len);
95
+ assert(start + bytes <= s->len ||
96
+ start + bytes == QEMU_ALIGN_UP(s->len, s->cluster_size));
97
+ assert(nbytes < INT_MAX);
98
99
if (zeroes) {
100
ret = bdrv_co_pwrite_zeroes(s->target, start, nbytes, s->write_flags &
101
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
102
}
103
104
int coroutine_fn block_copy(BlockCopyState *s,
105
- int64_t start, uint64_t bytes,
106
+ int64_t start, int64_t bytes,
107
bool *error_is_read)
108
{
109
int ret = 0;
110
- int64_t end = bytes + start; /* bytes */
111
BlockCopyInFlightReq req;
112
113
/*
114
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
115
bdrv_get_aio_context(s->target->bs));
116
117
assert(QEMU_IS_ALIGNED(start, s->cluster_size));
118
- assert(QEMU_IS_ALIGNED(end, s->cluster_size));
119
+ assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
120
121
block_copy_wait_inflight_reqs(s, start, bytes);
122
- block_copy_inflight_req_begin(s, &req, start, end);
123
+ block_copy_inflight_req_begin(s, &req, start, bytes);
124
125
- while (start < end) {
126
- int64_t next_zero, chunk_end, status_bytes;
127
+ while (bytes) {
128
+ int64_t next_zero, cur_bytes, status_bytes;
129
130
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, start)) {
131
trace_block_copy_skip(s, start);
132
start += s->cluster_size;
133
+ bytes -= s->cluster_size;
134
continue; /* already copied */
135
}
136
137
- chunk_end = MIN(end, start + s->copy_size);
138
+ cur_bytes = MIN(bytes, s->copy_size);
139
140
next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, start,
141
- chunk_end - start);
142
+ cur_bytes);
143
if (next_zero >= 0) {
144
assert(next_zero > start); /* start is dirty */
145
- assert(next_zero < chunk_end); /* no need to do MIN() */
146
- chunk_end = next_zero;
147
+ assert(next_zero < start + cur_bytes); /* no need to do MIN() */
148
+ cur_bytes = next_zero - start;
149
}
150
151
- ret = block_copy_block_status(s, start, chunk_end - start,
152
- &status_bytes);
153
+ ret = block_copy_block_status(s, start, cur_bytes, &status_bytes);
154
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
155
bdrv_reset_dirty_bitmap(s->copy_bitmap, start, status_bytes);
156
progress_set_remaining(s->progress,
157
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
158
s->in_flight_bytes);
159
trace_block_copy_skip_range(s, start, status_bytes);
160
start += status_bytes;
161
+ bytes -= status_bytes;
162
continue;
163
}
164
165
- chunk_end = MIN(chunk_end, start + status_bytes);
166
+ cur_bytes = MIN(cur_bytes, status_bytes);
167
168
trace_block_copy_process(s, start);
169
170
- bdrv_reset_dirty_bitmap(s->copy_bitmap, start, chunk_end - start);
171
- s->in_flight_bytes += chunk_end - start;
172
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, start, cur_bytes);
173
+ s->in_flight_bytes += cur_bytes;
174
175
- co_get_from_shres(s->mem, chunk_end - start);
176
- ret = block_copy_do_copy(s, start, chunk_end, ret & BDRV_BLOCK_ZERO,
177
+ co_get_from_shres(s->mem, cur_bytes);
178
+ ret = block_copy_do_copy(s, start, cur_bytes, ret & BDRV_BLOCK_ZERO,
179
error_is_read);
180
- co_put_to_shres(s->mem, chunk_end - start);
181
- s->in_flight_bytes -= chunk_end - start;
182
+ co_put_to_shres(s->mem, cur_bytes);
183
+ s->in_flight_bytes -= cur_bytes;
184
if (ret < 0) {
185
- bdrv_set_dirty_bitmap(s->copy_bitmap, start, chunk_end - start);
186
+ bdrv_set_dirty_bitmap(s->copy_bitmap, start, cur_bytes);
187
break;
188
}
189
190
- progress_work_done(s->progress, chunk_end - start);
191
- s->progress_bytes_callback(chunk_end - start, s->progress_opaque);
192
- start = chunk_end;
193
- ret = 0;
194
+ progress_work_done(s->progress, cur_bytes);
195
+ s->progress_bytes_callback(cur_bytes, s->progress_opaque);
196
+ start += cur_bytes;
197
+ bytes -= cur_bytes;
198
}
199
200
block_copy_inflight_req_end(&req);
201
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
202
index XXXXXXX..XXXXXXX 100644
203
--- a/include/block/block-copy.h
204
+++ b/include/block/block-copy.h
205
@@ -XXX,XX +XXX,XX @@
206
#include "qemu/co-shared-resource.h"
207
208
typedef struct BlockCopyInFlightReq {
209
- int64_t start_byte;
210
- int64_t end_byte;
211
+ int64_t start;
212
+ int64_t bytes;
213
QLIST_ENTRY(BlockCopyInFlightReq) list;
214
CoQueue wait_queue; /* coroutines blocked on this request */
215
} BlockCopyInFlightReq;
216
@@ -XXX,XX +XXX,XX @@ void block_copy_state_free(BlockCopyState *s);
217
int64_t block_copy_reset_unallocated(BlockCopyState *s,
218
int64_t offset, int64_t *count);
219
220
-int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes,
221
+int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
222
bool *error_is_read);
223
224
#endif /* BLOCK_COPY_H */
225
--
226
2.24.1
227
228
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
offset/bytes pair is more usual naming in block layer, let's use it.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200311103004.7649-8-vsementsov@virtuozzo.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/block-copy.c | 82 +++++++++++++++++++-------------------
12
include/block/block-copy.h | 4 +-
13
2 files changed, 43 insertions(+), 43 deletions(-)
14
15
diff --git a/block/block-copy.c b/block/block-copy.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/block-copy.c
18
+++ b/block/block-copy.c
19
@@ -XXX,XX +XXX,XX @@
20
#define BLOCK_COPY_MAX_MEM (128 * MiB)
21
22
static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
23
- int64_t start,
24
+ int64_t offset,
25
int64_t bytes)
26
{
27
BlockCopyInFlightReq *req;
28
29
QLIST_FOREACH(req, &s->inflight_reqs, list) {
30
- if (start + bytes > req->start && start < req->start + req->bytes) {
31
+ if (offset + bytes > req->offset && offset < req->offset + req->bytes) {
32
return req;
33
}
34
}
35
@@ -XXX,XX +XXX,XX @@ static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
36
}
37
38
static void coroutine_fn block_copy_wait_inflight_reqs(BlockCopyState *s,
39
- int64_t start,
40
+ int64_t offset,
41
int64_t bytes)
42
{
43
BlockCopyInFlightReq *req;
44
45
- while ((req = find_conflicting_inflight_req(s, start, bytes))) {
46
+ while ((req = find_conflicting_inflight_req(s, offset, bytes))) {
47
qemu_co_queue_wait(&req->wait_queue, NULL);
48
}
49
}
50
51
static void block_copy_inflight_req_begin(BlockCopyState *s,
52
BlockCopyInFlightReq *req,
53
- int64_t start, int64_t bytes)
54
+ int64_t offset, int64_t bytes)
55
{
56
- req->start = start;
57
+ req->offset = offset;
58
req->bytes = bytes;
59
qemu_co_queue_init(&req->wait_queue);
60
QLIST_INSERT_HEAD(&s->inflight_reqs, req, list);
61
@@ -XXX,XX +XXX,XX @@ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm)
62
* Returns 0 on success.
63
*/
64
static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
65
- int64_t start, int64_t bytes,
66
+ int64_t offset, int64_t bytes,
67
bool zeroes, bool *error_is_read)
68
{
69
int ret;
70
- int64_t nbytes = MIN(start + bytes, s->len) - start;
71
+ int64_t nbytes = MIN(offset + bytes, s->len) - offset;
72
void *bounce_buffer = NULL;
73
74
- assert(start >= 0 && bytes > 0 && INT64_MAX - start >= bytes);
75
- assert(QEMU_IS_ALIGNED(start, s->cluster_size));
76
+ assert(offset >= 0 && bytes > 0 && INT64_MAX - offset >= bytes);
77
+ assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
78
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
79
- assert(start < s->len);
80
- assert(start + bytes <= s->len ||
81
- start + bytes == QEMU_ALIGN_UP(s->len, s->cluster_size));
82
+ assert(offset < s->len);
83
+ assert(offset + bytes <= s->len ||
84
+ offset + bytes == QEMU_ALIGN_UP(s->len, s->cluster_size));
85
assert(nbytes < INT_MAX);
86
87
if (zeroes) {
88
- ret = bdrv_co_pwrite_zeroes(s->target, start, nbytes, s->write_flags &
89
+ ret = bdrv_co_pwrite_zeroes(s->target, offset, nbytes, s->write_flags &
90
~BDRV_REQ_WRITE_COMPRESSED);
91
if (ret < 0) {
92
- trace_block_copy_write_zeroes_fail(s, start, ret);
93
+ trace_block_copy_write_zeroes_fail(s, offset, ret);
94
if (error_is_read) {
95
*error_is_read = false;
96
}
97
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
98
}
99
100
if (s->use_copy_range) {
101
- ret = bdrv_co_copy_range(s->source, start, s->target, start, nbytes,
102
+ ret = bdrv_co_copy_range(s->source, offset, s->target, offset, nbytes,
103
0, s->write_flags);
104
if (ret < 0) {
105
- trace_block_copy_copy_range_fail(s, start, ret);
106
+ trace_block_copy_copy_range_fail(s, offset, ret);
107
s->use_copy_range = false;
108
s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
109
/* Fallback to read+write with allocated buffer */
110
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
111
112
bounce_buffer = qemu_blockalign(s->source->bs, nbytes);
113
114
- ret = bdrv_co_pread(s->source, start, nbytes, bounce_buffer, 0);
115
+ ret = bdrv_co_pread(s->source, offset, nbytes, bounce_buffer, 0);
116
if (ret < 0) {
117
- trace_block_copy_read_fail(s, start, ret);
118
+ trace_block_copy_read_fail(s, offset, ret);
119
if (error_is_read) {
120
*error_is_read = true;
121
}
122
goto out;
123
}
124
125
- ret = bdrv_co_pwrite(s->target, start, nbytes, bounce_buffer,
126
+ ret = bdrv_co_pwrite(s->target, offset, nbytes, bounce_buffer,
127
s->write_flags);
128
if (ret < 0) {
129
- trace_block_copy_write_fail(s, start, ret);
130
+ trace_block_copy_write_fail(s, offset, ret);
131
if (error_is_read) {
132
*error_is_read = false;
133
}
134
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
135
}
136
137
int coroutine_fn block_copy(BlockCopyState *s,
138
- int64_t start, int64_t bytes,
139
+ int64_t offset, int64_t bytes,
140
bool *error_is_read)
141
{
142
int ret = 0;
143
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
144
assert(bdrv_get_aio_context(s->source->bs) ==
145
bdrv_get_aio_context(s->target->bs));
146
147
- assert(QEMU_IS_ALIGNED(start, s->cluster_size));
148
+ assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
149
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
150
151
- block_copy_wait_inflight_reqs(s, start, bytes);
152
- block_copy_inflight_req_begin(s, &req, start, bytes);
153
+ block_copy_wait_inflight_reqs(s, offset, bytes);
154
+ block_copy_inflight_req_begin(s, &req, offset, bytes);
155
156
while (bytes) {
157
int64_t next_zero, cur_bytes, status_bytes;
158
159
- if (!bdrv_dirty_bitmap_get(s->copy_bitmap, start)) {
160
- trace_block_copy_skip(s, start);
161
- start += s->cluster_size;
162
+ if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
163
+ trace_block_copy_skip(s, offset);
164
+ offset += s->cluster_size;
165
bytes -= s->cluster_size;
166
continue; /* already copied */
167
}
168
169
cur_bytes = MIN(bytes, s->copy_size);
170
171
- next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, start,
172
+ next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, offset,
173
cur_bytes);
174
if (next_zero >= 0) {
175
- assert(next_zero > start); /* start is dirty */
176
- assert(next_zero < start + cur_bytes); /* no need to do MIN() */
177
- cur_bytes = next_zero - start;
178
+ assert(next_zero > offset); /* offset is dirty */
179
+ assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
180
+ cur_bytes = next_zero - offset;
181
}
182
183
- ret = block_copy_block_status(s, start, cur_bytes, &status_bytes);
184
+ ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
185
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
186
- bdrv_reset_dirty_bitmap(s->copy_bitmap, start, status_bytes);
187
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, status_bytes);
188
progress_set_remaining(s->progress,
189
bdrv_get_dirty_count(s->copy_bitmap) +
190
s->in_flight_bytes);
191
- trace_block_copy_skip_range(s, start, status_bytes);
192
- start += status_bytes;
193
+ trace_block_copy_skip_range(s, offset, status_bytes);
194
+ offset += status_bytes;
195
bytes -= status_bytes;
196
continue;
197
}
198
199
cur_bytes = MIN(cur_bytes, status_bytes);
200
201
- trace_block_copy_process(s, start);
202
+ trace_block_copy_process(s, offset);
203
204
- bdrv_reset_dirty_bitmap(s->copy_bitmap, start, cur_bytes);
205
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, cur_bytes);
206
s->in_flight_bytes += cur_bytes;
207
208
co_get_from_shres(s->mem, cur_bytes);
209
- ret = block_copy_do_copy(s, start, cur_bytes, ret & BDRV_BLOCK_ZERO,
210
+ ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
211
error_is_read);
212
co_put_to_shres(s->mem, cur_bytes);
213
s->in_flight_bytes -= cur_bytes;
214
if (ret < 0) {
215
- bdrv_set_dirty_bitmap(s->copy_bitmap, start, cur_bytes);
216
+ bdrv_set_dirty_bitmap(s->copy_bitmap, offset, cur_bytes);
217
break;
218
}
219
220
progress_work_done(s->progress, cur_bytes);
221
s->progress_bytes_callback(cur_bytes, s->progress_opaque);
222
- start += cur_bytes;
223
+ offset += cur_bytes;
224
bytes -= cur_bytes;
225
}
226
227
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
228
index XXXXXXX..XXXXXXX 100644
229
--- a/include/block/block-copy.h
230
+++ b/include/block/block-copy.h
231
@@ -XXX,XX +XXX,XX @@
232
#include "qemu/co-shared-resource.h"
233
234
typedef struct BlockCopyInFlightReq {
235
- int64_t start;
236
+ int64_t offset;
237
int64_t bytes;
238
QLIST_ENTRY(BlockCopyInFlightReq) list;
239
CoQueue wait_queue; /* coroutines blocked on this request */
240
@@ -XXX,XX +XXX,XX @@ void block_copy_state_free(BlockCopyState *s);
241
int64_t block_copy_reset_unallocated(BlockCopyState *s,
242
int64_t offset, int64_t *count);
243
244
-int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
245
+int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
246
bool *error_is_read);
247
248
#endif /* BLOCK_COPY_H */
249
--
250
2.24.1
251
252
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
Currently, block_copy operation lock the whole requested region. But
4
there is no reason to lock clusters, which are already copied, it will
5
disturb other parallel block_copy requests for no reason.
6
7
Let's instead do the following:
8
9
Lock only sub-region, which we are going to operate on. Then, after
10
copying all dirty sub-regions, we should wait for intersecting
11
requests block-copy, if they failed, we should retry these new dirty
12
clusters.
13
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
16
Message-Id: <20200311103004.7649-9-vsementsov@virtuozzo.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/block-copy.c | 129 ++++++++++++++++++++++++++++++++++++---------
20
1 file changed, 105 insertions(+), 24 deletions(-)
21
22
diff --git a/block/block-copy.c b/block/block-copy.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/block-copy.c
25
+++ b/block/block-copy.c
26
@@ -XXX,XX +XXX,XX @@ static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
27
return NULL;
28
}
29
30
-static void coroutine_fn block_copy_wait_inflight_reqs(BlockCopyState *s,
31
- int64_t offset,
32
- int64_t bytes)
33
+/*
34
+ * If there are no intersecting requests return false. Otherwise, wait for the
35
+ * first found intersecting request to finish and return true.
36
+ */
37
+static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t offset,
38
+ int64_t bytes)
39
{
40
- BlockCopyInFlightReq *req;
41
+ BlockCopyInFlightReq *req = find_conflicting_inflight_req(s, offset, bytes);
42
43
- while ((req = find_conflicting_inflight_req(s, offset, bytes))) {
44
- qemu_co_queue_wait(&req->wait_queue, NULL);
45
+ if (!req) {
46
+ return false;
47
}
48
+
49
+ qemu_co_queue_wait(&req->wait_queue, NULL);
50
+
51
+ return true;
52
}
53
54
+/* Called only on full-dirty region */
55
static void block_copy_inflight_req_begin(BlockCopyState *s,
56
BlockCopyInFlightReq *req,
57
int64_t offset, int64_t bytes)
58
{
59
+ assert(!find_conflicting_inflight_req(s, offset, bytes));
60
+
61
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
62
+ s->in_flight_bytes += bytes;
63
+
64
req->offset = offset;
65
req->bytes = bytes;
66
qemu_co_queue_init(&req->wait_queue);
67
QLIST_INSERT_HEAD(&s->inflight_reqs, req, list);
68
}
69
70
-static void coroutine_fn block_copy_inflight_req_end(BlockCopyInFlightReq *req)
71
+/*
72
+ * block_copy_inflight_req_shrink
73
+ *
74
+ * Drop the tail of the request to be handled later. Set dirty bits back and
75
+ * wake up all requests waiting for us (may be some of them are not intersecting
76
+ * with shrunk request)
77
+ */
78
+static void coroutine_fn block_copy_inflight_req_shrink(BlockCopyState *s,
79
+ BlockCopyInFlightReq *req, int64_t new_bytes)
80
{
81
+ if (new_bytes == req->bytes) {
82
+ return;
83
+ }
84
+
85
+ assert(new_bytes > 0 && new_bytes < req->bytes);
86
+
87
+ s->in_flight_bytes -= req->bytes - new_bytes;
88
+ bdrv_set_dirty_bitmap(s->copy_bitmap,
89
+ req->offset + new_bytes, req->bytes - new_bytes);
90
+
91
+ req->bytes = new_bytes;
92
+ qemu_co_queue_restart_all(&req->wait_queue);
93
+}
94
+
95
+static void coroutine_fn block_copy_inflight_req_end(BlockCopyState *s,
96
+ BlockCopyInFlightReq *req,
97
+ int ret)
98
+{
99
+ s->in_flight_bytes -= req->bytes;
100
+ if (ret < 0) {
101
+ bdrv_set_dirty_bitmap(s->copy_bitmap, req->offset, req->bytes);
102
+ }
103
QLIST_REMOVE(req, list);
104
qemu_co_queue_restart_all(&req->wait_queue);
105
}
106
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
107
return ret;
108
}
109
110
-int coroutine_fn block_copy(BlockCopyState *s,
111
- int64_t offset, int64_t bytes,
112
- bool *error_is_read)
113
+/*
114
+ * block_copy_dirty_clusters
115
+ *
116
+ * Copy dirty clusters in @offset/@bytes range.
117
+ * Returns 1 if dirty clusters found and successfully copied, 0 if no dirty
118
+ * clusters found and -errno on failure.
119
+ */
120
+static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
121
+ int64_t offset, int64_t bytes,
122
+ bool *error_is_read)
123
{
124
int ret = 0;
125
- BlockCopyInFlightReq req;
126
+ bool found_dirty = false;
127
128
/*
129
* block_copy() user is responsible for keeping source and target in same
130
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
131
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
132
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
133
134
- block_copy_wait_inflight_reqs(s, offset, bytes);
135
- block_copy_inflight_req_begin(s, &req, offset, bytes);
136
-
137
while (bytes) {
138
+ BlockCopyInFlightReq req;
139
int64_t next_zero, cur_bytes, status_bytes;
140
141
if (!bdrv_dirty_bitmap_get(s->copy_bitmap, offset)) {
142
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
143
continue; /* already copied */
144
}
145
146
+ found_dirty = true;
147
+
148
cur_bytes = MIN(bytes, s->copy_size);
149
150
next_zero = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, offset,
151
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
152
assert(next_zero < offset + cur_bytes); /* no need to do MIN() */
153
cur_bytes = next_zero - offset;
154
}
155
+ block_copy_inflight_req_begin(s, &req, offset, cur_bytes);
156
157
ret = block_copy_block_status(s, offset, cur_bytes, &status_bytes);
158
+ assert(ret >= 0); /* never fail */
159
+ cur_bytes = MIN(cur_bytes, status_bytes);
160
+ block_copy_inflight_req_shrink(s, &req, cur_bytes);
161
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
162
- bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, status_bytes);
163
+ block_copy_inflight_req_end(s, &req, 0);
164
progress_set_remaining(s->progress,
165
bdrv_get_dirty_count(s->copy_bitmap) +
166
s->in_flight_bytes);
167
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
168
continue;
169
}
170
171
- cur_bytes = MIN(cur_bytes, status_bytes);
172
-
173
trace_block_copy_process(s, offset);
174
175
- bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, cur_bytes);
176
- s->in_flight_bytes += cur_bytes;
177
-
178
co_get_from_shres(s->mem, cur_bytes);
179
ret = block_copy_do_copy(s, offset, cur_bytes, ret & BDRV_BLOCK_ZERO,
180
error_is_read);
181
co_put_to_shres(s->mem, cur_bytes);
182
- s->in_flight_bytes -= cur_bytes;
183
+ block_copy_inflight_req_end(s, &req, ret);
184
if (ret < 0) {
185
- bdrv_set_dirty_bitmap(s->copy_bitmap, offset, cur_bytes);
186
- break;
187
+ return ret;
188
}
189
190
progress_work_done(s->progress, cur_bytes);
191
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
192
bytes -= cur_bytes;
193
}
194
195
- block_copy_inflight_req_end(&req);
196
+ return found_dirty;
197
+}
198
+
199
+/*
200
+ * block_copy
201
+ *
202
+ * Copy requested region, accordingly to dirty bitmap.
203
+ * Collaborate with parallel block_copy requests: if they succeed it will help
204
+ * us. If they fail, we will retry not-copied regions. So, if we return error,
205
+ * it means that some I/O operation failed in context of _this_ block_copy call,
206
+ * not some parallel operation.
207
+ */
208
+int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
209
+ bool *error_is_read)
210
+{
211
+ int ret;
212
+
213
+ do {
214
+ ret = block_copy_dirty_clusters(s, offset, bytes, error_is_read);
215
+
216
+ if (ret == 0) {
217
+ ret = block_copy_wait_one(s, offset, bytes);
218
+ }
219
+
220
+ /*
221
+ * We retry in two cases:
222
+ * 1. Some progress done
223
+ * Something was copied, which means that there were yield points
224
+ * and some new dirty bits may have appeared (due to failed parallel
225
+ * block-copy requests).
226
+ * 2. We have waited for some intersecting block-copy request
227
+ * It may have failed and produced new dirty bits.
228
+ */
229
+ } while (ret > 0);
230
231
return ret;
232
}
233
--
234
2.24.1
235
236
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
Hide structure definitions and add explicit API instead, to keep an
4
eye on the scope of the shared fields.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200311103004.7649-10-vsementsov@virtuozzo.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/backup-top.c | 6 ++--
13
block/backup.c | 25 ++++++++--------
14
block/block-copy.c | 59 ++++++++++++++++++++++++++++++++++++++
15
include/block/block-copy.h | 52 +++------------------------------
16
4 files changed, 80 insertions(+), 62 deletions(-)
17
18
diff --git a/block/backup-top.c b/block/backup-top.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/backup-top.c
21
+++ b/block/backup-top.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVBackupTopState {
23
BlockCopyState *bcs;
24
BdrvChild *target;
25
bool active;
26
+ int64_t cluster_size;
27
} BDRVBackupTopState;
28
29
static coroutine_fn int backup_top_co_preadv(
30
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
31
return 0;
32
}
33
34
- off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size);
35
- end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size);
36
+ off = QEMU_ALIGN_DOWN(offset, s->cluster_size);
37
+ end = QEMU_ALIGN_UP(offset + bytes, s->cluster_size);
38
39
return block_copy(s->bcs, off, end - off, NULL);
40
}
41
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
42
goto fail;
43
}
44
45
+ state->cluster_size = cluster_size;
46
state->bcs = block_copy_state_new(top->backing, state->target,
47
cluster_size, write_flags, &local_err);
48
if (local_err) {
49
diff --git a/block/backup.c b/block/backup.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/backup.c
52
+++ b/block/backup.c
53
@@ -XXX,XX +XXX,XX @@ static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
54
55
if (ret < 0 && job->bitmap_mode == BITMAP_SYNC_MODE_ALWAYS) {
56
/* If we failed and synced, merge in the bits we didn't copy: */
57
- bdrv_dirty_bitmap_merge_internal(bm, job->bcs->copy_bitmap,
58
+ bdrv_dirty_bitmap_merge_internal(bm, block_copy_dirty_bitmap(job->bcs),
59
NULL, true);
60
}
61
}
62
@@ -XXX,XX +XXX,XX @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
63
return;
64
}
65
66
- bdrv_set_dirty_bitmap(backup_job->bcs->copy_bitmap, 0, backup_job->len);
67
+ bdrv_set_dirty_bitmap(block_copy_dirty_bitmap(backup_job->bcs), 0,
68
+ backup_job->len);
69
}
70
71
static BlockErrorAction backup_error_action(BackupBlockJob *job,
72
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_loop(BackupBlockJob *job)
73
BdrvDirtyBitmapIter *bdbi;
74
int ret = 0;
75
76
- bdbi = bdrv_dirty_iter_new(job->bcs->copy_bitmap);
77
+ bdbi = bdrv_dirty_iter_new(block_copy_dirty_bitmap(job->bcs));
78
while ((offset = bdrv_dirty_iter_next(bdbi)) != -1) {
79
do {
80
if (yield_and_check(job)) {
81
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_loop(BackupBlockJob *job)
82
return ret;
83
}
84
85
-static void backup_init_copy_bitmap(BackupBlockJob *job)
86
+static void backup_init_bcs_bitmap(BackupBlockJob *job)
87
{
88
bool ret;
89
uint64_t estimate;
90
+ BdrvDirtyBitmap *bcs_bitmap = block_copy_dirty_bitmap(job->bcs);
91
92
if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
93
- ret = bdrv_dirty_bitmap_merge_internal(job->bcs->copy_bitmap,
94
- job->sync_bitmap,
95
+ ret = bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap,
96
NULL, true);
97
assert(ret);
98
} else {
99
@@ -XXX,XX +XXX,XX @@ static void backup_init_copy_bitmap(BackupBlockJob *job)
100
* We can't hog the coroutine to initialize this thoroughly.
101
* Set a flag and resume work when we are able to yield safely.
102
*/
103
- job->bcs->skip_unallocated = true;
104
+ block_copy_set_skip_unallocated(job->bcs, true);
105
}
106
- bdrv_set_dirty_bitmap(job->bcs->copy_bitmap, 0, job->len);
107
+ bdrv_set_dirty_bitmap(bcs_bitmap, 0, job->len);
108
}
109
110
- estimate = bdrv_get_dirty_count(job->bcs->copy_bitmap);
111
+ estimate = bdrv_get_dirty_count(bcs_bitmap);
112
job_progress_set_remaining(&job->common.job, estimate);
113
}
114
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
116
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
117
int ret = 0;
118
119
- backup_init_copy_bitmap(s);
120
+ backup_init_bcs_bitmap(s);
121
122
if (s->sync_mode == MIRROR_SYNC_MODE_TOP) {
123
int64_t offset = 0;
124
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
125
126
offset += count;
127
}
128
- s->bcs->skip_unallocated = false;
129
+ block_copy_set_skip_unallocated(s->bcs, false);
130
}
131
132
if (s->sync_mode == MIRROR_SYNC_MODE_NONE) {
133
/*
134
- * All bits are set in copy_bitmap to allow any cluster to be copied.
135
+ * All bits are set in bcs bitmap to allow any cluster to be copied.
136
* This does not actually require them to be copied.
137
*/
138
while (!job_is_cancelled(job)) {
139
diff --git a/block/block-copy.c b/block/block-copy.c
140
index XXXXXXX..XXXXXXX 100644
141
--- a/block/block-copy.c
142
+++ b/block/block-copy.c
143
@@ -XXX,XX +XXX,XX @@
144
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
145
#define BLOCK_COPY_MAX_MEM (128 * MiB)
146
147
+typedef struct BlockCopyInFlightReq {
148
+ int64_t offset;
149
+ int64_t bytes;
150
+ QLIST_ENTRY(BlockCopyInFlightReq) list;
151
+ CoQueue wait_queue; /* coroutines blocked on this request */
152
+} BlockCopyInFlightReq;
153
+
154
+typedef struct BlockCopyState {
155
+ /*
156
+ * BdrvChild objects are not owned or managed by block-copy. They are
157
+ * provided by block-copy user and user is responsible for appropriate
158
+ * permissions on these children.
159
+ */
160
+ BdrvChild *source;
161
+ BdrvChild *target;
162
+ BdrvDirtyBitmap *copy_bitmap;
163
+ int64_t in_flight_bytes;
164
+ int64_t cluster_size;
165
+ bool use_copy_range;
166
+ int64_t copy_size;
167
+ uint64_t len;
168
+ QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs;
169
+
170
+ BdrvRequestFlags write_flags;
171
+
172
+ /*
173
+ * skip_unallocated:
174
+ *
175
+ * Used by sync=top jobs, which first scan the source node for unallocated
176
+ * areas and clear them in the copy_bitmap. During this process, the bitmap
177
+ * is thus not fully initialized: It may still have bits set for areas that
178
+ * are unallocated and should actually not be copied.
179
+ *
180
+ * This is indicated by skip_unallocated.
181
+ *
182
+ * In this case, block_copy() will query the source’s allocation status,
183
+ * skip unallocated regions, clear them in the copy_bitmap, and invoke
184
+ * block_copy_reset_unallocated() every time it does.
185
+ */
186
+ bool skip_unallocated;
187
+
188
+ ProgressMeter *progress;
189
+ /* progress_bytes_callback: called when some copying progress is done. */
190
+ ProgressBytesCallbackFunc progress_bytes_callback;
191
+ void *progress_opaque;
192
+
193
+ SharedResource *mem;
194
+} BlockCopyState;
195
+
196
static BlockCopyInFlightReq *find_conflicting_inflight_req(BlockCopyState *s,
197
int64_t offset,
198
int64_t bytes)
199
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
200
201
return ret;
202
}
203
+
204
+BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s)
205
+{
206
+ return s->copy_bitmap;
207
+}
208
+
209
+void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip)
210
+{
211
+ s->skip_unallocated = skip;
212
+}
213
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
214
index XXXXXXX..XXXXXXX 100644
215
--- a/include/block/block-copy.h
216
+++ b/include/block/block-copy.h
217
@@ -XXX,XX +XXX,XX @@
218
#include "block/block.h"
219
#include "qemu/co-shared-resource.h"
220
221
-typedef struct BlockCopyInFlightReq {
222
- int64_t offset;
223
- int64_t bytes;
224
- QLIST_ENTRY(BlockCopyInFlightReq) list;
225
- CoQueue wait_queue; /* coroutines blocked on this request */
226
-} BlockCopyInFlightReq;
227
-
228
typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
229
-typedef struct BlockCopyState {
230
- /*
231
- * BdrvChild objects are not owned or managed by block-copy. They are
232
- * provided by block-copy user and user is responsible for appropriate
233
- * permissions on these children.
234
- */
235
- BdrvChild *source;
236
- BdrvChild *target;
237
- BdrvDirtyBitmap *copy_bitmap;
238
- int64_t in_flight_bytes;
239
- int64_t cluster_size;
240
- bool use_copy_range;
241
- int64_t copy_size;
242
- uint64_t len;
243
- QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs;
244
-
245
- BdrvRequestFlags write_flags;
246
-
247
- /*
248
- * skip_unallocated:
249
- *
250
- * Used by sync=top jobs, which first scan the source node for unallocated
251
- * areas and clear them in the copy_bitmap. During this process, the bitmap
252
- * is thus not fully initialized: It may still have bits set for areas that
253
- * are unallocated and should actually not be copied.
254
- *
255
- * This is indicated by skip_unallocated.
256
- *
257
- * In this case, block_copy() will query the source’s allocation status,
258
- * skip unallocated regions, clear them in the copy_bitmap, and invoke
259
- * block_copy_reset_unallocated() every time it does.
260
- */
261
- bool skip_unallocated;
262
-
263
- ProgressMeter *progress;
264
- /* progress_bytes_callback: called when some copying progress is done. */
265
- ProgressBytesCallbackFunc progress_bytes_callback;
266
- void *progress_opaque;
267
-
268
- SharedResource *mem;
269
-} BlockCopyState;
270
+typedef struct BlockCopyState BlockCopyState;
271
272
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
273
int64_t cluster_size,
274
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
275
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
276
bool *error_is_read);
277
278
+BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
279
+void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
280
+
281
#endif /* BLOCK_COPY_H */
282
--
283
2.24.1
284
285
diff view generated by jsdifflib