1
The following changes since commit 609ef9f451759151d0bfe7c3843410ab94d68f18:
1
The following changes since commit 138d2931979cb7ee4a54a434a54088231f6980ff:
2
2
3
Merge remote-tracking branch 'remotes/berrange/tags/qio-next-pull-request' into staging (2018-06-28 17:53:31 +0100)
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210308' into staging (2021-03-08 11:57:36 +0000)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 583c99d39368526dfb57a715b04a6ceea27dbe1e:
9
for you to fetch changes up to ef2e38a1a1d2915b148c4a49f61626e62c46fbb6:
10
10
11
block: Remove unused sector-based vectored I/O (2018-06-29 14:20:56 +0200)
11
blockdev: Clarify error messages pertaining to 'node-name' (2021-03-08 14:56:55 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches:
15
15
16
- Make truncate operations asynchronous (so that preallocation in
16
- qemu-storage-daemon: add --pidfile option
17
blockdev-create doesn't block the main loop any more)
17
- qemu-storage-daemon: CLI error messages include the option name now
18
- usb-storage: Add rerror/werror properties
18
- vhost-user-blk export: Misc fixes
19
- nvme: Add num_queues property
19
- docs: Improvements for qemu-storage-daemon documentation
20
- qemu-img convert: Copy offloading fixes (including data corruption fix)
20
- parallels: load bitmap extension
21
- qcow2: Fix cluster leak on temporary write error
21
- backup-top: Don't crash on post-finalize accesses
22
- Use byte-based functions instead of bdrv_co_readv/writev()
22
- Improve error messages related to node-name options
23
- Various small fixes and cleanups
23
- iotests improvements
24
24
25
----------------------------------------------------------------
25
----------------------------------------------------------------
26
Eric Blake (8):
26
Alberto Garcia (1):
27
parallels: Switch to byte-based calls
27
iotests: Drop deprecated 'props' from object-add
28
qcow: Switch get_cluster_offset to be byte-based
29
qcow: Switch qcow_co_readv to byte-based calls
30
qcow: Switch qcow_co_writev to byte-based calls
31
qcow: Switch to a byte-based driver
32
replication: Switch to byte-based calls
33
vhdx: Switch to byte-based calls
34
block: Remove unused sector-based vectored I/O
35
28
36
Fam Zheng (5):
29
Connor Kuehl (2):
37
qcow2: Remove dead check on !ret
30
block: Clarify error messages pertaining to 'node-name'
38
block: Move request tracking to children in copy offloading
31
blockdev: Clarify error messages pertaining to 'node-name'
39
qcow2: Fix src_offset in copy offloading
40
iscsi: Don't blindly use designator length in response for memcpy
41
file-posix: Fix EINTR handling
42
32
43
Kevin Wolf (12):
33
Eric Blake (1):
44
qapi/job: The next release will be 3.0
34
iotests: Fix up python style in 300
45
usb-storage: Add rerror/werror properties
46
qcow2: Fix qcow2_truncate() error return value
47
block: Convert .bdrv_truncate callback to coroutine_fn
48
qcow2: Remove coroutine trampoline for preallocate_co()
49
block: Move bdrv_truncate() implementation to io.c
50
block: Use tracked request for truncate
51
file-posix: Make .bdrv_co_truncate asynchronous
52
qemu-iotests: Update 026.out.nocache reference output
53
qcow2: Free allocated clusters on write error
54
qemu-iotests: Test qcow2 not leaking clusters on write error
55
file-posix: Implement co versions of discard/flush
56
35
57
Markus Armbruster (3):
36
Kevin Wolf (1):
58
block-qdict: Pacify Coverity after commit f1b34a248e9
37
docs: qsd: Explain --export nbd,name=... default
59
block/crypto: Pacify Coverity after commit f853465aacb
60
block/crypto: Simplify block_crypto_{open,create}_opts_init()
61
38
62
Weiping Zhang (1):
39
Max Reitz (3):
63
hw/block/nvme: add optional parameter num_queues for nvme device
40
backup: Remove nodes from job in .clean()
41
backup-top: Refuse I/O in inactive state
42
iotests/283: Check that finalize drops backup-top
64
43
65
qapi/job.json | 18 +-
44
Paolo Bonzini (2):
66
block/crypto.h | 8 +-
45
storage-daemon: report unexpected arguments on the fly
67
block/qcow2.h | 1 +
46
storage-daemon: include current command line option in the errors
68
include/block/block.h | 8 +-
69
include/block/block_int.h | 7 +-
70
include/block/raw-aio.h | 4 +-
71
include/hw/scsi/scsi.h | 2 +
72
block.c | 64 +------
73
block/copy-on-read.c | 8 +-
74
block/crypto.c | 112 +++--------
75
block/file-posix.c | 367 +++++++++++++++++++------------------
76
block/file-win32.c | 6 +-
77
block/gluster.c | 14 +-
78
block/io.c | 219 +++++++++++++++-------
79
block/iscsi.c | 10 +-
80
block/nfs.c | 7 +-
81
block/parallels.c | 16 +-
82
block/qcow.c | 135 +++++++-------
83
block/qcow2-cluster.c | 11 ++
84
block/qcow2.c | 140 ++++++--------
85
block/qed.c | 8 +-
86
block/raw-format.c | 8 +-
87
block/rbd.c | 8 +-
88
block/replication.c | 14 +-
89
block/sheepdog.c | 12 +-
90
block/ssh.c | 6 +-
91
block/vhdx.c | 12 +-
92
hw/block/nvme.c | 5 +-
93
hw/scsi/scsi-bus.c | 11 +-
94
hw/usb/dev-storage.c | 2 +
95
qobject/block-qdict.c | 16 +-
96
tests/qemu-iotests/026 | 17 ++
97
tests/qemu-iotests/026.out | 8 +
98
tests/qemu-iotests/026.out.nocache | 14 +-
99
tests/qemu-iotests/063 | 9 +
100
tests/qemu-iotests/063.out | 12 ++
101
36 files changed, 685 insertions(+), 634 deletions(-)
102
47
48
Stefan Hajnoczi (12):
49
qemu-storage-daemon: add --pidfile option
50
docs: show how to spawn qemu-storage-daemon with fd passing
51
docs: replace insecure /tmp examples in qsd docs
52
vhost-user-blk: fix blkcfg->num_queues endianness
53
libqtest: add qtest_socket_server()
54
libqtest: add qtest_kill_qemu()
55
libqtest: add qtest_remove_abrt_handler()
56
block/export: fix blk_size double byteswap
57
block/export: use VIRTIO_BLK_SECTOR_BITS
58
block/export: fix vhost-user-blk export sector number calculation
59
block/export: port virtio-blk discard/write zeroes input validation
60
block/export: port virtio-blk read/write range check
61
62
Stefano Garzarella (1):
63
blockjob: report a better error message
64
65
Vladimir Sementsov-Ogievskiy (7):
66
qcow2-bitmap: make bytes_covered_by_bitmap_cluster() public
67
parallels.txt: fix bitmap L1 table description
68
block/parallels: BDRVParallelsState: add cluster_size field
69
parallels: support bitmap extension for read-only mode
70
iotests.py: add unarchive_sample_image() helper
71
iotests: add parallels-read-bitmap test
72
MAINTAINERS: update parallels block driver
73
74
docs/interop/parallels.txt | 28 +-
75
docs/tools/qemu-storage-daemon.rst | 68 ++++-
76
block/parallels.h | 7 +-
77
include/block/dirty-bitmap.h | 2 +
78
tests/qtest/libqos/libqtest.h | 37 +++
79
block.c | 8 +-
80
block/backup-top.c | 10 +
81
block/backup.c | 1 +
82
block/dirty-bitmap.c | 13 +
83
block/export/vhost-user-blk-server.c | 150 +++++++++--
84
block/parallels-ext.c | 300 +++++++++++++++++++++
85
block/parallels.c | 26 +-
86
block/qcow2-bitmap.c | 16 +-
87
blockdev.c | 13 +-
88
blockjob.c | 10 +-
89
hw/block/vhost-user-blk.c | 7 +-
90
storage-daemon/qemu-storage-daemon.c | 56 +++-
91
tests/qtest/libqtest.c | 82 ++++--
92
tests/qemu-iotests/iotests.py | 10 +
93
MAINTAINERS | 3 +
94
block/meson.build | 3 +-
95
tests/qemu-iotests/030 | 4 +-
96
tests/qemu-iotests/040 | 4 +-
97
tests/qemu-iotests/051.pc.out | 6 +-
98
tests/qemu-iotests/081.out | 2 +-
99
tests/qemu-iotests/085.out | 6 +-
100
tests/qemu-iotests/087 | 8 +-
101
tests/qemu-iotests/087.out | 2 +-
102
tests/qemu-iotests/184 | 18 +-
103
tests/qemu-iotests/206.out | 2 +-
104
tests/qemu-iotests/210.out | 2 +-
105
tests/qemu-iotests/211.out | 2 +-
106
tests/qemu-iotests/212.out | 2 +-
107
tests/qemu-iotests/213.out | 2 +-
108
tests/qemu-iotests/218 | 2 +-
109
tests/qemu-iotests/223.out | 4 +-
110
tests/qemu-iotests/235 | 2 +-
111
tests/qemu-iotests/237.out | 2 +-
112
tests/qemu-iotests/245 | 14 +-
113
tests/qemu-iotests/249.out | 2 +-
114
tests/qemu-iotests/258 | 6 +-
115
tests/qemu-iotests/258.out | 4 +-
116
tests/qemu-iotests/283 | 53 ++++
117
tests/qemu-iotests/283.out | 15 ++
118
tests/qemu-iotests/295 | 2 +-
119
tests/qemu-iotests/296 | 2 +-
120
tests/qemu-iotests/300 | 14 +-
121
.../sample_images/parallels-with-bitmap.bz2 | Bin 0 -> 203 bytes
122
.../sample_images/parallels-with-bitmap.sh | 51 ++++
123
tests/qemu-iotests/tests/parallels-read-bitmap | 55 ++++
124
tests/qemu-iotests/tests/parallels-read-bitmap.out | 6 +
125
51 files changed, 969 insertions(+), 175 deletions(-)
126
create mode 100644 block/parallels-ext.c
127
create mode 100644 tests/qemu-iotests/sample_images/parallels-with-bitmap.bz2
128
create mode 100755 tests/qemu-iotests/sample_images/parallels-with-bitmap.sh
129
create mode 100755 tests/qemu-iotests/tests/parallels-read-bitmap
130
create mode 100644 tests/qemu-iotests/tests/parallels-read-bitmap.out
131
132
diff view generated by jsdifflib
Deleted patch
1
From: Markus Armbruster <armbru@redhat.com>
2
1
3
Commit f1b34a248e9 replaced less-than-obvious test in
4
qdict_flatten_qdict() by the obvious one. Sadly, it made something
5
else non-obvious: the fact that @new_key passed to qdict_put_obj()
6
can't be null, because that depends on the function's precondition
7
(target == qdict) == !prefix.
8
9
Tweak the function some more to help Coverity and human readers alike.
10
11
Fixes: CID 1393620
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
qobject/block-qdict.c | 16 ++++++++--------
16
1 file changed, 8 insertions(+), 8 deletions(-)
17
18
diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/qobject/block-qdict.c
21
+++ b/qobject/block-qdict.c
22
@@ -XXX,XX +XXX,XX @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
23
const QDictEntry *entry, *next;
24
QDict *dict_val;
25
QList *list_val;
26
- char *new_key;
27
+ char *key, *new_key;
28
29
entry = qdict_first(qdict);
30
31
@@ -XXX,XX +XXX,XX @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
32
value = qdict_entry_value(entry);
33
dict_val = qobject_to(QDict, value);
34
list_val = qobject_to(QList, value);
35
- new_key = NULL;
36
37
if (prefix) {
38
- new_key = g_strdup_printf("%s.%s", prefix, entry->key);
39
+ key = new_key = g_strdup_printf("%s.%s", prefix, entry->key);
40
+ } else {
41
+ key = entry->key;
42
+ new_key = NULL;
43
}
44
45
/*
46
@@ -XXX,XX +XXX,XX @@ static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
47
* well advised not to modify them altogether.)
48
*/
49
if (dict_val && qdict_size(dict_val)) {
50
- qdict_flatten_qdict(dict_val, target,
51
- new_key ? new_key : entry->key);
52
+ qdict_flatten_qdict(dict_val, target, key);
53
if (target == qdict) {
54
qdict_del(qdict, entry->key);
55
}
56
} else if (list_val && !qlist_empty(list_val)) {
57
- qdict_flatten_qlist(list_val, target,
58
- new_key ? new_key : entry->key);
59
+ qdict_flatten_qlist(list_val, target, key);
60
if (target == qdict) {
61
qdict_del(qdict, entry->key);
62
}
63
} else if (target != qdict) {
64
- qdict_put_obj(target, new_key, qobject_ref(value));
65
+ qdict_put_obj(target, key, qobject_ref(value));
66
}
67
68
g_free(new_key);
69
--
70
2.13.6
71
72
diff view generated by jsdifflib
Deleted patch
1
From: Markus Armbruster <armbru@redhat.com>
2
1
3
Coverity can't see that qobject_input_visitor_new_flat_confused()
4
returns non-null when it doesn't set @local_err. Check the return
5
value instead, like all the other callers do.
6
7
Fixes: CID 1393615
8
Fixes: CID 1393616
9
Signed-off-by: Markus Armbruster <armbru@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/crypto.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/block/crypto.c b/block/crypto.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/crypto.c
18
+++ b/block/crypto.c
19
@@ -XXX,XX +XXX,XX @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
20
ret->format = format;
21
22
v = qobject_input_visitor_new_flat_confused(opts, &local_err);
23
- if (local_err) {
24
+ if (!v) {
25
goto out;
26
}
27
28
@@ -XXX,XX +XXX,XX @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
29
ret->format = format;
30
31
v = qobject_input_visitor_new_flat_confused(opts, &local_err);
32
- if (local_err) {
33
+ if (!v) {
34
goto out;
35
}
36
37
--
38
2.13.6
39
40
diff view generated by jsdifflib
Deleted patch
1
Commit 51f63ec7d tried to change all references to 2.13 into 3.0, but
2
it failed to achieve this because it was not properly rebased on top of
3
the series introducing qapi/job.json. Change the references now.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
9
qapi/job.json | 18 +++++++++---------
10
1 file changed, 9 insertions(+), 9 deletions(-)
11
12
diff --git a/qapi/job.json b/qapi/job.json
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/job.json
15
+++ b/qapi/job.json
16
@@ -XXX,XX +XXX,XX @@
17
# @id: The job identifier
18
# @status: The new job status
19
#
20
-# Since: 2.13
21
+# Since: 3.0
22
##
23
{ 'event': 'JOB_STATUS_CHANGE',
24
'data': { 'id': 'str',
25
@@ -XXX,XX +XXX,XX @@
26
#
27
# @id: The job identifier.
28
#
29
-# Since: 2.13
30
+# Since: 3.0
31
##
32
{ 'command': 'job-pause', 'data': { 'id': 'str' } }
33
34
@@ -XXX,XX +XXX,XX @@
35
#
36
# @id : The job identifier.
37
#
38
-# Since: 2.13
39
+# Since: 3.0
40
##
41
{ 'command': 'job-resume', 'data': { 'id': 'str' } }
42
43
@@ -XXX,XX +XXX,XX @@
44
#
45
# @id: The job identifier.
46
#
47
-# Since: 2.13
48
+# Since: 3.0
49
##
50
{ 'command': 'job-cancel', 'data': { 'id': 'str' } }
51
52
@@ -XXX,XX +XXX,XX @@
53
#
54
# @id: The job identifier.
55
#
56
-# Since: 2.13
57
+# Since: 3.0
58
##
59
{ 'command': 'job-complete', 'data': { 'id': 'str' } }
60
61
@@ -XXX,XX +XXX,XX @@
62
#
63
# @id: The job identifier.
64
#
65
-# Since: 2.13
66
+# Since: 3.0
67
##
68
{ 'command': 'job-dismiss', 'data': { 'id': 'str' } }
69
70
@@ -XXX,XX +XXX,XX @@
71
# @id: The identifier of any job in the transaction, or of a job that is not
72
# part of any transaction.
73
#
74
-# Since: 2.13
75
+# Since: 3.0
76
##
77
{ 'command': 'job-finalize', 'data': { 'id': 'str' } }
78
79
@@ -XXX,XX +XXX,XX @@
80
# the reason for the job failure. It should not be parsed
81
# by applications.
82
#
83
-# Since: 2.13
84
+# Since: 3.0
85
##
86
{ 'struct': 'JobInfo',
87
'data': { 'id': 'str', 'type': 'JobType', 'status': 'JobStatus',
88
@@ -XXX,XX +XXX,XX @@
89
#
90
# Returns: a list with a @JobInfo for each active job
91
#
92
-# Since: 2.13
93
+# Since: 3.0
94
##
95
{ 'command': 'query-jobs', 'returns': ['JobInfo'] }
96
--
97
2.13.6
98
99
diff view generated by jsdifflib
Deleted patch
1
The error handling policy was traditionally set with -drive, but with
2
-blockdev it is no longer possible to set frontend options. scsi-disk
3
(and other block devices) have long supported qdev properties to
4
configure the error handling policy, so let's add these options to
5
usb-storage as well and just forward them to the internal scsi-disk
6
instance.
7
1
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Markus Armbruster <armbru@redhat.com>
10
---
11
include/hw/scsi/scsi.h | 2 ++
12
hw/scsi/scsi-bus.c | 11 ++++++++++-
13
hw/usb/dev-storage.c | 2 ++
14
3 files changed, 14 insertions(+), 1 deletion(-)
15
16
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/scsi/scsi.h
19
+++ b/include/hw/scsi/scsi.h
20
@@ -XXX,XX +XXX,XX @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
21
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
22
int unit, bool removable, int bootindex,
23
bool share_rw,
24
+ BlockdevOnError rerror,
25
+ BlockdevOnError werror,
26
const char *serial, Error **errp);
27
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
28
void scsi_legacy_handle_cmdline(void);
29
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/scsi/scsi-bus.c
32
+++ b/hw/scsi/scsi-bus.c
33
@@ -XXX,XX +XXX,XX @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
34
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
35
int unit, bool removable, int bootindex,
36
bool share_rw,
37
+ BlockdevOnError rerror,
38
+ BlockdevOnError werror,
39
const char *serial, Error **errp)
40
{
41
const char *driver;
42
@@ -XXX,XX +XXX,XX @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
43
object_unparent(OBJECT(dev));
44
return NULL;
45
}
46
+
47
+ qdev_prop_set_enum(dev, "rerror", rerror);
48
+ qdev_prop_set_enum(dev, "werror", werror);
49
+
50
object_property_set_bool(OBJECT(dev), true, "realized", &err);
51
if (err != NULL) {
52
error_propagate(errp, err);
53
@@ -XXX,XX +XXX,XX @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
54
}
55
qemu_opts_loc_restore(dinfo->opts);
56
scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo),
57
- unit, false, -1, false, NULL, &error_fatal);
58
+ unit, false, -1, false,
59
+ BLOCKDEV_ON_ERROR_AUTO,
60
+ BLOCKDEV_ON_ERROR_AUTO,
61
+ NULL, &error_fatal);
62
}
63
loc_pop(&loc);
64
}
65
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/usb/dev-storage.c
68
+++ b/hw/usb/dev-storage.c
69
@@ -XXX,XX +XXX,XX @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
70
&usb_msd_scsi_info_storage, NULL);
71
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
72
s->conf.bootindex, s->conf.share_rw,
73
+ s->conf.rerror, s->conf.werror,
74
dev->serial,
75
errp);
76
blk_unref(blk);
77
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_usb_msd = {
78
79
static Property msd_properties[] = {
80
DEFINE_BLOCK_PROPERTIES(MSDState, conf),
81
+ DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
82
DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
83
DEFINE_PROP_END_OF_LIST(),
84
};
85
--
86
2.13.6
87
88
diff view generated by jsdifflib
Deleted patch
1
From: Weiping Zhang <zhangweiping@didichuxing.com>
2
1
3
Add an optional paramter num_queues for device, and set it
4
to 64 by default.
5
6
Signed-off-by: Weiping Zhang <zhangweiping@didichuxing.com>
7
Acked-by: Keith Busch <keith.busch@intel.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
hw/block/nvme.c | 5 +++--
11
1 file changed, 3 insertions(+), 2 deletions(-)
12
13
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/block/nvme.c
16
+++ b/hw/block/nvme.c
17
@@ -XXX,XX +XXX,XX @@
18
* Usage: add options:
19
* -drive file=<file>,if=none,id=<drive_id>
20
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
21
- * cmb_size_mb=<cmb_size_mb[optional]>
22
+ * cmb_size_mb=<cmb_size_mb[optional]>, \
23
+ * num_queues=<N[optional]>
24
*
25
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
26
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
27
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
28
pcie_endpoint_cap_init(&n->parent_obj, 0x80);
29
30
n->num_namespaces = 1;
31
- n->num_queues = 64;
32
n->reg_size = pow2ceil(0x1004 + 2 * (n->num_queues + 1) * 4);
33
n->ns_size = bs_size / (uint64_t)n->num_namespaces;
34
35
@@ -XXX,XX +XXX,XX @@ static Property nvme_props[] = {
36
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
37
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
38
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
39
+ DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
40
DEFINE_PROP_END_OF_LIST(),
41
};
42
43
--
44
2.13.6
45
46
diff view generated by jsdifflib
Deleted patch
1
If qcow2_alloc_clusters_at() returns an error, we do need to negate it
2
to get back the positive errno code for error_setg_errno(), but we still
3
need to return the negative error code.
4
1
5
Fixes: 772d1f973f87269f6a4a4ea4b880680f3779bbdf
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
block/qcow2.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/block/qcow2.c b/block/qcow2.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
15
+++ b/block/qcow2.c
16
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
17
if (clusters_allocated < 0) {
18
error_setg_errno(errp, -clusters_allocated,
19
"Failed to allocate data clusters");
20
- return -clusters_allocated;
21
+ return clusters_allocated;
22
}
23
24
assert(clusters_allocated == nb_new_data_clusters);
25
--
26
2.13.6
27
28
diff view generated by jsdifflib
Deleted patch
1
bdrv_truncate() is an operation that can block (even for a quite long
2
time, depending on the PreallocMode) in I/O paths that shouldn't block.
3
Convert it to a coroutine_fn so that we have the infrastructure for
4
drivers to make their .bdrv_co_truncate implementation asynchronous.
5
1
6
This change could potentially introduce new race conditions because
7
bdrv_truncate() isn't necessarily executed atomically any more. Whether
8
this is a problem needs to be evaluated for each block driver that
9
supports truncate:
10
11
* file-posix/win32, gluster, iscsi, nfs, rbd, ssh, sheepdog: The
12
protocol drivers are trivially safe because they don't actually yield
13
yet, so there is no change in behaviour.
14
15
* copy-on-read, crypto, raw-format: Essentially just filter drivers that
16
pass the request to a child node, no problem.
17
18
* qcow2: The implementation modifies metadata, so it needs to hold
19
s->lock to be safe with concurrent I/O requests. In order to avoid
20
double locking, this requires pulling the locking out into
21
preallocate_co() and using qcow2_write_caches() instead of
22
bdrv_flush().
23
24
* qed: Does a single header update, this is fine without locking.
25
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
28
---
29
include/block/block.h | 4 +++
30
include/block/block_int.h | 4 +--
31
block.c | 63 +++++++++++++++++++++++++++++++++++-----
32
block/copy-on-read.c | 8 ++---
33
block/crypto.c | 9 +++---
34
block/file-posix.c | 12 ++++----
35
block/file-win32.c | 6 ++--
36
block/gluster.c | 14 +++++----
37
block/iscsi.c | 8 ++---
38
block/nfs.c | 7 +++--
39
block/qcow2.c | 74 ++++++++++++++++++++++++++++-------------------
40
block/qed.c | 8 +++--
41
block/raw-format.c | 8 ++---
42
block/rbd.c | 8 +++--
43
block/sheepdog.c | 12 ++++----
44
block/ssh.c | 6 ++--
45
16 files changed, 162 insertions(+), 89 deletions(-)
46
47
diff --git a/include/block/block.h b/include/block/block.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/include/block/block.h
50
+++ b/include/block/block.h
51
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
52
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
53
const char *backing_file);
54
void bdrv_refresh_filename(BlockDriverState *bs);
55
+
56
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
57
+ PreallocMode prealloc, Error **errp);
58
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
59
Error **errp);
60
+
61
int64_t bdrv_nb_sectors(BlockDriverState *bs);
62
int64_t bdrv_getlength(BlockDriverState *bs);
63
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
64
diff --git a/include/block/block_int.h b/include/block/block_int.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/include/block/block_int.h
67
+++ b/include/block/block_int.h
68
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
69
* bdrv_parse_filename.
70
*/
71
const char *protocol_name;
72
- int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset,
73
- PreallocMode prealloc, Error **errp);
74
+ int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
75
+ PreallocMode prealloc, Error **errp);
76
77
int64_t (*bdrv_getlength)(BlockDriverState *bs);
78
bool has_variable_length;
79
diff --git a/block.c b/block.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/block.c
82
+++ b/block.c
83
@@ -XXX,XX +XXX,XX @@ exit:
84
/**
85
* Truncate file to 'offset' bytes (needed only for file protocols)
86
*/
87
-int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
88
- Error **errp)
89
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
90
+ PreallocMode prealloc, Error **errp)
91
{
92
BlockDriverState *bs = child->bs;
93
BlockDriver *drv = bs->drv;
94
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
95
return -EINVAL;
96
}
97
98
- if (!drv->bdrv_truncate) {
99
+ bdrv_inc_in_flight(bs);
100
+
101
+ if (!drv->bdrv_co_truncate) {
102
if (bs->file && drv->is_filter) {
103
- return bdrv_truncate(bs->file, offset, prealloc, errp);
104
+ ret = bdrv_co_truncate(bs->file, offset, prealloc, errp);
105
+ goto out;
106
}
107
error_setg(errp, "Image format driver does not support resize");
108
- return -ENOTSUP;
109
+ ret = -ENOTSUP;
110
+ goto out;
111
}
112
if (bs->read_only) {
113
error_setg(errp, "Image is read-only");
114
- return -EACCES;
115
+ ret = -EACCES;
116
+ goto out;
117
}
118
119
assert(!(bs->open_flags & BDRV_O_INACTIVE));
120
121
- ret = drv->bdrv_truncate(bs, offset, prealloc, errp);
122
+ ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
123
if (ret < 0) {
124
- return ret;
125
+ goto out;
126
}
127
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
128
if (ret < 0) {
129
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
130
bdrv_dirty_bitmap_truncate(bs, offset);
131
bdrv_parent_cb_resize(bs);
132
atomic_inc(&bs->write_gen);
133
+
134
+out:
135
+ bdrv_dec_in_flight(bs);
136
return ret;
137
}
138
139
+typedef struct TruncateCo {
140
+ BdrvChild *child;
141
+ int64_t offset;
142
+ PreallocMode prealloc;
143
+ Error **errp;
144
+ int ret;
145
+} TruncateCo;
146
+
147
+static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
148
+{
149
+ TruncateCo *tco = opaque;
150
+ tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
151
+ tco->errp);
152
+}
153
+
154
+int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
155
+ Error **errp)
156
+{
157
+ Coroutine *co;
158
+ TruncateCo tco = {
159
+ .child = child,
160
+ .offset = offset,
161
+ .prealloc = prealloc,
162
+ .errp = errp,
163
+ .ret = NOT_DONE,
164
+ };
165
+
166
+ if (qemu_in_coroutine()) {
167
+ /* Fast-path if already in coroutine context */
168
+ bdrv_truncate_co_entry(&tco);
169
+ } else {
170
+ co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
171
+ qemu_coroutine_enter(co);
172
+ BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
173
+ }
174
+
175
+ return tco.ret;
176
+}
177
+
178
/**
179
* Length of a allocated file in bytes. Sparse files are counted by actual
180
* allocated space. Return < 0 if error or unknown.
181
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/block/copy-on-read.c
184
+++ b/block/copy-on-read.c
185
@@ -XXX,XX +XXX,XX @@ static int64_t cor_getlength(BlockDriverState *bs)
186
}
187
188
189
-static int cor_truncate(BlockDriverState *bs, int64_t offset,
190
- PreallocMode prealloc, Error **errp)
191
+static int coroutine_fn cor_co_truncate(BlockDriverState *bs, int64_t offset,
192
+ PreallocMode prealloc, Error **errp)
193
{
194
- return bdrv_truncate(bs->file, offset, prealloc, errp);
195
+ return bdrv_co_truncate(bs->file, offset, prealloc, errp);
196
}
197
198
199
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_copy_on_read = {
200
.bdrv_child_perm = cor_child_perm,
201
202
.bdrv_getlength = cor_getlength,
203
- .bdrv_truncate = cor_truncate,
204
+ .bdrv_co_truncate = cor_co_truncate,
205
206
.bdrv_co_preadv = cor_co_preadv,
207
.bdrv_co_pwritev = cor_co_pwritev,
208
diff --git a/block/crypto.c b/block/crypto.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/crypto.c
211
+++ b/block/crypto.c
212
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
213
return ret;
214
}
215
216
-static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
217
- PreallocMode prealloc, Error **errp)
218
+static int coroutine_fn
219
+block_crypto_co_truncate(BlockDriverState *bs, int64_t offset,
220
+ PreallocMode prealloc, Error **errp)
221
{
222
BlockCrypto *crypto = bs->opaque;
223
uint64_t payload_offset =
224
@@ -XXX,XX +XXX,XX @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
225
226
offset += payload_offset;
227
228
- return bdrv_truncate(bs->file, offset, prealloc, errp);
229
+ return bdrv_co_truncate(bs->file, offset, prealloc, errp);
230
}
231
232
static void block_crypto_close(BlockDriverState *bs)
233
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
234
.bdrv_child_perm = bdrv_format_default_perms,
235
.bdrv_co_create = block_crypto_co_create_luks,
236
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
237
- .bdrv_truncate = block_crypto_truncate,
238
+ .bdrv_co_truncate = block_crypto_co_truncate,
239
.create_opts = &block_crypto_create_opts_luks,
240
241
.bdrv_reopen_prepare = block_crypto_reopen_prepare,
242
diff --git a/block/file-posix.c b/block/file-posix.c
243
index XXXXXXX..XXXXXXX 100644
244
--- a/block/file-posix.c
245
+++ b/block/file-posix.c
246
@@ -XXX,XX +XXX,XX @@ out:
247
return result;
248
}
249
250
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
251
- PreallocMode prealloc, Error **errp)
252
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
253
+ PreallocMode prealloc, Error **errp)
254
{
255
BDRVRawState *s = bs->opaque;
256
struct stat st;
257
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
258
.bdrv_io_unplug = raw_aio_unplug,
259
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
260
261
- .bdrv_truncate = raw_truncate,
262
+ .bdrv_co_truncate = raw_co_truncate,
263
.bdrv_getlength = raw_getlength,
264
.bdrv_get_info = raw_get_info,
265
.bdrv_get_allocated_file_size
266
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
267
.bdrv_io_plug = raw_aio_plug,
268
.bdrv_io_unplug = raw_aio_unplug,
269
270
- .bdrv_truncate = raw_truncate,
271
+ .bdrv_co_truncate = raw_co_truncate,
272
.bdrv_getlength    = raw_getlength,
273
.bdrv_get_info = raw_get_info,
274
.bdrv_get_allocated_file_size
275
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
276
.bdrv_io_plug = raw_aio_plug,
277
.bdrv_io_unplug = raw_aio_unplug,
278
279
- .bdrv_truncate = raw_truncate,
280
+ .bdrv_co_truncate = raw_co_truncate,
281
.bdrv_getlength = raw_getlength,
282
.has_variable_length = true,
283
.bdrv_get_allocated_file_size
284
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
285
.bdrv_io_plug = raw_aio_plug,
286
.bdrv_io_unplug = raw_aio_unplug,
287
288
- .bdrv_truncate = raw_truncate,
289
+ .bdrv_co_truncate = raw_co_truncate,
290
.bdrv_getlength = raw_getlength,
291
.has_variable_length = true,
292
.bdrv_get_allocated_file_size
293
diff --git a/block/file-win32.c b/block/file-win32.c
294
index XXXXXXX..XXXXXXX 100644
295
--- a/block/file-win32.c
296
+++ b/block/file-win32.c
297
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
298
}
299
}
300
301
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
302
- PreallocMode prealloc, Error **errp)
303
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
304
+ PreallocMode prealloc, Error **errp)
305
{
306
BDRVRawState *s = bs->opaque;
307
LONG low, high;
308
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
309
.bdrv_aio_pwritev = raw_aio_pwritev,
310
.bdrv_aio_flush = raw_aio_flush,
311
312
- .bdrv_truncate    = raw_truncate,
313
+ .bdrv_co_truncate = raw_co_truncate,
314
.bdrv_getlength    = raw_getlength,
315
.bdrv_get_allocated_file_size
316
= raw_get_allocated_file_size,
317
diff --git a/block/gluster.c b/block/gluster.c
318
index XXXXXXX..XXXXXXX 100644
319
--- a/block/gluster.c
320
+++ b/block/gluster.c
321
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
322
return acb.ret;
323
}
324
325
-static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
326
- PreallocMode prealloc, Error **errp)
327
+static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
328
+ int64_t offset,
329
+ PreallocMode prealloc,
330
+ Error **errp)
331
{
332
BDRVGlusterState *s = bs->opaque;
333
return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp);
334
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
335
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
336
.bdrv_getlength = qemu_gluster_getlength,
337
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
338
- .bdrv_truncate = qemu_gluster_truncate,
339
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
340
.bdrv_co_readv = qemu_gluster_co_readv,
341
.bdrv_co_writev = qemu_gluster_co_writev,
342
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
343
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
344
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
345
.bdrv_getlength = qemu_gluster_getlength,
346
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
347
- .bdrv_truncate = qemu_gluster_truncate,
348
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
349
.bdrv_co_readv = qemu_gluster_co_readv,
350
.bdrv_co_writev = qemu_gluster_co_writev,
351
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
352
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
353
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
354
.bdrv_getlength = qemu_gluster_getlength,
355
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
356
- .bdrv_truncate = qemu_gluster_truncate,
357
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
358
.bdrv_co_readv = qemu_gluster_co_readv,
359
.bdrv_co_writev = qemu_gluster_co_writev,
360
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
361
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
362
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
363
.bdrv_getlength = qemu_gluster_getlength,
364
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
365
- .bdrv_truncate = qemu_gluster_truncate,
366
+ .bdrv_co_truncate = qemu_gluster_co_truncate,
367
.bdrv_co_readv = qemu_gluster_co_readv,
368
.bdrv_co_writev = qemu_gluster_co_writev,
369
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
370
diff --git a/block/iscsi.c b/block/iscsi.c
371
index XXXXXXX..XXXXXXX 100644
372
--- a/block/iscsi.c
373
+++ b/block/iscsi.c
374
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
375
}
376
}
377
378
-static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
379
- PreallocMode prealloc, Error **errp)
380
+static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
381
+ PreallocMode prealloc, Error **errp)
382
{
383
IscsiLun *iscsilun = bs->opaque;
384
Error *local_err = NULL;
385
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
386
387
.bdrv_getlength = iscsi_getlength,
388
.bdrv_get_info = iscsi_get_info,
389
- .bdrv_truncate = iscsi_truncate,
390
+ .bdrv_co_truncate = iscsi_co_truncate,
391
.bdrv_refresh_limits = iscsi_refresh_limits,
392
393
.bdrv_co_block_status = iscsi_co_block_status,
394
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
395
396
.bdrv_getlength = iscsi_getlength,
397
.bdrv_get_info = iscsi_get_info,
398
- .bdrv_truncate = iscsi_truncate,
399
+ .bdrv_co_truncate = iscsi_co_truncate,
400
.bdrv_refresh_limits = iscsi_refresh_limits,
401
402
.bdrv_co_block_status = iscsi_co_block_status,
403
diff --git a/block/nfs.c b/block/nfs.c
404
index XXXXXXX..XXXXXXX 100644
405
--- a/block/nfs.c
406
+++ b/block/nfs.c
407
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
408
return (task.ret < 0 ? task.ret : st.st_blocks * 512);
409
}
410
411
-static int nfs_file_truncate(BlockDriverState *bs, int64_t offset,
412
- PreallocMode prealloc, Error **errp)
413
+static int coroutine_fn
414
+nfs_file_co_truncate(BlockDriverState *bs, int64_t offset,
415
+ PreallocMode prealloc, Error **errp)
416
{
417
NFSClient *client = bs->opaque;
418
int ret;
419
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
420
421
.bdrv_has_zero_init = nfs_has_zero_init,
422
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
423
- .bdrv_truncate = nfs_file_truncate,
424
+ .bdrv_co_truncate = nfs_file_co_truncate,
425
426
.bdrv_file_open = nfs_file_open,
427
.bdrv_close = nfs_file_close,
428
diff --git a/block/qcow2.c b/block/qcow2.c
429
index XXXXXXX..XXXXXXX 100644
430
--- a/block/qcow2.c
431
+++ b/block/qcow2.c
432
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
433
BlockDriverState *bs = params->bs;
434
uint64_t offset = params->offset;
435
uint64_t new_length = params->new_length;
436
- BDRVQcow2State *s = bs->opaque;
437
uint64_t bytes;
438
uint64_t host_offset = 0;
439
unsigned int cur_bytes;
440
int ret;
441
QCowL2Meta *meta;
442
443
- qemu_co_mutex_lock(&s->lock);
444
-
445
assert(offset <= new_length);
446
bytes = new_length - offset;
447
448
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
449
ret = 0;
450
451
done:
452
- qemu_co_mutex_unlock(&s->lock);
453
params->ret = ret;
454
}
455
456
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
457
458
/* And if we're supposed to preallocate metadata, do that now */
459
if (qcow2_opts->preallocation != PREALLOC_MODE_OFF) {
460
+ BDRVQcow2State *s = blk_bs(blk)->opaque;
461
+ qemu_co_mutex_lock(&s->lock);
462
ret = preallocate(blk_bs(blk), 0, qcow2_opts->size);
463
+ qemu_co_mutex_unlock(&s->lock);
464
+
465
if (ret < 0) {
466
error_setg_errno(errp, -ret, "Could not preallocate metadata");
467
goto out;
468
@@ -XXX,XX +XXX,XX @@ fail:
469
return ret;
470
}
471
472
-static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
473
- PreallocMode prealloc, Error **errp)
474
+static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
475
+ PreallocMode prealloc, Error **errp)
476
{
477
BDRVQcow2State *s = bs->opaque;
478
uint64_t old_length;
479
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
480
return -EINVAL;
481
}
482
483
+ qemu_co_mutex_lock(&s->lock);
484
+
485
/* cannot proceed if image has snapshots */
486
if (s->nb_snapshots) {
487
error_setg(errp, "Can't resize an image which has snapshots");
488
- return -ENOTSUP;
489
+ ret = -ENOTSUP;
490
+ goto fail;
491
}
492
493
/* cannot proceed if image has bitmaps */
494
if (s->nb_bitmaps) {
495
/* TODO: resize bitmaps in the image */
496
error_setg(errp, "Can't resize an image which has bitmaps");
497
- return -ENOTSUP;
498
+ ret = -ENOTSUP;
499
+ goto fail;
500
}
501
502
old_length = bs->total_sectors * 512;
503
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
504
if (prealloc != PREALLOC_MODE_OFF) {
505
error_setg(errp,
506
"Preallocation can't be used for shrinking an image");
507
- return -EINVAL;
508
+ ret = -EINVAL;
509
+ goto fail;
510
}
511
512
ret = qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size),
513
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
514
QCOW2_DISCARD_ALWAYS, true);
515
if (ret < 0) {
516
error_setg_errno(errp, -ret, "Failed to discard cropped clusters");
517
- return ret;
518
+ goto fail;
519
}
520
521
ret = qcow2_shrink_l1_table(bs, new_l1_size);
522
if (ret < 0) {
523
error_setg_errno(errp, -ret,
524
"Failed to reduce the number of L2 tables");
525
- return ret;
526
+ goto fail;
527
}
528
529
ret = qcow2_shrink_reftable(bs);
530
if (ret < 0) {
531
error_setg_errno(errp, -ret,
532
"Failed to discard unused refblocks");
533
- return ret;
534
+ goto fail;
535
}
536
537
old_file_size = bdrv_getlength(bs->file->bs);
538
if (old_file_size < 0) {
539
error_setg_errno(errp, -old_file_size,
540
"Failed to inquire current file length");
541
- return old_file_size;
542
+ ret = old_file_size;
543
+ goto fail;
544
}
545
last_cluster = qcow2_get_last_cluster(bs, old_file_size);
546
if (last_cluster < 0) {
547
error_setg_errno(errp, -last_cluster,
548
"Failed to find the last cluster");
549
- return last_cluster;
550
+ ret = last_cluster;
551
+ goto fail;
552
}
553
if ((last_cluster + 1) * s->cluster_size < old_file_size) {
554
Error *local_err = NULL;
555
556
- bdrv_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
557
- PREALLOC_MODE_OFF, &local_err);
558
+ bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
559
+ PREALLOC_MODE_OFF, &local_err);
560
if (local_err) {
561
warn_reportf_err(local_err,
562
"Failed to truncate the tail of the image: ");
563
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
564
ret = qcow2_grow_l1_table(bs, new_l1_size, true);
565
if (ret < 0) {
566
error_setg_errno(errp, -ret, "Failed to grow the L1 table");
567
- return ret;
568
+ goto fail;
569
}
570
}
571
572
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
573
ret = preallocate(bs, old_length, offset);
574
if (ret < 0) {
575
error_setg_errno(errp, -ret, "Preallocation failed");
576
- return ret;
577
+ goto fail;
578
}
579
break;
580
581
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
582
if (old_file_size < 0) {
583
error_setg_errno(errp, -old_file_size,
584
"Failed to inquire current file length");
585
- return old_file_size;
586
+ ret = old_file_size;
587
+ goto fail;
588
}
589
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
590
591
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
592
if (allocation_start < 0) {
593
error_setg_errno(errp, -allocation_start,
594
"Failed to resize refcount structures");
595
- return allocation_start;
596
+ ret = allocation_start;
597
+ goto fail;
598
}
599
600
clusters_allocated = qcow2_alloc_clusters_at(bs, allocation_start,
601
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
602
if (clusters_allocated < 0) {
603
error_setg_errno(errp, -clusters_allocated,
604
"Failed to allocate data clusters");
605
- return clusters_allocated;
606
+ ret = clusters_allocated;
607
+ goto fail;
608
}
609
610
assert(clusters_allocated == nb_new_data_clusters);
611
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
612
/* Allocate the data area */
613
new_file_size = allocation_start +
614
nb_new_data_clusters * s->cluster_size;
615
- ret = bdrv_truncate(bs->file, new_file_size, prealloc, errp);
616
+ ret = bdrv_co_truncate(bs->file, new_file_size, prealloc, errp);
617
if (ret < 0) {
618
error_prepend(errp, "Failed to resize underlying file: ");
619
qcow2_free_clusters(bs, allocation_start,
620
nb_new_data_clusters * s->cluster_size,
621
QCOW2_DISCARD_OTHER);
622
- return ret;
623
+ goto fail;
624
}
625
626
/* Create the necessary L2 entries */
627
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
628
qcow2_free_clusters(bs, host_offset,
629
nb_new_data_clusters * s->cluster_size,
630
QCOW2_DISCARD_OTHER);
631
- return ret;
632
+ goto fail;
633
}
634
635
guest_offset += nb_clusters * s->cluster_size;
636
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
637
638
if (prealloc != PREALLOC_MODE_OFF) {
639
/* Flush metadata before actually changing the image size */
640
- ret = bdrv_flush(bs);
641
+ ret = qcow2_write_caches(bs);
642
if (ret < 0) {
643
error_setg_errno(errp, -ret,
644
"Failed to flush the preallocated area to disk");
645
- return ret;
646
+ goto fail;
647
}
648
}
649
650
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset,
651
&offset, sizeof(uint64_t));
652
if (ret < 0) {
653
error_setg_errno(errp, -ret, "Failed to update the image size");
654
- return ret;
655
+ goto fail;
656
}
657
658
s->l1_vm_state_index = new_l1_size;
659
- return 0;
660
+ ret = 0;
661
+fail:
662
+ qemu_co_mutex_unlock(&s->lock);
663
+ return ret;
664
}
665
666
/* XXX: put compressed sectors first, then all the cluster aligned
667
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
668
if (cluster_offset < 0) {
669
return cluster_offset;
670
}
671
- return bdrv_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF, NULL);
672
+ return bdrv_co_truncate(bs->file, cluster_offset, PREALLOC_MODE_OFF,
673
+ NULL);
674
}
675
676
if (offset_into_cluster(s, offset)) {
677
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
678
.bdrv_co_pdiscard = qcow2_co_pdiscard,
679
.bdrv_co_copy_range_from = qcow2_co_copy_range_from,
680
.bdrv_co_copy_range_to = qcow2_co_copy_range_to,
681
- .bdrv_truncate = qcow2_truncate,
682
+ .bdrv_co_truncate = qcow2_co_truncate,
683
.bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
684
.bdrv_make_empty = qcow2_make_empty,
685
686
diff --git a/block/qed.c b/block/qed.c
687
index XXXXXXX..XXXXXXX 100644
688
--- a/block/qed.c
689
+++ b/block/qed.c
690
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
691
QED_AIOCB_WRITE | QED_AIOCB_ZERO);
692
}
693
694
-static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset,
695
- PreallocMode prealloc, Error **errp)
696
+static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
697
+ int64_t offset,
698
+ PreallocMode prealloc,
699
+ Error **errp)
700
{
701
BDRVQEDState *s = bs->opaque;
702
uint64_t old_image_size;
703
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
704
.bdrv_co_readv = bdrv_qed_co_readv,
705
.bdrv_co_writev = bdrv_qed_co_writev,
706
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
707
- .bdrv_truncate = bdrv_qed_truncate,
708
+ .bdrv_co_truncate = bdrv_qed_co_truncate,
709
.bdrv_getlength = bdrv_qed_getlength,
710
.bdrv_get_info = bdrv_qed_get_info,
711
.bdrv_refresh_limits = bdrv_qed_refresh_limits,
712
diff --git a/block/raw-format.c b/block/raw-format.c
713
index XXXXXXX..XXXXXXX 100644
714
--- a/block/raw-format.c
715
+++ b/block/raw-format.c
716
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
717
}
718
}
719
720
-static int raw_truncate(BlockDriverState *bs, int64_t offset,
721
- PreallocMode prealloc, Error **errp)
722
+static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
723
+ PreallocMode prealloc, Error **errp)
724
{
725
BDRVRawState *s = bs->opaque;
726
727
@@ -XXX,XX +XXX,XX @@ static int raw_truncate(BlockDriverState *bs, int64_t offset,
728
729
s->size = offset;
730
offset += s->offset;
731
- return bdrv_truncate(bs->file, offset, prealloc, errp);
732
+ return bdrv_co_truncate(bs->file, offset, prealloc, errp);
733
}
734
735
static void raw_eject(BlockDriverState *bs, bool eject_flag)
736
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
737
.bdrv_co_block_status = &raw_co_block_status,
738
.bdrv_co_copy_range_from = &raw_co_copy_range_from,
739
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
740
- .bdrv_truncate = &raw_truncate,
741
+ .bdrv_co_truncate = &raw_co_truncate,
742
.bdrv_getlength = &raw_getlength,
743
.has_variable_length = true,
744
.bdrv_measure = &raw_measure,
745
diff --git a/block/rbd.c b/block/rbd.c
746
index XXXXXXX..XXXXXXX 100644
747
--- a/block/rbd.c
748
+++ b/block/rbd.c
749
@@ -XXX,XX +XXX,XX @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs)
750
return info.size;
751
}
752
753
-static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset,
754
- PreallocMode prealloc, Error **errp)
755
+static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
756
+ int64_t offset,
757
+ PreallocMode prealloc,
758
+ Error **errp)
759
{
760
BDRVRBDState *s = bs->opaque;
761
int r;
762
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
763
.bdrv_get_info = qemu_rbd_getinfo,
764
.create_opts = &qemu_rbd_create_opts,
765
.bdrv_getlength = qemu_rbd_getlength,
766
- .bdrv_truncate = qemu_rbd_truncate,
767
+ .bdrv_co_truncate = qemu_rbd_co_truncate,
768
.protocol_name = "rbd",
769
770
.bdrv_aio_preadv = qemu_rbd_aio_preadv,
771
diff --git a/block/sheepdog.c b/block/sheepdog.c
772
index XXXXXXX..XXXXXXX 100644
773
--- a/block/sheepdog.c
774
+++ b/block/sheepdog.c
775
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
776
return s->inode.vdi_size;
777
}
778
779
-static int sd_truncate(BlockDriverState *bs, int64_t offset,
780
- PreallocMode prealloc, Error **errp)
781
+static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
782
+ PreallocMode prealloc, Error **errp)
783
{
784
BDRVSheepdogState *s = bs->opaque;
785
int ret, fd;
786
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
787
788
assert(!flags);
789
if (offset > s->inode.vdi_size) {
790
- ret = sd_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
791
+ ret = sd_co_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
792
if (ret < 0) {
793
return ret;
794
}
795
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
796
.bdrv_has_zero_init = bdrv_has_zero_init_1,
797
.bdrv_getlength = sd_getlength,
798
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
799
- .bdrv_truncate = sd_truncate,
800
+ .bdrv_co_truncate = sd_co_truncate,
801
802
.bdrv_co_readv = sd_co_readv,
803
.bdrv_co_writev = sd_co_writev,
804
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
805
.bdrv_has_zero_init = bdrv_has_zero_init_1,
806
.bdrv_getlength = sd_getlength,
807
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
808
- .bdrv_truncate = sd_truncate,
809
+ .bdrv_co_truncate = sd_co_truncate,
810
811
.bdrv_co_readv = sd_co_readv,
812
.bdrv_co_writev = sd_co_writev,
813
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
814
.bdrv_has_zero_init = bdrv_has_zero_init_1,
815
.bdrv_getlength = sd_getlength,
816
.bdrv_get_allocated_file_size = sd_get_allocated_file_size,
817
- .bdrv_truncate = sd_truncate,
818
+ .bdrv_co_truncate = sd_co_truncate,
819
820
.bdrv_co_readv = sd_co_readv,
821
.bdrv_co_writev = sd_co_writev,
822
diff --git a/block/ssh.c b/block/ssh.c
823
index XXXXXXX..XXXXXXX 100644
824
--- a/block/ssh.c
825
+++ b/block/ssh.c
826
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
827
return length;
828
}
829
830
-static int ssh_truncate(BlockDriverState *bs, int64_t offset,
831
- PreallocMode prealloc, Error **errp)
832
+static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
833
+ PreallocMode prealloc, Error **errp)
834
{
835
BDRVSSHState *s = bs->opaque;
836
837
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
838
.bdrv_co_readv = ssh_co_readv,
839
.bdrv_co_writev = ssh_co_writev,
840
.bdrv_getlength = ssh_getlength,
841
- .bdrv_truncate = ssh_truncate,
842
+ .bdrv_co_truncate = ssh_co_truncate,
843
.bdrv_co_flush_to_disk = ssh_co_flush,
844
.create_opts = &ssh_create_opts,
845
};
846
--
847
2.13.6
848
849
diff view generated by jsdifflib
Deleted patch
1
All callers are coroutine_fns now, so we can just directly call
2
preallocate_co().
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
block/qcow2.c | 51 ++++++++-------------------------------------------
8
1 file changed, 8 insertions(+), 43 deletions(-)
9
10
diff --git a/block/qcow2.c b/block/qcow2.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/qcow2.c
13
+++ b/block/qcow2.c
14
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
15
return ret;
16
}
17
18
-
19
-typedef struct PreallocCo {
20
- BlockDriverState *bs;
21
- uint64_t offset;
22
- uint64_t new_length;
23
-
24
- int ret;
25
-} PreallocCo;
26
-
27
/**
28
* Preallocates metadata structures for data clusters between @offset (in the
29
* guest disk) and @new_length (which is thus generally the new guest disk
30
@@ -XXX,XX +XXX,XX @@ typedef struct PreallocCo {
31
*
32
* Returns: 0 on success, -errno on failure.
33
*/
34
-static void coroutine_fn preallocate_co(void *opaque)
35
+static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
36
+ uint64_t new_length)
37
{
38
- PreallocCo *params = opaque;
39
- BlockDriverState *bs = params->bs;
40
- uint64_t offset = params->offset;
41
- uint64_t new_length = params->new_length;
42
uint64_t bytes;
43
uint64_t host_offset = 0;
44
unsigned int cur_bytes;
45
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
46
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
47
&host_offset, &meta);
48
if (ret < 0) {
49
- goto done;
50
+ return ret;
51
}
52
53
while (meta) {
54
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
55
if (ret < 0) {
56
qcow2_free_any_clusters(bs, meta->alloc_offset,
57
meta->nb_clusters, QCOW2_DISCARD_NEVER);
58
- goto done;
59
+ return ret;
60
}
61
62
/* There are no dependent requests, but we need to remove our
63
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn preallocate_co(void *opaque)
64
ret = bdrv_pwrite(bs->file, (host_offset + cur_bytes) - 1,
65
&data, 1);
66
if (ret < 0) {
67
- goto done;
68
+ return ret;
69
}
70
}
71
72
- ret = 0;
73
-
74
-done:
75
- params->ret = ret;
76
-}
77
-
78
-static int preallocate(BlockDriverState *bs,
79
- uint64_t offset, uint64_t new_length)
80
-{
81
- PreallocCo params = {
82
- .bs = bs,
83
- .offset = offset,
84
- .new_length = new_length,
85
- .ret = -EINPROGRESS,
86
- };
87
-
88
- if (qemu_in_coroutine()) {
89
- preallocate_co(&params);
90
- } else {
91
- Coroutine *co = qemu_coroutine_create(preallocate_co, &params);
92
- bdrv_coroutine_enter(bs, co);
93
- BDRV_POLL_WHILE(bs, params.ret == -EINPROGRESS);
94
- }
95
- return params.ret;
96
+ return 0;
97
}
98
99
/* qcow2_refcount_metadata_size:
100
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
101
if (qcow2_opts->preallocation != PREALLOC_MODE_OFF) {
102
BDRVQcow2State *s = blk_bs(blk)->opaque;
103
qemu_co_mutex_lock(&s->lock);
104
- ret = preallocate(blk_bs(blk), 0, qcow2_opts->size);
105
+ ret = preallocate_co(blk_bs(blk), 0, qcow2_opts->size);
106
qemu_co_mutex_unlock(&s->lock);
107
108
if (ret < 0) {
109
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
110
break;
111
112
case PREALLOC_MODE_METADATA:
113
- ret = preallocate(bs, old_length, offset);
114
+ ret = preallocate_co(bs, old_length, offset);
115
if (ret < 0) {
116
error_setg_errno(errp, -ret, "Preallocation failed");
117
goto fail;
118
--
119
2.13.6
120
121
diff view generated by jsdifflib
Deleted patch
1
This moves the bdrv_truncate() implementation from block.c to block/io.c
2
so it can have access to the tracked requests infrastructure.
3
1
4
This involves making refresh_total_sectors() public (in block_int.h).
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
include/block/block_int.h | 2 +
10
block.c | 111 +---------------------------------------------
11
block/io.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
12
3 files changed, 112 insertions(+), 110 deletions(-)
13
14
diff --git a/include/block/block_int.h b/include/block/block_int.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block_int.h
17
+++ b/include/block/block_int.h
18
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, uint64_t src_offset,
19
BdrvChild *dst, uint64_t dst_offset,
20
uint64_t bytes, BdrvRequestFlags flags);
21
22
+int refresh_total_sectors(BlockDriverState *bs, int64_t hint);
23
+
24
#endif /* BLOCK_INT_H */
25
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
28
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename,
30
* Set the current 'total_sectors' value
31
* Return 0 on success, -errno on error.
32
*/
33
-static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
34
+int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
35
{
36
BlockDriver *drv = bs->drv;
37
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
39
}
40
}
41
42
-static void bdrv_parent_cb_resize(BlockDriverState *bs)
43
-{
44
- BdrvChild *c;
45
- QLIST_FOREACH(c, &bs->parents, next_parent) {
46
- if (c->role->resize) {
47
- c->role->resize(c);
48
- }
49
- }
50
-}
51
-
52
/*
53
* Sets the backing file link of a BDS. A new reference is created; callers
54
* which don't need their own reference any more must call bdrv_unref().
55
@@ -XXX,XX +XXX,XX @@ exit:
56
}
57
58
/**
59
- * Truncate file to 'offset' bytes (needed only for file protocols)
60
- */
61
-int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
62
- PreallocMode prealloc, Error **errp)
63
-{
64
- BlockDriverState *bs = child->bs;
65
- BlockDriver *drv = bs->drv;
66
- int ret;
67
-
68
- assert(child->perm & BLK_PERM_RESIZE);
69
-
70
- /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
71
- if (!drv) {
72
- error_setg(errp, "No medium inserted");
73
- return -ENOMEDIUM;
74
- }
75
- if (offset < 0) {
76
- error_setg(errp, "Image size cannot be negative");
77
- return -EINVAL;
78
- }
79
-
80
- bdrv_inc_in_flight(bs);
81
-
82
- if (!drv->bdrv_co_truncate) {
83
- if (bs->file && drv->is_filter) {
84
- ret = bdrv_co_truncate(bs->file, offset, prealloc, errp);
85
- goto out;
86
- }
87
- error_setg(errp, "Image format driver does not support resize");
88
- ret = -ENOTSUP;
89
- goto out;
90
- }
91
- if (bs->read_only) {
92
- error_setg(errp, "Image is read-only");
93
- ret = -EACCES;
94
- goto out;
95
- }
96
-
97
- assert(!(bs->open_flags & BDRV_O_INACTIVE));
98
-
99
- ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
100
- if (ret < 0) {
101
- goto out;
102
- }
103
- ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
104
- if (ret < 0) {
105
- error_setg_errno(errp, -ret, "Could not refresh total sector count");
106
- } else {
107
- offset = bs->total_sectors * BDRV_SECTOR_SIZE;
108
- }
109
- bdrv_dirty_bitmap_truncate(bs, offset);
110
- bdrv_parent_cb_resize(bs);
111
- atomic_inc(&bs->write_gen);
112
-
113
-out:
114
- bdrv_dec_in_flight(bs);
115
- return ret;
116
-}
117
-
118
-typedef struct TruncateCo {
119
- BdrvChild *child;
120
- int64_t offset;
121
- PreallocMode prealloc;
122
- Error **errp;
123
- int ret;
124
-} TruncateCo;
125
-
126
-static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
127
-{
128
- TruncateCo *tco = opaque;
129
- tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
130
- tco->errp);
131
-}
132
-
133
-int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
134
- Error **errp)
135
-{
136
- Coroutine *co;
137
- TruncateCo tco = {
138
- .child = child,
139
- .offset = offset,
140
- .prealloc = prealloc,
141
- .errp = errp,
142
- .ret = NOT_DONE,
143
- };
144
-
145
- if (qemu_in_coroutine()) {
146
- /* Fast-path if already in coroutine context */
147
- bdrv_truncate_co_entry(&tco);
148
- } else {
149
- co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
150
- qemu_coroutine_enter(co);
151
- BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
152
- }
153
-
154
- return tco.ret;
155
-}
156
-
157
-/**
158
* Length of a allocated file in bytes. Sparse files are counted by actual
159
* allocated space. Return < 0 if error or unknown.
160
*/
161
diff --git a/block/io.c b/block/io.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/block/io.c
164
+++ b/block/io.c
165
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
166
bdrv_dec_in_flight(dst_bs);
167
return ret;
168
}
169
+
170
+static void bdrv_parent_cb_resize(BlockDriverState *bs)
171
+{
172
+ BdrvChild *c;
173
+ QLIST_FOREACH(c, &bs->parents, next_parent) {
174
+ if (c->role->resize) {
175
+ c->role->resize(c);
176
+ }
177
+ }
178
+}
179
+
180
+/**
181
+ * Truncate file to 'offset' bytes (needed only for file protocols)
182
+ */
183
+int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
184
+ PreallocMode prealloc, Error **errp)
185
+{
186
+ BlockDriverState *bs = child->bs;
187
+ BlockDriver *drv = bs->drv;
188
+ int ret;
189
+
190
+ assert(child->perm & BLK_PERM_RESIZE);
191
+
192
+ /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
193
+ if (!drv) {
194
+ error_setg(errp, "No medium inserted");
195
+ return -ENOMEDIUM;
196
+ }
197
+ if (offset < 0) {
198
+ error_setg(errp, "Image size cannot be negative");
199
+ return -EINVAL;
200
+ }
201
+
202
+ bdrv_inc_in_flight(bs);
203
+
204
+ if (!drv->bdrv_co_truncate) {
205
+ if (bs->file && drv->is_filter) {
206
+ ret = bdrv_co_truncate(bs->file, offset, prealloc, errp);
207
+ goto out;
208
+ }
209
+ error_setg(errp, "Image format driver does not support resize");
210
+ ret = -ENOTSUP;
211
+ goto out;
212
+ }
213
+ if (bs->read_only) {
214
+ error_setg(errp, "Image is read-only");
215
+ ret = -EACCES;
216
+ goto out;
217
+ }
218
+
219
+ assert(!(bs->open_flags & BDRV_O_INACTIVE));
220
+
221
+ ret = drv->bdrv_co_truncate(bs, offset, prealloc, errp);
222
+ if (ret < 0) {
223
+ goto out;
224
+ }
225
+ ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
226
+ if (ret < 0) {
227
+ error_setg_errno(errp, -ret, "Could not refresh total sector count");
228
+ } else {
229
+ offset = bs->total_sectors * BDRV_SECTOR_SIZE;
230
+ }
231
+ bdrv_dirty_bitmap_truncate(bs, offset);
232
+ bdrv_parent_cb_resize(bs);
233
+ atomic_inc(&bs->write_gen);
234
+
235
+out:
236
+ bdrv_dec_in_flight(bs);
237
+ return ret;
238
+}
239
+
240
+typedef struct TruncateCo {
241
+ BdrvChild *child;
242
+ int64_t offset;
243
+ PreallocMode prealloc;
244
+ Error **errp;
245
+ int ret;
246
+} TruncateCo;
247
+
248
+static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
249
+{
250
+ TruncateCo *tco = opaque;
251
+ tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->prealloc,
252
+ tco->errp);
253
+}
254
+
255
+int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
256
+ Error **errp)
257
+{
258
+ Coroutine *co;
259
+ TruncateCo tco = {
260
+ .child = child,
261
+ .offset = offset,
262
+ .prealloc = prealloc,
263
+ .errp = errp,
264
+ .ret = NOT_DONE,
265
+ };
266
+
267
+ if (qemu_in_coroutine()) {
268
+ /* Fast-path if already in coroutine context */
269
+ bdrv_truncate_co_entry(&tco);
270
+ } else {
271
+ co = qemu_coroutine_create(bdrv_truncate_co_entry, &tco);
272
+ qemu_coroutine_enter(co);
273
+ BDRV_POLL_WHILE(child->bs, tco.ret == NOT_DONE);
274
+ }
275
+
276
+ return tco.ret;
277
+}
278
--
279
2.13.6
280
281
diff view generated by jsdifflib
Deleted patch
1
When growing an image, block drivers (especially protocol drivers) may
2
initialise the newly added area. I/O requests to the same area need to
3
wait for this initialisation to be completed so that data writes don't
4
get overwritten and reads don't read uninitialised data.
5
1
6
To avoid overhead in the fast I/O path by adding new locking in the
7
protocol drivers and to restrict the impact to requests that actually
8
touch the new area, reuse the existing tracked request infrastructure in
9
block/io.c and mark all discard requests as serialising.
10
11
With this change, it is safe for protocol drivers to make
12
.bdrv_co_truncate actually asynchronous.
13
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
17
include/block/block_int.h | 1 +
18
block/io.c | 25 +++++++++++++++++++++++++
19
2 files changed, 26 insertions(+)
20
21
diff --git a/include/block/block_int.h b/include/block/block_int.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block_int.h
24
+++ b/include/block/block_int.h
25
@@ -XXX,XX +XXX,XX @@ enum BdrvTrackedRequestType {
26
BDRV_TRACKED_READ,
27
BDRV_TRACKED_WRITE,
28
BDRV_TRACKED_DISCARD,
29
+ BDRV_TRACKED_TRUNCATE,
30
};
31
32
typedef struct BdrvTrackedRequest {
33
diff --git a/block/io.c b/block/io.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block/io.c
36
+++ b/block/io.c
37
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
38
{
39
BlockDriverState *bs = child->bs;
40
BlockDriver *drv = bs->drv;
41
+ BdrvTrackedRequest req;
42
+ int64_t old_size, new_bytes;
43
int ret;
44
45
assert(child->perm & BLK_PERM_RESIZE);
46
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
47
return -EINVAL;
48
}
49
50
+ old_size = bdrv_getlength(bs);
51
+ if (old_size < 0) {
52
+ error_setg_errno(errp, -old_size, "Failed to get old image size");
53
+ return old_size;
54
+ }
55
+
56
+ if (offset > old_size) {
57
+ new_bytes = offset - old_size;
58
+ } else {
59
+ new_bytes = 0;
60
+ }
61
+
62
bdrv_inc_in_flight(bs);
63
+ tracked_request_begin(&req, bs, offset, new_bytes, BDRV_TRACKED_TRUNCATE);
64
+
65
+ /* If we are growing the image and potentially using preallocation for the
66
+ * new area, we need to make sure that no write requests are made to it
67
+ * concurrently or they might be overwritten by preallocation. */
68
+ if (new_bytes) {
69
+ mark_request_serialising(&req, 1);
70
+ wait_serialising_requests(&req);
71
+ }
72
73
if (!drv->bdrv_co_truncate) {
74
if (bs->file && drv->is_filter) {
75
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
76
atomic_inc(&bs->write_gen);
77
78
out:
79
+ tracked_request_end(&req);
80
bdrv_dec_in_flight(bs);
81
+
82
return ret;
83
}
84
85
--
86
2.13.6
87
88
diff view generated by jsdifflib
Deleted patch
1
This moves the code to resize an image file to the thread pool to avoid
2
blocking.
3
1
4
Creating large images with preallocation with blockdev-create is now
5
actually a background job instead of blocking the monitor (and most
6
other things) until the preallocation has completed.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
include/block/raw-aio.h | 4 +-
12
block/file-posix.c | 266 +++++++++++++++++++++++++++---------------------
13
2 files changed, 154 insertions(+), 116 deletions(-)
14
15
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/raw-aio.h
18
+++ b/include/block/raw-aio.h
19
@@ -XXX,XX +XXX,XX @@
20
#define QEMU_AIO_DISCARD 0x0010
21
#define QEMU_AIO_WRITE_ZEROES 0x0020
22
#define QEMU_AIO_COPY_RANGE 0x0040
23
+#define QEMU_AIO_TRUNCATE 0x0080
24
#define QEMU_AIO_TYPE_MASK \
25
(QEMU_AIO_READ | \
26
QEMU_AIO_WRITE | \
27
@@ -XXX,XX +XXX,XX @@
28
QEMU_AIO_FLUSH | \
29
QEMU_AIO_DISCARD | \
30
QEMU_AIO_WRITE_ZEROES | \
31
- QEMU_AIO_COPY_RANGE)
32
+ QEMU_AIO_COPY_RANGE | \
33
+ QEMU_AIO_TRUNCATE)
34
35
/* AIO flags */
36
#define QEMU_AIO_MISALIGNED 0x1000
37
diff --git a/block/file-posix.c b/block/file-posix.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block/file-posix.c
40
+++ b/block/file-posix.c
41
@@ -XXX,XX +XXX,XX @@ typedef struct RawPosixAIOData {
42
#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */
43
off_t aio_offset;
44
int aio_type;
45
- int aio_fd2;
46
- off_t aio_offset2;
47
+ union {
48
+ struct {
49
+ int aio_fd2;
50
+ off_t aio_offset2;
51
+ };
52
+ struct {
53
+ PreallocMode prealloc;
54
+ Error **errp;
55
+ };
56
+ };
57
} RawPosixAIOData;
58
59
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
60
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
61
return ret;
62
}
63
64
+static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
65
+{
66
+ int result = 0;
67
+ int64_t current_length = 0;
68
+ char *buf = NULL;
69
+ struct stat st;
70
+ int fd = aiocb->aio_fildes;
71
+ int64_t offset = aiocb->aio_offset;
72
+ Error **errp = aiocb->errp;
73
+
74
+ if (fstat(fd, &st) < 0) {
75
+ result = -errno;
76
+ error_setg_errno(errp, -result, "Could not stat file");
77
+ return result;
78
+ }
79
+
80
+ current_length = st.st_size;
81
+ if (current_length > offset && aiocb->prealloc != PREALLOC_MODE_OFF) {
82
+ error_setg(errp, "Cannot use preallocation for shrinking files");
83
+ return -ENOTSUP;
84
+ }
85
+
86
+ switch (aiocb->prealloc) {
87
+#ifdef CONFIG_POSIX_FALLOCATE
88
+ case PREALLOC_MODE_FALLOC:
89
+ /*
90
+ * Truncating before posix_fallocate() makes it about twice slower on
91
+ * file systems that do not support fallocate(), trying to check if a
92
+ * block is allocated before allocating it, so don't do that here.
93
+ */
94
+ if (offset != current_length) {
95
+ result = -posix_fallocate(fd, current_length,
96
+ offset - current_length);
97
+ if (result != 0) {
98
+ /* posix_fallocate() doesn't set errno. */
99
+ error_setg_errno(errp, -result,
100
+ "Could not preallocate new data");
101
+ }
102
+ } else {
103
+ result = 0;
104
+ }
105
+ goto out;
106
+#endif
107
+ case PREALLOC_MODE_FULL:
108
+ {
109
+ int64_t num = 0, left = offset - current_length;
110
+ off_t seek_result;
111
+
112
+ /*
113
+ * Knowing the final size from the beginning could allow the file
114
+ * system driver to do less allocations and possibly avoid
115
+ * fragmentation of the file.
116
+ */
117
+ if (ftruncate(fd, offset) != 0) {
118
+ result = -errno;
119
+ error_setg_errno(errp, -result, "Could not resize file");
120
+ goto out;
121
+ }
122
+
123
+ buf = g_malloc0(65536);
124
+
125
+ seek_result = lseek(fd, current_length, SEEK_SET);
126
+ if (seek_result < 0) {
127
+ result = -errno;
128
+ error_setg_errno(errp, -result,
129
+ "Failed to seek to the old end of file");
130
+ goto out;
131
+ }
132
+
133
+ while (left > 0) {
134
+ num = MIN(left, 65536);
135
+ result = write(fd, buf, num);
136
+ if (result < 0) {
137
+ result = -errno;
138
+ error_setg_errno(errp, -result,
139
+ "Could not write zeros for preallocation");
140
+ goto out;
141
+ }
142
+ left -= result;
143
+ }
144
+ if (result >= 0) {
145
+ result = fsync(fd);
146
+ if (result < 0) {
147
+ result = -errno;
148
+ error_setg_errno(errp, -result,
149
+ "Could not flush file to disk");
150
+ goto out;
151
+ }
152
+ }
153
+ goto out;
154
+ }
155
+ case PREALLOC_MODE_OFF:
156
+ if (ftruncate(fd, offset) != 0) {
157
+ result = -errno;
158
+ error_setg_errno(errp, -result, "Could not resize file");
159
+ }
160
+ return result;
161
+ default:
162
+ result = -ENOTSUP;
163
+ error_setg(errp, "Unsupported preallocation mode: %s",
164
+ PreallocMode_str(aiocb->prealloc));
165
+ return result;
166
+ }
167
+
168
+out:
169
+ if (result < 0) {
170
+ if (ftruncate(fd, current_length) < 0) {
171
+ error_report("Failed to restore old file length: %s",
172
+ strerror(errno));
173
+ }
174
+ }
175
+
176
+ g_free(buf);
177
+ return result;
178
+}
179
+
180
static int aio_worker(void *arg)
181
{
182
RawPosixAIOData *aiocb = arg;
183
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
184
case QEMU_AIO_COPY_RANGE:
185
ret = handle_aiocb_copy_range(aiocb);
186
break;
187
+ case QEMU_AIO_TRUNCATE:
188
+ ret = handle_aiocb_truncate(aiocb);
189
+ break;
190
default:
191
fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
192
ret = -EINVAL;
193
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
194
*
195
* Returns: 0 on success, -errno on failure.
196
*/
197
-static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc,
198
- Error **errp)
199
+static int coroutine_fn
200
+raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
201
+ PreallocMode prealloc, Error **errp)
202
{
203
- int result = 0;
204
- int64_t current_length = 0;
205
- char *buf = NULL;
206
- struct stat st;
207
-
208
- if (fstat(fd, &st) < 0) {
209
- result = -errno;
210
- error_setg_errno(errp, -result, "Could not stat file");
211
- return result;
212
- }
213
-
214
- current_length = st.st_size;
215
- if (current_length > offset && prealloc != PREALLOC_MODE_OFF) {
216
- error_setg(errp, "Cannot use preallocation for shrinking files");
217
- return -ENOTSUP;
218
- }
219
-
220
- switch (prealloc) {
221
-#ifdef CONFIG_POSIX_FALLOCATE
222
- case PREALLOC_MODE_FALLOC:
223
- /*
224
- * Truncating before posix_fallocate() makes it about twice slower on
225
- * file systems that do not support fallocate(), trying to check if a
226
- * block is allocated before allocating it, so don't do that here.
227
- */
228
- if (offset != current_length) {
229
- result = -posix_fallocate(fd, current_length, offset - current_length);
230
- if (result != 0) {
231
- /* posix_fallocate() doesn't set errno. */
232
- error_setg_errno(errp, -result,
233
- "Could not preallocate new data");
234
- }
235
- } else {
236
- result = 0;
237
- }
238
- goto out;
239
-#endif
240
- case PREALLOC_MODE_FULL:
241
- {
242
- int64_t num = 0, left = offset - current_length;
243
- off_t seek_result;
244
-
245
- /*
246
- * Knowing the final size from the beginning could allow the file
247
- * system driver to do less allocations and possibly avoid
248
- * fragmentation of the file.
249
- */
250
- if (ftruncate(fd, offset) != 0) {
251
- result = -errno;
252
- error_setg_errno(errp, -result, "Could not resize file");
253
- goto out;
254
- }
255
-
256
- buf = g_malloc0(65536);
257
-
258
- seek_result = lseek(fd, current_length, SEEK_SET);
259
- if (seek_result < 0) {
260
- result = -errno;
261
- error_setg_errno(errp, -result,
262
- "Failed to seek to the old end of file");
263
- goto out;
264
- }
265
-
266
- while (left > 0) {
267
- num = MIN(left, 65536);
268
- result = write(fd, buf, num);
269
- if (result < 0) {
270
- result = -errno;
271
- error_setg_errno(errp, -result,
272
- "Could not write zeros for preallocation");
273
- goto out;
274
- }
275
- left -= result;
276
- }
277
- if (result >= 0) {
278
- result = fsync(fd);
279
- if (result < 0) {
280
- result = -errno;
281
- error_setg_errno(errp, -result,
282
- "Could not flush file to disk");
283
- goto out;
284
- }
285
- }
286
- goto out;
287
- }
288
- case PREALLOC_MODE_OFF:
289
- if (ftruncate(fd, offset) != 0) {
290
- result = -errno;
291
- error_setg_errno(errp, -result, "Could not resize file");
292
- }
293
- return result;
294
- default:
295
- result = -ENOTSUP;
296
- error_setg(errp, "Unsupported preallocation mode: %s",
297
- PreallocMode_str(prealloc));
298
- return result;
299
- }
300
+ RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
301
+ ThreadPool *pool;
302
303
-out:
304
- if (result < 0) {
305
- if (ftruncate(fd, current_length) < 0) {
306
- error_report("Failed to restore old file length: %s",
307
- strerror(errno));
308
- }
309
- }
310
+ *acb = (RawPosixAIOData) {
311
+ .bs = bs,
312
+ .aio_fildes = fd,
313
+ .aio_type = QEMU_AIO_TRUNCATE,
314
+ .aio_offset = offset,
315
+ .prealloc = prealloc,
316
+ .errp = errp,
317
+ };
318
319
- g_free(buf);
320
- return result;
321
+ /* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
322
+ pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
323
+ return thread_pool_submit_co(pool, aio_worker, acb);
324
}
325
326
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
327
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
328
}
329
330
if (S_ISREG(st.st_mode)) {
331
- return raw_regular_truncate(s->fd, offset, prealloc, errp);
332
+ return raw_regular_truncate(bs, s->fd, offset, prealloc, errp);
333
}
334
335
if (prealloc != PREALLOC_MODE_OFF) {
336
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
337
return (int64_t)st.st_blocks * 512;
338
}
339
340
-static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
341
+static int coroutine_fn
342
+raw_co_create(BlockdevCreateOptions *options, Error **errp)
343
{
344
BlockdevCreateOptionsFile *file_opts;
345
int fd;
346
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
347
}
348
349
/* Clear the file by truncating it to 0 */
350
- result = raw_regular_truncate(fd, 0, PREALLOC_MODE_OFF, errp);
351
+ result = raw_regular_truncate(NULL, fd, 0, PREALLOC_MODE_OFF, errp);
352
if (result < 0) {
353
goto out_close;
354
}
355
@@ -XXX,XX +XXX,XX @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
356
357
/* Resize and potentially preallocate the file to the desired
358
* final size */
359
- result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
360
- errp);
361
+ result = raw_regular_truncate(NULL, fd, file_opts->size,
362
+ file_opts->preallocation, errp);
363
if (result < 0) {
364
goto out_close;
365
}
366
--
367
2.13.6
368
369
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
In the beginning of the function, we initialize the local variable to 0,
4
and in the body of the function, we check the assigned values and exit
5
the loop immediately. So here it can never be non-zero.
6
7
Reported-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/qcow2.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/block/qcow2.c b/block/qcow2.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.c
19
+++ b/block/qcow2.c
20
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
21
while (l2meta != NULL) {
22
QCowL2Meta *next;
23
24
- if (!ret && link_l2) {
25
+ if (link_l2) {
26
ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
27
if (ret) {
28
goto out;
29
--
30
2.13.6
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
in_flight and tracked requests need to be tracked in every layer during
4
recursion. For now the only user is qemu-img convert where overlapping
5
requests and IOThreads don't exist, therefore this change doesn't make
6
much difference form user point of view, but it is incorrect as part of
7
the API. Fix it.
8
9
Reported-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Fam Zheng <famz@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/io.c | 59 ++++++++++++++++++++++++++++-------------------------------
15
1 file changed, 28 insertions(+), 31 deletions(-)
16
17
diff --git a/block/io.c b/block/io.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/io.c
20
+++ b/block/io.c
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
22
BdrvRequestFlags flags,
23
bool recurse_src)
24
{
25
+ BdrvTrackedRequest src_req, dst_req;
26
+ BlockDriverState *src_bs = src->bs;
27
+ BlockDriverState *dst_bs = dst->bs;
28
int ret;
29
30
if (!src || !dst || !src->bs || !dst->bs) {
31
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
32
|| src->bs->encrypted || dst->bs->encrypted) {
33
return -ENOTSUP;
34
}
35
+ bdrv_inc_in_flight(src_bs);
36
+ bdrv_inc_in_flight(dst_bs);
37
+ tracked_request_begin(&src_req, src_bs, src_offset,
38
+ bytes, BDRV_TRACKED_READ);
39
+ tracked_request_begin(&dst_req, dst_bs, dst_offset,
40
+ bytes, BDRV_TRACKED_WRITE);
41
+
42
+ wait_serialising_requests(&src_req);
43
+ wait_serialising_requests(&dst_req);
44
if (recurse_src) {
45
- return src->bs->drv->bdrv_co_copy_range_from(src->bs,
46
- src, src_offset,
47
- dst, dst_offset,
48
- bytes, flags);
49
+ ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
50
+ src, src_offset,
51
+ dst, dst_offset,
52
+ bytes, flags);
53
} else {
54
- return dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
55
- src, src_offset,
56
- dst, dst_offset,
57
- bytes, flags);
58
+ ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
59
+ src, src_offset,
60
+ dst, dst_offset,
61
+ bytes, flags);
62
}
63
+ tracked_request_end(&src_req);
64
+ tracked_request_end(&dst_req);
65
+ bdrv_dec_in_flight(src_bs);
66
+ bdrv_dec_in_flight(dst_bs);
67
+ return ret;
68
}
69
70
/* Copy range from @src to @dst.
71
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, uint64_t src_offset,
72
BdrvChild *dst, uint64_t dst_offset,
73
uint64_t bytes, BdrvRequestFlags flags)
74
{
75
- BdrvTrackedRequest src_req, dst_req;
76
- BlockDriverState *src_bs = src->bs;
77
- BlockDriverState *dst_bs = dst->bs;
78
- int ret;
79
-
80
- bdrv_inc_in_flight(src_bs);
81
- bdrv_inc_in_flight(dst_bs);
82
- tracked_request_begin(&src_req, src_bs, src_offset,
83
- bytes, BDRV_TRACKED_READ);
84
- tracked_request_begin(&dst_req, dst_bs, dst_offset,
85
- bytes, BDRV_TRACKED_WRITE);
86
-
87
- wait_serialising_requests(&src_req);
88
- wait_serialising_requests(&dst_req);
89
- ret = bdrv_co_copy_range_from(src, src_offset,
90
- dst, dst_offset,
91
- bytes, flags);
92
-
93
- tracked_request_end(&src_req);
94
- tracked_request_end(&dst_req);
95
- bdrv_dec_in_flight(src_bs);
96
- bdrv_dec_in_flight(dst_bs);
97
- return ret;
98
+ return bdrv_co_copy_range_from(src, src_offset,
99
+ dst, dst_offset,
100
+ bytes, flags);
101
}
102
103
static void bdrv_parent_cb_resize(BlockDriverState *bs)
104
--
105
2.13.6
106
107
diff view generated by jsdifflib
Deleted patch
1
From: Markus Armbruster <armbru@redhat.com>
2
1
3
block_crypto_open_opts_init() and block_crypto_create_opts_init()
4
contain a virtual visit of QCryptoBlockOptions and
5
QCryptoBlockCreateOptions less member "format", respectively.
6
7
Change their callers to put member "format" in the QDict, so they can
8
use the generated visitors for these types instead.
9
10
Signed-off-by: Markus Armbruster <armbru@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/crypto.h | 8 ++---
15
block/crypto.c | 99 +++++++++-------------------------------------------------
16
block/qcow.c | 5 ++-
17
block/qcow2.c | 10 +++---
18
4 files changed, 22 insertions(+), 100 deletions(-)
19
20
diff --git a/block/crypto.h b/block/crypto.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/crypto.h
23
+++ b/block/crypto.h
24
@@ -XXX,XX +XXX,XX @@
25
}
26
27
QCryptoBlockCreateOptions *
28
-block_crypto_create_opts_init(QCryptoBlockFormat format,
29
- QDict *opts,
30
- Error **errp);
31
+block_crypto_create_opts_init(QDict *opts, Error **errp);
32
33
QCryptoBlockOpenOptions *
34
-block_crypto_open_opts_init(QCryptoBlockFormat format,
35
- QDict *opts,
36
- Error **errp);
37
+block_crypto_open_opts_init(QDict *opts, Error **errp);
38
39
#endif /* BLOCK_CRYPTO_H__ */
40
diff --git a/block/crypto.c b/block/crypto.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block/crypto.c
43
+++ b/block/crypto.c
44
@@ -XXX,XX +XXX,XX @@ static QemuOptsList block_crypto_create_opts_luks = {
45
46
47
QCryptoBlockOpenOptions *
48
-block_crypto_open_opts_init(QCryptoBlockFormat format,
49
- QDict *opts,
50
- Error **errp)
51
+block_crypto_open_opts_init(QDict *opts, Error **errp)
52
{
53
Visitor *v;
54
- QCryptoBlockOpenOptions *ret = NULL;
55
- Error *local_err = NULL;
56
-
57
- ret = g_new0(QCryptoBlockOpenOptions, 1);
58
- ret->format = format;
59
+ QCryptoBlockOpenOptions *ret;
60
61
- v = qobject_input_visitor_new_flat_confused(opts, &local_err);
62
+ v = qobject_input_visitor_new_flat_confused(opts, errp);
63
if (!v) {
64
- goto out;
65
- }
66
-
67
- visit_start_struct(v, NULL, NULL, 0, &local_err);
68
- if (local_err) {
69
- goto out;
70
- }
71
-
72
- switch (format) {
73
- case Q_CRYPTO_BLOCK_FORMAT_LUKS:
74
- visit_type_QCryptoBlockOptionsLUKS_members(
75
- v, &ret->u.luks, &local_err);
76
- break;
77
-
78
- case Q_CRYPTO_BLOCK_FORMAT_QCOW:
79
- visit_type_QCryptoBlockOptionsQCow_members(
80
- v, &ret->u.qcow, &local_err);
81
- break;
82
-
83
- default:
84
- error_setg(&local_err, "Unsupported block format %d", format);
85
- break;
86
- }
87
- if (!local_err) {
88
- visit_check_struct(v, &local_err);
89
+ return NULL;
90
}
91
92
- visit_end_struct(v, NULL);
93
+ visit_type_QCryptoBlockOpenOptions(v, NULL, &ret, errp);
94
95
- out:
96
- if (local_err) {
97
- error_propagate(errp, local_err);
98
- qapi_free_QCryptoBlockOpenOptions(ret);
99
- ret = NULL;
100
- }
101
visit_free(v);
102
return ret;
103
}
104
105
106
QCryptoBlockCreateOptions *
107
-block_crypto_create_opts_init(QCryptoBlockFormat format,
108
- QDict *opts,
109
- Error **errp)
110
+block_crypto_create_opts_init(QDict *opts, Error **errp)
111
{
112
Visitor *v;
113
- QCryptoBlockCreateOptions *ret = NULL;
114
- Error *local_err = NULL;
115
-
116
- ret = g_new0(QCryptoBlockCreateOptions, 1);
117
- ret->format = format;
118
+ QCryptoBlockCreateOptions *ret;
119
120
- v = qobject_input_visitor_new_flat_confused(opts, &local_err);
121
+ v = qobject_input_visitor_new_flat_confused(opts, errp);
122
if (!v) {
123
- goto out;
124
- }
125
-
126
- visit_start_struct(v, NULL, NULL, 0, &local_err);
127
- if (local_err) {
128
- goto out;
129
- }
130
-
131
- switch (format) {
132
- case Q_CRYPTO_BLOCK_FORMAT_LUKS:
133
- visit_type_QCryptoBlockCreateOptionsLUKS_members(
134
- v, &ret->u.luks, &local_err);
135
- break;
136
-
137
- case Q_CRYPTO_BLOCK_FORMAT_QCOW:
138
- visit_type_QCryptoBlockOptionsQCow_members(
139
- v, &ret->u.qcow, &local_err);
140
- break;
141
-
142
- default:
143
- error_setg(&local_err, "Unsupported block format %d", format);
144
- break;
145
- }
146
- if (!local_err) {
147
- visit_check_struct(v, &local_err);
148
+ return NULL;
149
}
150
151
- visit_end_struct(v, NULL);
152
+ visit_type_QCryptoBlockCreateOptions(v, NULL, &ret, errp);
153
154
- out:
155
- if (local_err) {
156
- error_propagate(errp, local_err);
157
- qapi_free_QCryptoBlockCreateOptions(ret);
158
- ret = NULL;
159
- }
160
visit_free(v);
161
return ret;
162
}
163
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
164
}
165
166
cryptoopts = qemu_opts_to_qdict(opts, NULL);
167
+ qdict_put_str(cryptoopts, "format", QCryptoBlockFormat_str(format));
168
169
- open_opts = block_crypto_open_opts_init(format, cryptoopts, errp);
170
+ open_opts = block_crypto_open_opts_init(cryptoopts, errp);
171
if (!open_opts) {
172
goto cleanup;
173
}
174
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
175
&block_crypto_create_opts_luks,
176
true);
177
178
- create_opts = block_crypto_create_opts_init(Q_CRYPTO_BLOCK_FORMAT_LUKS,
179
- cryptoopts, errp);
180
+ qdict_put_str(cryptoopts, "format", "luks");
181
+ create_opts = block_crypto_create_opts_init(cryptoopts, errp);
182
if (!create_opts) {
183
ret = -EINVAL;
184
goto fail;
185
diff --git a/block/qcow.c b/block/qcow.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/block/qcow.c
188
+++ b/block/qcow.c
189
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
190
ret = -EINVAL;
191
goto fail;
192
}
193
- qdict_del(encryptopts, "format");
194
- crypto_opts = block_crypto_open_opts_init(
195
- Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
196
+ qdict_put_str(encryptopts, "format", "qcow");
197
+ crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
198
if (!crypto_opts) {
199
ret = -EINVAL;
200
goto fail;
201
diff --git a/block/qcow2.c b/block/qcow2.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/block/qcow2.c
204
+++ b/block/qcow2.c
205
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
206
ret = -EINVAL;
207
goto fail;
208
}
209
- qdict_del(encryptopts, "format");
210
- r->crypto_opts = block_crypto_open_opts_init(
211
- Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
212
+ qdict_put_str(encryptopts, "format", "qcow");
213
+ r->crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
214
break;
215
216
case QCOW_CRYPT_LUKS:
217
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
218
ret = -EINVAL;
219
goto fail;
220
}
221
- qdict_del(encryptopts, "format");
222
- r->crypto_opts = block_crypto_open_opts_init(
223
- Q_CRYPTO_BLOCK_FORMAT_LUKS, encryptopts, errp);
224
+ qdict_put_str(encryptopts, "format", "luks");
225
+ r->crypto_opts = block_crypto_open_opts_init(encryptopts, errp);
226
break;
227
228
default:
229
--
230
2.13.6
231
232
diff view generated by jsdifflib
Deleted patch
1
Commit abf754fe406 updated 026.out, but forgot to also update
2
026.out.nocache.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
tests/qemu-iotests/026.out.nocache | 6 +++---
8
1 file changed, 3 insertions(+), 3 deletions(-)
9
10
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
11
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/qemu-iotests/026.out.nocache
13
+++ b/tests/qemu-iotests/026.out.nocache
14
@@ -XXX,XX +XXX,XX @@ Failed to flush the L2 table cache: No space left on device
15
Failed to flush the refcount block cache: No space left on device
16
write failed: No space left on device
17
18
-11 leaked clusters were found on the image.
19
+10 leaked clusters were found on the image.
20
This means waste of disk space, but no harm to data.
21
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
22
23
@@ -XXX,XX +XXX,XX @@ Failed to flush the L2 table cache: No space left on device
24
Failed to flush the refcount block cache: No space left on device
25
write failed: No space left on device
26
27
-11 leaked clusters were found on the image.
28
+10 leaked clusters were found on the image.
29
This means waste of disk space, but no harm to data.
30
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
31
32
@@ -XXX,XX +XXX,XX @@ Failed to flush the L2 table cache: No space left on device
33
Failed to flush the refcount block cache: No space left on device
34
write failed: No space left on device
35
36
-11 leaked clusters were found on the image.
37
+10 leaked clusters were found on the image.
38
This means waste of disk space, but no harm to data.
39
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
40
41
--
42
2.13.6
43
44
diff view generated by jsdifflib
Deleted patch
1
If we managed to allocate the clusters, but then failed to write the
2
data, there's a good chance that we'll still be able to free the
3
clusters again in order to avoid cluster leaks (the refcounts are
4
cached, so even if we can't write them out right now, we may be able to
5
do so when the VM is resumed after a werror=stop/enospc pause).
6
1
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Tested-by: Eric Blake <eblake@redhat.com>
11
---
12
block/qcow2.h | 1 +
13
block/qcow2-cluster.c | 11 +++++++++++
14
block/qcow2.c | 2 ++
15
3 files changed, 14 insertions(+)
16
17
diff --git a/block/qcow2.h b/block/qcow2.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2.h
20
+++ b/block/qcow2.h
21
@@ -XXX,XX +XXX,XX @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
22
int compressed_size);
23
24
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
25
+void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
26
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
27
uint64_t bytes, enum qcow2_discard_type type,
28
bool full_discard);
29
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block/qcow2-cluster.c
32
+++ b/block/qcow2-cluster.c
33
@@ -XXX,XX +XXX,XX @@ err:
34
return ret;
35
}
36
37
+/**
38
+ * Frees the allocated clusters because the request failed and they won't
39
+ * actually be linked.
40
+ */
41
+void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
42
+{
43
+ BDRVQcow2State *s = bs->opaque;
44
+ qcow2_free_clusters(bs, m->alloc_offset, m->nb_clusters << s->cluster_bits,
45
+ QCOW2_DISCARD_NEVER);
46
+}
47
+
48
/*
49
* Returns the number of contiguous clusters that can be used for an allocating
50
* write, but require COW to be performed (this includes yet unallocated space,
51
diff --git a/block/qcow2.c b/block/qcow2.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/qcow2.c
54
+++ b/block/qcow2.c
55
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
56
if (ret) {
57
goto out;
58
}
59
+ } else {
60
+ qcow2_alloc_cluster_abort(bs, l2meta);
61
}
62
63
/* Take the request off the list of running requests */
64
--
65
2.13.6
66
67
diff view generated by jsdifflib
Deleted patch
1
This adds a test for a temporary write failure, which simulates the
2
situation after werror=stop/enospc has stopped the VM. We shouldn't
3
leave leaked clusters behind in such cases.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/026 | 17 +++++++++++++++++
9
tests/qemu-iotests/026.out | 8 ++++++++
10
tests/qemu-iotests/026.out.nocache | 8 ++++++++
11
3 files changed, 33 insertions(+)
12
13
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/026
16
+++ b/tests/qemu-iotests/026
17
@@ -XXX,XX +XXX,XX @@ done
18
done
19
done
20
21
+echo
22
+echo === Avoid cluster leaks after temporary failure ===
23
+echo
24
+
25
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
26
+[inject-error]
27
+event = "write_aio"
28
+errno = "5"
29
+once = "on"
30
+EOF
31
+
32
+# After the failed first write, do a second write so that the updated refcount
33
+# block is actually written back
34
+_make_test_img 64M
35
+$QEMU_IO -c "write 0 1M" -c "write 0 1M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
36
+_check_test_img
37
+
38
# success, all done
39
echo "*** done"
40
rm -f $seq.full
41
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
42
index XXXXXXX..XXXXXXX 100644
43
--- a/tests/qemu-iotests/026.out
44
+++ b/tests/qemu-iotests/026.out
45
@@ -XXX,XX +XXX,XX @@ write failed: No space left on device
46
47
96 leaked clusters were found on the image.
48
This means waste of disk space, but no harm to data.
49
+
50
+=== Avoid cluster leaks after temporary failure ===
51
+
52
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
53
+write failed: Input/output error
54
+wrote 1048576/1048576 bytes at offset 0
55
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
56
+No errors were found on the image.
57
*** done
58
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
59
index XXXXXXX..XXXXXXX 100644
60
--- a/tests/qemu-iotests/026.out.nocache
61
+++ b/tests/qemu-iotests/026.out.nocache
62
@@ -XXX,XX +XXX,XX @@ write failed: No space left on device
63
64
96 leaked clusters were found on the image.
65
This means waste of disk space, but no harm to data.
66
+
67
+=== Avoid cluster leaks after temporary failure ===
68
+
69
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
70
+write failed: Input/output error
71
+wrote 1048576/1048576 bytes at offset 0
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+No errors were found on the image.
74
*** done
75
--
76
2.13.6
77
78
diff view generated by jsdifflib
Deleted patch
1
This simplifies file-posix by implementing the coroutine variants of
2
the discard and flush BlockDriver callbacks. These were the last
3
remaining users of paio_submit(), which can be removed now.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
block/file-posix.c | 72 ++++++++++++++++++------------------------------------
9
1 file changed, 24 insertions(+), 48 deletions(-)
10
11
diff --git a/block/file-posix.c b/block/file-posix.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-posix.c
14
+++ b/block/file-posix.c
15
@@ -XXX,XX +XXX,XX @@ static inline int paio_submit_co(BlockDriverState *bs, int fd,
16
return paio_submit_co_full(bs, fd, offset, -1, 0, qiov, bytes, type);
17
}
18
19
-static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
20
- int64_t offset, QEMUIOVector *qiov, int bytes,
21
- BlockCompletionFunc *cb, void *opaque, int type)
22
-{
23
- RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
24
- ThreadPool *pool;
25
-
26
- acb->bs = bs;
27
- acb->aio_type = type;
28
- acb->aio_fildes = fd;
29
-
30
- acb->aio_nbytes = bytes;
31
- acb->aio_offset = offset;
32
-
33
- if (qiov) {
34
- acb->aio_iov = qiov->iov;
35
- acb->aio_niov = qiov->niov;
36
- assert(qiov->size == acb->aio_nbytes);
37
- }
38
-
39
- trace_paio_submit(acb, opaque, offset, bytes, type);
40
- pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
41
- return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
42
-}
43
-
44
static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
45
uint64_t bytes, QEMUIOVector *qiov, int type)
46
{
47
@@ -XXX,XX +XXX,XX @@ static void raw_aio_unplug(BlockDriverState *bs)
48
#endif
49
}
50
51
-static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
52
- BlockCompletionFunc *cb, void *opaque)
53
+static int raw_co_flush_to_disk(BlockDriverState *bs)
54
{
55
BDRVRawState *s = bs->opaque;
56
+ int ret;
57
58
- if (fd_open(bs) < 0)
59
- return NULL;
60
+ ret = fd_open(bs);
61
+ if (ret < 0) {
62
+ return ret;
63
+ }
64
65
- return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
66
+ return paio_submit_co(bs, s->fd, 0, NULL, 0, QEMU_AIO_FLUSH);
67
}
68
69
static void raw_aio_attach_aio_context(BlockDriverState *bs,
70
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
71
#endif /* !__linux__ */
72
}
73
74
-static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs,
75
- int64_t offset, int bytes,
76
- BlockCompletionFunc *cb, void *opaque)
77
+static coroutine_fn int
78
+raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
79
{
80
BDRVRawState *s = bs->opaque;
81
82
- return paio_submit(bs, s->fd, offset, NULL, bytes,
83
- cb, opaque, QEMU_AIO_DISCARD);
84
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes, QEMU_AIO_DISCARD);
85
}
86
87
static int coroutine_fn raw_co_pwrite_zeroes(
88
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
89
90
.bdrv_co_preadv = raw_co_preadv,
91
.bdrv_co_pwritev = raw_co_pwritev,
92
- .bdrv_aio_flush = raw_aio_flush,
93
- .bdrv_aio_pdiscard = raw_aio_pdiscard,
94
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
95
+ .bdrv_co_pdiscard = raw_co_pdiscard,
96
.bdrv_co_copy_range_from = raw_co_copy_range_from,
97
.bdrv_co_copy_range_to = raw_co_copy_range_to,
98
.bdrv_refresh_limits = raw_refresh_limits,
99
@@ -XXX,XX +XXX,XX @@ static int fd_open(BlockDriverState *bs)
100
return -EIO;
101
}
102
103
-static coroutine_fn BlockAIOCB *hdev_aio_pdiscard(BlockDriverState *bs,
104
- int64_t offset, int bytes,
105
- BlockCompletionFunc *cb, void *opaque)
106
+static coroutine_fn int
107
+hdev_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
108
{
109
BDRVRawState *s = bs->opaque;
110
+ int ret;
111
112
- if (fd_open(bs) < 0) {
113
- return NULL;
114
+ ret = fd_open(bs);
115
+ if (ret < 0) {
116
+ return ret;
117
}
118
- return paio_submit(bs, s->fd, offset, NULL, bytes,
119
- cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
120
+ return paio_submit_co(bs, s->fd, offset, NULL, bytes,
121
+ QEMU_AIO_DISCARD | QEMU_AIO_BLKDEV);
122
}
123
124
static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
125
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
126
127
.bdrv_co_preadv = raw_co_preadv,
128
.bdrv_co_pwritev = raw_co_pwritev,
129
- .bdrv_aio_flush    = raw_aio_flush,
130
- .bdrv_aio_pdiscard = hdev_aio_pdiscard,
131
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
132
+ .bdrv_co_pdiscard = hdev_co_pdiscard,
133
.bdrv_co_copy_range_from = raw_co_copy_range_from,
134
.bdrv_co_copy_range_to = raw_co_copy_range_to,
135
.bdrv_refresh_limits = raw_refresh_limits,
136
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
137
138
.bdrv_co_preadv = raw_co_preadv,
139
.bdrv_co_pwritev = raw_co_pwritev,
140
- .bdrv_aio_flush    = raw_aio_flush,
141
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
142
.bdrv_refresh_limits = raw_refresh_limits,
143
.bdrv_io_plug = raw_aio_plug,
144
.bdrv_io_unplug = raw_aio_unplug,
145
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
146
147
.bdrv_co_preadv = raw_co_preadv,
148
.bdrv_co_pwritev = raw_co_pwritev,
149
- .bdrv_aio_flush    = raw_aio_flush,
150
+ .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
151
.bdrv_refresh_limits = raw_refresh_limits,
152
.bdrv_io_plug = raw_aio_plug,
153
.bdrv_io_unplug = raw_aio_unplug,
154
--
155
2.13.6
156
157
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Not updating src_offset will result in wrong data being written to dst
4
image.
5
6
Reported-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/qcow2.c | 1 +
11
tests/qemu-iotests/063 | 9 +++++++++
12
tests/qemu-iotests/063.out | 12 ++++++++++++
13
3 files changed, 22 insertions(+)
14
15
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
18
+++ b/block/qcow2.c
19
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
20
}
21
22
bytes -= cur_bytes;
23
+ src_offset += cur_bytes;
24
dst_offset += cur_bytes;
25
}
26
ret = 0;
27
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
28
index XXXXXXX..XXXXXXX 100755
29
--- a/tests/qemu-iotests/063
30
+++ b/tests/qemu-iotests/063
31
@@ -XXX,XX +XXX,XX @@ if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG.orig" "$TEST_IMG" >/dev
32
exit 1
33
fi
34
35
+echo "== Regression testing for copy offloading bug =="
36
+
37
+_make_test_img 1M
38
+TEST_IMG="$TEST_IMG.target" _make_test_img 1M
39
+$QEMU_IO -c 'write -P 1 0 512k' -c 'write -P 2 512k 512k' "$TEST_IMG" | _filter_qemu_io
40
+$QEMU_IO -c 'write -P 4 512k 512k' -c 'write -P 3 0 512k' "$TEST_IMG.target" | _filter_qemu_io
41
+$QEMU_IMG convert -n -O $IMGFMT "$TEST_IMG" "$TEST_IMG.target"
42
+$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.target"
43
+
44
echo "*** done"
45
rm -f $seq.full
46
status=0
47
diff --git a/tests/qemu-iotests/063.out b/tests/qemu-iotests/063.out
48
index XXXXXXX..XXXXXXX 100644
49
--- a/tests/qemu-iotests/063.out
50
+++ b/tests/qemu-iotests/063.out
51
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
52
No errors were found on the image.
53
== Testing conversion to a smaller file fails ==
54
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
55
+== Regression testing for copy offloading bug ==
56
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
57
+Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=1048576
58
+wrote 524288/524288 bytes at offset 0
59
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
60
+wrote 524288/524288 bytes at offset 524288
61
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
62
+wrote 524288/524288 bytes at offset 524288
63
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
64
+wrote 524288/524288 bytes at offset 0
65
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
66
+Images are identical.
67
*** done
68
--
69
2.13.6
70
71
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Per SCSI definition the designator_length we receive from INQUIRY is 8,
4
12 or at most 16, but we should be careful because the remote iscsi
5
target may misbehave, otherwise we could have a buffer overflow.
6
7
Reported-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/iscsi.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/block/iscsi.c b/block/iscsi.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/iscsi.c
17
+++ b/block/iscsi.c
18
@@ -XXX,XX +XXX,XX @@ static void iscsi_populate_target_desc(unsigned char *desc, IscsiLun *lun)
19
desc[5] = (dd->designator_type & 0xF)
20
| ((dd->association & 3) << 4);
21
desc[7] = dd->designator_length;
22
- memcpy(desc + 8, dd->designator, dd->designator_length);
23
+ memcpy(desc + 8, dd->designator, MIN(dd->designator_length, 20));
24
25
desc[28] = 0;
26
desc[29] = (lun->block_size >> 16) & 0xFF;
27
--
28
2.13.6
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
EINTR should be checked against errno, not ret. While fixing the bug,
4
collect the branches with a switch block.
5
6
Also, change the return value from -ENOSTUP to -ENOSPC when the actual
7
issue is request range passes EOF, which should be distinguishable from
8
the case of error == ENOSYS by the caller, so that it could still retry
9
with other byte ranges, whereas it shouldn't retry anymore upon ENOSYS.
10
11
Signed-off-by: Fam Zheng <famz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/file-posix.c | 17 +++++++++--------
15
1 file changed, 9 insertions(+), 8 deletions(-)
16
17
diff --git a/block/file-posix.c b/block/file-posix.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/file-posix.c
20
+++ b/block/file-posix.c
21
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
22
ssize_t ret = copy_file_range(aiocb->aio_fildes, &in_off,
23
aiocb->aio_fd2, &out_off,
24
bytes, 0);
25
- if (ret == -EINTR) {
26
- continue;
27
+ if (ret == 0) {
28
+ /* No progress (e.g. when beyond EOF), let the caller fall back to
29
+ * buffer I/O. */
30
+ return -ENOSPC;
31
}
32
if (ret < 0) {
33
- if (errno == ENOSYS) {
34
+ switch (errno) {
35
+ case ENOSYS:
36
return -ENOTSUP;
37
- } else {
38
+ case EINTR:
39
+ continue;
40
+ default:
41
return -errno;
42
}
43
}
44
- if (!ret) {
45
- /* No progress (e.g. when beyond EOF), fall back to buffer I/O. */
46
- return -ENOTSUP;
47
- }
48
bytes -= ret;
49
}
50
return 0;
51
--
52
2.13.6
53
54
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the last few sector-based calls
5
into the block layer from the parallels driver.
6
7
Ideally, the parallels driver should switch to doing everything
8
byte-based, but that's a more invasive change that requires a
9
bit more auditing.
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Denis V. Lunev <den@openvz.org>
14
Reviewed-by: Jeff Cody <jcody@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block/parallels.c | 16 ++++++++++------
18
1 file changed, 10 insertions(+), 6 deletions(-)
19
20
diff --git a/block/parallels.c b/block/parallels.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/parallels.c
23
+++ b/block/parallels.c
24
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
25
};
26
qemu_iovec_init_external(&qiov, &iov, 1);
27
28
- ret = bdrv_co_readv(bs->backing, idx * s->tracks, nb_cow_sectors,
29
- &qiov);
30
+ ret = bdrv_co_preadv(bs->backing, idx * s->tracks * BDRV_SECTOR_SIZE,
31
+ nb_cow_bytes, &qiov, 0);
32
if (ret < 0) {
33
qemu_vfree(iov.iov_base);
34
return ret;
35
}
36
37
- ret = bdrv_co_writev(bs->file, s->data_end, nb_cow_sectors, &qiov);
38
+ ret = bdrv_co_pwritev(bs->file, s->data_end * BDRV_SECTOR_SIZE,
39
+ nb_cow_bytes, &qiov, 0);
40
qemu_vfree(iov.iov_base);
41
if (ret < 0) {
42
return ret;
43
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
44
qemu_iovec_reset(&hd_qiov);
45
qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
46
47
- ret = bdrv_co_writev(bs->file, position, n, &hd_qiov);
48
+ ret = bdrv_co_pwritev(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
49
+ &hd_qiov, 0);
50
if (ret < 0) {
51
break;
52
}
53
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
54
55
if (position < 0) {
56
if (bs->backing) {
57
- ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
58
+ ret = bdrv_co_preadv(bs->backing, sector_num * BDRV_SECTOR_SIZE,
59
+ nbytes, &hd_qiov, 0);
60
if (ret < 0) {
61
break;
62
}
63
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
64
qemu_iovec_memset(&hd_qiov, 0, 0, nbytes);
65
}
66
} else {
67
- ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
68
+ ret = bdrv_co_preadv(bs->file, position * BDRV_SECTOR_SIZE, nbytes,
69
+ &hd_qiov, 0);
70
if (ret < 0) {
71
break;
72
}
73
--
74
2.13.6
75
76
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the internal helper function
5
get_cluster_offset(), by changing n_start and n_end to be byte
6
offsets rather than sector indices within the cluster being
7
allocated. However, assert that these values are still
8
sector-aligned (at least qcrypto_block_encrypt() still wants that).
9
For now we get that alignment for free because we still use
10
sector-based driver callbacks.
11
12
A later patch will then switch the qcow driver as a whole over
13
to byte-based operation; but will still leave things at sector
14
alignments as it is not worth auditing the qcow image format
15
to worry about sub-sector requests.
16
17
Signed-off-by: Eric Blake <eblake@redhat.com>
18
Reviewed-by: Jeff Cody <jcody@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
block/qcow.c | 29 +++++++++++++++--------------
22
1 file changed, 15 insertions(+), 14 deletions(-)
23
24
diff --git a/block/qcow.c b/block/qcow.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow.c
27
+++ b/block/qcow.c
28
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
29
*
30
* 0 to not allocate.
31
*
32
- * 1 to allocate a normal cluster (for sector indexes 'n_start' to
33
- * 'n_end')
34
+ * 1 to allocate a normal cluster (for sector-aligned byte offsets 'n_start'
35
+ * to 'n_end' within the cluster)
36
*
37
* 2 to allocate a compressed cluster of size
38
* 'compressed_size'. 'compressed_size' must be > 0 and <
39
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
40
if (!allocate)
41
return 0;
42
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
43
+ assert(QEMU_IS_ALIGNED(n_start | n_end, BDRV_SECTOR_SIZE));
44
/* allocate a new cluster */
45
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
46
- (n_end - n_start) < s->cluster_sectors) {
47
+ (n_end - n_start) < s->cluster_size) {
48
/* if the cluster is already compressed, we must
49
decompress it in the case it is not completely
50
overwritten */
51
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
52
/* if encrypted, we must initialize the cluster
53
content which won't be written */
54
if (bs->encrypted &&
55
- (n_end - n_start) < s->cluster_sectors) {
56
- uint64_t start_sect;
57
+ (n_end - n_start) < s->cluster_size) {
58
+ uint64_t start_offset;
59
assert(s->crypto);
60
- start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
61
- for(i = 0; i < s->cluster_sectors; i++) {
62
+ start_offset = offset & ~(s->cluster_size - 1);
63
+ for (i = 0; i < s->cluster_size; i += BDRV_SECTOR_SIZE) {
64
if (i < n_start || i >= n_end) {
65
- memset(s->cluster_data, 0x00, 512);
66
+ memset(s->cluster_data, 0x00, BDRV_SECTOR_SIZE);
67
if (qcrypto_block_encrypt(s->crypto,
68
- (start_sect + i) *
69
- BDRV_SECTOR_SIZE,
70
+ start_offset + i,
71
s->cluster_data,
72
BDRV_SECTOR_SIZE,
73
NULL) < 0) {
74
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
75
}
76
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
77
ret = bdrv_pwrite(bs->file,
78
- cluster_offset + i * 512,
79
- s->cluster_data, 512);
80
+ cluster_offset + i,
81
+ s->cluster_data,
82
+ BDRV_SECTOR_SIZE);
83
if (ret < 0) {
84
return ret;
85
}
86
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
87
n = nb_sectors;
88
}
89
ret = get_cluster_offset(bs, sector_num << 9, 1, 0,
90
- index_in_cluster,
91
- index_in_cluster + n, &cluster_offset);
92
+ index_in_cluster << 9,
93
+ (index_in_cluster + n) << 9, &cluster_offset);
94
if (ret < 0) {
95
break;
96
}
97
--
98
2.13.6
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the internals of the qcow
5
driver read function, by iterating over offset/bytes instead of
6
sector_num/nb_sectors, and with a rename of index_in_cluster and
7
repurposing of n to track bytes instead of sectors.
8
9
A later patch will then switch the qcow driver as a whole over
10
to byte-based operation.
11
12
Signed-off-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Jeff Cody <jcody@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/qcow.c | 42 ++++++++++++++++++++----------------------
17
1 file changed, 20 insertions(+), 22 deletions(-)
18
19
diff --git a/block/qcow.c b/block/qcow.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow.c
22
+++ b/block/qcow.c
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
24
int nb_sectors, QEMUIOVector *qiov)
25
{
26
BDRVQcowState *s = bs->opaque;
27
- int index_in_cluster;
28
+ int offset_in_cluster;
29
int ret = 0, n;
30
uint64_t cluster_offset;
31
struct iovec hd_iov;
32
QEMUIOVector hd_qiov;
33
uint8_t *buf;
34
void *orig_buf;
35
+ int64_t offset = sector_num * BDRV_SECTOR_SIZE;
36
+ int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
37
38
if (qiov->niov > 1) {
39
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
40
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
41
42
qemu_co_mutex_lock(&s->lock);
43
44
- while (nb_sectors != 0) {
45
+ while (bytes != 0) {
46
/* prepare next request */
47
- ret = get_cluster_offset(bs, sector_num << 9,
48
- 0, 0, 0, 0, &cluster_offset);
49
+ ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
50
if (ret < 0) {
51
break;
52
}
53
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
54
- n = s->cluster_sectors - index_in_cluster;
55
- if (n > nb_sectors) {
56
- n = nb_sectors;
57
+ offset_in_cluster = offset & (s->cluster_size - 1);
58
+ n = s->cluster_size - offset_in_cluster;
59
+ if (n > bytes) {
60
+ n = bytes;
61
}
62
63
if (!cluster_offset) {
64
if (bs->backing) {
65
/* read from the base image */
66
hd_iov.iov_base = (void *)buf;
67
- hd_iov.iov_len = n * 512;
68
+ hd_iov.iov_len = n;
69
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
70
qemu_co_mutex_unlock(&s->lock);
71
/* qcow2 emits this on bs->file instead of bs->backing */
72
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
73
- ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
74
+ ret = bdrv_co_preadv(bs->backing, offset, n, &hd_qiov, 0);
75
qemu_co_mutex_lock(&s->lock);
76
if (ret < 0) {
77
break;
78
}
79
} else {
80
/* Note: in this case, no need to wait */
81
- memset(buf, 0, 512 * n);
82
+ memset(buf, 0, n);
83
}
84
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
85
/* add AIO support for compressed blocks ? */
86
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
87
ret = -EIO;
88
break;
89
}
90
- memcpy(buf,
91
- s->cluster_cache + index_in_cluster * 512, 512 * n);
92
+ memcpy(buf, s->cluster_cache + offset_in_cluster, n);
93
} else {
94
if ((cluster_offset & 511) != 0) {
95
ret = -EIO;
96
break;
97
}
98
hd_iov.iov_base = (void *)buf;
99
- hd_iov.iov_len = n * 512;
100
+ hd_iov.iov_len = n;
101
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
102
qemu_co_mutex_unlock(&s->lock);
103
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
104
- ret = bdrv_co_readv(bs->file,
105
- (cluster_offset >> 9) + index_in_cluster,
106
- n, &hd_qiov);
107
+ ret = bdrv_co_preadv(bs->file, cluster_offset + offset_in_cluster,
108
+ n, &hd_qiov, 0);
109
qemu_co_mutex_lock(&s->lock);
110
if (ret < 0) {
111
break;
112
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
113
if (bs->encrypted) {
114
assert(s->crypto);
115
if (qcrypto_block_decrypt(s->crypto,
116
- sector_num * BDRV_SECTOR_SIZE, buf,
117
- n * BDRV_SECTOR_SIZE, NULL) < 0) {
118
+ offset, buf, n, NULL) < 0) {
119
ret = -EIO;
120
break;
121
}
122
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
123
}
124
ret = 0;
125
126
- nb_sectors -= n;
127
- sector_num += n;
128
- buf += n * 512;
129
+ bytes -= n;
130
+ offset += n;
131
+ buf += n;
132
}
133
134
qemu_co_mutex_unlock(&s->lock);
135
--
136
2.13.6
137
138
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the internals of the qcow
5
driver write function, by iterating over offset/bytes instead of
6
sector_num/nb_sectors, and with a rename of index_in_cluster and
7
repurposing of n to track bytes instead of sectors.
8
9
A later patch will then switch the qcow driver as a whole over
10
to byte-based operation.
11
12
Signed-off-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Jeff Cody <jcody@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block/qcow.c | 36 +++++++++++++++++-------------------
17
1 file changed, 17 insertions(+), 19 deletions(-)
18
19
diff --git a/block/qcow.c b/block/qcow.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow.c
22
+++ b/block/qcow.c
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
24
int flags)
25
{
26
BDRVQcowState *s = bs->opaque;
27
- int index_in_cluster;
28
+ int offset_in_cluster;
29
uint64_t cluster_offset;
30
int ret = 0, n;
31
struct iovec hd_iov;
32
QEMUIOVector hd_qiov;
33
uint8_t *buf;
34
void *orig_buf;
35
+ int64_t offset = sector_num * BDRV_SECTOR_SIZE;
36
+ int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
37
38
assert(!flags);
39
s->cluster_cache_offset = -1; /* disable compressed cache */
40
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
41
42
qemu_co_mutex_lock(&s->lock);
43
44
- while (nb_sectors != 0) {
45
-
46
- index_in_cluster = sector_num & (s->cluster_sectors - 1);
47
- n = s->cluster_sectors - index_in_cluster;
48
- if (n > nb_sectors) {
49
- n = nb_sectors;
50
+ while (bytes != 0) {
51
+ offset_in_cluster = offset & (s->cluster_size - 1);
52
+ n = s->cluster_size - offset_in_cluster;
53
+ if (n > bytes) {
54
+ n = bytes;
55
}
56
- ret = get_cluster_offset(bs, sector_num << 9, 1, 0,
57
- index_in_cluster << 9,
58
- (index_in_cluster + n) << 9, &cluster_offset);
59
+ ret = get_cluster_offset(bs, offset, 1, 0, offset_in_cluster,
60
+ offset_in_cluster + n, &cluster_offset);
61
if (ret < 0) {
62
break;
63
}
64
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
65
}
66
if (bs->encrypted) {
67
assert(s->crypto);
68
- if (qcrypto_block_encrypt(s->crypto, sector_num * BDRV_SECTOR_SIZE,
69
- buf, n * BDRV_SECTOR_SIZE, NULL) < 0) {
70
+ if (qcrypto_block_encrypt(s->crypto, offset, buf, n, NULL) < 0) {
71
ret = -EIO;
72
break;
73
}
74
}
75
76
hd_iov.iov_base = (void *)buf;
77
- hd_iov.iov_len = n * 512;
78
+ hd_iov.iov_len = n;
79
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
80
qemu_co_mutex_unlock(&s->lock);
81
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
82
- ret = bdrv_co_writev(bs->file,
83
- (cluster_offset >> 9) + index_in_cluster,
84
- n, &hd_qiov);
85
+ ret = bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster,
86
+ n, &hd_qiov, 0);
87
qemu_co_mutex_lock(&s->lock);
88
if (ret < 0) {
89
break;
90
}
91
ret = 0;
92
93
- nb_sectors -= n;
94
- sector_num += n;
95
- buf += n * 512;
96
+ bytes -= n;
97
+ offset += n;
98
+ buf += n;
99
}
100
qemu_co_mutex_unlock(&s->lock);
101
102
--
103
2.13.6
104
105
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. The qcow driver is now ready to fully utilize the
5
byte-based callback interface, as long as we override the default
6
alignment to still be 512 (needed at least for asserts present
7
because of encryption, but easier to do everywhere than to audit
8
which sub-sector requests are handled correctly, especially since
9
we no longer recommend qcow for new disk images).
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/qcow.c | 35 ++++++++++++++++++++---------------
16
1 file changed, 20 insertions(+), 15 deletions(-)
17
18
diff --git a/block/qcow.c b/block/qcow.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow.c
21
+++ b/block/qcow.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct QCowHeader {
23
typedef struct BDRVQcowState {
24
int cluster_bits;
25
int cluster_size;
26
- int cluster_sectors;
27
int l2_bits;
28
int l2_size;
29
unsigned int l1_size;
30
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
31
}
32
s->cluster_bits = header.cluster_bits;
33
s->cluster_size = 1 << s->cluster_bits;
34
- s->cluster_sectors = 1 << (s->cluster_bits - 9);
35
s->l2_bits = header.l2_bits;
36
s->l2_size = 1 << s->l2_bits;
37
bs->total_sectors = header.size / 512;
38
@@ -XXX,XX +XXX,XX @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
39
return 0;
40
}
41
42
-static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
43
- int nb_sectors, QEMUIOVector *qiov)
44
+static void qcow_refresh_limits(BlockDriverState *bs, Error **errp)
45
+{
46
+ /* At least encrypted images require 512-byte alignment. Apply the
47
+ * limit universally, rather than just on encrypted images, as
48
+ * it's easier to let the block layer handle rounding than to
49
+ * audit this code further. */
50
+ bs->bl.request_alignment = BDRV_SECTOR_SIZE;
51
+}
52
+
53
+static coroutine_fn int qcow_co_preadv(BlockDriverState *bs, uint64_t offset,
54
+ uint64_t bytes, QEMUIOVector *qiov,
55
+ int flags)
56
{
57
BDRVQcowState *s = bs->opaque;
58
int offset_in_cluster;
59
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
60
QEMUIOVector hd_qiov;
61
uint8_t *buf;
62
void *orig_buf;
63
- int64_t offset = sector_num * BDRV_SECTOR_SIZE;
64
- int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
65
66
+ assert(!flags);
67
if (qiov->niov > 1) {
68
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
69
if (buf == NULL) {
70
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
71
return ret;
72
}
73
74
-static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
75
- int nb_sectors, QEMUIOVector *qiov,
76
- int flags)
77
+static coroutine_fn int qcow_co_pwritev(BlockDriverState *bs, uint64_t offset,
78
+ uint64_t bytes, QEMUIOVector *qiov,
79
+ int flags)
80
{
81
BDRVQcowState *s = bs->opaque;
82
int offset_in_cluster;
83
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
84
QEMUIOVector hd_qiov;
85
uint8_t *buf;
86
void *orig_buf;
87
- int64_t offset = sector_num * BDRV_SECTOR_SIZE;
88
- int64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
89
90
assert(!flags);
91
s->cluster_cache_offset = -1; /* disable compressed cache */
92
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
93
94
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
95
/* could not compress: write normal cluster */
96
- ret = qcow_co_writev(bs, offset >> BDRV_SECTOR_BITS,
97
- bytes >> BDRV_SECTOR_BITS, qiov, 0);
98
+ ret = qcow_co_pwritev(bs, offset, bytes, qiov, 0);
99
if (ret < 0) {
100
goto fail;
101
}
102
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
103
.bdrv_co_create_opts = qcow_co_create_opts,
104
.bdrv_has_zero_init = bdrv_has_zero_init_1,
105
.supports_backing = true,
106
+ .bdrv_refresh_limits = qcow_refresh_limits,
107
108
- .bdrv_co_readv = qcow_co_readv,
109
- .bdrv_co_writev = qcow_co_writev,
110
+ .bdrv_co_preadv = qcow_co_preadv,
111
+ .bdrv_co_pwritev = qcow_co_pwritev,
112
.bdrv_co_block_status = qcow_co_block_status,
113
114
.bdrv_make_empty = qcow_make_empty,
115
--
116
2.13.6
117
118
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the last few sector-based calls
5
into the block layer from the replication driver.
6
7
Ideally, the replication driver should switch to doing everything
8
byte-based, but that's a more invasive change that requires a
9
bit more auditing.
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/replication.c | 14 ++++++++------
16
1 file changed, 8 insertions(+), 6 deletions(-)
17
18
diff --git a/block/replication.c b/block/replication.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/replication.c
21
+++ b/block/replication.c
22
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
23
backup_cow_request_begin(&req, child->bs->job,
24
sector_num * BDRV_SECTOR_SIZE,
25
remaining_bytes);
26
- ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors,
27
- qiov);
28
+ ret = bdrv_co_preadv(bs->file, sector_num * BDRV_SECTOR_SIZE,
29
+ remaining_bytes, qiov, 0);
30
backup_cow_request_end(&req);
31
goto out;
32
}
33
34
- ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors, qiov);
35
+ ret = bdrv_co_preadv(bs->file, sector_num * BDRV_SECTOR_SIZE,
36
+ remaining_sectors * BDRV_SECTOR_SIZE, qiov, 0);
37
out:
38
return replication_return_value(s, ret);
39
}
40
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
41
}
42
43
if (ret == 0) {
44
- ret = bdrv_co_writev(top, sector_num,
45
- remaining_sectors, qiov);
46
+ ret = bdrv_co_pwritev(top, sector_num * BDRV_SECTOR_SIZE,
47
+ remaining_sectors * BDRV_SECTOR_SIZE, qiov, 0);
48
return replication_return_value(s, ret);
49
}
50
51
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
52
qemu_iovec_concat(&hd_qiov, qiov, bytes_done, count);
53
54
target = ret ? top : base;
55
- ret = bdrv_co_writev(target, sector_num, n, &hd_qiov);
56
+ ret = bdrv_co_pwritev(target, sector_num * BDRV_SECTOR_SIZE,
57
+ n * BDRV_SECTOR_SIZE, &hd_qiov, 0);
58
if (ret < 0) {
59
goto out1;
60
}
61
--
62
2.13.6
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Make the change for the last few sector-based calls
5
into the block layer from the vhdx driver.
6
7
Ideally, the vhdx driver should switch to doing everything
8
byte-based, but that's a more invasive change that requires a
9
bit more auditing.
10
11
Signed-off-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/vhdx.c | 12 ++++++------
16
1 file changed, 6 insertions(+), 6 deletions(-)
17
18
diff --git a/block/vhdx.c b/block/vhdx.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/vhdx.c
21
+++ b/block/vhdx.c
22
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
23
break;
24
case PAYLOAD_BLOCK_FULLY_PRESENT:
25
qemu_co_mutex_unlock(&s->lock);
26
- ret = bdrv_co_readv(bs->file,
27
- sinfo.file_offset >> BDRV_SECTOR_BITS,
28
- sinfo.sectors_avail, &hd_qiov);
29
+ ret = bdrv_co_preadv(bs->file, sinfo.file_offset,
30
+ sinfo.sectors_avail * BDRV_SECTOR_SIZE,
31
+ &hd_qiov, 0);
32
qemu_co_mutex_lock(&s->lock);
33
if (ret < 0) {
34
goto exit;
35
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
36
}
37
/* block exists, so we can just overwrite it */
38
qemu_co_mutex_unlock(&s->lock);
39
- ret = bdrv_co_writev(bs->file,
40
- sinfo.file_offset >> BDRV_SECTOR_BITS,
41
- sectors_to_write, &hd_qiov);
42
+ ret = bdrv_co_pwritev(bs->file, sinfo.file_offset,
43
+ sectors_to_write * BDRV_SECTOR_SIZE,
44
+ &hd_qiov, 0);
45
qemu_co_mutex_lock(&s->lock);
46
if (ret < 0) {
47
goto error_bat_restore;
48
--
49
2.13.6
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Now that all callers of vectored I/O have been converted
5
to use our preferred byte-based bdrv_co_p{read,write}v(), we can
6
delete the unused bdrv_co_{read,write}v().
7
8
Furthermore, this gets rid of the signature difference between the
9
public bdrv_co_writev() and the callback .bdrv_co_writev (the
10
latter still exists, because some drivers still need more work
11
before they are fully byte-based).
12
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Reviewed-by: Jeff Cody <jcody@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
include/block/block.h | 4 ----
19
block/io.c | 36 ------------------------------------
20
2 files changed, 40 deletions(-)
21
22
diff --git a/include/block/block.h b/include/block/block.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/block/block.h
25
+++ b/include/block/block.h
26
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes);
27
int bdrv_pwritev(BdrvChild *child, int64_t offset, QEMUIOVector *qiov);
28
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
29
const void *buf, int count);
30
-int coroutine_fn bdrv_co_readv(BdrvChild *child, int64_t sector_num,
31
- int nb_sectors, QEMUIOVector *qiov);
32
-int coroutine_fn bdrv_co_writev(BdrvChild *child, int64_t sector_num,
33
- int nb_sectors, QEMUIOVector *qiov);
34
/*
35
* Efficiently zero a region of the disk image. Note that this is a regular
36
* I/O request like read or write and should have a reasonable size. This
37
diff --git a/block/io.c b/block/io.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block/io.c
40
+++ b/block/io.c
41
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
42
return ret;
43
}
44
45
-static int coroutine_fn bdrv_co_do_readv(BdrvChild *child,
46
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
47
- BdrvRequestFlags flags)
48
-{
49
- if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
50
- return -EINVAL;
51
- }
52
-
53
- return bdrv_co_preadv(child, sector_num << BDRV_SECTOR_BITS,
54
- nb_sectors << BDRV_SECTOR_BITS, qiov, flags);
55
-}
56
-
57
-int coroutine_fn bdrv_co_readv(BdrvChild *child, int64_t sector_num,
58
- int nb_sectors, QEMUIOVector *qiov)
59
-{
60
- return bdrv_co_do_readv(child, sector_num, nb_sectors, qiov, 0);
61
-}
62
-
63
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
64
int64_t offset, int bytes, BdrvRequestFlags flags)
65
{
66
@@ -XXX,XX +XXX,XX @@ out:
67
return ret;
68
}
69
70
-static int coroutine_fn bdrv_co_do_writev(BdrvChild *child,
71
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov,
72
- BdrvRequestFlags flags)
73
-{
74
- if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
75
- return -EINVAL;
76
- }
77
-
78
- return bdrv_co_pwritev(child, sector_num << BDRV_SECTOR_BITS,
79
- nb_sectors << BDRV_SECTOR_BITS, qiov, flags);
80
-}
81
-
82
-int coroutine_fn bdrv_co_writev(BdrvChild *child, int64_t sector_num,
83
- int nb_sectors, QEMUIOVector *qiov)
84
-{
85
- return bdrv_co_do_writev(child, sector_num, nb_sectors, qiov, 0);
86
-}
87
-
88
int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
89
int bytes, BdrvRequestFlags flags)
90
{
91
--
92
2.13.6
93
94
diff view generated by jsdifflib