1
The following changes since commit 013a18edbbc59cdad019100c7d03c0494642b74c:
1
The following changes since commit f1d33f55c47dfdaf8daacd618588ad3ae4c452d1:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200514' into staging (2020-05-14 16:17:55 +0100)
3
Merge tag 'pull-testing-gdbstub-plugins-gitdm-061022-3' of https://github.com/stsquad/qemu into staging (2022-10-06 07:11:56 -0400)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 7d8f21a650e562270f5ed5341134c9c2c39dc5e8:
9
for you to fetch changes up to a7ca2eb488ff149c898f43abe103f8bd8e3ca3c4:
10
10
11
iotests/030: Reduce run time by unthrottling job earlier (2020-05-15 14:12:34 +0200)
11
file-posix: Remove unused s->discard_zeroes (2022-10-07 12:11:41 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- Introduce real BdrvChildRole
16
- job: replace AioContext lock with job_mutex
17
- blk/bdrv_make_empty() functions instead of calling callbacks directly
17
- Fixes to make coroutine_fn annotations more accurate
18
- mirror: Make sure that source and target size match
18
- QAPI schema: Fix incorrect example
19
- block-copy: Fix uninitialized variable
19
- Code cleanup
20
- block/replication: Avoid cancelling the job twice
21
- ahci: Log lost IRQs
22
- iotests: Run pylint and mypy in a testcase
23
- iotests: log messages from notrun()
24
20
25
----------------------------------------------------------------
21
----------------------------------------------------------------
26
John Snow (1):
22
Alberto Faria (1):
27
iotests: log messages from notrun()
23
coroutine: Drop coroutine_fn annotation from qemu_coroutine_self()
28
24
29
Kevin Wolf (8):
25
Emanuele Giuseppe Esposito (20):
30
iotests/109: Don't mirror with mismatched size
26
job.c: make job_mutex and job_lock/unlock() public
31
iotests/229: Use blkdebug to inject an error
27
job.h: categorize fields in struct Job
32
mirror: Make sure that source and target size match
28
job.c: API functions not used outside should be static
33
iotests: Mirror with different source/target size
29
aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED
34
iotests: Fix incomplete type declarations
30
job.c: add job_lock/unlock while keeping job.h intact
35
iotests: Run pylint and mypy in a testcase
31
job: move and update comments from blockjob.c
36
replication: Avoid blk_make_empty() on read-only child
32
blockjob: introduce block_job _locked() APIs
37
iotests/030: Reduce run time by unthrottling job earlier
33
jobs: add job lock in find_* functions
34
jobs: use job locks also in the unit tests
35
block/mirror.c: use of job helpers in drivers
36
jobs: group together API calls under the same job lock
37
jobs: protect job.aio_context with BQL and job_mutex
38
blockjob.h: categorize fields in struct BlockJob
39
blockjob: rename notifier callbacks as _locked
40
blockjob: protect iostatus field in BlockJob struct
41
job.h: categorize JobDriver callbacks that need the AioContext lock
42
job.c: enable job lock/unlock and remove Aiocontext locks
43
block_job_query: remove atomic read
44
blockjob: remove unused functions
45
job: remove unused functions
38
46
39
Lukas Straub (1):
47
Kevin Wolf (2):
40
block/replication.c: Avoid cancelling the job twice
48
quorum: Remove unnecessary forward declaration
49
file-posix: Remove unused s->discard_zeroes
41
50
42
Max Reitz (38):
51
Marc-André Lureau (3):
43
block: Add bdrv_make_empty()
52
9p: add missing coroutine_fn annotations
44
block: Add blk_make_empty()
53
migration: add missing coroutine_fn annotations
45
block: Use blk_make_empty() after commits
54
test-coroutine: add missing coroutine_fn annotations
46
block: Use bdrv_make_empty() where possible
47
block: Mark commit, mirror, blkreplay as filters
48
block: Add BlockDriver.is_format
49
block: Rename BdrvChildRole to BdrvChildClass
50
block: Add BdrvChildRole and BdrvChildRoleBits
51
block: Add BdrvChildRole to BdrvChild
52
block: Pass BdrvChildRole to bdrv_child_perm()
53
block: Pass BdrvChildRole to .inherit_options()
54
block: Pass parent_is_format to .inherit_options()
55
block: Rename bdrv_inherited_options()
56
block: Add generic bdrv_inherited_options()
57
block: Use bdrv_inherited_options()
58
block: Unify bdrv_child_cb_attach()
59
block: Unify bdrv_child_cb_detach()
60
block: Add child_of_bds
61
block: Distinguish paths in *_format_default_perms
62
block: Pull out bdrv_default_perms_for_cow()
63
block: Pull out bdrv_default_perms_for_storage()
64
block: Relax *perms_for_storage for data children
65
block: Add bdrv_default_perms()
66
raw-format: Split raw_read_options()
67
block: Switch child_format users to child_of_bds
68
block: Drop child_format
69
block: Make backing files child_of_bds children
70
block: Drop child_backing
71
block: Make format drivers use child_of_bds
72
block: Make filter drivers use child_of_bds
73
block: Use child_of_bds in remaining places
74
tests: Use child_of_bds instead of child_file
75
block: Use bdrv_default_perms()
76
block: Make bdrv_filter_default_perms() static
77
block: Drop bdrv_format_default_perms()
78
block: Drop child_file
79
block: Pass BdrvChildRole in remaining cases
80
block: Drop @child_class from bdrv_child_perm()
81
55
82
Philippe Mathieu-Daudé (3):
56
Markus Armbruster (1):
83
block/block-copy: Fix uninitialized variable in block_copy_task_entry
57
Revert "qapi: fix examples of blockdev-add with qcow2"
84
block/block-copy: Simplify block_copy_do_copy()
85
hw/ide/ahci: Log lost IRQs
86
58
87
include/block/block.h | 65 ++++-
59
Paolo Bonzini (23):
88
include/block/block_int.h | 57 ++--
60
block/nvme: separate nvme_get_free_req cases for coroutine/non-coroutine context
89
include/sysemu/block-backend.h | 2 +
61
block: add missing coroutine_fn annotations
90
block.c | 601 ++++++++++++++++++++++++---------------
62
qcow2: remove incorrect coroutine_fn annotations
91
block/backup-top.c | 11 +-
63
nbd: remove incorrect coroutine_fn annotations
92
block/blkdebug.c | 10 +-
64
coroutine: remove incorrect coroutine_fn annotations
93
block/blklogwrites.c | 16 +-
65
blkverify: add missing coroutine_fn annotations
94
block/blkreplay.c | 8 +-
66
file-posix: add missing coroutine_fn annotations
95
block/blkverify.c | 10 +-
67
iscsi: add missing coroutine_fn annotations
96
block/block-backend.c | 30 +-
68
nbd: add missing coroutine_fn annotations
97
block/block-copy.c | 14 +-
69
nfs: add missing coroutine_fn annotations
98
block/bochs.c | 7 +-
70
nvme: add missing coroutine_fn annotations
99
block/cloop.c | 7 +-
71
parallels: add missing coroutine_fn annotations
100
block/commit.c | 20 +-
72
qcow2: add missing coroutine_fn annotations
101
block/copy-on-read.c | 7 +-
73
copy-before-write: add missing coroutine_fn annotations
102
block/crypto.c | 8 +-
74
curl: add missing coroutine_fn annotations
103
block/dmg.c | 7 +-
75
qed: add missing coroutine_fn annotations
104
block/filter-compress.c | 7 +-
76
quorum: add missing coroutine_fn annotations
77
throttle: add missing coroutine_fn annotations
78
vmdk: add missing coroutine_fn annotations
79
job: add missing coroutine_fn annotations
80
coroutine-lock: add missing coroutine_fn annotations
81
raw-format: add missing coroutine_fn annotations
82
job: detect change of aiocontext within job coroutine
83
84
qapi/block-core.json | 10 +-
85
block/qcow2.h | 19 +-
86
hw/9pfs/9p.h | 9 +-
87
include/block/aio-wait.h | 17 +-
88
include/block/blockjob.h | 59 +++-
89
include/block/nbd.h | 2 +-
90
include/qemu/coroutine.h | 4 +-
91
include/qemu/job.h | 306 +++++++++++++-----
92
block.c | 24 +-
93
block/blkverify.c | 2 +-
94
block/block-backend.c | 10 +-
95
block/copy-before-write.c | 9 +-
96
block/curl.c | 2 +-
97
block/file-posix.c | 11 +-
105
block/io.c | 22 +-
98
block/io.c | 22 +-
106
block/mirror.c | 25 +-
99
block/iscsi.c | 3 +-
107
block/parallels.c | 7 +-
100
block/mirror.c | 19 +-
108
block/qcow.c | 7 +-
101
block/nbd.c | 11 +-
109
block/qcow2.c | 20 +-
102
block/nfs.c | 2 +-
110
block/qed.c | 7 +-
103
block/nvme.c | 54 ++--
111
block/quorum.c | 8 +-
104
block/parallels.c | 5 +-
112
block/raw-format.c | 128 +++++----
105
block/qcow2-cluster.c | 21 +-
113
block/replication.c | 23 +-
106
block/qcow2-refcount.c | 6 +-
114
block/throttle.c | 7 +-
107
block/qcow2.c | 5 +-
115
block/vdi.c | 7 +-
108
block/qed.c | 4 +-
116
block/vhdx.c | 7 +-
109
block/quorum.c | 38 +--
117
block/vmdk.c | 23 +-
110
block/raw-format.c | 3 +-
118
block/vpc.c | 7 +-
111
block/replication.c | 3 +
119
block/vvfat.c | 17 +-
112
block/throttle.c | 2 +-
120
blockjob.c | 7 +-
113
block/vmdk.c | 22 +-
121
hw/ide/ahci.c | 1 +
114
blockdev.c | 129 ++++----
122
qemu-img.c | 19 +-
115
blockjob.c | 132 ++++----
123
tests/test-bdrv-drain.c | 72 +++--
116
job-qmp.c | 92 +++---
124
tests/test-bdrv-graph-mod.c | 10 +-
117
job.c | 674 +++++++++++++++++++++++++--------------
125
tests/test-block-iothread.c | 17 +-
118
migration/migration.c | 3 +-
126
tests/qemu-iotests/iotests.py | 19 +-
119
monitor/qmp-cmds.c | 7 +-
127
tests/qemu-iotests/030 | 6 +-
120
qemu-img.c | 17 +-
128
tests/qemu-iotests/041 | 45 +++
121
tests/unit/test-bdrv-drain.c | 80 +++--
129
tests/qemu-iotests/041.out | 4 +-
122
tests/unit/test-block-iothread.c | 8 +-
130
tests/qemu-iotests/098.out | 8 +-
123
tests/unit/test-blockjob-txn.c | 24 +-
131
tests/qemu-iotests/109 | 10 +-
124
tests/unit/test-blockjob.c | 136 ++++----
132
tests/qemu-iotests/109.out | 74 ++---
125
tests/unit/test-coroutine.c | 2 +-
133
tests/qemu-iotests/229 | 15 +-
126
util/qemu-coroutine-lock.c | 14 +-
134
tests/qemu-iotests/229.out | 6 +-
127
util/qemu-coroutine.c | 2 +-
135
tests/qemu-iotests/297 | 44 +++
128
44 files changed, 1237 insertions(+), 787 deletions(-)
136
tests/qemu-iotests/297.out | 3 +
137
tests/qemu-iotests/common.filter | 5 +
138
tests/qemu-iotests/group | 1 +
139
52 files changed, 995 insertions(+), 573 deletions(-)
140
create mode 100755 tests/qemu-iotests/297
141
create mode 100644 tests/qemu-iotests/297.out
142
129
143
130
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Markus Armbruster <armbru@redhat.com>
2
2
3
Shift the logging initialization up to occur prior to validation checks,
3
This reverts commit b6522938327141235b97ab38e40c6c4512587373.
4
so that notrun() messages still get printed to console.
5
4
6
(Also, remove the "debugging messages active" message, because we don't
5
Kevin Wolf NAKed this patch, because:
7
need to see that hundreds of times per iotest suite run.)
8
6
9
Signed-off-by: John Snow <jsnow@redhat.com>
7
'file' is a required member (defined in BlockdevOptionsGenericFormat),
10
Message-Id: <20200514201614.19941-2-jsnow@redhat.com>
8
removing it makes the example invalid. 'data-file' is only an additional
9
optional member to be used for external data files (i.e. when the guest
10
data is kept separate from the metadata in the .qcow2 file).
11
12
However, it had already been merged then. Revert.
13
14
Signed-off-by: Markus Armbruster <armbru@redhat.com>
15
Message-Id: <20220930171908.846769-1-armbru@redhat.com>
16
Reviewed-by: Victor Toso <victortoso@redhat.com>
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
19
---
13
tests/qemu-iotests/iotests.py | 11 +++++------
20
qapi/block-core.json | 10 +++++-----
14
1 file changed, 5 insertions(+), 6 deletions(-)
21
1 file changed, 5 insertions(+), 5 deletions(-)
15
22
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
23
diff --git a/qapi/block-core.json b/qapi/block-core.json
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
25
--- a/qapi/block-core.json
19
+++ b/tests/qemu-iotests/iotests.py
26
+++ b/qapi/block-core.json
20
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
27
@@ -XXX,XX +XXX,XX @@
21
sys.stderr.write('Please run this test via the "check" script\n')
28
# -> { "execute": "blockdev-add",
22
sys.exit(os.EX_USAGE)
29
# "arguments": { "driver": "qcow2",
23
30
# "node-name": "node1534",
24
+ debug = '-d' in sys.argv
31
-# "data-file": { "driver": "file",
25
+ if debug:
32
-# "filename": "hd1.qcow2" },
26
+ sys.argv.remove('-d')
33
+# "file": { "driver": "file",
27
+ logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
34
+# "filename": "hd1.qcow2" },
28
+
35
# "backing": null } }
29
_verify_image_format(supported_fmts, unsupported_fmts)
36
#
30
_verify_protocol(supported_protocols, unsupported_protocols)
37
# <- { "return": {} }
31
_verify_platform(supported=supported_platforms)
38
@@ -XXX,XX +XXX,XX @@
32
_verify_cache_mode(supported_cache_modes)
39
# "arguments": {
33
_verify_aio_mode(supported_aio_modes)
40
# "driver": "qcow2",
34
41
# "node-name": "test1",
35
- debug = '-d' in sys.argv
42
-# "data-file": {
36
- if debug:
43
+# "file": {
37
- sys.argv.remove('-d')
44
# "driver": "file",
38
- logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
45
# "filename": "test.qcow2"
39
- logger.debug("iotests debugging messages active")
46
# }
40
-
47
@@ -XXX,XX +XXX,XX @@
41
return debug
48
# "cache": {
42
49
# "direct": true
43
def execute_test(*args, test_function=None, **kwargs):
50
# },
51
-# "data-file": {
52
+# "file": {
53
# "driver": "file",
54
# "filename": "/tmp/test.qcow2"
55
# },
56
@@ -XXX,XX +XXX,XX @@
57
# "arguments": {
58
# "driver": "qcow2",
59
# "node-name": "node0",
60
-# "data-file": {
61
+# "file": {
62
# "driver": "file",
63
# "filename": "test.qcow2"
64
# }
44
--
65
--
45
2.25.4
66
2.37.3
46
47
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
These calls have no real use for the child role yet, but it will not
3
qemu_coroutine_self() can be called from outside coroutine context,
4
harm to give one.
4
returning the leader coroutine, and several such invocations currently
5
exist (mostly in qcow2 tracing calls).
5
6
6
Notably, the bdrv_root_attach_child() call in blockjob.c is left
7
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
unmodified because there is not much the generic BlockJob object wants
8
Message-Id: <20221005175209.975797-1-afaria@redhat.com>
8
from its children.
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
10
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20200513110544.176672-34-mreitz@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
12
---
15
block/block-backend.c | 11 +++++++----
13
include/qemu/coroutine.h | 2 +-
16
block/vvfat.c | 4 +++-
14
1 file changed, 1 insertion(+), 1 deletion(-)
17
2 files changed, 10 insertions(+), 5 deletions(-)
18
15
19
diff --git a/block/block-backend.c b/block/block-backend.c
16
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/block/block-backend.c
18
--- a/include/qemu/coroutine.h
22
+++ b/block/block-backend.c
19
+++ b/include/qemu/coroutine.h
23
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
20
@@ -XXX,XX +XXX,XX @@ AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co);
24
return NULL;
21
/**
25
}
22
* Get the currently executing coroutine
26
23
*/
27
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
24
-Coroutine *coroutine_fn qemu_coroutine_self(void);
28
- perm, BLK_PERM_ALL, blk, errp);
25
+Coroutine *qemu_coroutine_self(void);
29
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root,
26
30
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
27
/**
31
+ blk->ctx, perm, BLK_PERM_ALL, blk, errp);
28
* Return whether or not currently inside a coroutine
32
if (!blk->root) {
33
blk_unref(blk);
34
return NULL;
35
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
36
{
37
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
38
bdrv_ref(bs);
39
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
40
- blk->perm, blk->shared_perm, blk, errp);
41
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root,
42
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
43
+ blk->ctx, blk->perm, blk->shared_perm,
44
+ blk, errp);
45
if (blk->root == NULL) {
46
return -EPERM;
47
}
48
diff --git a/block/vvfat.c b/block/vvfat.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/vvfat.c
51
+++ b/block/vvfat.c
52
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
53
options = qdict_new();
54
qdict_put_str(options, "write-target.driver", "qcow");
55
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
56
- &child_vvfat_qcow, 0, false, errp);
57
+ &child_vvfat_qcow,
58
+ BDRV_CHILD_DATA | BDRV_CHILD_METADATA,
59
+ false, errp);
60
qobject_unref(options);
61
if (!s->qcow) {
62
ret = -EINVAL;
63
--
29
--
64
2.25.4
30
2.37.3
65
66
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Replace child_file by child_of_bds in all remaining places (excluding
3
nvme_get_free_req has very difference semantics when called in
4
tests).
4
coroutine context (where it waits) and in non-coroutine context
5
(where it doesn't). Split the two cases to make it clear what
6
is being requested.
5
7
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Cc: qemu-block@nongnu.org
7
Message-Id: <20200513110544.176672-28-mreitz@redhat.com>
9
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Message-Id: <20220922084924.201610-2-pbonzini@redhat.com>
12
[kwolf: Fixed up coding style]
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
block.c | 3 ++-
16
block/nvme.c | 48 ++++++++++++++++++++++++++++--------------------
12
block/backup-top.c | 4 ++--
17
1 file changed, 28 insertions(+), 20 deletions(-)
13
block/blklogwrites.c | 4 ++--
14
block/raw-format.c | 15 +++++++++++++--
15
4 files changed, 19 insertions(+), 7 deletions(-)
16
18
17
diff --git a/block.c b/block.c
19
diff --git a/block/nvme.c b/block/nvme.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
21
--- a/block/nvme.c
20
+++ b/block.c
22
+++ b/block/nvme.c
21
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
23
@@ -XXX,XX +XXX,XX @@ static void nvme_kick(NVMeQueuePair *q)
22
BlockDriverState *file_bs;
24
q->need_kick = 0;
23
25
}
24
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
26
25
- &child_file, 0, true, &local_err);
27
-/* Find a free request element if any, otherwise:
26
+ &child_of_bds, BDRV_CHILD_IMAGE,
28
- * a) if in coroutine context, try to wait for one to become available;
27
+ true, &local_err);
29
- * b) if not in coroutine, return NULL;
28
if (local_err) {
30
- */
29
goto fail;
31
-static NVMeRequest *nvme_get_free_req(NVMeQueuePair *q)
30
}
32
+static NVMeRequest *nvme_get_free_req_nofail_locked(NVMeQueuePair *q)
31
diff --git a/block/backup-top.c b/block/backup-top.c
33
{
32
index XXXXXXX..XXXXXXX 100644
34
NVMeRequest *req;
33
--- a/block/backup-top.c
35
34
+++ b/block/backup-top.c
36
- qemu_mutex_lock(&q->lock);
35
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
37
-
36
source->supported_zero_flags);
38
- while (q->free_req_head == -1) {
37
39
- if (qemu_in_coroutine()) {
38
bdrv_ref(target);
40
- trace_nvme_free_req_queue_wait(q->s, q->index);
39
- state->target = bdrv_attach_child(top, target, "target", &child_file, 0,
41
- qemu_co_queue_wait(&q->free_req_queue, &q->lock);
40
- errp);
42
- } else {
41
+ state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
43
- qemu_mutex_unlock(&q->lock);
42
+ BDRV_CHILD_DATA, errp);
44
- return NULL;
43
if (!state->target) {
45
- }
44
bdrv_unref(target);
46
- }
45
bdrv_unref(top);
47
-
46
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
48
req = &q->reqs[q->free_req_head];
47
index XXXXXXX..XXXXXXX 100644
49
q->free_req_head = req->free_req_next;
48
--- a/block/blklogwrites.c
50
req->free_req_next = -1;
49
+++ b/block/blklogwrites.c
51
-
50
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
52
- qemu_mutex_unlock(&q->lock);
51
}
53
return req;
52
54
}
53
/* Open the log file */
55
54
- s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, 0,
56
+/* Return a free request element if any, otherwise return NULL. */
55
- false, &local_err);
57
+static NVMeRequest *nvme_get_free_req_nowait(NVMeQueuePair *q)
56
+ s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_of_bds,
58
+{
57
+ BDRV_CHILD_METADATA, false, &local_err);
59
+ QEMU_LOCK_GUARD(&q->lock);
58
if (local_err) {
60
+ if (q->free_req_head == -1) {
59
ret = -EINVAL;
61
+ return NULL;
60
error_propagate(errp, local_err);
62
+ }
61
diff --git a/block/raw-format.c b/block/raw-format.c
63
+ return nvme_get_free_req_nofail_locked(q);
62
index XXXXXXX..XXXXXXX 100644
64
+}
63
--- a/block/raw-format.c
65
+
64
+++ b/block/raw-format.c
66
+/*
65
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
67
+ * Wait for a free request to become available if necessary, then
66
BDRVRawState *s = bs->opaque;
68
+ * return it.
67
bool has_size;
69
+ */
68
uint64_t offset, size;
70
+static coroutine_fn NVMeRequest *nvme_get_free_req(NVMeQueuePair *q)
69
+ BdrvChildRole file_role;
71
+{
70
int ret;
72
+ QEMU_LOCK_GUARD(&q->lock);
71
73
+
72
ret = raw_read_options(options, &offset, &has_size, &size, errp);
74
+ while (q->free_req_head == -1) {
73
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
75
+ trace_nvme_free_req_queue_wait(q->s, q->index);
74
return ret;
76
+ qemu_co_queue_wait(&q->free_req_queue, &q->lock);
75
}
76
77
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
78
- false, errp);
79
+ /*
80
+ * Without offset and a size limit, this driver behaves very much
81
+ * like a filter. With any such limit, it does not.
82
+ */
83
+ if (offset || has_size) {
84
+ file_role = BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY;
85
+ } else {
86
+ file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
87
+ }
77
+ }
88
+
78
+
89
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
79
+ return nvme_get_free_req_nofail_locked(q);
90
+ file_role, false, errp);
80
+}
91
if (!bs->file) {
81
+
92
return -EINVAL;
82
/* With q->lock */
83
static void nvme_put_free_req_locked(NVMeQueuePair *q, NVMeRequest *req)
84
{
85
@@ -XXX,XX +XXX,XX @@ static int nvme_admin_cmd_sync(BlockDriverState *bs, NvmeCmd *cmd)
86
AioContext *aio_context = bdrv_get_aio_context(bs);
87
NVMeRequest *req;
88
int ret = -EINPROGRESS;
89
- req = nvme_get_free_req(q);
90
+ req = nvme_get_free_req_nowait(q);
91
if (!req) {
92
return -EBUSY;
93
}
93
}
94
--
94
--
95
2.25.4
95
2.37.3
96
97
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Make bdrv_child_cb_detach() call bdrv_backing_detach() for children with
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
a COW role (and drop the reverse call from bdrv_backing_detach()), so it
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
can be used for any child (with a proper role set).
5
functions where this holds.
6
6
7
Because so far no child has a proper role set, we need a temporary new
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
callback for child_backing.detach that ensures bdrv_backing_detach() is
8
Message-Id: <20220922084924.201610-3-pbonzini@redhat.com>
9
called for all COW children that do not have their role set yet.
9
[kwolf: Fixed up coding style]
10
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
(Also, move bdrv_child_cb_detach() down to group it with
12
bdrv_inherited_options() and bdrv_child_cb_attach().)
13
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <20200513110544.176672-14-mreitz@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
12
---
19
block.c | 27 ++++++++++++++++++++-------
13
block.c | 7 ++++---
20
1 file changed, 20 insertions(+), 7 deletions(-)
14
block/block-backend.c | 10 +++++-----
15
block/io.c | 22 +++++++++++-----------
16
3 files changed, 20 insertions(+), 19 deletions(-)
21
17
22
diff --git a/block.c b/block.c
18
diff --git a/block.c b/block.c
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/block.c
20
--- a/block.c
25
+++ b/block.c
21
+++ b/block.c
26
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
22
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
27
int *child_flags, QDict *child_options,
23
* Helper function for bdrv_create_file_fallback(): Zero the first
28
int parent_flags, QDict *parent_options);
24
* sector to remove any potentially pre-existing image header.
29
static void bdrv_child_cb_attach(BdrvChild *child);
25
*/
30
+static void bdrv_child_cb_detach(BdrvChild *child);
26
-static int create_file_fallback_zero_first_sector(BlockBackend *blk,
31
27
- int64_t current_size,
32
/* If non-zero, use only whitelisted block drivers */
28
- Error **errp)
33
static int use_bdrv_whitelist;
29
+static int coroutine_fn
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_drained_end(BdrvChild *child,
30
+create_file_fallback_zero_first_sector(BlockBackend *blk,
35
bdrv_drained_end_no_poll(bs, drained_end_counter);
31
+ int64_t current_size,
32
+ Error **errp)
33
{
34
int64_t bytes_to_clear;
35
int ret;
36
diff --git a/block/block-backend.c b/block/block-backend.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/block-backend.c
39
+++ b/block/block-backend.c
40
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
41
return &acb->common;
36
}
42
}
37
43
38
-static void bdrv_child_cb_detach(BdrvChild *child)
44
-static void blk_aio_read_entry(void *opaque)
39
-{
45
+static void coroutine_fn blk_aio_read_entry(void *opaque)
40
- BlockDriverState *bs = child->opaque;
41
- bdrv_unapply_subtree_drain(child, bs);
42
-}
43
-
44
static int bdrv_child_cb_inactivate(BdrvChild *child)
45
{
46
{
46
BlockDriverState *bs = child->opaque;
47
BlkAioEmAIOCB *acb = opaque;
47
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
48
BlkRwCo *rwco = &acb->rwco;
48
bdrv_op_unblock_all(c->bs, parent->backing_blocker);
49
@@ -XXX,XX +XXX,XX @@ static void blk_aio_read_entry(void *opaque)
49
error_free(parent->backing_blocker);
50
blk_aio_complete(acb);
50
parent->backing_blocker = NULL;
51
+}
52
53
+/* XXX: Will be removed along with child_backing */
54
+static void bdrv_child_cb_detach_backing(BdrvChild *c)
55
+{
56
+ if (!(c->role & BDRV_CHILD_COW)) {
57
+ bdrv_backing_detach(c);
58
+ }
59
bdrv_child_cb_detach(c);
60
}
51
}
61
52
62
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_backing = {
53
-static void blk_aio_write_entry(void *opaque)
63
.parent_is_bds = true,
54
+static void coroutine_fn blk_aio_write_entry(void *opaque)
64
.get_parent_desc = bdrv_child_get_parent_desc,
55
{
65
.attach = bdrv_child_cb_attach_backing,
56
BlkAioEmAIOCB *acb = opaque;
66
- .detach = bdrv_backing_detach,
57
BlkRwCo *rwco = &acb->rwco;
67
+ .detach = bdrv_child_cb_detach_backing,
58
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
68
.inherit_options = bdrv_backing_options,
59
return ret;
69
.drained_begin = bdrv_child_cb_drained_begin,
70
.drained_poll = bdrv_child_cb_drained_poll,
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_attach(BdrvChild *child)
72
bdrv_apply_subtree_drain(child, bs);
73
}
60
}
74
61
75
+static void bdrv_child_cb_detach(BdrvChild *child)
62
-static void blk_aio_ioctl_entry(void *opaque)
76
+{
63
+static void coroutine_fn blk_aio_ioctl_entry(void *opaque)
77
+ BlockDriverState *bs = child->opaque;
78
+
79
+ if (child->role & BDRV_CHILD_COW) {
80
+ bdrv_backing_detach(child);
81
+ }
82
+
83
+ bdrv_unapply_subtree_drain(child, bs);
84
+}
85
+
86
static int bdrv_open_flags(BlockDriverState *bs, int flags)
87
{
64
{
88
int open_flags = flags;
65
BlkAioEmAIOCB *acb = opaque;
66
BlkRwCo *rwco = &acb->rwco;
67
@@ -XXX,XX +XXX,XX @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
68
return bdrv_co_pdiscard(blk->root, offset, bytes);
69
}
70
71
-static void blk_aio_pdiscard_entry(void *opaque)
72
+static void coroutine_fn blk_aio_pdiscard_entry(void *opaque)
73
{
74
BlkAioEmAIOCB *acb = opaque;
75
BlkRwCo *rwco = &acb->rwco;
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
77
return bdrv_co_flush(blk_bs(blk));
78
}
79
80
-static void blk_aio_flush_entry(void *opaque)
81
+static void coroutine_fn blk_aio_flush_entry(void *opaque)
82
{
83
BlkAioEmAIOCB *acb = opaque;
84
BlkRwCo *rwco = &acb->rwco;
85
diff --git a/block/io.c b/block/io.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/block/io.c
88
+++ b/block/io.c
89
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn tracked_request_end(BdrvTrackedRequest *req)
90
/**
91
* Add an active request to the tracked requests list
92
*/
93
-static void tracked_request_begin(BdrvTrackedRequest *req,
94
- BlockDriverState *bs,
95
- int64_t offset,
96
- int64_t bytes,
97
- enum BdrvTrackedRequestType type)
98
+static void coroutine_fn tracked_request_begin(BdrvTrackedRequest *req,
99
+ BlockDriverState *bs,
100
+ int64_t offset,
101
+ int64_t bytes,
102
+ enum BdrvTrackedRequestType type)
103
{
104
bdrv_check_request(offset, bytes, &error_abort);
105
106
@@ -XXX,XX +XXX,XX @@ static bool tracked_request_overlaps(BdrvTrackedRequest *req,
107
}
108
109
/* Called with self->bs->reqs_lock held */
110
-static BdrvTrackedRequest *
111
+static coroutine_fn BdrvTrackedRequest *
112
bdrv_find_conflicting_request(BdrvTrackedRequest *self)
113
{
114
BdrvTrackedRequest *req;
115
@@ -XXX,XX +XXX,XX @@ static bool bdrv_init_padding(BlockDriverState *bs,
116
return true;
117
}
118
119
-static int bdrv_padding_rmw_read(BdrvChild *child,
120
- BdrvTrackedRequest *req,
121
- BdrvRequestPadding *pad,
122
- bool zero_middle)
123
+static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
124
+ BdrvTrackedRequest *req,
125
+ BdrvRequestPadding *pad,
126
+ bool zero_middle)
127
{
128
QEMUIOVector local_qiov;
129
BlockDriverState *bs = child->bs;
130
@@ -XXX,XX +XXX,XX @@ out:
131
return ret;
132
}
133
134
-int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
135
+int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
136
{
137
BlockDriver *drv = bs->drv;
138
CoroutineIOCompletion co = {
89
--
139
--
90
2.25.4
140
2.37.3
91
92
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We can be less restrictive about pure data children than those with
3
This is incorrect because qcow2_mark_clean() calls qcow2_flush_caches().
4
metadata on them, so let bdrv_default_perms_for_storage() handle
4
qcow2_mark_clean() is called from non-coroutine context in
5
metadata children differently from pure data children.
5
qcow2_inactivate() and qcow2_amend_options().
6
6
7
As explained in the code, the restrictions on metadata children are
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
strictly stricter than those for pure data children, so in theory we
9
just have to distinguish between pure-data and all other storage
10
children (pure metadata or data+metadata). In practice, that is not
11
obvious, though, so we have two independent code paths for metadata and
12
for data children, and data+metadata children will go through both
13
(without the path for data children doing anything meaningful).
14
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Message-Id: <20200513110544.176672-19-mreitz@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-4-pbonzini@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
13
---
20
block.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++----------
14
block/qcow2.h | 4 ++--
21
1 file changed, 48 insertions(+), 10 deletions(-)
15
block/qcow2-refcount.c | 4 ++--
16
2 files changed, 4 insertions(+), 4 deletions(-)
22
17
23
diff --git a/block.c b/block.c
18
diff --git a/block/qcow2.h b/block/qcow2.h
24
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
20
--- a/block/qcow2.h
26
+++ b/block.c
21
+++ b/block/qcow2.h
27
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
22
@@ -XXX,XX +XXX,XX @@ void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
28
bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
23
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
29
perm, shared, &perm, &shared);
24
int64_t l1_table_offset, int l1_size, int addend);
30
25
31
- /* Format drivers may touch metadata even if the guest doesn't write */
26
-int coroutine_fn qcow2_flush_caches(BlockDriverState *bs);
32
- if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
27
-int coroutine_fn qcow2_write_caches(BlockDriverState *bs);
33
- perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
28
+int qcow2_flush_caches(BlockDriverState *bs);
34
+ if (role & BDRV_CHILD_METADATA) {
29
+int qcow2_write_caches(BlockDriverState *bs);
35
+ /* Format drivers may touch metadata even if the guest doesn't write */
30
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
36
+ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
31
BdrvCheckMode fix);
37
+ perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
32
38
+ }
33
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
39
+
34
index XXXXXXX..XXXXXXX 100644
40
+ /*
35
--- a/block/qcow2-refcount.c
41
+ * bs->file always needs to be consistent because of the
36
+++ b/block/qcow2-refcount.c
42
+ * metadata. We can never allow other users to resize or write
37
@@ -XXX,XX +XXX,XX @@ void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
43
+ * to it.
44
+ */
45
+ if (!(flags & BDRV_O_NO_IO)) {
46
+ perm |= BLK_PERM_CONSISTENT_READ;
47
+ }
48
+ shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
49
}
38
}
50
39
}
51
- /*
40
52
- * bs->file always needs to be consistent because of the metadata. We
41
-int coroutine_fn qcow2_write_caches(BlockDriverState *bs)
53
- * can never allow other users to resize or write to it.
42
+int qcow2_write_caches(BlockDriverState *bs)
54
- */
43
{
55
- if (!(flags & BDRV_O_NO_IO)) {
44
BDRVQcow2State *s = bs->opaque;
56
- perm |= BLK_PERM_CONSISTENT_READ;
45
int ret;
57
+ if (role & BDRV_CHILD_DATA) {
46
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_write_caches(BlockDriverState *bs)
58
+ /*
47
return 0;
59
+ * Technically, everything in this block is a subset of the
48
}
60
+ * BDRV_CHILD_METADATA path taken above, and so this could
49
61
+ * be an "else if" branch. However, that is not obvious, and
50
-int coroutine_fn qcow2_flush_caches(BlockDriverState *bs)
62
+ * this function is not performance critical, therefore we let
51
+int qcow2_flush_caches(BlockDriverState *bs)
63
+ * this be an independent "if".
52
{
64
+ */
53
int ret = qcow2_write_caches(bs);
65
+
54
if (ret < 0) {
66
+ /*
67
+ * We cannot allow other users to resize the file because the
68
+ * format driver might have some assumptions about the size
69
+ * (e.g. because it is stored in metadata, or because the file
70
+ * is split into fixed-size data files).
71
+ */
72
+ shared &= ~BLK_PERM_RESIZE;
73
+
74
+ /*
75
+ * WRITE_UNCHANGED often cannot be performed as such on the
76
+ * data file. For example, the qcow2 driver may still need to
77
+ * write copied clusters on copy-on-read.
78
+ */
79
+ if (perm & BLK_PERM_WRITE_UNCHANGED) {
80
+ perm |= BLK_PERM_WRITE;
81
+ }
82
+
83
+ /*
84
+ * If the data file is written to, the format driver may
85
+ * expect to be able to resize it by writing beyond the EOF.
86
+ */
87
+ if (perm & BLK_PERM_WRITE) {
88
+ perm |= BLK_PERM_RESIZE;
89
+ }
90
}
91
- shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
92
93
if (bs->open_flags & BDRV_O_INACTIVE) {
94
shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
95
--
55
--
96
2.25.4
56
2.37.3
97
98
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Fix when building with -Os:
3
nbd_co_establish_connection_cancel() cancels a coroutine but is not called
4
from coroutine context itself, for example in nbd_cancel_in_flight()
5
and in timer callbacks reconnect_delay_timer_cb() and open_timer_cb().
4
6
5
CC block/block-copy.o
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
6
block/block-copy.c: In function ‘block_copy_task_entry’:
7
block/block-copy.c:428:38: error: ‘error_is_read’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
8
428 | t->call_state->error_is_read = error_is_read;
9
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
10
11
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Message-Id: <20200507121129.29760-2-philmd@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-5-pbonzini@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
13
---
16
block/block-copy.c | 2 +-
14
include/block/nbd.h | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
18
16
19
diff --git a/block/block-copy.c b/block/block-copy.c
17
diff --git a/include/block/nbd.h b/include/block/nbd.h
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/block/block-copy.c
19
--- a/include/block/nbd.h
22
+++ b/block/block-copy.c
20
+++ b/include/block/nbd.h
23
@@ -XXX,XX +XXX,XX @@ out:
21
@@ -XXX,XX +XXX,XX @@ QIOChannel *coroutine_fn
24
static coroutine_fn int block_copy_task_entry(AioTask *task)
22
nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info,
25
{
23
bool blocking, Error **errp);
26
BlockCopyTask *t = container_of(task, BlockCopyTask, task);
24
27
- bool error_is_read;
25
-void coroutine_fn nbd_co_establish_connection_cancel(NBDClientConnection *conn);
28
+ bool error_is_read = false;
26
+void nbd_co_establish_connection_cancel(NBDClientConnection *conn);
29
int ret;
27
30
28
#endif
31
ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
32
--
29
--
33
2.25.4
30
2.37.3
34
35
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
qemu_coroutine_get_aio_context inspects a coroutine, but it does
4
Message-Id: <20200513110544.176672-33-mreitz@redhat.com>
4
not have to be called from the coroutine itself (or from any
5
coroutine).
6
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-6-pbonzini@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
13
---
8
include/block/block_int.h | 1 -
14
include/qemu/coroutine.h | 2 +-
9
block.c | 39 ++-------------------------------------
15
util/qemu-coroutine.c | 2 +-
10
tests/test-bdrv-drain.c | 8 +++-----
16
2 files changed, 2 insertions(+), 2 deletions(-)
11
3 files changed, 5 insertions(+), 43 deletions(-)
12
17
13
diff --git a/include/block/block_int.h b/include/block/block_int.h
18
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block_int.h
20
--- a/include/qemu/coroutine.h
16
+++ b/include/block/block_int.h
21
+++ b/include/qemu/coroutine.h
17
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
22
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_coroutine_yield(void);
18
};
23
/**
19
24
* Get the AioContext of the given coroutine
20
extern const BdrvChildClass child_of_bds;
25
*/
21
-extern const BdrvChildClass child_file;
26
-AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co);
22
27
+AioContext *qemu_coroutine_get_aio_context(Coroutine *co);
23
struct BdrvChild {
28
24
BlockDriverState *bs;
29
/**
25
diff --git a/block.c b/block.c
30
* Get the currently executing coroutine
31
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
26
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
33
--- a/util/qemu-coroutine.c
28
+++ b/block.c
34
+++ b/util/qemu-coroutine.c
29
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
35
@@ -XXX,XX +XXX,XX @@ bool qemu_coroutine_entered(Coroutine *co)
30
BdrvChildRole child_role,
36
return co->caller;
31
Error **errp);
32
33
-/* TODO: Remove when no longer needed */
34
-static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
35
- int *child_flags, QDict *child_options,
36
- int parent_flags, QDict *parent_options);
37
-static void bdrv_child_cb_attach(BdrvChild *child);
38
-static void bdrv_child_cb_detach(BdrvChild *child);
39
-
40
/* If non-zero, use only whitelisted block drivers */
41
static int use_bdrv_whitelist;
42
43
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
44
*child_flags &= ~BDRV_O_NATIVE_AIO;
45
}
37
}
46
38
47
-/*
39
-AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co)
48
- * Returns the options and flags that bs->file should get if a protocol driver
40
+AioContext *qemu_coroutine_get_aio_context(Coroutine *co)
49
- * is expected, based on the given options and flags for the parent BDS
50
- */
51
-static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format,
52
- int *child_flags, QDict *child_options,
53
- int parent_flags, QDict *parent_options)
54
-{
55
- bdrv_inherited_options(BDRV_CHILD_IMAGE, true,
56
- child_flags, child_options,
57
- parent_flags, parent_options);
58
-}
59
-
60
-const BdrvChildClass child_file = {
61
- .parent_is_bds = true,
62
- .get_parent_desc = bdrv_child_get_parent_desc,
63
- .inherit_options = bdrv_protocol_options,
64
- .drained_begin = bdrv_child_cb_drained_begin,
65
- .drained_poll = bdrv_child_cb_drained_poll,
66
- .drained_end = bdrv_child_cb_drained_end,
67
- .attach = bdrv_child_cb_attach,
68
- .detach = bdrv_child_cb_detach,
69
- .inactivate = bdrv_child_cb_inactivate,
70
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
71
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
72
-};
73
-
74
static void bdrv_backing_attach(BdrvChild *c)
75
{
41
{
76
BlockDriverState *parent = c->opaque;
42
return co->ctx;
77
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
43
}
78
{
79
int flags;
80
81
- assert(child_class == &child_file ||
82
- (child_class == &child_of_bds &&
83
- (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA))));
84
+ assert(child_class == &child_of_bds &&
85
+ (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)));
86
87
flags = bdrv_reopen_get_flags(reopen_queue, bs);
88
89
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/tests/test-bdrv-drain.c
92
+++ b/tests/test-bdrv-drain.c
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
94
uint64_t *nperm, uint64_t *nshared)
95
{
96
/*
97
- * bdrv_default_perms() accepts only these two, so disguise
98
- * detach_by_driver_cb_parent as one of them.
99
+ * bdrv_default_perms() accepts nothing else, so disguise
100
+ * detach_by_driver_cb_parent.
101
*/
102
- if (child_class != &child_file && child_class != &child_of_bds) {
103
- child_class = &child_of_bds;
104
- }
105
+ child_class = &child_of_bds;
106
107
bdrv_default_perms(bs, c, child_class, role, reopen_queue,
108
perm, shared, nperm, nshared);
109
--
44
--
110
2.25.4
45
2.37.3
111
112
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Both users (quorum and blkverify) use child_format for
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
not-really-filtered children, so the appropriate BdrvChildRole in both
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
cases is DATA. (Note that this will cause bdrv_inherited_options() to
5
functions where this holds.
6
force-allow format probing.)
7
6
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-Id: <20200513110544.176672-22-mreitz@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-8-pbonzini@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
---
13
block/blkverify.c | 4 ++--
14
block/blkverify.c | 2 +-
14
block/quorum.c | 6 ++++--
15
1 file changed, 1 insertion(+), 1 deletion(-)
15
2 files changed, 6 insertions(+), 4 deletions(-)
16
16
17
diff --git a/block/blkverify.c b/block/blkverify.c
17
diff --git a/block/blkverify.c b/block/blkverify.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blkverify.c
19
--- a/block/blkverify.c
20
+++ b/block/blkverify.c
20
+++ b/block/blkverify.c
21
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
21
@@ -XXX,XX +XXX,XX @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
22
22
return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true);
23
/* Open the test file */
23
}
24
s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options,
24
25
- "test", bs, &child_format, 0, false,
25
-static int blkverify_co_flush(BlockDriverState *bs)
26
- &local_err);
26
+static int coroutine_fn blkverify_co_flush(BlockDriverState *bs)
27
+ "test", bs, &child_of_bds, BDRV_CHILD_DATA,
27
{
28
+ false, &local_err);
28
BDRVBlkverifyState *s = bs->opaque;
29
if (local_err) {
29
30
ret = -EINVAL;
31
error_propagate(errp, local_err);
32
diff --git a/block/quorum.c b/block/quorum.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/quorum.c
35
+++ b/block/quorum.c
36
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
37
assert(ret < 32);
38
39
s->children[i] = bdrv_open_child(NULL, options, indexstr, bs,
40
- &child_format, 0, false, &local_err);
41
+ &child_of_bds, BDRV_CHILD_DATA, false,
42
+ &local_err);
43
if (local_err) {
44
ret = -EINVAL;
45
goto close_exit;
46
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
47
/* We can safely add the child now */
48
bdrv_ref(child_bs);
49
50
- child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, 0, errp);
51
+ child = bdrv_attach_child(bs, child_bs, indexstr, &child_of_bds,
52
+ BDRV_CHILD_DATA, errp);
53
if (child == NULL) {
54
s->next_child_index--;
55
goto out;
56
--
30
--
57
2.25.4
31
2.37.3
58
59
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
6
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
4
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Message-Id: <20200513110544.176672-32-mreitz@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-9-pbonzini@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
13
---
8
include/block/block_int.h | 11 -----------
14
block/file-posix.c | 2 +-
9
block.c | 19 -------------------
15
1 file changed, 1 insertion(+), 1 deletion(-)
10
2 files changed, 30 deletions(-)
11
16
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
17
diff --git a/block/file-posix.c b/block/file-posix.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/include/block/block_int.h
19
--- a/block/file-posix.c
15
+++ b/include/block/block_int.h
20
+++ b/block/file-posix.c
16
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
21
@@ -XXX,XX +XXX,XX @@ static void raw_aio_unplug(BlockDriverState *bs)
17
*/
22
#endif
18
int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
19
20
-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
21
- * (non-raw) image formats: Like above for bs->backing, but for bs->file it
22
- * requires WRITE | RESIZE for read-write images, always requires
23
- * CONSISTENT_READ and doesn't share WRITE. */
24
-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
25
- const BdrvChildClass *child_class,
26
- BdrvChildRole child_role,
27
- BlockReopenQueue *reopen_queue,
28
- uint64_t perm, uint64_t shared,
29
- uint64_t *nperm, uint64_t *nshared);
30
-
31
bool bdrv_recurse_can_replace(BlockDriverState *bs,
32
BlockDriverState *to_replace);
33
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
37
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
39
*nshared = shared;
40
}
23
}
41
24
42
-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
25
-static int raw_co_flush_to_disk(BlockDriverState *bs)
43
- const BdrvChildClass *child_class,
26
+static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
44
- BdrvChildRole role,
27
{
45
- BlockReopenQueue *reopen_queue,
28
BDRVRawState *s = bs->opaque;
46
- uint64_t perm, uint64_t shared,
29
RawPosixAIOData acb;
47
- uint64_t *nperm, uint64_t *nshared)
48
-{
49
- if (child_class == &child_of_bds) {
50
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
51
- perm, shared, nperm, nshared);
52
- return;
53
- }
54
-
55
- assert(child_class == &child_file);
56
-
57
- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
58
- perm, shared, nperm, nshared);
59
-}
60
-
61
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
62
const BdrvChildClass *child_class, BdrvChildRole role,
63
BlockReopenQueue *reopen_queue,
64
--
30
--
65
2.25.4
31
2.37.3
66
67
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
This callback can be used by BDSs that use child_of_bds with the
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
appropriate BdrvChildRole for their children.
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
5
6
6
Also, make bdrv_format_default_perms() use it for child_of_bds children
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
7
(just a temporary solution until we can drop bdrv_format_default_perms()
8
altogether).
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20200513110544.176672-20-mreitz@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-10-pbonzini@redhat.com>
11
[kwolf: Fixed up coding style]
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
14
---
15
include/block/block_int.h | 11 +++++++++++
15
block/iscsi.c | 3 ++-
16
block.c | 32 ++++++++++++++++++++++++++++++++
16
1 file changed, 2 insertions(+), 1 deletion(-)
17
2 files changed, 43 insertions(+)
18
17
19
diff --git a/include/block/block_int.h b/include/block/block_int.h
18
diff --git a/block/iscsi.c b/block/iscsi.c
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/block_int.h
20
--- a/block/iscsi.c
22
+++ b/include/block/block_int.h
21
+++ b/block/iscsi.c
23
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
22
@@ -XXX,XX +XXX,XX @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
24
bool bdrv_recurse_can_replace(BlockDriverState *bs,
25
BlockDriverState *to_replace);
26
27
+/*
28
+ * Default implementation for BlockDriver.bdrv_child_perm() that can
29
+ * be used by block filters and image formats, as long as they use the
30
+ * child_of_bds child class and set an appropriate BdrvChildRole.
31
+ */
32
+void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
33
+ const BdrvChildClass *child_class, BdrvChildRole role,
34
+ BlockReopenQueue *reopen_queue,
35
+ uint64_t perm, uint64_t shared,
36
+ uint64_t *nperm, uint64_t *nshared);
37
+
38
/*
39
* Default implementation for drivers to pass bdrv_co_block_status() to
40
* their file.
41
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
44
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
46
uint64_t *nperm, uint64_t *nshared)
47
{
48
bool backing = (child_class == &child_backing);
49
+
50
+ if (child_class == &child_of_bds) {
51
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
52
+ perm, shared, nperm, nshared);
53
+ return;
54
+ }
55
+
56
assert(child_class == &child_backing || child_class == &child_file);
57
58
if (!backing) {
59
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
60
}
23
}
61
}
24
}
62
25
63
+void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
26
-static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
64
+ const BdrvChildClass *child_class, BdrvChildRole role,
27
+static void coroutine_fn
65
+ BlockReopenQueue *reopen_queue,
28
+iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
66
+ uint64_t perm, uint64_t shared,
67
+ uint64_t *nperm, uint64_t *nshared)
68
+{
69
+ assert(child_class == &child_of_bds);
70
+
71
+ if (role & BDRV_CHILD_FILTERED) {
72
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
73
+ BDRV_CHILD_COW)));
74
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
75
+ perm, shared, nperm, nshared);
76
+ } else if (role & BDRV_CHILD_COW) {
77
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA)));
78
+ bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
79
+ perm, shared, nperm, nshared);
80
+ } else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) {
81
+ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
82
+ perm, shared, nperm, nshared);
83
+ } else {
84
+ g_assert_not_reached();
85
+ }
86
+}
87
+
88
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
89
{
29
{
90
static const uint64_t permissions[] = {
30
*iTask = (struct IscsiTask) {
31
.co = qemu_coroutine_self(),
91
--
32
--
92
2.25.4
33
2.37.3
93
94
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
The other two .inherit_options implementations specify exactly for what
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
case they are used in their name, so do it for this one as well.
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
5
6
6
(The actual intention behind this patch is to follow it up with a
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
7
generic bdrv_inherited_options() that works for all three cases.)
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-Id: <20200513110544.176672-10-mreitz@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-11-pbonzini@redhat.com>
11
[kwolf: Fixed up coding style]
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
---
14
block.c | 8 ++++----
15
block/nbd.c | 11 ++++++-----
15
1 file changed, 4 insertions(+), 4 deletions(-)
16
1 file changed, 6 insertions(+), 5 deletions(-)
16
17
17
diff --git a/block.c b/block.c
18
diff --git a/block/nbd.c b/block/nbd.c
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
--- a/block/nbd.c
20
+++ b/block.c
21
+++ b/block/nbd.c
21
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
22
@@ -XXX,XX +XXX,XX @@ static void nbd_iter_request_error(NBDReplyChunkIter *iter, int ret)
22
* Returns the options and flags that bs->file should get if a protocol driver
23
* nbd_reply_chunk_iter_receive
23
* is expected, based on the given options and flags for the parent BDS
24
* The pointer stored in @payload requires g_free() to free it.
24
*/
25
*/
25
-static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
26
-static bool nbd_reply_chunk_iter_receive(BDRVNBDState *s,
26
- int *child_flags, QDict *child_options,
27
- NBDReplyChunkIter *iter,
27
- int parent_flags, QDict *parent_options)
28
- uint64_t handle,
28
+static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format,
29
- QEMUIOVector *qiov, NBDReply *reply,
29
+ int *child_flags, QDict *child_options,
30
- void **payload)
30
+ int parent_flags, QDict *parent_options)
31
+static bool coroutine_fn nbd_reply_chunk_iter_receive(BDRVNBDState *s,
32
+ NBDReplyChunkIter *iter,
33
+ uint64_t handle,
34
+ QEMUIOVector *qiov,
35
+ NBDReply *reply,
36
+ void **payload)
31
{
37
{
32
int flags = parent_flags;
38
int ret, request_ret;
33
39
NBDReply local_reply;
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
35
const BdrvChildClass child_file = {
36
.parent_is_bds = true,
37
.get_parent_desc = bdrv_child_get_parent_desc,
38
- .inherit_options = bdrv_inherited_options,
39
+ .inherit_options = bdrv_protocol_options,
40
.drained_begin = bdrv_child_cb_drained_begin,
41
.drained_poll = bdrv_child_cb_drained_poll,
42
.drained_end = bdrv_child_cb_drained_end,
43
--
40
--
44
2.25.4
41
2.37.3
45
46
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
Reviewed-by: Eric Blake <eblake@redhat.com>
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
Message-Id: <20200513110544.176672-31-mreitz@redhat.com>
5
functions where this holds.
6
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20220922084924.201610-12-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
12
---
8
include/block/block_int.h | 10 ----------
13
block/nfs.c | 2 +-
9
block.c | 17 +++++++++++------
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
2 files changed, 11 insertions(+), 16 deletions(-)
11
15
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
16
diff --git a/block/nfs.c b/block/nfs.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/include/block/block_int.h
18
--- a/block/nfs.c
15
+++ b/include/block/block_int.h
19
+++ b/block/nfs.c
16
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
20
@@ -XXX,XX +XXX,XX @@ static void nfs_process_write(void *arg)
17
*/
21
qemu_mutex_unlock(&client->mutex);
18
int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
19
20
-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
21
- * block filters: Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED and RESIZE to
22
- * all children */
23
-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
24
- const BdrvChildClass *child_class,
25
- BdrvChildRole child_role,
26
- BlockReopenQueue *reopen_queue,
27
- uint64_t perm, uint64_t shared,
28
- uint64_t *nperm, uint64_t *nshared);
29
-
30
/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
31
* (non-raw) image formats: Like above for bs->backing, but for bs->file it
32
* requires WRITE | RESIZE for read-write images, always requires
33
diff --git a/block.c b/block.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block.c
36
+++ b/block.c
37
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
38
return bdrv_child_try_set_perm(c, perms, shared, errp);
39
}
22
}
40
23
41
-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
24
-static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task)
42
- const BdrvChildClass *child_class,
25
+static void coroutine_fn nfs_co_init_task(BlockDriverState *bs, NFSRPC *task)
43
- BdrvChildRole role,
44
- BlockReopenQueue *reopen_queue,
45
- uint64_t perm, uint64_t shared,
46
- uint64_t *nperm, uint64_t *nshared)
47
+/*
48
+ * Default implementation for .bdrv_child_perm() for block filters:
49
+ * Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED, and RESIZE to the
50
+ * filtered child.
51
+ */
52
+static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
53
+ const BdrvChildClass *child_class,
54
+ BdrvChildRole role,
55
+ BlockReopenQueue *reopen_queue,
56
+ uint64_t perm, uint64_t shared,
57
+ uint64_t *nperm, uint64_t *nshared)
58
{
26
{
59
*nperm = perm & DEFAULT_PERM_PASSTHROUGH;
27
*task = (NFSRPC) {
60
*nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED;
28
.co = qemu_coroutine_self(),
61
--
29
--
62
2.25.4
30
2.37.3
63
64
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
bdrv_format_default_perms() has one code path for backing files, and one
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
for storage files. We want to pull them out into their own functions,
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
so make sure they are completely distinct before so the next patches
5
functions where this holds.
6
will be a bit cleaner.
7
6
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20200513110544.176672-16-mreitz@redhat.com>
9
Message-Id: <20220922084924.201610-13-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
---
13
block.c | 19 +++++++++++++------
14
block/nvme.c | 6 ++++--
14
1 file changed, 13 insertions(+), 6 deletions(-)
15
1 file changed, 4 insertions(+), 2 deletions(-)
15
16
16
diff --git a/block.c b/block.c
17
diff --git a/block/nvme.c b/block/nvme.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
19
--- a/block/nvme.c
19
+++ b/block.c
20
+++ b/block/nvme.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
21
@@ -XXX,XX +XXX,XX @@ static inline bool nvme_qiov_aligned(BlockDriverState *bs,
21
perm |= BLK_PERM_CONSISTENT_READ;
22
return true;
22
}
23
shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
24
+
25
+ if (bs->open_flags & BDRV_O_INACTIVE) {
26
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
27
+ }
28
+
29
+ *nperm = perm;
30
+ *nshared = shared;
31
} else {
32
/* We want consistent read from backing files if the parent needs it.
33
* No other operations are performed on backing files. */
34
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
35
36
shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
37
BLK_PERM_WRITE_UNCHANGED;
38
- }
39
40
- if (bs->open_flags & BDRV_O_INACTIVE) {
41
- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
42
- }
43
+ if (bs->open_flags & BDRV_O_INACTIVE) {
44
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
45
+ }
46
47
- *nperm = perm;
48
- *nshared = shared;
49
+ *nperm = perm;
50
+ *nshared = shared;
51
+ }
52
}
23
}
53
24
54
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
25
-static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
26
- QEMUIOVector *qiov, bool is_write, int flags)
27
+static coroutine_fn int nvme_co_prw(BlockDriverState *bs,
28
+ uint64_t offset, uint64_t bytes,
29
+ QEMUIOVector *qiov, bool is_write,
30
+ int flags)
31
{
32
BDRVNVMeState *s = bs->opaque;
33
int r;
55
--
34
--
56
2.25.4
35
2.37.3
57
58
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Commonly, they need to pass the BDRV_CHILD_IMAGE set as the
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
BdrvChildRole; but there are exceptions for drivers with external data
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
files (qcow2 and vmdk).
5
functions where this holds.
6
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20200513110544.176672-26-mreitz@redhat.com>
9
Message-Id: <20220922084924.201610-14-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
13
---
12
block/bochs.c | 4 ++--
14
block/parallels.c | 5 +++--
13
block/cloop.c | 4 ++--
15
1 file changed, 3 insertions(+), 2 deletions(-)
14
block/crypto.c | 4 ++--
15
block/dmg.c | 4 ++--
16
block/parallels.c | 4 ++--
17
block/qcow.c | 4 ++--
18
block/qcow2.c | 19 +++++++++++++------
19
block/qed.c | 4 ++--
20
block/vdi.c | 4 ++--
21
block/vhdx.c | 4 ++--
22
block/vmdk.c | 20 +++++++++++++++++---
23
block/vpc.c | 4 ++--
24
12 files changed, 50 insertions(+), 29 deletions(-)
25
16
26
diff --git a/block/bochs.c b/block/bochs.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/bochs.c
29
+++ b/block/bochs.c
30
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
31
return ret;
32
}
33
34
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
35
- false, errp);
36
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
37
+ BDRV_CHILD_IMAGE, false, errp);
38
if (!bs->file) {
39
return -EINVAL;
40
}
41
diff --git a/block/cloop.c b/block/cloop.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block/cloop.c
44
+++ b/block/cloop.c
45
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
46
return ret;
47
}
48
49
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
50
- false, errp);
51
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
52
+ BDRV_CHILD_IMAGE, false, errp);
53
if (!bs->file) {
54
return -EINVAL;
55
}
56
diff --git a/block/crypto.c b/block/crypto.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block/crypto.c
59
+++ b/block/crypto.c
60
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
61
unsigned int cflags = 0;
62
QDict *cryptoopts = NULL;
63
64
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
65
- false, errp);
66
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
67
+ BDRV_CHILD_IMAGE, false, errp);
68
if (!bs->file) {
69
return -EINVAL;
70
}
71
diff --git a/block/dmg.c b/block/dmg.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/block/dmg.c
74
+++ b/block/dmg.c
75
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
76
return ret;
77
}
78
79
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
80
- false, errp);
81
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
82
+ BDRV_CHILD_IMAGE, false, errp);
83
if (!bs->file) {
84
return -EINVAL;
85
}
86
diff --git a/block/parallels.c b/block/parallels.c
17
diff --git a/block/parallels.c b/block/parallels.c
87
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
88
--- a/block/parallels.c
19
--- a/block/parallels.c
89
+++ b/block/parallels.c
20
+++ b/block/parallels.c
90
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
21
@@ -XXX,XX +XXX,XX @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
91
Error *local_err = NULL;
22
return start_off;
92
char *buf;
23
}
93
24
94
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
25
-static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
95
- false, errp);
26
- int nb_sectors, int *pnum)
96
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
27
+static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
97
+ BDRV_CHILD_IMAGE, false, errp);
28
+ int64_t sector_num,
98
if (!bs->file) {
29
+ int nb_sectors, int *pnum)
99
return -EINVAL;
30
{
100
}
31
int ret = 0;
101
diff --git a/block/qcow.c b/block/qcow.c
32
BDRVParallelsState *s = bs->opaque;
102
index XXXXXXX..XXXXXXX 100644
103
--- a/block/qcow.c
104
+++ b/block/qcow.c
105
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
106
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
107
encryptfmt = qdict_get_try_str(encryptopts, "format");
108
109
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
110
- false, errp);
111
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
112
+ BDRV_CHILD_IMAGE, false, errp);
113
if (!bs->file) {
114
ret = -EINVAL;
115
goto fail;
116
diff --git a/block/qcow2.c b/block/qcow2.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/block/qcow2.c
119
+++ b/block/qcow2.c
120
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
121
}
122
123
/* Open external data file */
124
- s->data_file = bdrv_open_child(NULL, options, "data-file", bs, &child_file,
125
- 0, true, &local_err);
126
+ s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
127
+ &child_of_bds, BDRV_CHILD_DATA,
128
+ true, &local_err);
129
if (local_err) {
130
error_propagate(errp, local_err);
131
ret = -EINVAL;
132
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
133
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
134
if (!s->data_file && s->image_data_file) {
135
s->data_file = bdrv_open_child(s->image_data_file, options,
136
- "data-file", bs, &child_file, 0,
137
- false, errp);
138
+ "data-file", bs, &child_of_bds,
139
+ BDRV_CHILD_DATA, false, errp);
140
if (!s->data_file) {
141
ret = -EINVAL;
142
goto fail;
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
144
ret = -EINVAL;
145
goto fail;
146
}
147
+
148
+ /* No data here */
149
+ bs->file->role &= ~BDRV_CHILD_DATA;
150
+
151
+ /* Must succeed because we have given up permissions if anything */
152
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
153
} else {
154
if (s->data_file) {
155
error_setg(errp, "'data-file' can only be set for images with an "
156
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
157
.ret = -EINPROGRESS
158
};
159
160
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
161
- false, errp);
162
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
163
+ BDRV_CHILD_IMAGE, false, errp);
164
if (!bs->file) {
165
return -EINVAL;
166
}
167
diff --git a/block/qed.c b/block/qed.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/block/qed.c
170
+++ b/block/qed.c
171
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
172
.ret = -EINPROGRESS
173
};
174
175
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
176
- false, errp);
177
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
178
+ BDRV_CHILD_IMAGE, false, errp);
179
if (!bs->file) {
180
return -EINVAL;
181
}
182
diff --git a/block/vdi.c b/block/vdi.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/vdi.c
185
+++ b/block/vdi.c
186
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
187
Error *local_err = NULL;
188
QemuUUID uuid_link, uuid_parent;
189
190
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
191
- false, errp);
192
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
193
+ BDRV_CHILD_IMAGE, false, errp);
194
if (!bs->file) {
195
return -EINVAL;
196
}
197
diff --git a/block/vhdx.c b/block/vhdx.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/block/vhdx.c
200
+++ b/block/vhdx.c
201
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
202
uint64_t signature;
203
Error *local_err = NULL;
204
205
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
206
- false, errp);
207
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
208
+ BDRV_CHILD_IMAGE, false, errp);
209
if (!bs->file) {
210
return -EINVAL;
211
}
212
diff --git a/block/vmdk.c b/block/vmdk.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/block/vmdk.c
215
+++ b/block/vmdk.c
216
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
217
char *desc_file_dir = NULL;
218
char *extent_path;
219
BdrvChild *extent_file;
220
+ BdrvChildRole extent_role;
221
BDRVVmdkState *s = bs->opaque;
222
VmdkExtent *extent;
223
char extent_opt_prefix[32];
224
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
225
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
226
assert(ret < 32);
227
228
+ extent_role = BDRV_CHILD_DATA;
229
+ if (strcmp(type, "FLAT") != 0 && strcmp(type, "VMFS") != 0) {
230
+ /* non-flat extents have metadata */
231
+ extent_role |= BDRV_CHILD_METADATA;
232
+ }
233
+
234
extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,
235
- bs, &child_file, 0, false, &local_err);
236
+ bs, &child_of_bds, extent_role, false,
237
+ &local_err);
238
g_free(extent_path);
239
if (local_err) {
240
error_propagate(errp, local_err);
241
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
242
uint32_t magic;
243
Error *local_err = NULL;
244
245
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
246
- false, errp);
247
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
248
+ BDRV_CHILD_IMAGE, false, errp);
249
if (!bs->file) {
250
return -EINVAL;
251
}
252
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
253
s->desc_offset = 0x200;
254
break;
255
default:
256
+ /* No data in the descriptor file */
257
+ bs->file->role &= ~BDRV_CHILD_DATA;
258
+
259
+ /* Must succeed because we have given up permissions if anything */
260
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
261
+
262
ret = vmdk_open_desc_file(bs, flags, buf, options, errp);
263
break;
264
}
265
diff --git a/block/vpc.c b/block/vpc.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/block/vpc.c
268
+++ b/block/vpc.c
269
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
270
int ret;
271
int64_t bs_size;
272
273
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
274
- false, errp);
275
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
276
+ BDRV_CHILD_IMAGE, false, errp);
277
if (!bs->file) {
278
return -EINVAL;
279
}
280
--
33
--
281
2.25.4
34
2.37.3
282
283
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
bdrv_default_perms() can decide which permission profile to use based on
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
the BdrvChildRole, so block drivers do not need to select it explicitly.
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
5
6
6
The blkverify driver now no longer shares the WRITE permission for the
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
7
image to verify. We thus have to adjust two places in
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
test-block-iothread not to take it. (Note that in theory, blkverify
9
Message-Id: <20220922084924.201610-15-pbonzini@redhat.com>
9
should behave like quorum in this regard and share neither WRITE nor
10
[kwolf: Fixed up coding style]
10
RESIZE for both of its children. In practice, it does not really
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
matter, because blkverify is used only for debugging, so we might as
12
well keep its permissions rather liberal.)
13
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Message-Id: <20200513110544.176672-30-mreitz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
13
---
19
block/backup-top.c | 4 ++--
14
block/qcow2.h | 15 ++++++++-------
20
block/blkdebug.c | 4 ++--
15
block/qcow2-cluster.c | 21 ++++++++++++---------
21
block/blklogwrites.c | 9 ++-------
16
block/qcow2-refcount.c | 2 +-
22
block/blkreplay.c | 2 +-
17
block/qcow2.c | 5 +++--
23
block/blkverify.c | 2 +-
18
4 files changed, 24 insertions(+), 19 deletions(-)
24
block/bochs.c | 2 +-
25
block/cloop.c | 2 +-
26
block/crypto.c | 2 +-
27
block/dmg.c | 2 +-
28
block/filter-compress.c | 2 +-
29
block/parallels.c | 2 +-
30
block/qcow.c | 2 +-
31
block/qcow2.c | 2 +-
32
block/qed.c | 2 +-
33
block/raw-format.c | 2 +-
34
block/throttle.c | 2 +-
35
block/vdi.c | 2 +-
36
block/vhdx.c | 2 +-
37
block/vmdk.c | 2 +-
38
block/vpc.c | 2 +-
39
tests/test-bdrv-drain.c | 10 +++++-----
40
tests/test-bdrv-graph-mod.c | 2 +-
41
tests/test-block-iothread.c | 17 ++++++++++++++---
42
23 files changed, 43 insertions(+), 37 deletions(-)
43
19
44
diff --git a/block/backup-top.c b/block/backup-top.c
20
diff --git a/block/qcow2.h b/block/qcow2.h
45
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
46
--- a/block/backup-top.c
22
--- a/block/qcow2.h
47
+++ b/block/backup-top.c
23
+++ b/block/qcow2.h
48
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
24
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
49
*nperm = BLK_PERM_WRITE;
25
void *cb_opaque, Error **errp);
50
} else {
26
int qcow2_shrink_reftable(BlockDriverState *bs);
51
/* Source child */
27
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
52
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
28
-int qcow2_detect_metadata_preallocation(BlockDriverState *bs);
53
- perm, shared, nperm, nshared);
29
+int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
54
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
30
55
+ perm, shared, nperm, nshared);
31
/* qcow2-cluster.c functions */
56
32
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
57
if (perm & BLK_PERM_WRITE) {
33
@@ -XXX,XX +XXX,XX @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
58
*nperm = *nperm | BLK_PERM_CONSISTENT_READ;
34
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
59
diff --git a/block/blkdebug.c b/block/blkdebug.c
35
unsigned int *bytes, uint64_t *host_offset,
36
QCow2SubclusterType *subcluster_type);
37
-int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
38
- unsigned int *bytes, uint64_t *host_offset,
39
- QCowL2Meta **m);
40
+int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
41
+ unsigned int *bytes,
42
+ uint64_t *host_offset, QCowL2Meta **m);
43
int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
44
uint64_t offset,
45
int compressed_size,
46
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
47
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
48
uint64_t *coffset, int *csize);
49
50
-int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
51
+int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs,
52
+ QCowL2Meta *m);
53
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
54
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
55
uint64_t bytes, enum qcow2_discard_type type,
56
bool full_discard);
57
-int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
58
- uint64_t bytes, int flags);
59
+int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
60
+ uint64_t bytes, int flags);
61
62
int qcow2_expand_zero_clusters(BlockDriverState *bs,
63
BlockDriverAmendStatusCB *status_cb,
64
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
60
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
61
--- a/block/blkdebug.c
66
--- a/block/qcow2-cluster.c
62
+++ b/block/blkdebug.c
67
+++ b/block/qcow2-cluster.c
63
@@ -XXX,XX +XXX,XX @@ static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
68
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
69
return 0;
70
}
71
72
-static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
73
+static int coroutine_fn perform_cow(BlockDriverState *bs, QCowL2Meta *m)
64
{
74
{
65
BDRVBlkdebugState *s = bs->opaque;
75
BDRVQcow2State *s = bs->opaque;
66
76
Qcow2COWRegion *start = &m->cow_start;
67
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
77
@@ -XXX,XX +XXX,XX @@ fail:
68
- perm, shared, nperm, nshared);
78
return ret;
69
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
79
}
70
+ perm, shared, nperm, nshared);
80
71
81
-int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
72
*nperm |= s->take_child_perms;
82
+int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs,
73
*nshared &= ~s->unshare_child_perms;
83
+ QCowL2Meta *m)
74
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
84
{
85
BDRVQcow2State *s = bs->opaque;
86
int i, j = 0, l2_index, ret;
87
@@ -XXX,XX +XXX,XX @@ static int count_single_write_clusters(BlockDriverState *bs, int nb_clusters,
88
* information on cluster allocation may be invalid now. The caller
89
* must start over anyway, so consider *cur_bytes undefined.
90
*/
91
-static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
92
- uint64_t *cur_bytes, QCowL2Meta **m)
93
+static int coroutine_fn handle_dependencies(BlockDriverState *bs,
94
+ uint64_t guest_offset,
95
+ uint64_t *cur_bytes, QCowL2Meta **m)
96
{
97
BDRVQcow2State *s = bs->opaque;
98
QCowL2Meta *old_alloc;
99
@@ -XXX,XX +XXX,XX @@ out:
100
*
101
* Return 0 on success and -errno in error cases
102
*/
103
-int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
104
- unsigned int *bytes, uint64_t *host_offset,
105
- QCowL2Meta **m)
106
+int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
107
+ unsigned int *bytes,
108
+ uint64_t *host_offset,
109
+ QCowL2Meta **m)
110
{
111
BDRVQcow2State *s = bs->opaque;
112
uint64_t start, remaining;
113
@@ -XXX,XX +XXX,XX @@ out:
114
return ret;
115
}
116
117
-int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
118
- uint64_t bytes, int flags)
119
+int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
120
+ uint64_t bytes, int flags)
121
{
122
BDRVQcow2State *s = bs->opaque;
123
uint64_t end_offset = offset + bytes;
124
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
75
index XXXXXXX..XXXXXXX 100644
125
index XXXXXXX..XXXXXXX 100644
76
--- a/block/blklogwrites.c
126
--- a/block/qcow2-refcount.c
77
+++ b/block/blklogwrites.c
127
+++ b/block/qcow2-refcount.c
78
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
128
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size)
79
return;
129
return -EIO;
80
}
81
82
- if (!strcmp(c->name, "log")) {
83
- bdrv_format_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
84
- nperm, nshrd);
85
- } else {
86
- bdrv_filter_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
87
- nperm, nshrd);
88
- }
89
+ bdrv_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
90
+ nperm, nshrd);
91
}
130
}
92
131
93
static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
132
-int qcow2_detect_metadata_preallocation(BlockDriverState *bs)
94
diff --git a/block/blkreplay.c b/block/blkreplay.c
133
+int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs)
95
index XXXXXXX..XXXXXXX 100644
134
{
96
--- a/block/blkreplay.c
135
BDRVQcow2State *s = bs->opaque;
97
+++ b/block/blkreplay.c
136
int64_t i, end_cluster, cluster_count = 0, threshold;
98
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkreplay = {
99
.is_filter = true,
100
101
.bdrv_open = blkreplay_open,
102
- .bdrv_child_perm = bdrv_filter_default_perms,
103
+ .bdrv_child_perm = bdrv_default_perms,
104
.bdrv_getlength = blkreplay_getlength,
105
106
.bdrv_co_preadv = blkreplay_co_preadv,
107
diff --git a/block/blkverify.c b/block/blkverify.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/blkverify.c
110
+++ b/block/blkverify.c
111
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkverify = {
112
.bdrv_parse_filename = blkverify_parse_filename,
113
.bdrv_file_open = blkverify_open,
114
.bdrv_close = blkverify_close,
115
- .bdrv_child_perm = bdrv_filter_default_perms,
116
+ .bdrv_child_perm = bdrv_default_perms,
117
.bdrv_getlength = blkverify_getlength,
118
.bdrv_refresh_filename = blkverify_refresh_filename,
119
.bdrv_dirname = blkverify_dirname,
120
diff --git a/block/bochs.c b/block/bochs.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/block/bochs.c
123
+++ b/block/bochs.c
124
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_bochs = {
125
.instance_size    = sizeof(BDRVBochsState),
126
.bdrv_probe        = bochs_probe,
127
.bdrv_open        = bochs_open,
128
- .bdrv_child_perm = bdrv_format_default_perms,
129
+ .bdrv_child_perm = bdrv_default_perms,
130
.bdrv_refresh_limits = bochs_refresh_limits,
131
.bdrv_co_preadv = bochs_co_preadv,
132
.bdrv_close        = bochs_close,
133
diff --git a/block/cloop.c b/block/cloop.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/block/cloop.c
136
+++ b/block/cloop.c
137
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_cloop = {
138
.instance_size = sizeof(BDRVCloopState),
139
.bdrv_probe = cloop_probe,
140
.bdrv_open = cloop_open,
141
- .bdrv_child_perm = bdrv_format_default_perms,
142
+ .bdrv_child_perm = bdrv_default_perms,
143
.bdrv_refresh_limits = cloop_refresh_limits,
144
.bdrv_co_preadv = cloop_co_preadv,
145
.bdrv_close = cloop_close,
146
diff --git a/block/crypto.c b/block/crypto.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/crypto.c
149
+++ b/block/crypto.c
150
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_crypto_luks = {
151
.bdrv_close = block_crypto_close,
152
/* This driver doesn't modify LUKS metadata except when creating image.
153
* Allow share-rw=on as a special case. */
154
- .bdrv_child_perm = bdrv_filter_default_perms,
155
+ .bdrv_child_perm = bdrv_default_perms,
156
.bdrv_co_create = block_crypto_co_create_luks,
157
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
158
.bdrv_co_truncate = block_crypto_co_truncate,
159
diff --git a/block/dmg.c b/block/dmg.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/dmg.c
162
+++ b/block/dmg.c
163
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_dmg = {
164
.bdrv_probe = dmg_probe,
165
.bdrv_open = dmg_open,
166
.bdrv_refresh_limits = dmg_refresh_limits,
167
- .bdrv_child_perm = bdrv_format_default_perms,
168
+ .bdrv_child_perm = bdrv_default_perms,
169
.bdrv_co_preadv = dmg_co_preadv,
170
.bdrv_close = dmg_close,
171
.is_format = true,
172
diff --git a/block/filter-compress.c b/block/filter-compress.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/filter-compress.c
175
+++ b/block/filter-compress.c
176
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_compress = {
177
.format_name = "compress",
178
179
.bdrv_open = compress_open,
180
- .bdrv_child_perm = bdrv_filter_default_perms,
181
+ .bdrv_child_perm = bdrv_default_perms,
182
183
.bdrv_getlength = compress_getlength,
184
185
diff --git a/block/parallels.c b/block/parallels.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/block/parallels.c
188
+++ b/block/parallels.c
189
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
190
.bdrv_probe        = parallels_probe,
191
.bdrv_open        = parallels_open,
192
.bdrv_close        = parallels_close,
193
- .bdrv_child_perm = bdrv_format_default_perms,
194
+ .bdrv_child_perm = bdrv_default_perms,
195
.bdrv_co_block_status = parallels_co_block_status,
196
.bdrv_has_zero_init = bdrv_has_zero_init_1,
197
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
198
diff --git a/block/qcow.c b/block/qcow.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/block/qcow.c
201
+++ b/block/qcow.c
202
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
203
.bdrv_probe        = qcow_probe,
204
.bdrv_open        = qcow_open,
205
.bdrv_close        = qcow_close,
206
- .bdrv_child_perm = bdrv_format_default_perms,
207
+ .bdrv_child_perm = bdrv_default_perms,
208
.bdrv_reopen_prepare = qcow_reopen_prepare,
209
.bdrv_co_create = qcow_co_create,
210
.bdrv_co_create_opts = qcow_co_create_opts,
211
diff --git a/block/qcow2.c b/block/qcow2.c
137
diff --git a/block/qcow2.c b/block/qcow2.c
212
index XXXXXXX..XXXXXXX 100644
138
index XXXXXXX..XXXXXXX 100644
213
--- a/block/qcow2.c
139
--- a/block/qcow2.c
214
+++ b/block/qcow2.c
140
+++ b/block/qcow2.c
215
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
141
@@ -XXX,XX +XXX,XX @@ static bool merge_cow(uint64_t offset, unsigned bytes,
216
.bdrv_reopen_commit_post = qcow2_reopen_commit_post,
142
* Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error.
217
.bdrv_reopen_abort = qcow2_reopen_abort,
143
* Note that returning 0 does not guarantee non-zero data.
218
.bdrv_join_options = qcow2_join_options,
144
*/
219
- .bdrv_child_perm = bdrv_format_default_perms,
145
-static int is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
220
+ .bdrv_child_perm = bdrv_default_perms,
146
+static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
221
.bdrv_co_create_opts = qcow2_co_create_opts,
222
.bdrv_co_create = qcow2_co_create,
223
.bdrv_has_zero_init = qcow2_has_zero_init,
224
diff --git a/block/qed.c b/block/qed.c
225
index XXXXXXX..XXXXXXX 100644
226
--- a/block/qed.c
227
+++ b/block/qed.c
228
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
229
.bdrv_open = bdrv_qed_open,
230
.bdrv_close = bdrv_qed_close,
231
.bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
232
- .bdrv_child_perm = bdrv_format_default_perms,
233
+ .bdrv_child_perm = bdrv_default_perms,
234
.bdrv_co_create = bdrv_qed_co_create,
235
.bdrv_co_create_opts = bdrv_qed_co_create_opts,
236
.bdrv_has_zero_init = bdrv_has_zero_init_1,
237
diff --git a/block/raw-format.c b/block/raw-format.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/raw-format.c
240
+++ b/block/raw-format.c
241
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
242
.bdrv_reopen_commit = &raw_reopen_commit,
243
.bdrv_reopen_abort = &raw_reopen_abort,
244
.bdrv_open = &raw_open,
245
- .bdrv_child_perm = bdrv_filter_default_perms,
246
+ .bdrv_child_perm = bdrv_default_perms,
247
.bdrv_co_create_opts = &raw_co_create_opts,
248
.bdrv_co_preadv = &raw_co_preadv,
249
.bdrv_co_pwritev = &raw_co_pwritev,
250
diff --git a/block/throttle.c b/block/throttle.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/block/throttle.c
253
+++ b/block/throttle.c
254
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
255
.bdrv_close = throttle_close,
256
.bdrv_co_flush = throttle_co_flush,
257
258
- .bdrv_child_perm = bdrv_filter_default_perms,
259
+ .bdrv_child_perm = bdrv_default_perms,
260
261
.bdrv_getlength = throttle_getlength,
262
263
diff --git a/block/vdi.c b/block/vdi.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/block/vdi.c
266
+++ b/block/vdi.c
267
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
268
.bdrv_open = vdi_open,
269
.bdrv_close = vdi_close,
270
.bdrv_reopen_prepare = vdi_reopen_prepare,
271
- .bdrv_child_perm = bdrv_format_default_perms,
272
+ .bdrv_child_perm = bdrv_default_perms,
273
.bdrv_co_create = vdi_co_create,
274
.bdrv_co_create_opts = vdi_co_create_opts,
275
.bdrv_has_zero_init = vdi_has_zero_init,
276
diff --git a/block/vhdx.c b/block/vhdx.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/block/vhdx.c
279
+++ b/block/vhdx.c
280
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
281
.bdrv_open = vhdx_open,
282
.bdrv_close = vhdx_close,
283
.bdrv_reopen_prepare = vhdx_reopen_prepare,
284
- .bdrv_child_perm = bdrv_format_default_perms,
285
+ .bdrv_child_perm = bdrv_default_perms,
286
.bdrv_co_readv = vhdx_co_readv,
287
.bdrv_co_writev = vhdx_co_writev,
288
.bdrv_co_create = vhdx_co_create,
289
diff --git a/block/vmdk.c b/block/vmdk.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/block/vmdk.c
292
+++ b/block/vmdk.c
293
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
294
.bdrv_open = vmdk_open,
295
.bdrv_co_check = vmdk_co_check,
296
.bdrv_reopen_prepare = vmdk_reopen_prepare,
297
- .bdrv_child_perm = bdrv_format_default_perms,
298
+ .bdrv_child_perm = bdrv_default_perms,
299
.bdrv_co_preadv = vmdk_co_preadv,
300
.bdrv_co_pwritev = vmdk_co_pwritev,
301
.bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed,
302
diff --git a/block/vpc.c b/block/vpc.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/block/vpc.c
305
+++ b/block/vpc.c
306
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
307
.bdrv_open = vpc_open,
308
.bdrv_close = vpc_close,
309
.bdrv_reopen_prepare = vpc_reopen_prepare,
310
- .bdrv_child_perm = bdrv_format_default_perms,
311
+ .bdrv_child_perm = bdrv_default_perms,
312
.bdrv_co_create = vpc_co_create,
313
.bdrv_co_create_opts = vpc_co_create_opts,
314
315
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
316
index XXXXXXX..XXXXXXX 100644
317
--- a/tests/test-bdrv-drain.c
318
+++ b/tests/test-bdrv-drain.c
319
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
320
uint64_t *nperm, uint64_t *nshared)
321
{
147
{
322
/*
148
/*
323
- * bdrv_format_default_perms() accepts only these two, so disguise
149
* This check is designed for optimization shortcut so it must be
324
+ * bdrv_default_perms() accepts only these two, so disguise
150
@@ -XXX,XX +XXX,XX @@ static int is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
325
* detach_by_driver_cb_parent as one of them.
151
m->cow_end.nb_bytes);
326
*/
327
if (child_class != &child_file && child_class != &child_of_bds) {
328
child_class = &child_of_bds;
329
}
330
331
- bdrv_format_default_perms(bs, c, child_class, role, reopen_queue,
332
- perm, shared, nperm, nshared);
333
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
334
+ perm, shared, nperm, nshared);
335
}
152
}
336
153
337
static int bdrv_test_change_backing_file(BlockDriverState *bs,
154
-static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
338
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_test_top_driver = {
155
+static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
339
.bdrv_close = bdrv_test_top_close,
156
+ QCowL2Meta *l2meta)
340
.bdrv_co_preadv = bdrv_test_top_co_preadv,
157
{
341
158
BDRVQcow2State *s = bs->opaque;
342
- .bdrv_child_perm = bdrv_format_default_perms,
159
QCowL2Meta *m;
343
+ .bdrv_child_perm = bdrv_default_perms,
344
};
345
346
typedef struct TestCoDeleteByDrainData {
347
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_replace_test = {
348
.bdrv_co_drain_begin = bdrv_replace_test_co_drain_begin,
349
.bdrv_co_drain_end = bdrv_replace_test_co_drain_end,
350
351
- .bdrv_child_perm = bdrv_format_default_perms,
352
+ .bdrv_child_perm = bdrv_default_perms,
353
};
354
355
static void coroutine_fn test_replace_child_mid_drain_read_co(void *opaque)
356
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/tests/test-bdrv-graph-mod.c
359
+++ b/tests/test-bdrv-graph-mod.c
360
@@ -XXX,XX +XXX,XX @@
361
362
static BlockDriver bdrv_pass_through = {
363
.format_name = "pass-through",
364
- .bdrv_child_perm = bdrv_filter_default_perms,
365
+ .bdrv_child_perm = bdrv_default_perms,
366
};
367
368
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
369
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
370
index XXXXXXX..XXXXXXX 100644
371
--- a/tests/test-block-iothread.c
372
+++ b/tests/test-block-iothread.c
373
@@ -XXX,XX +XXX,XX @@ static void test_propagate_basic(void)
374
BlockDriverState *bs_a, *bs_b, *bs_verify;
375
QDict *options;
376
377
- /* Create bs_a and its BlockBackend */
378
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
379
+ /*
380
+ * Create bs_a and its BlockBackend. We cannot take the RESIZE
381
+ * permission because blkverify will not share it on the test
382
+ * image.
383
+ */
384
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
385
+ BLK_PERM_ALL);
386
bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
387
blk_insert_bs(blk, bs_a, &error_abort);
388
389
@@ -XXX,XX +XXX,XX @@ static void test_propagate_diamond(void)
390
qdict_put_str(options, "raw", "bs_c");
391
392
bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
393
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
394
+ /*
395
+ * Do not take the RESIZE permission: This would require the same
396
+ * from bs_c and thus from bs_a; however, blkverify will not share
397
+ * it on bs_b, and thus it will not be available for bs_a.
398
+ */
399
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
400
+ BLK_PERM_ALL);
401
blk_insert_bs(blk, bs_verify, &error_abort);
402
403
/* Switch the AioContext */
404
--
160
--
405
2.25.4
161
2.37.3
406
407
diff view generated by jsdifflib
1
test_overlapping_3() throttles its active commit job so it can be sure
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
the job is still busy when it checks that you can't start a conflicting
3
streaming job.
4
2
5
However, it only sets the commit job back to full speed when it is
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
6
ready, which takes a few seconds while it's throttled. We can already
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
7
reset the limit after having checked that block-stream returns an error
5
functions where this holds.
8
and save these seconds.
9
6
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
11
Message-Id: <20200513100025.33543-1-kwolf@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-Id: <20220922084924.201610-16-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
tests/qemu-iotests/030 | 6 +++---
14
block/copy-before-write.c | 9 +++++----
16
1 file changed, 3 insertions(+), 3 deletions(-)
15
1 file changed, 5 insertions(+), 4 deletions(-)
17
16
18
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
17
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
19
index XXXXXXX..XXXXXXX 100755
18
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/030
19
--- a/block/copy-before-write.c
21
+++ b/tests/qemu-iotests/030
20
+++ b/block/copy-before-write.c
22
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
23
self.assert_qmp(result, 'error/desc',
22
* It's guaranteed that guest writes will not interact in the region until
24
"Node 'node5' is busy: block device is in use by block job: commit")
23
* cbw_snapshot_read_unlock() called.
25
24
*/
26
+ result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
25
-static BlockReq *cbw_snapshot_read_lock(BlockDriverState *bs,
27
+ self.assert_qmp(result, 'return', {})
26
- int64_t offset, int64_t bytes,
28
+
27
- int64_t *pnum, BdrvChild **file)
29
event = self.vm.event_wait(name='BLOCK_JOB_READY')
28
+static coroutine_fn BlockReq *
30
self.assert_qmp(event, 'data/device', 'commit-drive0')
29
+cbw_snapshot_read_lock(BlockDriverState *bs, int64_t offset, int64_t bytes,
31
self.assert_qmp(event, 'data/type', 'commit')
30
+ int64_t *pnum, BdrvChild **file)
32
self.assert_qmp_absent(event, 'data/error')
31
{
33
32
BDRVCopyBeforeWriteState *s = bs->opaque;
34
- result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
33
BlockReq *req = g_new(BlockReq, 1);
35
- self.assert_qmp(result, 'return', {})
34
@@ -XXX,XX +XXX,XX @@ static BlockReq *cbw_snapshot_read_lock(BlockDriverState *bs,
36
-
35
return req;
37
result = self.vm.qmp('block-job-complete', device='commit-drive0')
36
}
38
self.assert_qmp(result, 'return', {})
37
38
-static void cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
39
+static coroutine_fn void
40
+cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
41
{
42
BDRVCopyBeforeWriteState *s = bs->opaque;
39
43
40
--
44
--
41
2.25.4
45
2.37.3
42
43
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Any current user of child_file, child_format, and child_backing can and
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
should use this generic BdrvChildClass instead, as it can handle all of
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
these cases. However, to be able to do so, the users must pass the
5
functions where this holds.
6
appropriate BdrvChildRole when the child is created/attached. (The
7
following commits will take care of that.)
8
6
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
10
Message-Id: <20200513110544.176672-15-mreitz@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Message-Id: <20220922084924.201610-17-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
include/block/block_int.h | 1 +
13
block/curl.c | 2 +-
15
block.c | 24 ++++++++++++++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
16
2 files changed, 25 insertions(+)
17
15
18
diff --git a/include/block/block_int.h b/include/block/block_int.h
16
diff --git a/block/curl.c b/block/curl.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/block_int.h
18
--- a/block/curl.c
21
+++ b/include/block/block_int.h
19
+++ b/block/curl.c
22
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
20
@@ -XXX,XX +XXX,XX @@ out_noclean:
23
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
21
return -EINVAL;
24
};
25
26
+extern const BdrvChildClass child_of_bds;
27
extern const BdrvChildClass child_file;
28
extern const BdrvChildClass child_format;
29
extern const BdrvChildClass child_backing;
30
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
33
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_detach(BdrvChild *child)
35
bdrv_unapply_subtree_drain(child, bs);
36
}
22
}
37
23
38
+static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
24
-static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb)
39
+ const char *filename, Error **errp)
25
+static void coroutine_fn curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb)
40
+{
41
+ if (c->role & BDRV_CHILD_COW) {
42
+ return bdrv_backing_update_filename(c, base, filename, errp);
43
+ }
44
+ return 0;
45
+}
46
+
47
+const BdrvChildClass child_of_bds = {
48
+ .parent_is_bds = true,
49
+ .get_parent_desc = bdrv_child_get_parent_desc,
50
+ .inherit_options = bdrv_inherited_options,
51
+ .drained_begin = bdrv_child_cb_drained_begin,
52
+ .drained_poll = bdrv_child_cb_drained_poll,
53
+ .drained_end = bdrv_child_cb_drained_end,
54
+ .attach = bdrv_child_cb_attach,
55
+ .detach = bdrv_child_cb_detach,
56
+ .inactivate = bdrv_child_cb_inactivate,
57
+ .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
58
+ .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
59
+ .update_filename = bdrv_child_cb_update_filename,
60
+};
61
+
62
static int bdrv_open_flags(BlockDriverState *bs, int flags)
63
{
26
{
64
int open_flags = flags;
27
CURLState *state;
28
int running;
65
--
29
--
66
2.25.4
30
2.37.3
67
68
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
One might find interesting to look at AHCI IRQs.
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
4
6
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
6
Message-Id: <20200504094858.5975-1-f4bug@amsat.org>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-Id: <20220922084924.201610-18-pbonzini@redhat.com>
8
Acked-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
12
---
11
hw/ide/ahci.c | 1 +
13
block/qed.c | 4 ++--
12
1 file changed, 1 insertion(+)
14
1 file changed, 2 insertions(+), 2 deletions(-)
13
15
14
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
16
diff --git a/block/qed.c b/block/qed.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/ide/ahci.c
18
--- a/block/qed.c
17
+++ b/hw/ide/ahci.c
19
+++ b/block/qed.c
18
@@ -XXX,XX +XXX,XX @@ static void ahci_cmd_done(IDEDMA *dma)
20
@@ -XXX,XX +XXX,XX @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s)
19
21
return l2_table;
20
static void ahci_irq_set(void *opaque, int n, int level)
22
}
23
24
-static bool qed_plug_allocating_write_reqs(BDRVQEDState *s)
25
+static bool coroutine_fn qed_plug_allocating_write_reqs(BDRVQEDState *s)
21
{
26
{
22
+ qemu_log_mask(LOG_UNIMP, "ahci: IRQ#%d level:%d\n", n, level);
27
qemu_co_mutex_lock(&s->table_lock);
28
29
@@ -XXX,XX +XXX,XX @@ static bool qed_plug_allocating_write_reqs(BDRVQEDState *s)
30
return true;
23
}
31
}
24
32
25
static const IDEDMAOps ahci_dma_ops = {
33
-static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
34
+static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s)
35
{
36
qemu_co_mutex_lock(&s->table_lock);
37
assert(s->allocating_write_reqs_plugged);
26
--
38
--
27
2.25.4
39
2.37.3
28
29
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
This structure nearly only contains parent callbacks for child state
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
changes. It cannot really reflect a child's role, because different
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
roles may overlap (as we will see when real roles are introduced), and
5
functions where this holds.
6
because parents can have custom callbacks even when the child fulfills a
7
standard role.
8
6
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-Id: <20220922084924.201610-19-pbonzini@redhat.com>
12
Message-Id: <20200513110544.176672-4-mreitz@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
include/block/block.h | 6 +-
14
block/quorum.c | 36 +++++++++++++++++++-----------------
16
include/block/block_int.h | 22 +++---
15
1 file changed, 19 insertions(+), 17 deletions(-)
17
block.c | 142 ++++++++++++++++++------------------
18
block/backup-top.c | 8 +-
19
block/blkdebug.c | 4 +-
20
block/blklogwrites.c | 8 +-
21
block/block-backend.c | 6 +-
22
block/commit.c | 2 +-
23
block/copy-on-read.c | 2 +-
24
block/io.c | 22 +++---
25
block/mirror.c | 2 +-
26
block/quorum.c | 2 +-
27
block/replication.c | 2 +-
28
block/vvfat.c | 6 +-
29
blockjob.c | 2 +-
30
tests/test-bdrv-drain.c | 36 ++++-----
31
tests/test-bdrv-graph-mod.c | 2 +-
32
17 files changed, 141 insertions(+), 133 deletions(-)
33
16
34
diff --git a/include/block/block.h b/include/block/block.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block.h
37
+++ b/include/block/block.h
38
@@ -XXX,XX +XXX,XX @@
39
/* block.c */
40
typedef struct BlockDriver BlockDriver;
41
typedef struct BdrvChild BdrvChild;
42
-typedef struct BdrvChildRole BdrvChildRole;
43
+typedef struct BdrvChildClass BdrvChildClass;
44
45
typedef struct BlockDriverInfo {
46
/* in bytes, 0 if irrelevant */
47
@@ -XXX,XX +XXX,XX @@ int bdrv_parse_discard_flags(const char *mode, int *flags);
48
BdrvChild *bdrv_open_child(const char *filename,
49
QDict *options, const char *bdref_key,
50
BlockDriverState* parent,
51
- const BdrvChildRole *child_role,
52
+ const BdrvChildClass *child_class,
53
bool allow_none, Error **errp);
54
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
55
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
56
@@ -XXX,XX +XXX,XX @@ void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
57
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
58
BlockDriverState *child_bs,
59
const char *child_name,
60
- const BdrvChildRole *child_role,
61
+ const BdrvChildClass *child_class,
62
Error **errp);
63
64
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
65
diff --git a/include/block/block_int.h b/include/block/block_int.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/block_int.h
68
+++ b/include/block/block_int.h
69
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
70
* the parents in @parent_perm and @parent_shared.
71
*
72
* If @c is NULL, return the permissions for attaching a new child for the
73
- * given @role.
74
+ * given @child_class.
75
*
76
* If @reopen_queue is non-NULL, don't return the currently needed
77
* permissions, but those that will be needed after applying the
78
* @reopen_queue.
79
*/
80
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
81
- const BdrvChildRole *role,
82
+ const BdrvChildClass *child_class,
83
BlockReopenQueue *reopen_queue,
84
uint64_t parent_perm, uint64_t parent_shared,
85
uint64_t *nperm, uint64_t *nshared);
86
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvAioNotifier {
87
QLIST_ENTRY(BdrvAioNotifier) list;
88
} BdrvAioNotifier;
89
90
-struct BdrvChildRole {
91
+struct BdrvChildClass {
92
/* If true, bdrv_replace_node() doesn't change the node this BdrvChild
93
* points to. */
94
bool stay_at_node;
95
@@ -XXX,XX +XXX,XX @@ struct BdrvChildRole {
96
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
97
};
98
99
-extern const BdrvChildRole child_file;
100
-extern const BdrvChildRole child_format;
101
-extern const BdrvChildRole child_backing;
102
+extern const BdrvChildClass child_file;
103
+extern const BdrvChildClass child_format;
104
+extern const BdrvChildClass child_backing;
105
106
struct BdrvChild {
107
BlockDriverState *bs;
108
char *name;
109
- const BdrvChildRole *role;
110
+ const BdrvChildClass *klass;
111
void *opaque;
112
113
/**
114
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
115
116
/*
117
* How many times the parent of this child has been drained
118
- * (through role->drained_*).
119
+ * (through klass->drained_*).
120
* Usually, this is equal to bs->quiesce_counter (potentially
121
* reduced by bdrv_drain_all_count). It may differ while the
122
* child is entering or leaving a drained section.
123
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
124
125
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
126
const char *child_name,
127
- const BdrvChildRole *child_role,
128
+ const BdrvChildClass *child_class,
129
AioContext *ctx,
130
uint64_t perm, uint64_t shared_perm,
131
void *opaque, Error **errp);
132
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
133
* block filters: Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED and RESIZE to
134
* all children */
135
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
136
- const BdrvChildRole *role,
137
+ const BdrvChildClass *child_class,
138
BlockReopenQueue *reopen_queue,
139
uint64_t perm, uint64_t shared,
140
uint64_t *nperm, uint64_t *nshared);
141
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
142
* requires WRITE | RESIZE for read-write images, always requires
143
* CONSISTENT_READ and doesn't share WRITE. */
144
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
145
- const BdrvChildRole *role,
146
+ const BdrvChildClass *child_class,
147
BlockReopenQueue *reopen_queue,
148
uint64_t perm, uint64_t shared,
149
uint64_t *nperm, uint64_t *nshared);
150
diff --git a/block.c b/block.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/block.c
153
+++ b/block.c
154
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
155
const char *reference,
156
QDict *options, int flags,
157
BlockDriverState *parent,
158
- const BdrvChildRole *child_role,
159
+ const BdrvChildClass *child_class,
160
Error **errp);
161
162
/* If non-zero, use only whitelisted block drivers */
163
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
164
*child_flags = flags;
165
}
166
167
-const BdrvChildRole child_file = {
168
+const BdrvChildClass child_file = {
169
.parent_is_bds = true,
170
.get_parent_desc = bdrv_child_get_parent_desc,
171
.inherit_options = bdrv_inherited_options,
172
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options,
173
*child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
174
}
175
176
-const BdrvChildRole child_format = {
177
+const BdrvChildClass child_format = {
178
.parent_is_bds = true,
179
.get_parent_desc = bdrv_child_get_parent_desc,
180
.inherit_options = bdrv_inherited_fmt_options,
181
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
182
return ret;
183
}
184
185
-const BdrvChildRole child_backing = {
186
+const BdrvChildClass child_backing = {
187
.parent_is_bds = true,
188
.get_parent_desc = bdrv_child_get_parent_desc,
189
.attach = bdrv_backing_attach,
190
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
191
}
192
193
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
194
- BdrvChild *c, const BdrvChildRole *role,
195
+ BdrvChild *c, const BdrvChildClass *child_class,
196
BlockReopenQueue *reopen_queue,
197
uint64_t parent_perm, uint64_t parent_shared,
198
uint64_t *nperm, uint64_t *nshared)
199
{
200
assert(bs->drv && bs->drv->bdrv_child_perm);
201
- bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
202
+ bs->drv->bdrv_child_perm(bs, c, child_class, reopen_queue,
203
parent_perm, parent_shared,
204
nperm, nshared);
205
/* TODO Take force_share from reopen_queue */
206
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
207
uint64_t cur_perm, cur_shared;
208
bool child_tighten_restr;
209
210
- bdrv_child_perm(bs, c->bs, c, c->role, q,
211
+ bdrv_child_perm(bs, c->bs, c, c->klass, q,
212
cumulative_perms, cumulative_shared_perms,
213
&cur_perm, &cur_shared);
214
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
215
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
216
/* Update all children */
217
QLIST_FOREACH(c, &bs->children, next) {
218
uint64_t cur_perm, cur_shared;
219
- bdrv_child_perm(bs, c->bs, c, c->role, NULL,
220
+ bdrv_child_perm(bs, c->bs, c, c->klass, NULL,
221
cumulative_perms, cumulative_shared_perms,
222
&cur_perm, &cur_shared);
223
bdrv_child_set_perm(c, cur_perm, cur_shared);
224
@@ -XXX,XX +XXX,XX @@ void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
225
226
static char *bdrv_child_user_desc(BdrvChild *c)
227
{
228
- if (c->role->get_parent_desc) {
229
- return c->role->get_parent_desc(c);
230
+ if (c->klass->get_parent_desc) {
231
+ return c->klass->get_parent_desc(c);
232
}
233
234
return g_strdup("another user");
235
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
236
uint64_t perms, shared;
237
238
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
239
- bdrv_child_perm(bs, c->bs, c, c->role, NULL, parent_perms, parent_shared,
240
+ bdrv_child_perm(bs, c->bs, c, c->klass, NULL, parent_perms, parent_shared,
241
&perms, &shared);
242
243
return bdrv_child_try_set_perm(c, perms, shared, errp);
244
}
245
246
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
247
- const BdrvChildRole *role,
248
+ const BdrvChildClass *child_class,
249
BlockReopenQueue *reopen_queue,
250
uint64_t perm, uint64_t shared,
251
uint64_t *nperm, uint64_t *nshared)
252
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
253
}
254
255
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
256
- const BdrvChildRole *role,
257
+ const BdrvChildClass *child_class,
258
BlockReopenQueue *reopen_queue,
259
uint64_t perm, uint64_t shared,
260
uint64_t *nperm, uint64_t *nshared)
261
{
262
- bool backing = (role == &child_backing);
263
- assert(role == &child_backing || role == &child_file);
264
+ bool backing = (child_class == &child_backing);
265
+ assert(child_class == &child_backing || child_class == &child_file);
266
267
if (!backing) {
268
int flags = bdrv_reopen_get_flags(reopen_queue, bs);
269
270
/* Apart from the modifications below, the same permissions are
271
* forwarded and left alone as for filters */
272
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
273
- &perm, &shared);
274
+ bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
275
+ perm, shared, &perm, &shared);
276
277
/* Format drivers may touch metadata even if the guest doesn't write */
278
if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
279
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
280
* If the new child node is drained but the old one was not, flush
281
* all outstanding requests to the old child node.
282
*/
283
- while (drain_saldo > 0 && child->role->drained_begin) {
284
+ while (drain_saldo > 0 && child->klass->drained_begin) {
285
bdrv_parent_drained_begin_single(child, true);
286
drain_saldo--;
287
}
288
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
289
/* Detach first so that the recursive drain sections coming from @child
290
* are already gone and we only end the drain sections that came from
291
* elsewhere. */
292
- if (child->role->detach) {
293
- child->role->detach(child);
294
+ if (child->klass->detach) {
295
+ child->klass->detach(child);
296
}
297
QLIST_REMOVE(child, next_parent);
298
}
299
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
300
/* Attach only after starting new drained sections, so that recursive
301
* drain sections coming from @child don't get an extra .drained_begin
302
* callback. */
303
- if (child->role->attach) {
304
- child->role->attach(child);
305
+ if (child->klass->attach) {
306
+ child->klass->attach(child);
307
}
308
}
309
310
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
311
* If the old child node was drained but the new one is not, allow
312
* requests to come in only after the new node has been attached.
313
*/
314
- while (drain_saldo < 0 && child->role->drained_end) {
315
+ while (drain_saldo < 0 && child->klass->drained_end) {
316
bdrv_parent_drained_end_single(child);
317
drain_saldo++;
318
}
319
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
320
*/
321
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
322
const char *child_name,
323
- const BdrvChildRole *child_role,
324
+ const BdrvChildClass *child_class,
325
AioContext *ctx,
326
uint64_t perm, uint64_t shared_perm,
327
void *opaque, Error **errp)
328
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
329
*child = (BdrvChild) {
330
.bs = NULL,
331
.name = g_strdup(child_name),
332
- .role = child_role,
333
+ .klass = child_class,
334
.perm = perm,
335
.shared_perm = shared_perm,
336
.opaque = opaque,
337
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
338
* try moving the parent into the AioContext of child_bs instead. */
339
if (bdrv_get_aio_context(child_bs) != ctx) {
340
ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err);
341
- if (ret < 0 && child_role->can_set_aio_ctx) {
342
+ if (ret < 0 && child_class->can_set_aio_ctx) {
343
GSList *ignore = g_slist_prepend(NULL, child);
344
ctx = bdrv_get_aio_context(child_bs);
345
- if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
346
+ if (child_class->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
347
error_free(local_err);
348
ret = 0;
349
g_slist_free(ignore);
350
ignore = g_slist_prepend(NULL, child);
351
- child_role->set_aio_ctx(child, ctx, &ignore);
352
+ child_class->set_aio_ctx(child, ctx, &ignore);
353
}
354
g_slist_free(ignore);
355
}
356
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
357
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
358
BlockDriverState *child_bs,
359
const char *child_name,
360
- const BdrvChildRole *child_role,
361
+ const BdrvChildClass *child_class,
362
Error **errp)
363
{
364
BdrvChild *child;
365
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
366
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
367
368
assert(parent_bs->drv);
369
- bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
370
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_class, NULL,
371
perm, shared_perm, &perm, &shared_perm);
372
373
- child = bdrv_root_attach_child(child_bs, child_name, child_role,
374
+ child = bdrv_root_attach_child(child_bs, child_name, child_class,
375
bdrv_get_aio_context(parent_bs),
376
perm, shared_perm, parent_bs, errp);
377
if (child == NULL) {
378
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
379
{
380
BdrvChild *c;
381
QLIST_FOREACH(c, &bs->parents, next_parent) {
382
- if (c->role->change_media) {
383
- c->role->change_media(c, load);
384
+ if (c->klass->change_media) {
385
+ c->klass->change_media(c, load);
386
}
387
}
388
}
389
@@ -XXX,XX +XXX,XX @@ free_exit:
390
391
static BlockDriverState *
392
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
393
- BlockDriverState *parent, const BdrvChildRole *child_role,
394
+ BlockDriverState *parent, const BdrvChildClass *child_class,
395
bool allow_none, Error **errp)
396
{
397
BlockDriverState *bs = NULL;
398
@@ -XXX,XX +XXX,XX @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
399
char *bdref_key_dot;
400
const char *reference;
401
402
- assert(child_role != NULL);
403
+ assert(child_class != NULL);
404
405
bdref_key_dot = g_strdup_printf("%s.", bdref_key);
406
qdict_extract_subqdict(options, &image_options, bdref_key_dot);
407
@@ -XXX,XX +XXX,XX @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
408
}
409
410
bs = bdrv_open_inherit(filename, reference, image_options, 0,
411
- parent, child_role, errp);
412
+ parent, child_class, errp);
413
if (!bs) {
414
goto done;
415
}
416
@@ -XXX,XX +XXX,XX @@ done:
417
BdrvChild *bdrv_open_child(const char *filename,
418
QDict *options, const char *bdref_key,
419
BlockDriverState *parent,
420
- const BdrvChildRole *child_role,
421
+ const BdrvChildClass *child_class,
422
bool allow_none, Error **errp)
423
{
424
BlockDriverState *bs;
425
426
- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_role,
427
+ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
428
allow_none, errp);
429
if (bs == NULL) {
430
return NULL;
431
}
432
433
- return bdrv_attach_child(parent, bs, bdref_key, child_role, errp);
434
+ return bdrv_attach_child(parent, bs, bdref_key, child_class, errp);
435
}
436
437
-/* TODO Future callers may need to specify parent/child_role in order for
438
- * option inheritance to work. Existing callers use it for the root node. */
439
+/*
440
+ * TODO Future callers may need to specify parent/child_class in order for
441
+ * option inheritance to work. Existing callers use it for the root node.
442
+ */
443
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
444
{
445
BlockDriverState *bs = NULL;
446
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
447
const char *reference,
448
QDict *options, int flags,
449
BlockDriverState *parent,
450
- const BdrvChildRole *child_role,
451
+ const BdrvChildClass *child_class,
452
Error **errp)
453
{
454
int ret;
455
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
456
QDict *snapshot_options = NULL;
457
int snapshot_flags = 0;
458
459
- assert(!child_role || !flags);
460
- assert(!child_role == !parent);
461
+ assert(!child_class || !flags);
462
+ assert(!child_class == !parent);
463
464
if (reference) {
465
bool options_non_empty = options ? qdict_size(options) : false;
466
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
467
468
bs->explicit_options = qdict_clone_shallow(options);
469
470
- if (child_role) {
471
+ if (child_class) {
472
bs->inherits_from = parent;
473
- child_role->inherit_options(&flags, options,
474
- parent->open_flags, parent->options);
475
+ child_class->inherit_options(&flags, options,
476
+ parent->open_flags, parent->options);
477
}
478
479
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
480
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
481
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
482
BlockDriverState *bs,
483
QDict *options,
484
- const BdrvChildRole *role,
485
+ const BdrvChildClass *klass,
486
QDict *parent_options,
487
int parent_flags,
488
bool keep_old_opts)
489
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
490
/* Inherit from parent node */
491
if (parent_options) {
492
flags = 0;
493
- role->inherit_options(&flags, options, parent_flags, parent_options);
494
+ klass->inherit_options(&flags, options, parent_flags, parent_options);
495
} else {
496
flags = bdrv_get_flags(bs);
497
}
498
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
499
}
500
501
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
502
- child->role, options, flags, child_keep_old);
503
+ child->klass, options, flags, child_keep_old);
504
}
505
506
return bs_queue;
507
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
508
} else {
509
uint64_t nperm, nshared;
510
511
- bdrv_child_perm(parent->state.bs, bs, c, c->role, q,
512
+ bdrv_child_perm(parent->state.bs, bs, c, c->klass, q,
513
parent->state.perm, parent->state.shared_perm,
514
&nperm, &nshared);
515
516
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
517
GHashTable *found;
518
bool ret;
519
520
- if (c->role->stay_at_node) {
521
+ if (c->klass->stay_at_node) {
522
return false;
523
}
524
525
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
526
}
527
528
/* If so, update the backing file path in the image file */
529
- if (c->role->update_filename) {
530
- ret = c->role->update_filename(c, base, backing_file_str,
531
- &local_err);
532
+ if (c->klass->update_filename) {
533
+ ret = c->klass->update_filename(c, base, backing_file_str,
534
+ &local_err);
535
if (ret < 0) {
536
bdrv_abort_perm_update(base);
537
error_report_err(local_err);
538
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_parent_name(const BlockDriverState *bs)
539
540
/* If multiple parents have a name, just pick the first one. */
541
QLIST_FOREACH(c, &bs->parents, next_parent) {
542
- if (c->role->get_name) {
543
- name = c->role->get_name(c);
544
+ if (c->klass->get_name) {
545
+ name = c->klass->get_name(c);
546
if (name && *name) {
547
return name;
548
}
549
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
550
}
551
552
QLIST_FOREACH(parent, &bs->parents, next_parent) {
553
- if (parent->role->activate) {
554
- parent->role->activate(parent, &local_err);
555
+ if (parent->klass->activate) {
556
+ parent->klass->activate(parent, &local_err);
557
if (local_err) {
558
bs->open_flags |= BDRV_O_INACTIVE;
559
error_propagate(errp, local_err);
560
@@ -XXX,XX +XXX,XX @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
561
BdrvChild *parent;
562
563
QLIST_FOREACH(parent, &bs->parents, next_parent) {
564
- if (parent->role->parent_is_bds) {
565
+ if (parent->klass->parent_is_bds) {
566
BlockDriverState *parent_bs = parent->opaque;
567
if (!only_active || !(parent_bs->open_flags & BDRV_O_INACTIVE)) {
568
return true;
569
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
570
}
571
572
QLIST_FOREACH(parent, &bs->parents, next_parent) {
573
- if (parent->role->inactivate) {
574
- ret = parent->role->inactivate(parent);
575
+ if (parent->klass->inactivate) {
576
+ ret = parent->klass->inactivate(parent);
577
if (ret < 0) {
578
return ret;
579
}
580
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
581
if (g_slist_find(*ignore, child)) {
582
continue;
583
}
584
- assert(child->role->set_aio_ctx);
585
+ assert(child->klass->set_aio_ctx);
586
*ignore = g_slist_prepend(*ignore, child);
587
- child->role->set_aio_ctx(child, new_context, ignore);
588
+ child->klass->set_aio_ctx(child, new_context, ignore);
589
}
590
591
bdrv_detach_aio_context(bs);
592
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
593
}
594
*ignore = g_slist_prepend(*ignore, c);
595
596
- /* A BdrvChildRole that doesn't handle AioContext changes cannot
597
- * tolerate any AioContext changes */
598
- if (!c->role->can_set_aio_ctx) {
599
+ /*
600
+ * A BdrvChildClass that doesn't handle AioContext changes cannot
601
+ * tolerate any AioContext changes
602
+ */
603
+ if (!c->klass->can_set_aio_ctx) {
604
char *user = bdrv_child_user_desc(c);
605
error_setg(errp, "Changing iothreads is not supported by %s", user);
606
g_free(user);
607
return false;
608
}
609
- if (!c->role->can_set_aio_ctx(c, ctx, ignore, errp)) {
610
+ if (!c->klass->can_set_aio_ctx(c, ctx, ignore, errp)) {
611
assert(!errp || *errp);
612
return false;
613
}
614
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
615
drv->bdrv_gather_child_options(bs, opts, backing_overridden);
616
} else {
617
QLIST_FOREACH(child, &bs->children, next) {
618
- if (child->role == &child_backing && !backing_overridden) {
619
+ if (child->klass == &child_backing && !backing_overridden) {
620
/* We can skip the backing BDS if it has not been overridden */
621
continue;
622
}
623
diff --git a/block/backup-top.c b/block/backup-top.c
624
index XXXXXXX..XXXXXXX 100644
625
--- a/block/backup-top.c
626
+++ b/block/backup-top.c
627
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
628
}
629
630
static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
631
- const BdrvChildRole *role,
632
+ const BdrvChildClass *child_class,
633
BlockReopenQueue *reopen_queue,
634
uint64_t perm, uint64_t shared,
635
uint64_t *nperm, uint64_t *nshared)
636
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
637
return;
638
}
639
640
- if (role == &child_file) {
641
+ if (child_class == &child_file) {
642
/*
643
* Target child
644
*
645
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
646
*nperm = BLK_PERM_WRITE;
647
} else {
648
/* Source child */
649
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
650
- nperm, nshared);
651
+ bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
652
+ perm, shared, nperm, nshared);
653
654
if (perm & BLK_PERM_WRITE) {
655
*nperm = *nperm | BLK_PERM_CONSISTENT_READ;
656
diff --git a/block/blkdebug.c b/block/blkdebug.c
657
index XXXXXXX..XXXXXXX 100644
658
--- a/block/blkdebug.c
659
+++ b/block/blkdebug.c
660
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
661
}
662
663
static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
664
- const BdrvChildRole *role,
665
+ const BdrvChildClass *child_class,
666
BlockReopenQueue *reopen_queue,
667
uint64_t perm, uint64_t shared,
668
uint64_t *nperm, uint64_t *nshared)
669
{
670
BDRVBlkdebugState *s = bs->opaque;
671
672
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
673
+ bdrv_filter_default_perms(bs, c, child_class, reopen_queue, perm, shared,
674
nperm, nshared);
675
676
*nperm |= s->take_child_perms;
677
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
678
index XXXXXXX..XXXXXXX 100644
679
--- a/block/blklogwrites.c
680
+++ b/block/blklogwrites.c
681
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
682
}
683
684
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
685
- const BdrvChildRole *role,
686
+ const BdrvChildClass *child_class,
687
BlockReopenQueue *ro_q,
688
uint64_t perm, uint64_t shrd,
689
uint64_t *nperm, uint64_t *nshrd)
690
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
691
}
692
693
if (!strcmp(c->name, "log")) {
694
- bdrv_format_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd);
695
+ bdrv_format_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
696
+ nshrd);
697
} else {
698
- bdrv_filter_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd);
699
+ bdrv_filter_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
700
+ nshrd);
701
}
702
}
703
704
diff --git a/block/block-backend.c b/block/block-backend.c
705
index XXXXXXX..XXXXXXX 100644
706
--- a/block/block-backend.c
707
+++ b/block/block-backend.c
708
@@ -XXX,XX +XXX,XX @@ static void blk_root_detach(BdrvChild *child)
709
}
710
}
711
712
-static const BdrvChildRole child_root = {
713
+static const BdrvChildClass child_root = {
714
.inherit_options = blk_root_inherit_options,
715
716
.change_media = blk_root_change_media,
717
@@ -XXX,XX +XXX,XX @@ static BlockBackend *bdrv_first_blk(BlockDriverState *bs)
718
{
719
BdrvChild *child;
720
QLIST_FOREACH(child, &bs->parents, next_parent) {
721
- if (child->role == &child_root) {
722
+ if (child->klass == &child_root) {
723
return child->opaque;
724
}
725
}
726
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_root_node(BlockDriverState *bs)
727
BdrvChild *c;
728
729
QLIST_FOREACH(c, &bs->parents, next_parent) {
730
- if (c->role != &child_root) {
731
+ if (c->klass != &child_root) {
732
return false;
733
}
734
}
735
diff --git a/block/commit.c b/block/commit.c
736
index XXXXXXX..XXXXXXX 100644
737
--- a/block/commit.c
738
+++ b/block/commit.c
739
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
740
}
741
742
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
743
- const BdrvChildRole *role,
744
+ const BdrvChildClass *child_class,
745
BlockReopenQueue *reopen_queue,
746
uint64_t perm, uint64_t shared,
747
uint64_t *nperm, uint64_t *nshared)
748
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
749
index XXXXXXX..XXXXXXX 100644
750
--- a/block/copy-on-read.c
751
+++ b/block/copy-on-read.c
752
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
753
#define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH)
754
755
static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
756
- const BdrvChildRole *role,
757
+ const BdrvChildClass *child_class,
758
BlockReopenQueue *reopen_queue,
759
uint64_t perm, uint64_t shared,
760
uint64_t *nperm, uint64_t *nshared)
761
diff --git a/block/io.c b/block/io.c
762
index XXXXXXX..XXXXXXX 100644
763
--- a/block/io.c
764
+++ b/block/io.c
765
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
766
BdrvChild *c, *next;
767
768
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
769
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
770
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
771
continue;
772
}
773
bdrv_parent_drained_begin_single(c, false);
774
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end_single_no_poll(BdrvChild *c,
775
{
776
assert(c->parent_quiesce_counter > 0);
777
c->parent_quiesce_counter--;
778
- if (c->role->drained_end) {
779
- c->role->drained_end(c, drained_end_counter);
780
+ if (c->klass->drained_end) {
781
+ c->klass->drained_end(c, drained_end_counter);
782
}
783
}
784
785
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
786
BdrvChild *c;
787
788
QLIST_FOREACH(c, &bs->parents, next_parent) {
789
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
790
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
791
continue;
792
}
793
bdrv_parent_drained_end_single_no_poll(c, drained_end_counter);
794
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
795
796
static bool bdrv_parent_drained_poll_single(BdrvChild *c)
797
{
798
- if (c->role->drained_poll) {
799
- return c->role->drained_poll(c);
800
+ if (c->klass->drained_poll) {
801
+ return c->klass->drained_poll(c);
802
}
803
return false;
804
}
805
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
806
bool busy = false;
807
808
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
809
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
810
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
811
continue;
812
}
813
busy |= bdrv_parent_drained_poll_single(c);
814
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
815
void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
816
{
817
c->parent_quiesce_counter++;
818
- if (c->role->drained_begin) {
819
- c->role->drained_begin(c);
820
+ if (c->klass->drained_begin) {
821
+ c->klass->drained_begin(c);
822
}
823
if (poll) {
824
BDRV_POLL_WHILE(c->bs, bdrv_parent_drained_poll_single(c));
825
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
826
{
827
BdrvChild *c;
828
QLIST_FOREACH(c, &bs->parents, next_parent) {
829
- if (c->role->resize) {
830
- c->role->resize(c);
831
+ if (c->klass->resize) {
832
+ c->klass->resize(c);
833
}
834
}
835
}
836
diff --git a/block/mirror.c b/block/mirror.c
837
index XXXXXXX..XXXXXXX 100644
838
--- a/block/mirror.c
839
+++ b/block/mirror.c
840
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
841
}
842
843
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
844
- const BdrvChildRole *role,
845
+ const BdrvChildClass *child_class,
846
BlockReopenQueue *reopen_queue,
847
uint64_t perm, uint64_t shared,
848
uint64_t *nperm, uint64_t *nshared)
849
diff --git a/block/quorum.c b/block/quorum.c
17
diff --git a/block/quorum.c b/block/quorum.c
850
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
851
--- a/block/quorum.c
19
--- a/block/quorum.c
852
+++ b/block/quorum.c
20
+++ b/block/quorum.c
853
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ static bool quorum_64bits_compare(QuorumVoteValue *a, QuorumVoteValue *b)
22
return a->l == b->l;
854
}
23
}
855
24
856
static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
25
-static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
857
- const BdrvChildRole *role,
26
- QEMUIOVector *qiov,
858
+ const BdrvChildClass *child_class,
27
- uint64_t offset,
859
BlockReopenQueue *reopen_queue,
28
- uint64_t bytes,
860
uint64_t perm, uint64_t shared,
29
- int flags)
861
uint64_t *nperm, uint64_t *nshared)
30
+static QuorumAIOCB *coroutine_fn quorum_aio_get(BlockDriverState *bs,
862
diff --git a/block/replication.c b/block/replication.c
31
+ QEMUIOVector *qiov,
863
index XXXXXXX..XXXXXXX 100644
32
+ uint64_t offset, uint64_t bytes,
864
--- a/block/replication.c
33
+ int flags)
865
+++ b/block/replication.c
34
{
866
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
35
BDRVQuorumState *s = bs->opaque;
36
QuorumAIOCB *acb = g_new(QuorumAIOCB, 1);
37
@@ -XXX,XX +XXX,XX @@ static void quorum_report_bad_versions(BDRVQuorumState *s,
38
}
867
}
39
}
868
40
869
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
41
-static void quorum_rewrite_entry(void *opaque)
870
- const BdrvChildRole *role,
42
+static void coroutine_fn quorum_rewrite_entry(void *opaque)
871
+ const BdrvChildClass *child_class,
43
{
872
BlockReopenQueue *reopen_queue,
44
QuorumCo *co = opaque;
873
uint64_t perm, uint64_t shared,
45
QuorumAIOCB *acb = co->acb;
874
uint64_t *nperm, uint64_t *nshared)
46
@@ -XXX,XX +XXX,XX @@ free_exit:
875
diff --git a/block/vvfat.c b/block/vvfat.c
47
quorum_free_vote_list(&acb->votes);
876
index XXXXXXX..XXXXXXX 100644
877
--- a/block/vvfat.c
878
+++ b/block/vvfat.c
879
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
880
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
881
}
48
}
882
49
883
-static const BdrvChildRole child_vvfat_qcow = {
50
-static void read_quorum_children_entry(void *opaque)
884
+static const BdrvChildClass child_vvfat_qcow = {
51
+static void coroutine_fn read_quorum_children_entry(void *opaque)
885
.parent_is_bds = true,
52
{
886
.inherit_options = vvfat_qcow_options,
53
QuorumCo *co = opaque;
887
};
54
QuorumAIOCB *acb = co->acb;
888
@@ -XXX,XX +XXX,XX @@ err:
55
@@ -XXX,XX +XXX,XX @@ static void read_quorum_children_entry(void *opaque)
56
}
889
}
57
}
890
58
891
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
59
-static int read_quorum_children(QuorumAIOCB *acb)
892
- const BdrvChildRole *role,
60
+static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
893
+ const BdrvChildClass *child_class,
894
BlockReopenQueue *reopen_queue,
895
uint64_t perm, uint64_t shared,
896
uint64_t *nperm, uint64_t *nshared)
897
{
61
{
898
BDRVVVFATState *s = bs->opaque;
62
BDRVQuorumState *s = acb->bs->opaque;
899
63
int i;
900
- assert(c == s->qcow || role == &child_backing);
64
@@ -XXX,XX +XXX,XX @@ static int read_quorum_children(QuorumAIOCB *acb)
901
+ assert(c == s->qcow || child_class == &child_backing);
65
return acb->vote_ret;
902
903
if (c == s->qcow) {
904
/* This is a private node, nobody should try to attach to it */
905
diff --git a/blockjob.c b/blockjob.c
906
index XXXXXXX..XXXXXXX 100644
907
--- a/blockjob.c
908
+++ b/blockjob.c
909
@@ -XXX,XX +XXX,XX @@ static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
910
job->job.aio_context = ctx;
911
}
66
}
912
67
913
-static const BdrvChildRole child_job = {
68
-static int read_fifo_child(QuorumAIOCB *acb)
914
+static const BdrvChildClass child_job = {
69
+static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
915
.get_parent_desc = child_job_get_parent_desc,
70
{
916
.drained_begin = child_job_drained_begin,
71
BDRVQuorumState *s = acb->bs->opaque;
917
.drained_poll = child_job_drained_poll,
72
int n, ret;
918
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
73
@@ -XXX,XX +XXX,XX @@ static int read_fifo_child(QuorumAIOCB *acb)
919
index XXXXXXX..XXXXXXX 100644
74
return ret;
920
--- a/tests/test-bdrv-drain.c
921
+++ b/tests/test-bdrv-drain.c
922
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
923
}
75
}
924
76
925
static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
77
-static int quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
926
- const BdrvChildRole *role,
78
- QEMUIOVector *qiov, BdrvRequestFlags flags)
927
+ const BdrvChildClass *child_class,
79
+static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
928
BlockReopenQueue *reopen_queue,
80
+ int64_t offset, int64_t bytes,
929
uint64_t perm, uint64_t shared,
81
+ QEMUIOVector *qiov,
930
uint64_t *nperm, uint64_t *nshared)
82
+ BdrvRequestFlags flags)
931
{
83
{
932
- /* bdrv_format_default_perms() accepts only these two, so disguise
84
BDRVQuorumState *s = bs->opaque;
933
- * detach_by_driver_cb_role as one of them. */
85
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
934
- if (role != &child_file && role != &child_backing) {
86
@@ -XXX,XX +XXX,XX @@ static int quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
935
- role = &child_file;
87
return ret;
936
+ /*
88
}
937
+ * bdrv_format_default_perms() accepts only these two, so disguise
89
938
+ * detach_by_driver_cb_parent as one of them.
90
-static void write_quorum_entry(void *opaque)
939
+ */
91
+static void coroutine_fn write_quorum_entry(void *opaque)
940
+ if (child_class != &child_file && child_class != &child_backing) {
92
{
941
+ child_class = &child_file;
93
QuorumCo *co = opaque;
94
QuorumAIOCB *acb = co->acb;
95
@@ -XXX,XX +XXX,XX @@ static void write_quorum_entry(void *opaque)
942
}
96
}
943
944
- bdrv_format_default_perms(bs, c, role, reopen_queue, perm, shared,
945
+ bdrv_format_default_perms(bs, c, child_class, reopen_queue, perm, shared,
946
nperm, nshared);
947
}
97
}
948
98
949
@@ -XXX,XX +XXX,XX @@ static void detach_by_driver_cb_drained_begin(BdrvChild *child)
99
-static int quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
950
child_file.drained_begin(child);
100
- int64_t bytes, QEMUIOVector *qiov,
101
- BdrvRequestFlags flags)
102
+static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
103
+ int64_t bytes, QEMUIOVector *qiov,
104
+ BdrvRequestFlags flags)
105
{
106
BDRVQuorumState *s = bs->opaque;
107
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
108
@@ -XXX,XX +XXX,XX @@ static int quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
109
return ret;
951
}
110
}
952
111
953
-static BdrvChildRole detach_by_driver_cb_role;
112
-static int quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
954
+static BdrvChildClass detach_by_driver_cb_class;
113
- int64_t bytes, BdrvRequestFlags flags)
955
114
+static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
956
/*
115
+ int64_t offset, int64_t bytes,
957
* Initial graph:
116
+ BdrvRequestFlags flags)
958
@@ -XXX,XX +XXX,XX @@ static BdrvChildRole detach_by_driver_cb_role;
117
959
*
960
* by_parent_cb == false: Test that bdrv_drain_invoke() doesn't poll
961
*
962
- * PA's BdrvChildRole has a .drained_begin callback that schedules a BH
963
+ * PA's BdrvChildClass has a .drained_begin callback that schedules a BH
964
* that does the same graph change. If bdrv_drain_invoke() calls it, the
965
* state is messed up, but if it is only polled in the single
966
* BDRV_POLL_WHILE() at the end of the drain, this should work fine.
967
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
968
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
969
970
if (!by_parent_cb) {
971
- detach_by_driver_cb_role = child_file;
972
- detach_by_driver_cb_role.drained_begin =
973
+ detach_by_driver_cb_class = child_file;
974
+ detach_by_driver_cb_class.drained_begin =
975
detach_by_driver_cb_drained_begin;
976
}
977
978
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
979
980
bdrv_ref(a);
981
bdrv_attach_child(parent_a, a, "PA-A",
982
- by_parent_cb ? &child_file : &detach_by_driver_cb_role,
983
+ by_parent_cb ? &child_file : &detach_by_driver_cb_class,
984
&error_abort);
985
986
g_assert_cmpint(parent_a->refcnt, ==, 1);
987
@@ -XXX,XX +XXX,XX @@ static int drop_intermediate_poll_update_filename(BdrvChild *child,
988
/**
989
* Test a poll in the midst of bdrv_drop_intermediate().
990
*
991
- * bdrv_drop_intermediate() calls BdrvChildRole.update_filename(),
992
+ * bdrv_drop_intermediate() calls BdrvChildClass.update_filename(),
993
* which can yield or poll. This may lead to graph changes, unless
994
* the whole subtree in question is drained.
995
*
996
@@ -XXX,XX +XXX,XX @@ static int drop_intermediate_poll_update_filename(BdrvChild *child,
997
*
998
* The solution is for bdrv_drop_intermediate() to drain top's
999
* subtree. This prevents graph changes from happening just because
1000
- * BdrvChildRole.update_filename() yields or polls. Thus, the block
1001
+ * BdrvChildClass.update_filename() yields or polls. Thus, the block
1002
* job is paused during that drained section and must finish before or
1003
* after.
1004
*
1005
@@ -XXX,XX +XXX,XX @@ static int drop_intermediate_poll_update_filename(BdrvChild *child,
1006
*/
1007
static void test_drop_intermediate_poll(void)
1008
{
118
{
1009
- static BdrvChildRole chain_child_role;
119
return quorum_co_pwritev(bs, offset, bytes, NULL,
1010
+ static BdrvChildClass chain_child_class;
1011
BlockDriverState *chain[3];
1012
TestSimpleBlockJob *job;
1013
BlockDriverState *job_node;
1014
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
1015
int i;
1016
int ret;
1017
1018
- chain_child_role = child_backing;
1019
- chain_child_role.update_filename = drop_intermediate_poll_update_filename;
1020
+ chain_child_class = child_backing;
1021
+ chain_child_class.update_filename = drop_intermediate_poll_update_filename;
1022
1023
for (i = 0; i < 3; i++) {
1024
char name[32];
1025
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
1026
if (i) {
1027
/* Takes the reference to chain[i - 1] */
1028
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
1029
- "chain", &chain_child_role,
1030
+ "chain", &chain_child_class,
1031
&error_abort);
1032
}
1033
}
1034
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
1035
index XXXXXXX..XXXXXXX 100644
1036
--- a/tests/test-bdrv-graph-mod.c
1037
+++ b/tests/test-bdrv-graph-mod.c
1038
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_pass_through = {
1039
};
1040
1041
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
1042
- const BdrvChildRole *role,
1043
+ const BdrvChildClass *child_class,
1044
BlockReopenQueue *reopen_queue,
1045
uint64_t perm, uint64_t shared,
1046
uint64_t *nperm, uint64_t *nshared)
1047
--
120
--
1048
2.25.4
121
2.37.3
1049
1050
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Note that some filters have secondary children, namely blkverify (the
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
image to be verified) and blklogwrites (the log). This patch does not
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
touch those children.
5
functions where this holds.
6
6
7
Note that for blkverify, the filtered child should not be format-probed.
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
While there is nothing enforcing this here, in practice, it will not be:
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
blkverify implements .bdrv_file_open. The block layer ensures (and in
9
Message-Id: <20220922084924.201610-20-pbonzini@redhat.com>
10
fact, asserts) that BDRV_O_PROTOCOL is set for every BDS whose driver
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
implements .bdrv_file_open. This flag will then be bequeathed to
12
blkverify's children, and they will thus (by default) not be probed
13
either.
14
15
("By default" refers to the fact that blkverify's other child (the
16
non-filtered one) will have BDRV_O_PROTOCOL force-unset, because that is
17
what happens for all non-filtered children of non-format drivers.)
18
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Message-Id: <20200513110544.176672-27-mreitz@redhat.com>
21
Reviewed-by: Eric Blake <eblake@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
12
---
24
block/blkdebug.c | 4 +++-
13
block/throttle.c | 2 +-
25
block/blklogwrites.c | 3 ++-
14
1 file changed, 1 insertion(+), 1 deletion(-)
26
block/blkreplay.c | 5 +++--
27
block/blkverify.c | 4 +++-
28
block/copy-on-read.c | 5 +++--
29
block/filter-compress.c | 5 +++--
30
block/replication.c | 3 ++-
31
block/throttle.c | 5 +++--
32
8 files changed, 22 insertions(+), 12 deletions(-)
33
15
34
diff --git a/block/blkdebug.c b/block/blkdebug.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/blkdebug.c
37
+++ b/block/blkdebug.c
38
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
39
40
/* Open the image file */
41
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
42
- bs, &child_file, 0, false, &local_err);
43
+ bs, &child_of_bds,
44
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
45
+ false, &local_err);
46
if (local_err) {
47
ret = -EINVAL;
48
error_propagate(errp, local_err);
49
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/blklogwrites.c
52
+++ b/block/blklogwrites.c
53
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
54
}
55
56
/* Open the file */
57
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
58
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
59
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
60
&local_err);
61
if (local_err) {
62
ret = -EINVAL;
63
diff --git a/block/blkreplay.c b/block/blkreplay.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/blkreplay.c
66
+++ b/block/blkreplay.c
67
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
68
int ret;
69
70
/* Open the image file */
71
- bs->file = bdrv_open_child(NULL, options, "image",
72
- bs, &child_file, 0, false, &local_err);
73
+ bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
74
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
75
+ false, &local_err);
76
if (local_err) {
77
ret = -EINVAL;
78
error_propagate(errp, local_err);
79
diff --git a/block/blkverify.c b/block/blkverify.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/block/blkverify.c
82
+++ b/block/blkverify.c
83
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
84
85
/* Open the raw file */
86
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
87
- bs, &child_file, 0, false, &local_err);
88
+ bs, &child_of_bds,
89
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
90
+ false, &local_err);
91
if (local_err) {
92
ret = -EINVAL;
93
error_propagate(errp, local_err);
94
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/copy-on-read.c
97
+++ b/block/copy-on-read.c
98
@@ -XXX,XX +XXX,XX @@
99
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
100
Error **errp)
101
{
102
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
103
- errp);
104
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
105
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
106
+ false, errp);
107
if (!bs->file) {
108
return -EINVAL;
109
}
110
diff --git a/block/filter-compress.c b/block/filter-compress.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/filter-compress.c
113
+++ b/block/filter-compress.c
114
@@ -XXX,XX +XXX,XX @@
115
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
116
Error **errp)
117
{
118
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
119
- errp);
120
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
121
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
122
+ false, errp);
123
if (!bs->file) {
124
return -EINVAL;
125
}
126
diff --git a/block/replication.c b/block/replication.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/block/replication.c
129
+++ b/block/replication.c
130
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
131
const char *mode;
132
const char *top_id;
133
134
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
135
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
136
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
137
false, errp);
138
if (!bs->file) {
139
return -EINVAL;
140
diff --git a/block/throttle.c b/block/throttle.c
16
diff --git a/block/throttle.c b/block/throttle.c
141
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
142
--- a/block/throttle.c
18
--- a/block/throttle.c
143
+++ b/block/throttle.c
19
+++ b/block/throttle.c
144
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
20
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
145
char *group;
21
BDRV_REQ_WRITE_COMPRESSED);
146
int ret;
22
}
147
23
148
- bs->file = bdrv_open_child(NULL, options, "file", bs,
24
-static int throttle_co_flush(BlockDriverState *bs)
149
- &child_file, 0, false, errp);
25
+static int coroutine_fn throttle_co_flush(BlockDriverState *bs)
150
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
26
{
151
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
27
return bdrv_co_flush(bs->file->bs);
152
+ false, errp);
28
}
153
if (!bs->file) {
154
return -EINVAL;
155
}
156
--
29
--
157
2.25.4
30
2.37.3
158
159
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We want to unify child_format and child_file at some point. One of the
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
important things that set format drivers apart from other drivers is
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
that they do not expect other format nodes under them (except in the
5
functions where this holds.
6
backing chain), i.e. we must not probe formats inside of formats. That
7
means we need something on which to distinguish format drivers from
8
others, and hence this flag.
9
6
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-Id: <20220922084924.201610-21-pbonzini@redhat.com>
13
Message-Id: <20200513110544.176672-3-mreitz@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
13
---
16
include/block/block_int.h | 7 +++++++
14
block/vmdk.c | 22 ++++++++++++----------
17
block/bochs.c | 1 +
15
1 file changed, 12 insertions(+), 10 deletions(-)
18
block/cloop.c | 1 +
19
block/crypto.c | 2 ++
20
block/dmg.c | 1 +
21
block/parallels.c | 1 +
22
block/qcow.c | 1 +
23
block/qcow2.c | 1 +
24
block/qed.c | 1 +
25
block/raw-format.c | 1 +
26
block/vdi.c | 1 +
27
block/vhdx.c | 1 +
28
block/vmdk.c | 1 +
29
block/vpc.c | 1 +
30
14 files changed, 21 insertions(+)
31
16
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
35
+++ b/include/block/block_int.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
* must implement them and return -ENOTSUP.
38
*/
39
bool is_filter;
40
+ /*
41
+ * Set to true if the BlockDriver is a format driver. Format nodes
42
+ * generally do not expect their children to be other format nodes
43
+ * (except for backing files), and so format probing is disabled
44
+ * on those children.
45
+ */
46
+ bool is_format;
47
/*
48
* Return true if @to_replace can be replaced by a BDS with the
49
* same data as @bs without it affecting @bs's behavior (that is,
50
diff --git a/block/bochs.c b/block/bochs.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/block/bochs.c
53
+++ b/block/bochs.c
54
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_bochs = {
55
.bdrv_refresh_limits = bochs_refresh_limits,
56
.bdrv_co_preadv = bochs_co_preadv,
57
.bdrv_close        = bochs_close,
58
+ .is_format = true,
59
};
60
61
static void bdrv_bochs_init(void)
62
diff --git a/block/cloop.c b/block/cloop.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/cloop.c
65
+++ b/block/cloop.c
66
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_cloop = {
67
.bdrv_refresh_limits = cloop_refresh_limits,
68
.bdrv_co_preadv = cloop_co_preadv,
69
.bdrv_close = cloop_close,
70
+ .is_format = true,
71
};
72
73
static void bdrv_cloop_init(void)
74
diff --git a/block/crypto.c b/block/crypto.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/crypto.c
77
+++ b/block/crypto.c
78
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_crypto_luks = {
79
.bdrv_get_info = block_crypto_get_info_luks,
80
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
81
82
+ .is_format = true,
83
+
84
.strong_runtime_opts = block_crypto_strong_runtime_opts,
85
};
86
87
diff --git a/block/dmg.c b/block/dmg.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/dmg.c
90
+++ b/block/dmg.c
91
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_dmg = {
92
.bdrv_child_perm = bdrv_format_default_perms,
93
.bdrv_co_preadv = dmg_co_preadv,
94
.bdrv_close = dmg_close,
95
+ .is_format = true,
96
};
97
98
static void bdrv_dmg_init(void)
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
104
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
105
.bdrv_co_readv = parallels_co_readv,
106
.bdrv_co_writev = parallels_co_writev,
107
+ .is_format = true,
108
.supports_backing = true,
109
.bdrv_co_create = parallels_co_create,
110
.bdrv_co_create_opts = parallels_co_create_opts,
111
diff --git a/block/qcow.c b/block/qcow.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/qcow.c
114
+++ b/block/qcow.c
115
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
116
.bdrv_co_create = qcow_co_create,
117
.bdrv_co_create_opts = qcow_co_create_opts,
118
.bdrv_has_zero_init = bdrv_has_zero_init_1,
119
+ .is_format = true,
120
.supports_backing = true,
121
.bdrv_refresh_limits = qcow_refresh_limits,
122
123
diff --git a/block/qcow2.c b/block/qcow2.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/block/qcow2.c
126
+++ b/block/qcow2.c
127
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
128
.bdrv_save_vmstate = qcow2_save_vmstate,
129
.bdrv_load_vmstate = qcow2_load_vmstate,
130
131
+ .is_format = true,
132
.supports_backing = true,
133
.bdrv_change_backing_file = qcow2_change_backing_file,
134
135
diff --git a/block/qed.c b/block/qed.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/block/qed.c
138
+++ b/block/qed.c
139
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
140
.format_name = "qed",
141
.instance_size = sizeof(BDRVQEDState),
142
.create_opts = &qed_create_opts,
143
+ .is_format = true,
144
.supports_backing = true,
145
146
.bdrv_probe = bdrv_qed_probe,
147
diff --git a/block/raw-format.c b/block/raw-format.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/block/raw-format.c
150
+++ b/block/raw-format.c
151
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
152
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
153
.bdrv_co_truncate = &raw_co_truncate,
154
.bdrv_getlength = &raw_getlength,
155
+ .is_format = true,
156
.has_variable_length = true,
157
.bdrv_measure = &raw_measure,
158
.bdrv_get_info = &raw_get_info,
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
164
165
.bdrv_get_info = vdi_get_info,
166
167
+ .is_format = true,
168
.create_opts = &vdi_create_opts,
169
.bdrv_co_check = vdi_co_check,
170
};
171
diff --git a/block/vhdx.c b/block/vhdx.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/block/vhdx.c
174
+++ b/block/vhdx.c
175
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
176
.bdrv_co_check = vhdx_co_check,
177
.bdrv_has_zero_init = vhdx_has_zero_init,
178
179
+ .is_format = true,
180
.create_opts = &vhdx_create_opts,
181
};
182
183
diff --git a/block/vmdk.c b/block/vmdk.c
17
diff --git a/block/vmdk.c b/block/vmdk.c
184
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
185
--- a/block/vmdk.c
19
--- a/block/vmdk.c
186
+++ b/block/vmdk.c
20
+++ b/block/vmdk.c
187
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
188
.bdrv_get_info = vmdk_get_info,
22
return ret;
189
.bdrv_gather_child_options = vmdk_gather_child_options,
23
}
190
24
191
+ .is_format = true,
25
-static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
192
.supports_backing = true,
26
- int64_t offset_in_cluster, QEMUIOVector *qiov,
193
.create_opts = &vmdk_create_opts,
27
- uint64_t qiov_offset, uint64_t n_bytes,
194
};
28
- uint64_t offset)
195
diff --git a/block/vpc.c b/block/vpc.c
29
+static int coroutine_fn
196
index XXXXXXX..XXXXXXX 100644
30
+vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
197
--- a/block/vpc.c
31
+ int64_t offset_in_cluster, QEMUIOVector *qiov,
198
+++ b/block/vpc.c
32
+ uint64_t qiov_offset, uint64_t n_bytes,
199
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
33
+ uint64_t offset)
200
34
{
201
.bdrv_get_info = vpc_get_info,
35
int ret;
202
36
VmdkGrainMarker *data = NULL;
203
+ .is_format = true,
37
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
204
.create_opts = &vpc_create_opts,
38
return ret;
205
.bdrv_has_zero_init = vpc_has_zero_init,
39
}
206
.strong_runtime_opts = vpc_strong_runtime_opts,
40
41
-static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
42
- int64_t offset_in_cluster, QEMUIOVector *qiov,
43
- int bytes)
44
+static int coroutine_fn
45
+vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
46
+ int64_t offset_in_cluster, QEMUIOVector *qiov,
47
+ int bytes)
48
{
49
int ret;
50
int cluster_bytes, buf_bytes;
51
@@ -XXX,XX +XXX,XX @@ fail:
52
*
53
* Returns: error code with 0 for success.
54
*/
55
-static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
56
- uint64_t bytes, QEMUIOVector *qiov,
57
- bool zeroed, bool zero_dry_run)
58
+static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
59
+ uint64_t bytes, QEMUIOVector *qiov,
60
+ bool zeroed, bool zero_dry_run)
61
{
62
BDRVVmdkState *s = bs->opaque;
63
VmdkExtent *extent = NULL;
207
--
64
--
208
2.25.4
65
2.37.3
209
210
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
Reviewed-by: Eric Blake <eblake@redhat.com>
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
Message-Id: <20200513110544.176672-29-mreitz@redhat.com>
5
functions where this holds.
6
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20220922084924.201610-22-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
12
---
8
tests/test-bdrv-drain.c | 29 +++++++++++++++++------------
13
include/qemu/job.h | 2 +-
9
tests/test-bdrv-graph-mod.c | 6 ++++--
14
job.c | 2 +-
10
2 files changed, 21 insertions(+), 14 deletions(-)
15
2 files changed, 2 insertions(+), 2 deletions(-)
11
16
12
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
17
diff --git a/include/qemu/job.h b/include/qemu/job.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/test-bdrv-drain.c
19
--- a/include/qemu/job.h
15
+++ b/tests/test-bdrv-drain.c
20
+++ b/include/qemu/job.h
16
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
21
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job);
17
* detach_by_driver_cb_parent as one of them.
22
*
18
*/
23
* Yield the job coroutine.
19
if (child_class != &child_file && child_class != &child_of_bds) {
24
*/
20
- child_class = &child_file;
25
-void job_yield(Job *job);
21
+ child_class = &child_of_bds;
26
+void coroutine_fn job_yield(Job *job);
27
28
/**
29
* @job: The job that calls the function.
30
diff --git a/job.c b/job.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/job.c
33
+++ b/job.c
34
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job)
22
}
35
}
23
24
bdrv_format_default_perms(bs, c, child_class, role, reopen_queue,
25
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
26
27
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
28
&error_abort);
29
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
30
+ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds,
31
+ BDRV_CHILD_DATA, &error_abort);
32
33
/* This child will be the one to pass to requests through to, and
34
* it will stall until a drain occurs */
35
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
36
&error_abort);
37
child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS;
38
/* Takes our reference to child_bs */
39
- tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", &child_file,
40
- 0, &error_abort);
41
+ tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child",
42
+ &child_of_bds,
43
+ BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
44
+ &error_abort);
45
46
/* This child is just there to be deleted
47
* (for detach_instead_of_delete == true) */
48
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
49
&error_abort);
50
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
51
+ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA,
52
+ &error_abort);
53
54
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
55
blk_insert_bs(blk, bs, &error_abort);
56
@@ -XXX,XX +XXX,XX @@ static void detach_indirect_bh(void *opaque)
57
58
bdrv_ref(data->c);
59
data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C",
60
- &child_file, 0, &error_abort);
61
+ &child_of_bds, BDRV_CHILD_DATA,
62
+ &error_abort);
63
}
36
}
64
37
65
static void detach_by_parent_aio_cb(void *opaque, int ret)
38
-void job_yield(Job *job)
66
@@ -XXX,XX +XXX,XX @@ static void detach_by_driver_cb_drained_begin(BdrvChild *child)
39
+void coroutine_fn job_yield(Job *job)
67
{
40
{
68
aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
41
assert(job->busy);
69
detach_indirect_bh, &detach_by_parent_data);
70
- child_file.drained_begin(child);
71
+ child_of_bds.drained_begin(child);
72
}
73
74
static BdrvChildClass detach_by_driver_cb_class;
75
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
76
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
77
78
if (!by_parent_cb) {
79
- detach_by_driver_cb_class = child_file;
80
+ detach_by_driver_cb_class = child_of_bds;
81
detach_by_driver_cb_class.drained_begin =
82
detach_by_driver_cb_drained_begin;
83
}
84
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
85
/* Set child relationships */
86
bdrv_ref(b);
87
bdrv_ref(a);
88
- child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0,
89
- &error_abort);
90
+ child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_of_bds,
91
+ BDRV_CHILD_DATA, &error_abort);
92
child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds,
93
BDRV_CHILD_COW, &error_abort);
94
95
bdrv_ref(a);
96
bdrv_attach_child(parent_a, a, "PA-A",
97
- by_parent_cb ? &child_file : &detach_by_driver_cb_class,
98
- 0, &error_abort);
99
+ by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class,
100
+ BDRV_CHILD_DATA, &error_abort);
101
102
g_assert_cmpint(parent_a->refcnt, ==, 1);
103
g_assert_cmpint(parent_b->refcnt, ==, 1);
104
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/tests/test-bdrv-graph-mod.c
107
+++ b/tests/test-bdrv-graph-mod.c
108
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
109
110
blk_insert_bs(root, bs, &error_abort);
111
112
- bdrv_attach_child(filter, bs, "child", &child_file, 0, &error_abort);
113
+ bdrv_attach_child(filter, bs, "child", &child_of_bds,
114
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
115
116
bdrv_append(filter, bs, &local_err);
117
118
@@ -XXX,XX +XXX,XX @@ static void test_should_update_child(void)
119
bdrv_set_backing_hd(target, bs, &error_abort);
120
121
g_assert(target->backing->bs == bs);
122
- bdrv_attach_child(filter, target, "target", &child_file, 0, &error_abort);
123
+ bdrv_attach_child(filter, target, "target", &child_of_bds,
124
+ BDRV_CHILD_DATA, &error_abort);
125
bdrv_append(filter, bs, &error_abort);
126
g_assert(target->backing->bs == bs);
127
42
128
--
43
--
129
2.25.4
44
2.37.3
130
131
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Implementations should decide the necessary permissions based on @role.
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
4
6
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
6
Message-Id: <20200513110544.176672-35-mreitz@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Message-Id: <20220922084924.201610-23-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
12
---
10
include/block/block_int.h | 4 +---
13
util/qemu-coroutine-lock.c | 14 +++++++-------
11
block.c | 39 +++++++++++++++----------------------
14
1 file changed, 7 insertions(+), 7 deletions(-)
12
block/backup-top.c | 3 +--
13
block/blkdebug.c | 3 +--
14
block/blklogwrites.c | 3 +--
15
block/commit.c | 1 -
16
block/copy-on-read.c | 1 -
17
block/mirror.c | 1 -
18
block/quorum.c | 1 -
19
block/replication.c | 1 -
20
block/vvfat.c | 4 +---
21
tests/test-bdrv-drain.c | 19 +-----------------
22
tests/test-bdrv-graph-mod.c | 1 -
23
13 files changed, 22 insertions(+), 59 deletions(-)
24
15
25
diff --git a/include/block/block_int.h b/include/block/block_int.h
16
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block_int.h
18
--- a/util/qemu-coroutine-lock.c
28
+++ b/include/block/block_int.h
19
+++ b/util/qemu-coroutine-lock.c
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
20
@@ -XXX,XX +XXX,XX @@ typedef struct CoWaitRecord {
30
* @reopen_queue.
21
QSLIST_ENTRY(CoWaitRecord) next;
31
*/
22
} CoWaitRecord;
32
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
23
33
- const BdrvChildClass *child_class,
24
-static void push_waiter(CoMutex *mutex, CoWaitRecord *w)
34
BdrvChildRole role,
25
+static void coroutine_fn push_waiter(CoMutex *mutex, CoWaitRecord *w)
35
BlockReopenQueue *reopen_queue,
26
{
36
uint64_t parent_perm, uint64_t parent_shared,
27
w->co = qemu_coroutine_self();
37
@@ -XXX,XX +XXX,XX @@ bool bdrv_recurse_can_replace(BlockDriverState *bs,
28
QSLIST_INSERT_HEAD_ATOMIC(&mutex->from_push, w, next);
38
* child_of_bds child class and set an appropriate BdrvChildRole.
29
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_init(CoRwlock *lock)
39
*/
40
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
41
- const BdrvChildClass *child_class, BdrvChildRole role,
42
- BlockReopenQueue *reopen_queue,
43
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
44
uint64_t perm, uint64_t shared,
45
uint64_t *nperm, uint64_t *nshared);
46
47
diff --git a/block.c b/block.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block.c
50
+++ b/block.c
51
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
52
}
30
}
53
31
54
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
32
/* Releases the internal CoMutex. */
55
- BdrvChild *c, const BdrvChildClass *child_class,
33
-static void qemu_co_rwlock_maybe_wake_one(CoRwlock *lock)
56
- BdrvChildRole role, BlockReopenQueue *reopen_queue,
34
+static void coroutine_fn qemu_co_rwlock_maybe_wake_one(CoRwlock *lock)
57
+ BdrvChild *c, BdrvChildRole role,
58
+ BlockReopenQueue *reopen_queue,
59
uint64_t parent_perm, uint64_t parent_shared,
60
uint64_t *nperm, uint64_t *nshared)
61
{
35
{
62
assert(bs->drv && bs->drv->bdrv_child_perm);
36
CoRwTicket *tkt = QSIMPLEQ_FIRST(&lock->tickets);
63
- bs->drv->bdrv_child_perm(bs, c, child_class, role, reopen_queue,
37
Coroutine *co = NULL;
64
+ bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
38
@@ -XXX,XX +XXX,XX @@ static void qemu_co_rwlock_maybe_wake_one(CoRwlock *lock)
65
parent_perm, parent_shared,
39
}
66
nperm, nshared);
67
/* TODO Take force_share from reopen_queue */
68
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
69
uint64_t cur_perm, cur_shared;
70
bool child_tighten_restr;
71
72
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, q,
73
+ bdrv_child_perm(bs, c->bs, c, c->role, q,
74
cumulative_perms, cumulative_shared_perms,
75
&cur_perm, &cur_shared);
76
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
77
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
78
/* Update all children */
79
QLIST_FOREACH(c, &bs->children, next) {
80
uint64_t cur_perm, cur_shared;
81
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
82
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
83
cumulative_perms, cumulative_shared_perms,
84
&cur_perm, &cur_shared);
85
bdrv_child_set_perm(c, cur_perm, cur_shared);
86
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
87
uint64_t perms, shared;
88
89
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
90
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
91
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
92
parent_perms, parent_shared, &perms, &shared);
93
94
return bdrv_child_try_set_perm(c, perms, shared, errp);
95
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
96
* filtered child.
97
*/
98
static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
99
- const BdrvChildClass *child_class,
100
BdrvChildRole role,
101
BlockReopenQueue *reopen_queue,
102
uint64_t perm, uint64_t shared,
103
@@ -XXX,XX +XXX,XX @@ static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
104
}
40
}
105
41
106
static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
42
-void qemu_co_rwlock_rdlock(CoRwlock *lock)
107
- const BdrvChildClass *child_class,
43
+void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock)
108
BdrvChildRole role,
109
BlockReopenQueue *reopen_queue,
110
uint64_t perm, uint64_t shared,
111
uint64_t *nperm, uint64_t *nshared)
112
{
44
{
113
- assert(child_class == &child_of_bds && (role & BDRV_CHILD_COW));
45
Coroutine *self = qemu_coroutine_self();
114
+ assert(role & BDRV_CHILD_COW);
46
115
47
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_rdlock(CoRwlock *lock)
116
/*
48
self->locks_held++;
117
* We want consistent read from backing files if the parent needs it.
118
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
119
}
49
}
120
50
121
static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
51
-void qemu_co_rwlock_unlock(CoRwlock *lock)
122
- const BdrvChildClass *child_class,
52
+void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock)
123
BdrvChildRole role,
124
BlockReopenQueue *reopen_queue,
125
uint64_t perm, uint64_t shared,
126
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
127
{
53
{
128
int flags;
54
Coroutine *self = qemu_coroutine_self();
129
55
130
- assert(child_class == &child_of_bds &&
56
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_unlock(CoRwlock *lock)
131
- (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)));
57
qemu_co_rwlock_maybe_wake_one(lock);
132
+ assert(role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA));
133
134
flags = bdrv_reopen_get_flags(reopen_queue, bs);
135
136
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
137
* Apart from the modifications below, the same permissions are
138
* forwarded and left alone as for filters
139
*/
140
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
141
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
142
perm, shared, &perm, &shared);
143
144
if (role & BDRV_CHILD_METADATA) {
145
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
146
}
58
}
147
59
148
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
60
-void qemu_co_rwlock_downgrade(CoRwlock *lock)
149
- const BdrvChildClass *child_class, BdrvChildRole role,
61
+void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock)
150
- BlockReopenQueue *reopen_queue,
151
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
152
uint64_t perm, uint64_t shared,
153
uint64_t *nperm, uint64_t *nshared)
154
{
62
{
155
- assert(child_class == &child_of_bds);
63
qemu_co_mutex_lock(&lock->mutex);
156
-
64
assert(lock->owners == -1);
157
if (role & BDRV_CHILD_FILTERED) {
65
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_downgrade(CoRwlock *lock)
158
assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
66
qemu_co_rwlock_maybe_wake_one(lock);
159
BDRV_CHILD_COW)));
160
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
161
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
162
perm, shared, nperm, nshared);
163
} else if (role & BDRV_CHILD_COW) {
164
assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA)));
165
- bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
166
+ bdrv_default_perms_for_cow(bs, c, role, reopen_queue,
167
perm, shared, nperm, nshared);
168
} else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) {
169
- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
170
+ bdrv_default_perms_for_storage(bs, c, role, reopen_queue,
171
perm, shared, nperm, nshared);
172
} else {
173
g_assert_not_reached();
174
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
175
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
176
177
assert(parent_bs->drv);
178
- bdrv_child_perm(parent_bs, child_bs, NULL, child_class, child_role, NULL,
179
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
180
perm, shared_perm, &perm, &shared_perm);
181
182
child = bdrv_root_attach_child(child_bs, child_name, child_class,
183
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
184
if (state->replace_backing_bs && state->new_backing_bs) {
185
uint64_t nperm, nshared;
186
bdrv_child_perm(state->bs, state->new_backing_bs,
187
- NULL, &child_of_bds, bdrv_backing_role(state->bs),
188
+ NULL, bdrv_backing_role(state->bs),
189
bs_queue, state->perm, state->shared_perm,
190
&nperm, &nshared);
191
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
192
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
193
} else {
194
uint64_t nperm, nshared;
195
196
- bdrv_child_perm(parent->state.bs, bs, c, c->klass, c->role, q,
197
+ bdrv_child_perm(parent->state.bs, bs, c, c->role, q,
198
parent->state.perm, parent->state.shared_perm,
199
&nperm, &nshared);
200
201
diff --git a/block/backup-top.c b/block/backup-top.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/block/backup-top.c
204
+++ b/block/backup-top.c
205
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
206
}
67
}
207
68
208
static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
69
-void qemu_co_rwlock_wrlock(CoRwlock *lock)
209
- const BdrvChildClass *child_class,
70
+void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock)
210
BdrvChildRole role,
71
{
211
BlockReopenQueue *reopen_queue,
72
Coroutine *self = qemu_coroutine_self();
212
uint64_t perm, uint64_t shared,
73
213
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
74
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_wrlock(CoRwlock *lock)
214
*nperm = BLK_PERM_WRITE;
75
self->locks_held++;
215
} else {
216
/* Source child */
217
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
218
+ bdrv_default_perms(bs, c, role, reopen_queue,
219
perm, shared, nperm, nshared);
220
221
if (perm & BLK_PERM_WRITE) {
222
diff --git a/block/blkdebug.c b/block/blkdebug.c
223
index XXXXXXX..XXXXXXX 100644
224
--- a/block/blkdebug.c
225
+++ b/block/blkdebug.c
226
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
227
}
76
}
228
77
229
static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
78
-void qemu_co_rwlock_upgrade(CoRwlock *lock)
230
- const BdrvChildClass *child_class,
79
+void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock)
231
BdrvChildRole role,
232
BlockReopenQueue *reopen_queue,
233
uint64_t perm, uint64_t shared,
234
@@ -XXX,XX +XXX,XX @@ static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
235
{
80
{
236
BDRVBlkdebugState *s = bs->opaque;
81
qemu_co_mutex_lock(&lock->mutex);
237
82
assert(lock->owners > 0);
238
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
239
+ bdrv_default_perms(bs, c, role, reopen_queue,
240
perm, shared, nperm, nshared);
241
242
*nperm |= s->take_child_perms;
243
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
244
index XXXXXXX..XXXXXXX 100644
245
--- a/block/blklogwrites.c
246
+++ b/block/blklogwrites.c
247
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
248
}
249
250
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
251
- const BdrvChildClass *child_class,
252
BdrvChildRole role,
253
BlockReopenQueue *ro_q,
254
uint64_t perm, uint64_t shrd,
255
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
256
return;
257
}
258
259
- bdrv_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
260
+ bdrv_default_perms(bs, c, role, ro_q, perm, shrd,
261
nperm, nshrd);
262
}
263
264
diff --git a/block/commit.c b/block/commit.c
265
index XXXXXXX..XXXXXXX 100644
266
--- a/block/commit.c
267
+++ b/block/commit.c
268
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
269
}
270
271
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
272
- const BdrvChildClass *child_class,
273
BdrvChildRole role,
274
BlockReopenQueue *reopen_queue,
275
uint64_t perm, uint64_t shared,
276
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/block/copy-on-read.c
279
+++ b/block/copy-on-read.c
280
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
281
#define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH)
282
283
static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
284
- const BdrvChildClass *child_class,
285
BdrvChildRole role,
286
BlockReopenQueue *reopen_queue,
287
uint64_t perm, uint64_t shared,
288
diff --git a/block/mirror.c b/block/mirror.c
289
index XXXXXXX..XXXXXXX 100644
290
--- a/block/mirror.c
291
+++ b/block/mirror.c
292
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
293
}
294
295
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
296
- const BdrvChildClass *child_class,
297
BdrvChildRole role,
298
BlockReopenQueue *reopen_queue,
299
uint64_t perm, uint64_t shared,
300
diff --git a/block/quorum.c b/block/quorum.c
301
index XXXXXXX..XXXXXXX 100644
302
--- a/block/quorum.c
303
+++ b/block/quorum.c
304
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
305
}
306
307
static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
308
- const BdrvChildClass *child_class,
309
BdrvChildRole role,
310
BlockReopenQueue *reopen_queue,
311
uint64_t perm, uint64_t shared,
312
diff --git a/block/replication.c b/block/replication.c
313
index XXXXXXX..XXXXXXX 100644
314
--- a/block/replication.c
315
+++ b/block/replication.c
316
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
317
}
318
319
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
320
- const BdrvChildClass *child_class,
321
BdrvChildRole role,
322
BlockReopenQueue *reopen_queue,
323
uint64_t perm, uint64_t shared,
324
diff --git a/block/vvfat.c b/block/vvfat.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/block/vvfat.c
327
+++ b/block/vvfat.c
328
@@ -XXX,XX +XXX,XX @@ err:
329
}
330
331
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
332
- const BdrvChildClass *child_class,
333
BdrvChildRole role,
334
BlockReopenQueue *reopen_queue,
335
uint64_t perm, uint64_t shared,
336
@@ -XXX,XX +XXX,XX @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
337
{
338
BDRVVVFATState *s = bs->opaque;
339
340
- assert(c == s->qcow ||
341
- (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
342
+ assert(c == s->qcow || (role & BDRV_CHILD_COW));
343
344
if (c == s->qcow) {
345
/* This is a private node, nobody should try to attach to it */
346
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
347
index XXXXXXX..XXXXXXX 100644
348
--- a/tests/test-bdrv-drain.c
349
+++ b/tests/test-bdrv-drain.c
350
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
351
return 0;
352
}
353
354
-static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
355
- const BdrvChildClass *child_class,
356
- BdrvChildRole role,
357
- BlockReopenQueue *reopen_queue,
358
- uint64_t perm, uint64_t shared,
359
- uint64_t *nperm, uint64_t *nshared)
360
-{
361
- /*
362
- * bdrv_default_perms() accepts nothing else, so disguise
363
- * detach_by_driver_cb_parent.
364
- */
365
- child_class = &child_of_bds;
366
-
367
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
368
- perm, shared, nperm, nshared);
369
-}
370
-
371
static int bdrv_test_change_backing_file(BlockDriverState *bs,
372
const char *backing_file,
373
const char *backing_fmt)
374
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_test = {
375
.bdrv_co_drain_begin = bdrv_test_co_drain_begin,
376
.bdrv_co_drain_end = bdrv_test_co_drain_end,
377
378
- .bdrv_child_perm = bdrv_test_child_perm,
379
+ .bdrv_child_perm = bdrv_default_perms,
380
381
.bdrv_change_backing_file = bdrv_test_change_backing_file,
382
};
383
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
384
index XXXXXXX..XXXXXXX 100644
385
--- a/tests/test-bdrv-graph-mod.c
386
+++ b/tests/test-bdrv-graph-mod.c
387
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_pass_through = {
388
};
389
390
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
391
- const BdrvChildClass *child_class,
392
BdrvChildRole role,
393
BlockReopenQueue *reopen_queue,
394
uint64_t perm, uint64_t shared,
395
--
83
--
396
2.25.4
84
2.37.3
397
398
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Split raw_read_options() into one function that actually just reads the
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
options, and another that applies them. This will allow us to detect
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
whether the user has specified any options before attaching the file
5
functions where this holds.
6
child (so we can decide on its role based on the options).
7
6
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20200513110544.176672-21-mreitz@redhat.com>
9
Message-Id: <20220922084924.201610-24-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
---
13
block/raw-format.c | 110 ++++++++++++++++++++++++++-------------------
14
block/raw-format.c | 3 ++-
14
1 file changed, 65 insertions(+), 45 deletions(-)
15
1 file changed, 2 insertions(+), 1 deletion(-)
15
16
16
diff --git a/block/raw-format.c b/block/raw-format.c
17
diff --git a/block/raw-format.c b/block/raw-format.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/block/raw-format.c
19
--- a/block/raw-format.c
19
+++ b/block/raw-format.c
20
+++ b/block/raw-format.c
20
@@ -XXX,XX +XXX,XX @@ static QemuOptsList raw_create_opts = {
21
@@ -XXX,XX +XXX,XX @@ static void raw_lock_medium(BlockDriverState *bs, bool locked)
21
}
22
bdrv_lock_medium(bs->file->bs, locked);
22
};
23
24
-static int raw_read_options(QDict *options, BlockDriverState *bs,
25
- BDRVRawState *s, Error **errp)
26
+static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size,
27
+ uint64_t *size, Error **errp)
28
{
29
Error *local_err = NULL;
30
QemuOpts *opts = NULL;
31
- int64_t real_size = 0;
32
int ret;
33
34
- real_size = bdrv_getlength(bs->file->bs);
35
- if (real_size < 0) {
36
- error_setg_errno(errp, -real_size, "Could not get image size");
37
- return real_size;
38
- }
39
-
40
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
41
qemu_opts_absorb_qdict(opts, options, &local_err);
42
if (local_err) {
43
@@ -XXX,XX +XXX,XX @@ static int raw_read_options(QDict *options, BlockDriverState *bs,
44
goto end;
45
}
46
47
- s->offset = qemu_opt_get_size(opts, "offset", 0);
48
- if (s->offset > real_size) {
49
- error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
50
- "size of the containing file (%" PRId64 ")",
51
- s->offset, real_size);
52
- ret = -EINVAL;
53
- goto end;
54
- }
55
+ *offset = qemu_opt_get_size(opts, "offset", 0);
56
+ *has_size = qemu_opt_find(opts, "size");
57
+ *size = qemu_opt_get_size(opts, "size", 0);
58
59
- if (qemu_opt_find(opts, "size") != NULL) {
60
- s->size = qemu_opt_get_size(opts, "size", 0);
61
- s->has_size = true;
62
- } else {
63
- s->has_size = false;
64
- s->size = real_size - s->offset;
65
+ ret = 0;
66
+end:
67
+ qemu_opts_del(opts);
68
+ return ret;
69
+}
70
+
71
+static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
72
+ uint64_t offset, bool has_size, uint64_t size,
73
+ Error **errp)
74
+{
75
+ int64_t real_size = 0;
76
+
77
+ real_size = bdrv_getlength(bs->file->bs);
78
+ if (real_size < 0) {
79
+ error_setg_errno(errp, -real_size, "Could not get image size");
80
+ return real_size;
81
}
82
83
/* Check size and offset */
84
- if ((real_size - s->offset) < s->size) {
85
+ if (offset > real_size) {
86
+ error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
87
+ "size of the containing file (%" PRId64 ")",
88
+ s->offset, real_size);
89
+ return -EINVAL;
90
+ }
91
+
92
+ if (has_size && (real_size - offset) < size) {
93
error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
94
- "(%" PRIu64 ") has to be smaller or equal to the "
95
- " actual size of the containing file (%" PRId64 ")",
96
- s->offset, s->size, real_size);
97
- ret = -EINVAL;
98
- goto end;
99
+ "(%" PRIu64 ") has to be smaller or equal to the "
100
+ " actual size of the containing file (%" PRId64 ")",
101
+ s->offset, s->size, real_size);
102
+ return -EINVAL;
103
}
104
105
/* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding
106
* up and leaking out of the specified area. */
107
- if (s->has_size && !QEMU_IS_ALIGNED(s->size, BDRV_SECTOR_SIZE)) {
108
+ if (has_size && !QEMU_IS_ALIGNED(size, BDRV_SECTOR_SIZE)) {
109
error_setg(errp, "Specified size is not multiple of %llu",
110
- BDRV_SECTOR_SIZE);
111
- ret = -EINVAL;
112
- goto end;
113
+ BDRV_SECTOR_SIZE);
114
+ return -EINVAL;
115
}
116
117
- ret = 0;
118
-
119
-end:
120
+ s->offset = offset;
121
+ s->has_size = has_size;
122
+ s->size = has_size ? size : real_size - offset;
123
124
- qemu_opts_del(opts);
125
-
126
- return ret;
127
+ return 0;
128
}
23
}
129
24
130
static int raw_reopen_prepare(BDRVReopenState *reopen_state,
25
-static int raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
131
BlockReopenQueue *queue, Error **errp)
26
+static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
132
{
27
+ unsigned long int req, void *buf)
133
+ bool has_size;
134
+ uint64_t offset, size;
135
+ int ret;
136
+
137
assert(reopen_state != NULL);
138
assert(reopen_state->bs != NULL);
139
140
reopen_state->opaque = g_new0(BDRVRawState, 1);
141
142
- return raw_read_options(
143
- reopen_state->options,
144
- reopen_state->bs,
145
- reopen_state->opaque,
146
- errp);
147
+ ret = raw_read_options(reopen_state->options, &offset, &has_size, &size,
148
+ errp);
149
+ if (ret < 0) {
150
+ return ret;
151
+ }
152
+
153
+ ret = raw_apply_options(reopen_state->bs, reopen_state->opaque,
154
+ offset, has_size, size, errp);
155
+ if (ret < 0) {
156
+ return ret;
157
+ }
158
+
159
+ return 0;
160
}
161
162
static void raw_reopen_commit(BDRVReopenState *state)
163
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
164
Error **errp)
165
{
28
{
166
BDRVRawState *s = bs->opaque;
29
BDRVRawState *s = bs->opaque;
167
+ bool has_size;
30
if (s->offset || s->has_size) {
168
+ uint64_t offset, size;
169
int ret;
170
171
+ ret = raw_read_options(options, &offset, &has_size, &size, errp);
172
+ if (ret < 0) {
173
+ return ret;
174
+ }
175
+
176
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
177
false, errp);
178
if (!bs->file) {
179
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
180
bs->file->bs->filename);
181
}
182
183
- ret = raw_read_options(options, bs, s, errp);
184
+ ret = raw_apply_options(bs, s, offset, has_size, size, errp);
185
if (ret < 0) {
186
return ret;
187
}
188
--
31
--
189
2.25.4
32
2.37.3
190
191
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
2
3
Let child_file's, child_format's, and child_backing's .inherit_options()
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
implementations fall back to bdrv_inherited_options() to show that it
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
would really work for all of these cases, if only the parents passed the
5
functions where this holds.
6
appropriate BdrvChildRole and parent_is_format values.
7
6
8
(Also, make bdrv_open_inherit(), the only place to explicitly call
7
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
bdrv_backing_options(), call bdrv_inherited_options() instead.)
8
Acked-by: Greg Kurz <groug@kaod.org>
10
9
Reviewed-by: Alberto Faria <afaria@redhat.com>
11
This patch should incur only two visible changes, both for child_format
10
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
children, both of which are effectively bug fixes:
11
Message-Id: <20220922084924.201610-25-pbonzini@redhat.com>
13
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
First, they no longer have discard=unmap set by default. This reason it
15
was set is because bdrv_inherited_fmt_options() fell through to
16
bdrv_protocol_options(), and that set it because "format drivers take
17
care to send flushes and respect unmap policy". None of the drivers
18
that use child_format for their children (quorum and blkverify) are
19
format drivers, though, so this reasoning does not apply here.
20
21
Second, they no longer have BDRV_O_NO_IO force-cleared. child_format
22
was used solely for children that do not store any metadata and as such
23
will not be accessed by their parents as long as those parents do not
24
receive I/O themselves. Thus, such children should inherit
25
BDRV_O_NO_IO.
26
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
Message-Id: <20200513110544.176672-12-mreitz@redhat.com>
29
Reviewed-by: Eric Blake <eblake@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
---
14
---
32
block.c | 71 +++++++++++++++------------------------------------------
15
hw/9pfs/9p.h | 9 ++++++---
33
1 file changed, 19 insertions(+), 52 deletions(-)
16
1 file changed, 6 insertions(+), 3 deletions(-)
34
17
35
diff --git a/block.c b/block.c
18
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
36
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
37
--- a/block.c
20
--- a/hw/9pfs/9p.h
38
+++ b/block.c
21
+++ b/hw/9pfs/9p.h
39
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
22
@@ -XXX,XX +XXX,XX @@ typedef struct V9fsGetlock
40
BdrvChildRole child_role,
23
extern int open_fd_hw;
41
Error **errp);
24
extern int total_open_fd;
42
25
43
+/* TODO: Remove when no longer needed */
26
-static inline void v9fs_path_write_lock(V9fsState *s)
44
+static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
27
+static inline void coroutine_fn
45
+ int *child_flags, QDict *child_options,
28
+v9fs_path_write_lock(V9fsState *s)
46
+ int parent_flags, QDict *parent_options);
47
+
48
/* If non-zero, use only whitelisted block drivers */
49
static int use_bdrv_whitelist;
50
51
@@ -XXX,XX +XXX,XX @@ static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format,
52
int *child_flags, QDict *child_options,
53
int parent_flags, QDict *parent_options)
54
{
29
{
55
- int flags = parent_flags;
30
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
56
-
31
qemu_co_rwlock_wrlock(&s->rename_lock);
57
- /* Enable protocol handling, disable format probing for bs->file */
32
}
58
- flags |= BDRV_O_PROTOCOL;
59
-
60
- /* If the cache mode isn't explicitly set, inherit direct and no-flush from
61
- * the parent. */
62
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
63
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
64
- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
65
-
66
- /* Inherit the read-only option from the parent if it's not set */
67
- qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
68
- qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
69
-
70
- /* Our block drivers take care to send flushes and respect unmap policy,
71
- * so we can default to enable both on lower layers regardless of the
72
- * corresponding parent options. */
73
- qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");
74
-
75
- /* Clear flags that only apply to the top layer */
76
- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ |
77
- BDRV_O_NO_IO);
78
-
79
- *child_flags = flags;
80
+ bdrv_inherited_options(BDRV_CHILD_IMAGE, true,
81
+ child_flags, child_options,
82
+ parent_flags, parent_options);
83
}
33
}
84
34
85
const BdrvChildClass child_file = {
35
-static inline void v9fs_path_read_lock(V9fsState *s)
86
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_fmt_options(BdrvChildRole role,
36
+static inline void coroutine_fn
87
int *child_flags, QDict *child_options,
37
+v9fs_path_read_lock(V9fsState *s)
88
int parent_flags, QDict *parent_options)
89
{
38
{
90
- child_file.inherit_options(role, parent_is_format,
39
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
91
- child_flags, child_options,
40
qemu_co_rwlock_rdlock(&s->rename_lock);
92
- parent_flags, parent_options);
41
}
93
-
94
- *child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
95
+ bdrv_inherited_options(BDRV_CHILD_DATA, false,
96
+ child_flags, child_options,
97
+ parent_flags, parent_options);
98
}
42
}
99
43
100
const BdrvChildClass child_format = {
44
-static inline void v9fs_path_unlock(V9fsState *s)
101
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format,
45
+static inline void coroutine_fn
102
int *child_flags, QDict *child_options,
46
+v9fs_path_unlock(V9fsState *s)
103
int parent_flags, QDict *parent_options)
104
{
47
{
105
- int flags = parent_flags;
48
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
106
-
49
qemu_co_rwlock_unlock(&s->rename_lock);
107
- /* The cache mode is inherited unmodified for backing files; except WCE,
108
- * which is only applied on the top level (BlockBackend) */
109
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
110
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
111
- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
112
-
113
- /* backing files always opened read-only */
114
- qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
115
- qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
116
- flags &= ~BDRV_O_COPY_ON_READ;
117
-
118
- /* snapshot=on is handled on the top layer */
119
- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
120
-
121
- *child_flags = flags;
122
+ bdrv_inherited_options(BDRV_CHILD_COW, true,
123
+ child_flags, child_options,
124
+ parent_flags, parent_options);
125
}
126
127
static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
128
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_backing = {
129
* Returns the options and flags that a generic child of a BDS should
130
* get, based on the given options and flags for the parent BDS.
131
*/
132
-static void __attribute__((unused))
133
- bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
134
- int *child_flags, QDict *child_options,
135
- int parent_flags, QDict *parent_options)
136
+static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
137
+ int *child_flags, QDict *child_options,
138
+ int parent_flags, QDict *parent_options)
139
{
140
int flags = parent_flags;
141
142
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
143
flags, options);
144
/* Let bdrv_backing_options() override "read-only" */
145
qdict_del(options, BDRV_OPT_READ_ONLY);
146
- bdrv_backing_options(0, true, &flags, options, flags, options);
147
+ bdrv_inherited_options(BDRV_CHILD_COW, true,
148
+ &flags, options, flags, options);
149
}
150
151
bs->open_flags = flags;
152
--
50
--
153
2.25.4
51
2.37.3
154
52
155
53
diff view generated by jsdifflib
1
This patch makes the raw image the same size as the file in a different
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
format that is mirrored as raw to it to avoid errors when mirror starts
3
to enforce that source and target are the same size.
4
2
5
We check only that the first 512 bytes are zeroed (instead of 64k)
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
6
because some image formats create image files that are smaller than 64k,
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
7
so trying to read 64k would result in I/O errors. Apart from this, 512
5
functions where this holds.
8
is more appropriate anyway because the raw format driver protects
9
specifically the first 512 bytes.
10
6
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
Message-Id: <20200511135825.219437-2-kwolf@redhat.com>
8
Reviewed-by: Juan Quintela <quintela@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Alberto Faria <afaria@redhat.com>
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Message-Id: <20220922084924.201610-26-pbonzini@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
15
---
17
tests/qemu-iotests/109 | 10 ++---
16
migration/migration.c | 3 ++-
18
tests/qemu-iotests/109.out | 74 +++++++++++++-------------------
17
1 file changed, 2 insertions(+), 1 deletion(-)
19
tests/qemu-iotests/common.filter | 5 +++
20
3 files changed, 41 insertions(+), 48 deletions(-)
21
18
22
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
19
diff --git a/migration/migration.c b/migration/migration.c
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/109
25
+++ b/tests/qemu-iotests/109
26
@@ -XXX,XX +XXX,XX @@ for fmt in qcow qcow2 qed vdi vmdk vpc; do
27
echo "=== Writing a $fmt header into raw ==="
28
echo
29
30
- _make_test_img 64M
31
TEST_IMG="$TEST_IMG.src" IMGFMT=$fmt _make_test_img 64M
32
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
33
34
# This first test should fail: The image format was probed, we may not
35
# write an image header at the start of the image
36
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
37
_filter_block_job_len
38
- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
39
+ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io
40
41
42
# When raw was explicitly specified, the same must succeed
43
@@ -XXX,XX +XXX,XX @@ for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \
44
45
# Can't use _use_sample_img because that isn't designed to be used multiple
46
# times and it overwrites $TEST_IMG (both breaks cleanup)
47
- _make_test_img 64M
48
bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
49
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
50
51
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
52
_filter_block_job_offset | _filter_block_job_len
53
- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
54
+ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io
55
56
run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY"
57
$QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src"
58
@@ -XXX,XX +XXX,XX @@ echo "=== Write legitimate MBR into raw ==="
59
echo
60
61
for sample_img in grub_mbr.raw; do
62
- _make_test_img 64M
63
bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
64
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
65
66
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_READY"
67
$QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src"
68
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
69
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
70
--- a/tests/qemu-iotests/109.out
21
--- a/migration/migration.c
71
+++ b/tests/qemu-iotests/109.out
22
+++ b/migration/migration.c
72
@@ -XXX,XX +XXX,XX @@ QA output created by 109
23
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_bh(void *opaque)
73
24
migration_incoming_state_destroy();
74
=== Writing a qcow header into raw ===
75
76
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
77
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
78
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
79
{ 'execute': 'qmp_capabilities' }
80
{"return": {}}
81
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
82
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
83
{"execute":"quit"}
84
{"return": {}}
85
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
86
-read 65536/65536 bytes at offset 0
87
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
88
+read 512/512 bytes at offset 0
89
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
90
{ 'execute': 'qmp_capabilities' }
91
{"return": {}}
92
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
93
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
94
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
95
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
96
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
97
-Warning: Image size mismatch!
98
Images are identical.
99
100
=== Writing a qcow2 header into raw ===
101
102
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
103
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
104
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
105
{ 'execute': 'qmp_capabilities' }
106
{"return": {}}
107
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
108
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
109
{"execute":"quit"}
110
{"return": {}}
111
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
112
-read 65536/65536 bytes at offset 0
113
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
114
+read 512/512 bytes at offset 0
115
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
116
{ 'execute': 'qmp_capabilities' }
117
{"return": {}}
118
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
119
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
120
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
121
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
122
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
123
-Warning: Image size mismatch!
124
Images are identical.
125
126
=== Writing a qed header into raw ===
127
128
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
129
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
130
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
131
{ 'execute': 'qmp_capabilities' }
132
{"return": {}}
133
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
134
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
135
{"execute":"quit"}
136
{"return": {}}
137
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
138
-read 65536/65536 bytes at offset 0
139
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
140
+read 512/512 bytes at offset 0
141
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
142
{ 'execute': 'qmp_capabilities' }
143
{"return": {}}
144
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
145
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
146
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
147
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
148
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
149
-Warning: Image size mismatch!
150
Images are identical.
151
152
=== Writing a vdi header into raw ===
153
154
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
155
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
156
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
157
{ 'execute': 'qmp_capabilities' }
158
{"return": {}}
159
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
160
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
161
{"execute":"quit"}
162
{"return": {}}
163
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
164
-read 65536/65536 bytes at offset 0
165
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
166
+read 512/512 bytes at offset 0
167
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
{ 'execute': 'qmp_capabilities' }
169
{"return": {}}
170
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
171
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
172
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
173
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
174
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
175
-Warning: Image size mismatch!
176
Images are identical.
177
178
=== Writing a vmdk header into raw ===
179
180
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
181
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
182
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
183
{ 'execute': 'qmp_capabilities' }
184
{"return": {}}
185
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
186
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
187
{"execute":"quit"}
188
{"return": {}}
189
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
190
-read 65536/65536 bytes at offset 0
191
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
192
+read 512/512 bytes at offset 0
193
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
{ 'execute': 'qmp_capabilities' }
195
{"return": {}}
196
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
197
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
198
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
199
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
200
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
201
-Warning: Image size mismatch!
202
Images are identical.
203
204
=== Writing a vpc header into raw ===
205
206
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
207
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
208
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
209
{ 'execute': 'qmp_capabilities' }
210
{"return": {}}
211
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
212
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
213
{"execute":"quit"}
214
{"return": {}}
215
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
216
-read 65536/65536 bytes at offset 0
217
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
218
+read 512/512 bytes at offset 0
219
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
220
{ 'execute': 'qmp_capabilities' }
221
{"return": {}}
222
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
223
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
224
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
225
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
226
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
227
-Warning: Image size mismatch!
228
Images are identical.
229
230
=== Copying sample image empty.bochs into raw ===
231
232
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
233
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
234
{ 'execute': 'qmp_capabilities' }
235
{"return": {}}
236
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
237
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
238
{"execute":"quit"}
239
{"return": {}}
240
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
241
-read 65536/65536 bytes at offset 0
242
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
243
+read 512/512 bytes at offset 0
244
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
245
{ 'execute': 'qmp_capabilities' }
246
{"return": {}}
247
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
248
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
249
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
250
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
251
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
252
-Warning: Image size mismatch!
253
Images are identical.
254
255
=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw ===
256
257
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
258
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
259
{ 'execute': 'qmp_capabilities' }
260
{"return": {}}
261
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
262
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
263
{"execute":"quit"}
264
{"return": {}}
265
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
266
-read 65536/65536 bytes at offset 0
267
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
268
+read 512/512 bytes at offset 0
269
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
{ 'execute': 'qmp_capabilities' }
271
{"return": {}}
272
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
273
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
274
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
275
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
276
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
277
-Warning: Image size mismatch!
278
Images are identical.
279
280
=== Copying sample image parallels-v1 into raw ===
281
282
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
283
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
284
{ 'execute': 'qmp_capabilities' }
285
{"return": {}}
286
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
287
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
288
{"execute":"quit"}
289
{"return": {}}
290
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
291
-read 65536/65536 bytes at offset 0
292
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
293
+read 512/512 bytes at offset 0
294
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
295
{ 'execute': 'qmp_capabilities' }
296
{"return": {}}
297
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
298
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
299
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
300
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
301
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
302
-Warning: Image size mismatch!
303
Images are identical.
304
305
=== Copying sample image simple-pattern.cloop into raw ===
306
307
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
308
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
309
{ 'execute': 'qmp_capabilities' }
310
{"return": {}}
311
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
312
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
313
{"execute":"quit"}
314
{"return": {}}
315
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
316
-read 65536/65536 bytes at offset 0
317
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
318
+read 512/512 bytes at offset 0
319
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
320
{ 'execute': 'qmp_capabilities' }
321
{"return": {}}
322
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
323
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
324
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
325
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
326
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
327
-Warning: Image size mismatch!
328
Images are identical.
329
330
=== Write legitimate MBR into raw ===
331
332
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
333
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
334
{ 'execute': 'qmp_capabilities' }
335
{"return": {}}
336
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
337
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
338
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
339
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
340
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
341
-Warning: Image size mismatch!
342
Images are identical.
343
{ 'execute': 'qmp_capabilities' }
344
{"return": {}}
345
@@ -XXX,XX +XXX,XX @@ Images are identical.
346
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
347
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
348
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
349
-Warning: Image size mismatch!
350
Images are identical.
351
*** done
352
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
353
index XXXXXXX..XXXXXXX 100644
354
--- a/tests/qemu-iotests/common.filter
355
+++ b/tests/qemu-iotests/common.filter
356
@@ -XXX,XX +XXX,XX @@ _filter_img_create()
357
-e "s# compression_type=[a-zA-Z0-9]\\+##g"
358
}
25
}
359
26
360
+_filter_img_create_size()
27
-static void process_incoming_migration_co(void *opaque)
361
+{
28
+static void coroutine_fn
362
+ $SED -e "s# size=[0-9]\\+# size=SIZE#g"
29
+process_incoming_migration_co(void *opaque)
363
+}
364
+
365
_filter_img_info()
366
{
30
{
367
if [[ "$1" == "--format-specific" ]]; then
31
MigrationIncomingState *mis = migration_incoming_get_current();
32
PostcopyState ps;
368
--
33
--
369
2.25.4
34
2.37.3
370
35
371
36
diff view generated by jsdifflib
Deleted patch
1
229 relies on the mirror running into an I/O error when the target is
2
smaller than the source. After changing mirror to catch this condition
3
while starting the job, this test case won't get a job that is paused
4
for an I/O error any more. Use blkdebug instead to inject an error.
5
1
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Message-Id: <20200511135825.219437-3-kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
tests/qemu-iotests/229 | 15 +++++++++++----
14
tests/qemu-iotests/229.out | 6 +++---
15
2 files changed, 14 insertions(+), 7 deletions(-)
16
17
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/229
20
+++ b/tests/qemu-iotests/229
21
@@ -XXX,XX +XXX,XX @@ _cleanup()
22
_cleanup_test_img
23
_rm_test_img "$TEST_IMG"
24
_rm_test_img "$DEST_IMG"
25
+ rm -f "$TEST_DIR/blkdebug.conf"
26
}
27
trap "_cleanup; exit \$status" 0 1 2 3 15
28
29
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
30
31
DEST_IMG="$TEST_DIR/d.$IMGFMT"
32
TEST_IMG="$TEST_DIR/b.$IMGFMT"
33
+BLKDEBUG_CONF="$TEST_DIR/blkdebug.conf"
34
35
_make_test_img 2M
36
-
37
-# destination for mirror will be too small, causing error
38
-TEST_IMG=$DEST_IMG _make_test_img 1M
39
+TEST_IMG=$DEST_IMG _make_test_img 2M
40
41
$QEMU_IO -c 'write 0 2M' "$TEST_IMG" | _filter_qemu_io
42
43
@@ -XXX,XX +XXX,XX @@ echo
44
echo '=== Starting drive-mirror, causing error & stop ==='
45
echo
46
47
+cat > "$BLKDEBUG_CONF" <<EOF
48
+[inject-error]
49
+event = "write_aio"
50
+errno = "5"
51
+once = "on"
52
+EOF
53
+
54
_send_qemu_cmd $QEMU_HANDLE \
55
"{'execute': 'drive-mirror',
56
'arguments': {'device': 'testdisk',
57
'format': '$IMGFMT',
58
- 'target': '$DEST_IMG',
59
+ 'target': 'blkdebug:$BLKDEBUG_CONF:$DEST_IMG',
60
'sync': 'full',
61
'mode': 'existing',
62
'on-source-error': 'stop',
63
diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out
64
index XXXXXXX..XXXXXXX 100644
65
--- a/tests/qemu-iotests/229.out
66
+++ b/tests/qemu-iotests/229.out
67
@@ -XXX,XX +XXX,XX @@
68
QA output created by 229
69
Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=2097152
70
-Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=1048576
71
+Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=2097152
72
wrote 2097152/2097152 bytes at offset 0
73
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
74
{'execute': 'qmp_capabilities'}
75
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 0
76
77
=== Starting drive-mirror, causing error & stop ===
78
79
-{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'TEST_DIR/d.IMGFMT', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
80
+{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/d.IMGFMT', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
81
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "testdisk"}}
82
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
83
{"return": {}}
84
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 0
85
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
86
{"return": {}}
87
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
88
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}}
89
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 2097152, "speed": 0, "type": "mirror"}}
90
*** done
91
--
92
2.25.4
93
94
diff view generated by jsdifflib
1
This is just a bandaid to keep tests/test-replication working after
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
bdrv_make_empty() starts to assert that we're not trying to call it on a
3
read-only child.
4
2
5
For the real solution in the future, replication should not steal the
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
6
BdrvChild from its backing file (this is never correct to do!), but
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
7
instead have its own child node references, with the appropriate
5
functions where this holds.
8
permissions.
9
6
7
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-27-pbonzini@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
13
---
12
block/replication.c | 13 +++++++++++--
14
tests/unit/test-coroutine.c | 2 +-
13
1 file changed, 11 insertions(+), 2 deletions(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
14
16
15
diff --git a/block/replication.c b/block/replication.c
17
diff --git a/tests/unit/test-coroutine.c b/tests/unit/test-coroutine.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/block/replication.c
19
--- a/tests/unit/test-coroutine.c
18
+++ b/block/replication.c
20
+++ b/tests/unit/test-coroutine.c
19
@@ -XXX,XX +XXX,XX @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ static void perf_baseline(void)
20
return;
22
g_test_message("Function call %u iterations: %f s", maxcycles, duration);
21
}
23
}
22
24
23
- ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs);
25
-static __attribute__((noinline)) void perf_cost_func(void *opaque)
24
+ BlockBackend *blk = blk_new(qemu_get_current_aio_context(),
26
+static __attribute__((noinline)) void coroutine_fn perf_cost_func(void *opaque)
25
+ BLK_PERM_WRITE, BLK_PERM_ALL);
27
{
26
+ blk_insert_bs(blk, s->hidden_disk->bs, &local_err);
28
qemu_coroutine_yield();
27
+ if (local_err) {
28
+ error_propagate(errp, local_err);
29
+ blk_unref(blk);
30
+ return;
31
+ }
32
+
33
+ ret = blk_make_empty(blk, errp);
34
+ blk_unref(blk);
35
if (ret < 0) {
36
- error_setg(errp, "Cannot make hidden disk empty");
37
return;
38
}
39
}
29
}
40
--
30
--
41
2.25.4
31
2.37.3
42
32
43
33
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20221006122607.162769-1-kwolf@redhat.com>
3
For now, all callers pass 0 and no callee evaluates this value. Later
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
patches will change both.
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Message-Id: <20200513110544.176672-7-mreitz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
6
---
11
include/block/block_int.h | 5 ++++-
7
block/quorum.c | 2 --
12
block.c | 22 ++++++++++++----------
8
1 file changed, 2 deletions(-)
13
block/backup-top.c | 3 ++-
14
block/blkdebug.c | 5 +++--
15
block/blklogwrites.c | 9 +++++----
16
block/commit.c | 1 +
17
block/copy-on-read.c | 1 +
18
block/mirror.c | 1 +
19
block/quorum.c | 1 +
20
block/replication.c | 1 +
21
block/vvfat.c | 1 +
22
tests/test-bdrv-drain.c | 5 +++--
23
tests/test-bdrv-graph-mod.c | 1 +
24
13 files changed, 36 insertions(+), 20 deletions(-)
25
9
26
diff --git a/include/block/block_int.h b/include/block/block_int.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/block/block_int.h
29
+++ b/include/block/block_int.h
30
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
31
* the parents in @parent_perm and @parent_shared.
32
*
33
* If @c is NULL, return the permissions for attaching a new child for the
34
- * given @child_class.
35
+ * given @child_class and @role.
36
*
37
* If @reopen_queue is non-NULL, don't return the currently needed
38
* permissions, but those that will be needed after applying the
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
40
*/
41
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
42
const BdrvChildClass *child_class,
43
+ BdrvChildRole role,
44
BlockReopenQueue *reopen_queue,
45
uint64_t parent_perm, uint64_t parent_shared,
46
uint64_t *nperm, uint64_t *nshared);
47
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
48
* all children */
49
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
50
const BdrvChildClass *child_class,
51
+ BdrvChildRole child_role,
52
BlockReopenQueue *reopen_queue,
53
uint64_t perm, uint64_t shared,
54
uint64_t *nperm, uint64_t *nshared);
55
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
56
* CONSISTENT_READ and doesn't share WRITE. */
57
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
58
const BdrvChildClass *child_class,
59
+ BdrvChildRole child_role,
60
BlockReopenQueue *reopen_queue,
61
uint64_t perm, uint64_t shared,
62
uint64_t *nperm, uint64_t *nshared);
63
diff --git a/block.c b/block.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block.c
66
+++ b/block.c
67
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
68
69
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
70
BdrvChild *c, const BdrvChildClass *child_class,
71
- BlockReopenQueue *reopen_queue,
72
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
73
uint64_t parent_perm, uint64_t parent_shared,
74
uint64_t *nperm, uint64_t *nshared)
75
{
76
assert(bs->drv && bs->drv->bdrv_child_perm);
77
- bs->drv->bdrv_child_perm(bs, c, child_class, reopen_queue,
78
+ bs->drv->bdrv_child_perm(bs, c, child_class, role, reopen_queue,
79
parent_perm, parent_shared,
80
nperm, nshared);
81
/* TODO Take force_share from reopen_queue */
82
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
83
uint64_t cur_perm, cur_shared;
84
bool child_tighten_restr;
85
86
- bdrv_child_perm(bs, c->bs, c, c->klass, q,
87
+ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, q,
88
cumulative_perms, cumulative_shared_perms,
89
&cur_perm, &cur_shared);
90
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
91
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
92
/* Update all children */
93
QLIST_FOREACH(c, &bs->children, next) {
94
uint64_t cur_perm, cur_shared;
95
- bdrv_child_perm(bs, c->bs, c, c->klass, NULL,
96
+ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
97
cumulative_perms, cumulative_shared_perms,
98
&cur_perm, &cur_shared);
99
bdrv_child_set_perm(c, cur_perm, cur_shared);
100
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
101
uint64_t perms, shared;
102
103
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
104
- bdrv_child_perm(bs, c->bs, c, c->klass, NULL, parent_perms, parent_shared,
105
- &perms, &shared);
106
+ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
107
+ parent_perms, parent_shared, &perms, &shared);
108
109
return bdrv_child_try_set_perm(c, perms, shared, errp);
110
}
111
112
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
113
const BdrvChildClass *child_class,
114
+ BdrvChildRole role,
115
BlockReopenQueue *reopen_queue,
116
uint64_t perm, uint64_t shared,
117
uint64_t *nperm, uint64_t *nshared)
118
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
119
120
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
121
const BdrvChildClass *child_class,
122
+ BdrvChildRole role,
123
BlockReopenQueue *reopen_queue,
124
uint64_t perm, uint64_t shared,
125
uint64_t *nperm, uint64_t *nshared)
126
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
127
128
/* Apart from the modifications below, the same permissions are
129
* forwarded and left alone as for filters */
130
- bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
131
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
132
perm, shared, &perm, &shared);
133
134
/* Format drivers may touch metadata even if the guest doesn't write */
135
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
136
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
137
138
assert(parent_bs->drv);
139
- bdrv_child_perm(parent_bs, child_bs, NULL, child_class, NULL,
140
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_class, child_role, NULL,
141
perm, shared_perm, &perm, &shared_perm);
142
143
child = bdrv_root_attach_child(child_bs, child_name, child_class,
144
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
145
if (state->replace_backing_bs && state->new_backing_bs) {
146
uint64_t nperm, nshared;
147
bdrv_child_perm(state->bs, state->new_backing_bs,
148
- NULL, &child_backing, bs_queue,
149
+ NULL, &child_backing, 0, bs_queue,
150
state->perm, state->shared_perm,
151
&nperm, &nshared);
152
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
153
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
154
} else {
155
uint64_t nperm, nshared;
156
157
- bdrv_child_perm(parent->state.bs, bs, c, c->klass, q,
158
+ bdrv_child_perm(parent->state.bs, bs, c, c->klass, c->role, q,
159
parent->state.perm, parent->state.shared_perm,
160
&nperm, &nshared);
161
162
diff --git a/block/backup-top.c b/block/backup-top.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/block/backup-top.c
165
+++ b/block/backup-top.c
166
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
167
168
static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
169
const BdrvChildClass *child_class,
170
+ BdrvChildRole role,
171
BlockReopenQueue *reopen_queue,
172
uint64_t perm, uint64_t shared,
173
uint64_t *nperm, uint64_t *nshared)
174
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
175
*nperm = BLK_PERM_WRITE;
176
} else {
177
/* Source child */
178
- bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
179
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
180
perm, shared, nperm, nshared);
181
182
if (perm & BLK_PERM_WRITE) {
183
diff --git a/block/blkdebug.c b/block/blkdebug.c
184
index XXXXXXX..XXXXXXX 100644
185
--- a/block/blkdebug.c
186
+++ b/block/blkdebug.c
187
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
188
189
static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
190
const BdrvChildClass *child_class,
191
+ BdrvChildRole role,
192
BlockReopenQueue *reopen_queue,
193
uint64_t perm, uint64_t shared,
194
uint64_t *nperm, uint64_t *nshared)
195
{
196
BDRVBlkdebugState *s = bs->opaque;
197
198
- bdrv_filter_default_perms(bs, c, child_class, reopen_queue, perm, shared,
199
- nperm, nshared);
200
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
201
+ perm, shared, nperm, nshared);
202
203
*nperm |= s->take_child_perms;
204
*nshared &= ~s->unshare_child_perms;
205
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/block/blklogwrites.c
208
+++ b/block/blklogwrites.c
209
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
210
211
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
212
const BdrvChildClass *child_class,
213
+ BdrvChildRole role,
214
BlockReopenQueue *ro_q,
215
uint64_t perm, uint64_t shrd,
216
uint64_t *nperm, uint64_t *nshrd)
217
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
218
}
219
220
if (!strcmp(c->name, "log")) {
221
- bdrv_format_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
222
- nshrd);
223
+ bdrv_format_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
224
+ nperm, nshrd);
225
} else {
226
- bdrv_filter_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
227
- nshrd);
228
+ bdrv_filter_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
229
+ nperm, nshrd);
230
}
231
}
232
233
diff --git a/block/commit.c b/block/commit.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/block/commit.c
236
+++ b/block/commit.c
237
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
238
239
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
240
const BdrvChildClass *child_class,
241
+ BdrvChildRole role,
242
BlockReopenQueue *reopen_queue,
243
uint64_t perm, uint64_t shared,
244
uint64_t *nperm, uint64_t *nshared)
245
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
246
index XXXXXXX..XXXXXXX 100644
247
--- a/block/copy-on-read.c
248
+++ b/block/copy-on-read.c
249
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
250
251
static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
252
const BdrvChildClass *child_class,
253
+ BdrvChildRole role,
254
BlockReopenQueue *reopen_queue,
255
uint64_t perm, uint64_t shared,
256
uint64_t *nperm, uint64_t *nshared)
257
diff --git a/block/mirror.c b/block/mirror.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/block/mirror.c
260
+++ b/block/mirror.c
261
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
262
263
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
264
const BdrvChildClass *child_class,
265
+ BdrvChildRole role,
266
BlockReopenQueue *reopen_queue,
267
uint64_t perm, uint64_t shared,
268
uint64_t *nperm, uint64_t *nshared)
269
diff --git a/block/quorum.c b/block/quorum.c
10
diff --git a/block/quorum.c b/block/quorum.c
270
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
271
--- a/block/quorum.c
12
--- a/block/quorum.c
272
+++ b/block/quorum.c
13
+++ b/block/quorum.c
273
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
14
@@ -XXX,XX +XXX,XX @@ static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb)
274
15
return false;
275
static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
276
const BdrvChildClass *child_class,
277
+ BdrvChildRole role,
278
BlockReopenQueue *reopen_queue,
279
uint64_t perm, uint64_t shared,
280
uint64_t *nperm, uint64_t *nshared)
281
diff --git a/block/replication.c b/block/replication.c
282
index XXXXXXX..XXXXXXX 100644
283
--- a/block/replication.c
284
+++ b/block/replication.c
285
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
286
287
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
288
const BdrvChildClass *child_class,
289
+ BdrvChildRole role,
290
BlockReopenQueue *reopen_queue,
291
uint64_t perm, uint64_t shared,
292
uint64_t *nperm, uint64_t *nshared)
293
diff --git a/block/vvfat.c b/block/vvfat.c
294
index XXXXXXX..XXXXXXX 100644
295
--- a/block/vvfat.c
296
+++ b/block/vvfat.c
297
@@ -XXX,XX +XXX,XX @@ err:
298
299
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
300
const BdrvChildClass *child_class,
301
+ BdrvChildRole role,
302
BlockReopenQueue *reopen_queue,
303
uint64_t perm, uint64_t shared,
304
uint64_t *nperm, uint64_t *nshared)
305
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
306
index XXXXXXX..XXXXXXX 100644
307
--- a/tests/test-bdrv-drain.c
308
+++ b/tests/test-bdrv-drain.c
309
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
310
311
static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
312
const BdrvChildClass *child_class,
313
+ BdrvChildRole role,
314
BlockReopenQueue *reopen_queue,
315
uint64_t perm, uint64_t shared,
316
uint64_t *nperm, uint64_t *nshared)
317
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
318
child_class = &child_file;
319
}
320
321
- bdrv_format_default_perms(bs, c, child_class, reopen_queue, perm, shared,
322
- nperm, nshared);
323
+ bdrv_format_default_perms(bs, c, child_class, role, reopen_queue,
324
+ perm, shared, nperm, nshared);
325
}
16
}
326
17
327
static int bdrv_test_change_backing_file(BlockDriverState *bs,
18
-static int read_fifo_child(QuorumAIOCB *acb);
328
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
19
-
329
index XXXXXXX..XXXXXXX 100644
20
static void quorum_copy_qiov(QEMUIOVector *dest, QEMUIOVector *source)
330
--- a/tests/test-bdrv-graph-mod.c
21
{
331
+++ b/tests/test-bdrv-graph-mod.c
22
int i;
332
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_pass_through = {
333
334
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
335
const BdrvChildClass *child_class,
336
+ BdrvChildRole role,
337
BlockReopenQueue *reopen_queue,
338
uint64_t perm, uint64_t shared,
339
uint64_t *nperm, uint64_t *nshared)
340
--
23
--
341
2.25.4
24
2.37.3
342
25
343
26
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
job mutex will be used to protect the job struct elements and list,
4
Reviewed-by: Eric Blake <eblake@redhat.com>
4
replacing AioContext locks.
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
6
Message-Id: <20200429141126.85159-3-mreitz@redhat.com>
6
Right now use a shared lock for all jobs, in order to keep things
7
simple. Once the AioContext lock is gone, we can introduce per-job
8
locks.
9
10
To simplify the switch from aiocontext to job lock, introduce
11
*nop* lock/unlock functions and macros.
12
We want to always call job_lock/unlock outside the AioContext locks,
13
and not vice-versa, otherwise we might get a deadlock. This is not
14
straightforward to do, and that's why we start with nop functions.
15
Once everything is protected by job_lock/unlock, we can change the nop into
16
an actual mutex and remove the aiocontext lock.
17
18
Since job_mutex is already being used, add static
19
real_job_{lock/unlock} for the existing usage.
20
21
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
22
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
23
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
24
Message-Id: <20220926093214.506243-2-eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
26
---
9
block/replication.c | 3 +--
27
include/qemu/job.h | 24 ++++++++++++++++++++++++
10
block/vvfat.c | 4 +---
28
job.c | 35 +++++++++++++++++++++++------------
11
2 files changed, 2 insertions(+), 5 deletions(-)
29
2 files changed, 47 insertions(+), 12 deletions(-)
12
30
13
diff --git a/block/replication.c b/block/replication.c
31
diff --git a/include/qemu/job.h b/include/qemu/job.h
14
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
15
--- a/block/replication.c
33
--- a/include/qemu/job.h
16
+++ b/block/replication.c
34
+++ b/include/qemu/job.h
17
@@ -XXX,XX +XXX,XX @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
35
@@ -XXX,XX +XXX,XX @@ typedef enum JobCreateFlags {
36
JOB_MANUAL_DISMISS = 0x04,
37
} JobCreateFlags;
38
39
+extern QemuMutex job_mutex;
40
+
41
+#define JOB_LOCK_GUARD() /* QEMU_LOCK_GUARD(&job_mutex) */
42
+
43
+#define WITH_JOB_LOCK_GUARD() /* WITH_QEMU_LOCK_GUARD(&job_mutex) */
44
+
45
+/**
46
+ * job_lock:
47
+ *
48
+ * Take the mutex protecting the list of jobs and their status.
49
+ * Most functions called by the monitor need to call job_lock
50
+ * and job_unlock manually. On the other hand, function called
51
+ * by the block jobs themselves and by the block layer will take the
52
+ * lock for you.
53
+ */
54
+void job_lock(void);
55
+
56
+/**
57
+ * job_unlock:
58
+ *
59
+ * Release the mutex protecting the list of jobs and their status.
60
+ */
61
+void job_unlock(void);
62
+
63
/**
64
* Allocate and return a new job transaction. Jobs can be added to the
65
* transaction using job_txn_add_job().
66
diff --git a/job.c b/job.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/job.c
69
+++ b/job.c
70
@@ -XXX,XX +XXX,XX @@
71
#include "trace/trace-root.h"
72
#include "qapi/qapi-events-job.h"
73
74
+/*
75
+ * job_mutex protects the jobs list, but also makes the
76
+ * struct job fields thread-safe.
77
+ */
78
+QemuMutex job_mutex;
79
+
80
static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);
81
82
/* Job State Transition Table */
83
@@ -XXX,XX +XXX,XX @@ struct JobTxn {
84
int refcnt;
85
};
86
87
-/* Right now, this mutex is only needed to synchronize accesses to job->busy
88
- * and job->sleep_timer, such as concurrent calls to job_do_yield and
89
- * job_enter. */
90
-static QemuMutex job_mutex;
91
+void job_lock(void)
92
+{
93
+ /* nop */
94
+}
95
+
96
+void job_unlock(void)
97
+{
98
+ /* nop */
99
+}
100
101
-static void job_lock(void)
102
+static void real_job_lock(void)
103
{
104
qemu_mutex_lock(&job_mutex);
105
}
106
107
-static void job_unlock(void)
108
+static void real_job_unlock(void)
109
{
110
qemu_mutex_unlock(&job_mutex);
111
}
112
@@ -XXX,XX +XXX,XX @@ void job_enter_cond(Job *job, bool(*fn)(Job *job))
18
return;
113
return;
19
}
114
}
20
115
21
- ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs);
116
- job_lock();
22
+ ret = bdrv_make_empty(s->active_disk, errp);
117
+ real_job_lock();
23
if (ret < 0) {
118
if (job->busy) {
24
- error_setg(errp, "Cannot make active disk empty");
119
- job_unlock();
120
+ real_job_unlock();
25
return;
121
return;
26
}
122
}
27
123
28
diff --git a/block/vvfat.c b/block/vvfat.c
124
if (fn && !fn(job)) {
29
index XXXXXXX..XXXXXXX 100644
125
- job_unlock();
30
--- a/block/vvfat.c
126
+ real_job_unlock();
31
+++ b/block/vvfat.c
127
return;
32
@@ -XXX,XX +XXX,XX @@ static int do_commit(BDRVVVFATState* s)
33
return ret;
34
}
128
}
35
129
36
- if (s->qcow->bs->drv && s->qcow->bs->drv->bdrv_make_empty) {
130
assert(!job->deferred_to_main_loop);
37
- s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs);
131
timer_del(&job->sleep_timer);
38
- }
132
job->busy = true;
39
+ bdrv_make_empty(s->qcow, NULL);
133
- job_unlock();
40
134
+ real_job_unlock();
41
memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
135
aio_co_enter(job->aio_context, job->co);
42
136
}
137
138
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job)
139
* called explicitly. */
140
static void coroutine_fn job_do_yield(Job *job, uint64_t ns)
141
{
142
- job_lock();
143
+ real_job_lock();
144
if (ns != -1) {
145
timer_mod(&job->sleep_timer, ns);
146
}
147
job->busy = false;
148
job_event_idle(job);
149
- job_unlock();
150
+ real_job_unlock();
151
qemu_coroutine_yield();
152
153
/* Set by job_enter_cond() before re-entering the coroutine. */
43
--
154
--
44
2.25.4
155
2.37.3
45
46
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This mask will supplement BdrvChildClass when it comes to what role (or
3
Categorize the fields in struct Job to understand which ones
4
combination of roles) a child takes for its parent. It consists of
4
need to be protected by the job mutex and which don't.
5
BdrvChildRoleBits values (which is an enum).
6
5
7
Because empty enums are not allowed, let us just start with it filled.
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20200513110544.176672-5-mreitz@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-Id: <20220926093214.506243-3-eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
include/block/block.h | 56 +++++++++++++++++++++++++++++++++++++++++++
13
include/qemu/job.h | 61 +++++++++++++++++++++++++++-------------------
15
1 file changed, 56 insertions(+)
14
1 file changed, 36 insertions(+), 25 deletions(-)
16
15
17
diff --git a/include/block/block.h b/include/block/block.h
16
diff --git a/include/qemu/job.h b/include/qemu/job.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block.h
18
--- a/include/qemu/job.h
20
+++ b/include/block/block.h
19
+++ b/include/qemu/job.h
21
@@ -XXX,XX +XXX,XX @@ enum {
20
@@ -XXX,XX +XXX,XX @@ typedef struct JobTxn JobTxn;
22
DEFAULT_PERM_UNCHANGED = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH,
21
* Long-running operation.
23
};
22
*/
24
23
typedef struct Job {
25
+/*
24
+
26
+ * Flags that parent nodes assign to child nodes to specify what kind of
25
+ /* Fields set at initialization (job_create), and never modified */
27
+ * role(s) they take.
26
+
28
+ *
27
/** The ID of the job. May be NULL for internal jobs. */
29
+ * At least one of DATA, METADATA, FILTERED, or COW must be set for
28
char *id;
30
+ * every child.
29
31
+ */
30
- /** The type of this job. */
32
+enum BdrvChildRoleBits {
31
+ /**
33
+ /*
32
+ * The type of this job.
34
+ * This child stores data.
33
+ * All callbacks are called with job_mutex *not* held.
35
+ * Any node may have an arbitrary number of such children.
36
+ */
34
+ */
37
+ BDRV_CHILD_DATA = (1 << 0),
35
const JobDriver *driver;
36
37
- /** Reference count of the block job */
38
- int refcnt;
39
-
40
- /** Current state; See @JobStatus for details. */
41
- JobStatus status;
42
-
43
- /** AioContext to run the job coroutine in */
44
- AioContext *aio_context;
45
-
46
/**
47
* The coroutine that executes the job. If not NULL, it is reentered when
48
* busy is false and the job is cancelled.
49
+ * Initialized in job_start()
50
*/
51
Coroutine *co;
52
53
+ /** True if this job should automatically finalize itself */
54
+ bool auto_finalize;
38
+
55
+
39
+ /*
56
+ /** True if this job should automatically dismiss itself */
40
+ * This child stores metadata.
57
+ bool auto_dismiss;
41
+ * Any node may have an arbitrary number of metadata-storing
42
+ * children.
43
+ */
44
+ BDRV_CHILD_METADATA = (1 << 1),
45
+
58
+
46
+ /*
59
+ /** The completion function that will be called when the job completes. */
47
+ * A child that always presents exactly the same visible data as
60
+ BlockCompletionFunc *cb;
48
+ * the parent, e.g. by virtue of the parent forwarding all reads
49
+ * and writes.
50
+ * This flag is mutually exclusive with DATA, METADATA, and COW.
51
+ * Any node may have at most one filtered child at a time.
52
+ */
53
+ BDRV_CHILD_FILTERED = (1 << 2),
54
+
61
+
55
+ /*
62
+ /** The opaque value that is passed to the completion function. */
56
+ * Child from which to read all data that isn’t allocated in the
63
+ void *opaque;
57
+ * parent (i.e., the backing child); such data is copied to the
58
+ * parent through COW (and optionally COR).
59
+ * This field is mutually exclusive with DATA, METADATA, and
60
+ * FILTERED.
61
+ * Any node may have at most one such backing child at a time.
62
+ */
63
+ BDRV_CHILD_COW = (1 << 3),
64
+
64
+
65
+ /*
65
+ /* ProgressMeter API is thread-safe */
66
+ * The primary child. For most drivers, this is the child whose
66
+ ProgressMeter progress;
67
+ * filename applies best to the parent node.
68
+ * Any node may have at most one primary child at a time.
69
+ */
70
+ BDRV_CHILD_PRIMARY = (1 << 4),
71
+
67
+
72
+ /* Useful combination of flags */
73
+ BDRV_CHILD_IMAGE = BDRV_CHILD_DATA
74
+ | BDRV_CHILD_METADATA
75
+ | BDRV_CHILD_PRIMARY,
76
+};
77
+
68
+
78
+/* Mask of BdrvChildRoleBits values */
69
+ /** Protected by AioContext lock */
79
+typedef unsigned int BdrvChildRole;
80
+
70
+
81
char *bdrv_perm_names(uint64_t perm);
71
+ /** AioContext to run the job coroutine in */
82
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm);
72
+ AioContext *aio_context;
73
+
74
+ /** Reference count of the block job */
75
+ int refcnt;
76
+
77
+ /** Current state; See @JobStatus for details. */
78
+ JobStatus status;
79
+
80
/**
81
* Timer that is used by @job_sleep_ns. Accessed under job_mutex (in
82
* job.c).
83
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
84
/** Set to true when the job has deferred work to the main loop. */
85
bool deferred_to_main_loop;
86
87
- /** True if this job should automatically finalize itself */
88
- bool auto_finalize;
89
-
90
- /** True if this job should automatically dismiss itself */
91
- bool auto_dismiss;
92
-
93
- ProgressMeter progress;
94
-
95
/**
96
* Return code from @run and/or @prepare callback(s).
97
* Not final until the job has reached the CONCLUDED status.
98
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
99
*/
100
Error *err;
101
102
- /** The completion function that will be called when the job completes. */
103
- BlockCompletionFunc *cb;
104
-
105
- /** The opaque value that is passed to the completion function. */
106
- void *opaque;
107
-
108
/** Notifiers called when a cancelled job is finalised */
109
NotifierList on_finalize_cancelled;
110
111
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
112
113
/**
114
* Callbacks and other information about a Job driver.
115
+ * All callbacks are invoked with job_mutex *not* held.
116
*/
117
struct JobDriver {
118
119
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_yield(Job *job);
120
*/
121
void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
122
123
-
124
/** Returns the JobType of a given Job. */
125
JobType job_type(const Job *job);
83
126
84
--
127
--
85
2.25.4
128
2.37.3
86
87
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Make bdrv_child_cb_attach() call bdrv_backing_attach() for children with
3
job_event_* functions can all be static, as they are not used
4
a COW role (and drop the reverse call from bdrv_backing_attach()), so it
4
outside job.c.
5
can be used for any child (with a proper role set).
6
5
7
Because so far no child has a proper role set, we need a temporary new
6
Same applies for job_txn_add_job().
8
callback for child_backing.attach that ensures bdrv_backing_attach() is
9
called for all COW children that do not have their role set yet.
10
7
11
(Also, move bdrv_child_cb_attach() down to group it with
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
bdrv_inherited_options().)
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Message-Id: <20200513110544.176672-13-mreitz@redhat.com>
12
Message-Id: <20220926093214.506243-4-eesposit@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
14
---
19
block.c | 27 ++++++++++++++++++++-------
15
include/qemu/job.h | 18 ------------------
20
1 file changed, 20 insertions(+), 7 deletions(-)
16
job.c | 22 +++++++++++++++++++---
17
2 files changed, 19 insertions(+), 21 deletions(-)
21
18
22
diff --git a/block.c b/block.c
19
diff --git a/include/qemu/job.h b/include/qemu/job.h
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
24
--- a/block.c
21
--- a/include/qemu/job.h
25
+++ b/block.c
22
+++ b/include/qemu/job.h
26
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
23
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void);
27
static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
24
*/
28
int *child_flags, QDict *child_options,
25
void job_txn_unref(JobTxn *txn);
29
int parent_flags, QDict *parent_options);
26
30
+static void bdrv_child_cb_attach(BdrvChild *child);
27
-/**
31
28
- * @txn: The transaction (may be NULL)
32
/* If non-zero, use only whitelisted block drivers */
29
- * @job: Job to add to the transaction
33
static int use_bdrv_whitelist;
30
- *
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_drained_end(BdrvChild *child,
31
- * Add @job to the transaction. The @job must not already be in a transaction.
35
bdrv_drained_end_no_poll(bs, drained_end_counter);
32
- * The caller must call either job_txn_unref() or job_completed() to release
33
- * the reference that is automatically grabbed here.
34
- *
35
- * If @txn is NULL, the function does nothing.
36
- */
37
-void job_txn_add_job(JobTxn *txn, Job *job);
38
-
39
/**
40
* Create a new long-running job and return it.
41
*
42
@@ -XXX,XX +XXX,XX @@ void job_progress_set_remaining(Job *job, uint64_t remaining);
43
*/
44
void job_progress_increase_remaining(Job *job, uint64_t delta);
45
46
-/** To be called when a cancelled job is finalised. */
47
-void job_event_cancelled(Job *job);
48
-
49
-/** To be called when a successfully completed job is finalised. */
50
-void job_event_completed(Job *job);
51
-
52
/**
53
* Conditionally enter the job coroutine if the job is ready to run, not
54
* already busy and fn() returns true. fn() is called while under the job_lock
55
diff --git a/job.c b/job.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/job.c
58
+++ b/job.c
59
@@ -XXX,XX +XXX,XX @@ void job_txn_unref(JobTxn *txn)
60
}
36
}
61
}
37
62
38
-static void bdrv_child_cb_attach(BdrvChild *child)
63
-void job_txn_add_job(JobTxn *txn, Job *job)
39
-{
64
+/**
40
- BlockDriverState *bs = child->opaque;
65
+ * @txn: The transaction (may be NULL)
41
- bdrv_apply_subtree_drain(child, bs);
66
+ * @job: Job to add to the transaction
42
-}
67
+ *
43
-
68
+ * Add @job to the transaction. The @job must not already be in a transaction.
44
static void bdrv_child_cb_detach(BdrvChild *child)
69
+ * The caller must call either job_txn_unref() or job_completed() to release
70
+ * the reference that is automatically grabbed here.
71
+ *
72
+ * If @txn is NULL, the function does nothing.
73
+ */
74
+static void job_txn_add_job(JobTxn *txn, Job *job)
45
{
75
{
46
BlockDriverState *bs = child->opaque;
76
if (!txn) {
47
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
77
return;
48
parent->backing_blocker);
78
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta)
49
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET,
79
progress_increase_remaining(&job->progress, delta);
50
parent->backing_blocker);
51
+}
52
53
+/* XXX: Will be removed along with child_backing */
54
+static void bdrv_child_cb_attach_backing(BdrvChild *c)
55
+{
56
+ if (!(c->role & BDRV_CHILD_COW)) {
57
+ bdrv_backing_attach(c);
58
+ }
59
bdrv_child_cb_attach(c);
60
}
80
}
61
81
62
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
82
-void job_event_cancelled(Job *job)
63
const BdrvChildClass child_backing = {
83
+/**
64
.parent_is_bds = true,
84
+ * To be called when a cancelled job is finalised.
65
.get_parent_desc = bdrv_child_get_parent_desc,
85
+ */
66
- .attach = bdrv_backing_attach,
86
+static void job_event_cancelled(Job *job)
67
+ .attach = bdrv_child_cb_attach_backing,
87
{
68
.detach = bdrv_backing_detach,
88
notifier_list_notify(&job->on_finalize_cancelled, job);
69
.inherit_options = bdrv_backing_options,
70
.drained_begin = bdrv_child_cb_drained_begin,
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
72
*child_flags = flags;
73
}
89
}
74
90
75
+static void bdrv_child_cb_attach(BdrvChild *child)
91
-void job_event_completed(Job *job)
76
+{
92
+/**
77
+ BlockDriverState *bs = child->opaque;
93
+ * To be called when a successfully completed job is finalised.
78
+
94
+ */
79
+ if (child->role & BDRV_CHILD_COW) {
95
+static void job_event_completed(Job *job)
80
+ bdrv_backing_attach(child);
81
+ }
82
+
83
+ bdrv_apply_subtree_drain(child, bs);
84
+}
85
+
86
static int bdrv_open_flags(BlockDriverState *bs, int flags)
87
{
96
{
88
int open_flags = flags;
97
notifier_list_notify(&job->on_finalize_completed, job);
98
}
89
--
99
--
90
2.25.4
100
2.37.3
91
92
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Two callers of BlockDriver.bdrv_make_empty() remain that should not call
3
Same as AIO_WAIT_WHILE macro, but if we are in the Main loop
4
this method directly. Both do not have access to a BdrvChild, but they
4
do not release and then acquire ctx_ 's aiocontext.
5
can use a BlockBackend, so we add this function that lets them use it.
6
5
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Once all Aiocontext locks go away, this macro will replace
8
Message-Id: <20200429141126.85159-4-mreitz@redhat.com>
7
AIO_WAIT_WHILE.
9
Reviewed-by: Eric Blake <eblake@redhat.com>
8
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
12
Message-Id: <20220926093214.506243-5-eesposit@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
15
---
12
include/sysemu/block-backend.h | 2 ++
16
include/block/aio-wait.h | 17 +++++++++++++----
13
block/block-backend.c | 10 ++++++++++
17
1 file changed, 13 insertions(+), 4 deletions(-)
14
2 files changed, 12 insertions(+)
15
18
16
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
19
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/include/sysemu/block-backend.h
21
--- a/include/block/aio-wait.h
19
+++ b/include/sysemu/block-backend.h
22
+++ b/include/block/aio-wait.h
20
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
24
extern AioWait global_aio_wait;
22
const BdrvChild *blk_root(BlockBackend *blk);
25
23
26
/**
24
+int blk_make_empty(BlockBackend *blk, Error **errp);
27
- * AIO_WAIT_WHILE:
28
+ * AIO_WAIT_WHILE_INTERNAL:
29
* @ctx: the aio context, or NULL if multiple aio contexts (for which the
30
* caller does not hold a lock) are involved in the polling condition.
31
* @cond: wait while this conditional expression is true
32
+ * @unlock: whether to unlock and then lock again @ctx. This apples
33
+ * only when waiting for another AioContext from the main loop.
34
+ * Otherwise it's ignored.
35
*
36
* Wait while a condition is true. Use this to implement synchronous
37
* operations that require event loop activity.
38
@@ -XXX,XX +XXX,XX @@ extern AioWait global_aio_wait;
39
* wait on conditions between two IOThreads since that could lead to deadlock,
40
* go via the main loop instead.
41
*/
42
-#define AIO_WAIT_WHILE(ctx, cond) ({ \
43
+#define AIO_WAIT_WHILE_INTERNAL(ctx, cond, unlock) ({ \
44
bool waited_ = false; \
45
AioWait *wait_ = &global_aio_wait; \
46
AioContext *ctx_ = (ctx); \
47
@@ -XXX,XX +XXX,XX @@ extern AioWait global_aio_wait;
48
assert(qemu_get_current_aio_context() == \
49
qemu_get_aio_context()); \
50
while ((cond)) { \
51
- if (ctx_) { \
52
+ if (unlock && ctx_) { \
53
aio_context_release(ctx_); \
54
} \
55
aio_poll(qemu_get_aio_context(), true); \
56
- if (ctx_) { \
57
+ if (unlock && ctx_) { \
58
aio_context_acquire(ctx_); \
59
} \
60
waited_ = true; \
61
@@ -XXX,XX +XXX,XX @@ extern AioWait global_aio_wait;
62
qatomic_dec(&wait_->num_waiters); \
63
waited_; })
64
65
+#define AIO_WAIT_WHILE(ctx, cond) \
66
+ AIO_WAIT_WHILE_INTERNAL(ctx, cond, true)
25
+
67
+
26
#endif
68
+#define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \
27
diff --git a/block/block-backend.c b/block/block-backend.c
69
+ AIO_WAIT_WHILE_INTERNAL(ctx, cond, false)
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/block-backend.c
30
+++ b/block/block-backend.c
31
@@ -XXX,XX +XXX,XX @@ const BdrvChild *blk_root(BlockBackend *blk)
32
{
33
return blk->root;
34
}
35
+
70
+
36
+int blk_make_empty(BlockBackend *blk, Error **errp)
71
/**
37
+{
72
* aio_wait_kick:
38
+ if (!blk_is_available(blk)) {
73
* Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During
39
+ error_setg(errp, "No medium inserted");
40
+ return -ENOMEDIUM;
41
+ }
42
+
43
+ return bdrv_make_empty(blk->root, errp);
44
+}
45
--
74
--
46
2.25.4
75
2.37.3
47
48
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Right now, all users of bdrv_make_empty() call the BlockDriver method
3
With "intact" we mean that all job.h functions implicitly
4
directly. That is not only bad style, it is also wrong, unless the
4
take the lock. Therefore API callers are unmodified.
5
caller has a BdrvChild with a WRITE or WRITE_UNCHANGED permission.
6
(WRITE_UNCHANGED suffices, because callers generally use this function
7
to clear a node with a backing file after a commit operation.)
8
5
9
Introduce bdrv_make_empty() that verifies that it does.
6
This means that:
7
- many static functions that will be always called with job lock held
8
become _locked, and call _locked functions
9
- all public functions take the lock internally if needed, and call _locked
10
functions
11
- all public functions called internally by other functions in job.c will have a
12
_locked counterpart (sometimes public), to avoid deadlocks (job lock already taken).
13
These functions are not used for now.
14
- some public functions called only from exernal files (not job.c) do not
15
have _locked() counterpart and take the lock inside. Others won't need
16
the lock at all because use fields only set at initialization and
17
never modified.
10
18
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
job_{lock/unlock} is independent from real_job_{lock/unlock}.
12
Message-Id: <20200429141126.85159-2-mreitz@redhat.com>
20
13
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Note: at this stage, job_{lock/unlock} and job lock guard macros
22
are *nop*
23
24
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
25
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
26
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
27
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
28
Message-Id: <20220926093214.506243-6-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
30
---
16
include/block/block.h | 1 +
31
include/qemu/job.h | 138 +++++++++-
17
block.c | 23 +++++++++++++++++++++++
32
job.c | 610 ++++++++++++++++++++++++++++++++-------------
18
2 files changed, 24 insertions(+)
33
2 files changed, 561 insertions(+), 187 deletions(-)
19
34
20
diff --git a/include/block/block.h b/include/block/block.h
35
diff --git a/include/qemu/job.h b/include/qemu/job.h
21
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
22
--- a/include/block/block.h
37
--- a/include/qemu/job.h
23
+++ b/include/block/block.h
38
+++ b/include/qemu/job.h
24
@@ -XXX,XX +XXX,XX @@ BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
39
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void);
25
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
40
*/
26
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
41
void job_txn_unref(JobTxn *txn);
27
int bdrv_commit(BlockDriverState *bs);
42
28
+int bdrv_make_empty(BdrvChild *c, Error **errp);
43
+/*
29
int bdrv_change_backing_file(BlockDriverState *bs,
44
+ * Same as job_txn_unref(), but called with job lock held.
30
const char *backing_file, const char *backing_fmt);
45
+ * Might release the lock temporarily.
31
void bdrv_register(BlockDriver *bdrv);
46
+ */
32
diff --git a/block.c b/block.c
47
+void job_txn_unref_locked(JobTxn *txn);
48
+
49
/**
50
* Create a new long-running job and return it.
51
+ * Called with job_mutex *not* held.
52
*
53
* @job_id: The id of the newly-created job, or %NULL for internal jobs
54
* @driver: The class object for the newly-created job.
55
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
56
*/
57
void job_ref(Job *job);
58
59
+/* Same as job_ref(), but called with job lock held. */
60
+void job_ref_locked(Job *job);
61
+
62
/**
63
* Release a reference that was previously acquired with job_ref() or
64
* job_create(). If it's the last reference to the object, it will be freed.
65
*/
66
void job_unref(Job *job);
67
68
+/* Same as job_unref(), but called with job lock held. */
69
+void job_unref_locked(Job *job);
70
+
71
/**
72
* @job: The job that has made progress
73
* @done: How much progress the job made since the last call
74
*
75
* Updates the progress counter of the job.
76
+ *
77
+ * May be called with mutex held or not held.
78
*/
79
void job_progress_update(Job *job, uint64_t done);
80
81
@@ -XXX,XX +XXX,XX @@ void job_progress_update(Job *job, uint64_t done);
82
*
83
* Sets the expected end value of the progress counter of a job so that a
84
* completion percentage can be calculated when the progress is updated.
85
+ *
86
+ * May be called with mutex held or not held.
87
*/
88
void job_progress_set_remaining(Job *job, uint64_t remaining);
89
90
@@ -XXX,XX +XXX,XX @@ void job_progress_set_remaining(Job *job, uint64_t remaining);
91
* length before, and job_progress_update() afterwards.
92
* (So the operation acts as a parenthesis in regards to the main job
93
* operation running in background.)
94
+ *
95
+ * May be called with mutex held or not held.
96
*/
97
void job_progress_increase_remaining(Job *job, uint64_t delta);
98
99
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta);
100
*/
101
void job_enter_cond(Job *job, bool(*fn)(Job *job));
102
103
+/*
104
+ * Same as job_enter_cond(), but called with job lock held.
105
+ * Might release the lock temporarily.
106
+ */
107
+void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
108
+
109
/**
110
* @job: A job that has not yet been started.
111
*
112
* Begins execution of a job.
113
* Takes ownership of one reference to the job object.
114
+ *
115
+ * Called with job_mutex *not* held.
116
*/
117
void job_start(Job *job);
118
119
@@ -XXX,XX +XXX,XX @@ void job_start(Job *job);
120
* @job: The job to enter.
121
*
122
* Continue the specified job by entering the coroutine.
123
+ * Called with job_mutex *not* held.
124
*/
125
void job_enter(Job *job);
126
127
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job);
128
*
129
* Pause now if job_pause() has been called. Jobs that perform lots of I/O
130
* must call this between requests so that the job can be paused.
131
+ *
132
+ * Called with job_mutex *not* held.
133
*/
134
void coroutine_fn job_pause_point(Job *job);
135
136
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job);
137
* @job: The job that calls the function.
138
*
139
* Yield the job coroutine.
140
+ * Called with job_mutex *not* held.
141
*/
142
void coroutine_fn job_yield(Job *job);
143
144
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_yield(Job *job);
145
* Put the job to sleep (assuming that it wasn't canceled) for @ns
146
* %QEMU_CLOCK_REALTIME nanoseconds. Canceling the job will immediately
147
* interrupt the wait.
148
+ *
149
+ * Called with job_mutex *not* held.
150
*/
151
void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
152
153
@@ -XXX,XX +XXX,XX @@ const char *job_type_str(const Job *job);
154
/** Returns true if the job should not be visible to the management layer. */
155
bool job_is_internal(Job *job);
156
157
-/** Returns whether the job is being cancelled. */
158
+/**
159
+ * Returns whether the job is being cancelled.
160
+ * Called with job_mutex *not* held.
161
+ */
162
bool job_is_cancelled(Job *job);
163
164
+/* Same as job_is_cancelled(), but called with job lock held. */
165
+bool job_is_cancelled_locked(Job *job);
166
+
167
/**
168
* Returns whether the job is scheduled for cancellation (at an
169
* indefinite point).
170
+ * Called with job_mutex *not* held.
171
*/
172
bool job_cancel_requested(Job *job);
173
174
-/** Returns whether the job is in a completed state. */
175
+/**
176
+ * Returns whether the job is in a completed state.
177
+ * Called with job_mutex *not* held.
178
+ */
179
bool job_is_completed(Job *job);
180
181
-/** Returns whether the job is ready to be completed. */
182
+/* Same as job_is_completed(), but called with job lock held. */
183
+bool job_is_completed_locked(Job *job);
184
+
185
+/**
186
+ * Returns whether the job is ready to be completed.
187
+ * Called with job_mutex *not* held.
188
+ */
189
bool job_is_ready(Job *job);
190
191
+/* Same as job_is_ready(), but called with job lock held. */
192
+bool job_is_ready_locked(Job *job);
193
+
194
/**
195
* Request @job to pause at the next pause point. Must be paired with
196
* job_resume(). If the job is supposed to be resumed by user action, call
197
@@ -XXX,XX +XXX,XX @@ bool job_is_ready(Job *job);
198
*/
199
void job_pause(Job *job);
200
201
+/* Same as job_pause(), but called with job lock held. */
202
+void job_pause_locked(Job *job);
203
+
204
/** Resumes a @job paused with job_pause. */
205
void job_resume(Job *job);
206
207
+/*
208
+ * Same as job_resume(), but called with job lock held.
209
+ * Might release the lock temporarily.
210
+ */
211
+void job_resume_locked(Job *job);
212
+
213
/**
214
* Asynchronously pause the specified @job.
215
* Do not allow a resume until a matching call to job_user_resume.
216
*/
217
void job_user_pause(Job *job, Error **errp);
218
219
+/* Same as job_user_pause(), but called with job lock held. */
220
+void job_user_pause_locked(Job *job, Error **errp);
221
+
222
/** Returns true if the job is user-paused. */
223
bool job_user_paused(Job *job);
224
225
+/* Same as job_user_paused(), but called with job lock held. */
226
+bool job_user_paused_locked(Job *job);
227
+
228
/**
229
* Resume the specified @job.
230
* Must be paired with a preceding job_user_pause.
231
*/
232
void job_user_resume(Job *job, Error **errp);
233
234
+/*
235
+ * Same as job_user_resume(), but called with job lock held.
236
+ * Might release the lock temporarily.
237
+ */
238
+void job_user_resume_locked(Job *job, Error **errp);
239
+
240
/**
241
* Get the next element from the list of block jobs after @job, or the
242
* first one if @job is %NULL.
243
@@ -XXX,XX +XXX,XX @@ void job_user_resume(Job *job, Error **errp);
244
*/
245
Job *job_next(Job *job);
246
247
+/* Same as job_next(), but called with job lock held. */
248
+Job *job_next_locked(Job *job);
249
+
250
/**
251
* Get the job identified by @id (which must not be %NULL).
252
*
253
@@ -XXX,XX +XXX,XX @@ Job *job_next(Job *job);
254
*/
255
Job *job_get(const char *id);
256
257
+/* Same as job_get(), but called with job lock held. */
258
+Job *job_get_locked(const char *id);
259
+
260
/**
261
* Check whether the verb @verb can be applied to @job in its current state.
262
* Returns 0 if the verb can be applied; otherwise errp is set and -EPERM
263
@@ -XXX,XX +XXX,XX @@ Job *job_get(const char *id);
264
*/
265
int job_apply_verb(Job *job, JobVerb verb, Error **errp);
266
267
-/** The @job could not be started, free it. */
268
+/* Same as job_apply_verb, but called with job lock held. */
269
+int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp);
270
+
271
+/**
272
+ * The @job could not be started, free it.
273
+ * Called with job_mutex *not* held.
274
+ */
275
void job_early_fail(Job *job);
276
277
-/** Moves the @job from RUNNING to READY */
278
+/**
279
+ * Moves the @job from RUNNING to READY.
280
+ * Called with job_mutex *not* held.
281
+ */
282
void job_transition_to_ready(Job *job);
283
284
/** Asynchronously complete the specified @job. */
285
void job_complete(Job *job, Error **errp);
286
287
+/*
288
+ * Same as job_complete(), but called with job lock held.
289
+ * Might release the lock temporarily.
290
+ */
291
+void job_complete_locked(Job *job, Error **errp);
292
+
293
/**
294
* Asynchronously cancel the specified @job. If @force is true, the job should
295
* be cancelled immediately without waiting for a consistent state.
296
*/
297
void job_cancel(Job *job, bool force);
298
299
+/* Same as job_cancel(), but called with job lock held. */
300
+void job_cancel_locked(Job *job, bool force);
301
+
302
/**
303
* Cancels the specified job like job_cancel(), but may refuse to do so if the
304
* operation isn't meaningful in the current state of the job.
305
*/
306
void job_user_cancel(Job *job, bool force, Error **errp);
307
308
+/* Same as job_user_cancel(), but called with job lock held. */
309
+void job_user_cancel_locked(Job *job, bool force, Error **errp);
310
+
311
/**
312
* Synchronously cancel the @job. The completion callback is called
313
* before the function returns. If @force is false, the job may
314
@@ -XXX,XX +XXX,XX @@ void job_user_cancel(Job *job, bool force, Error **errp);
315
*/
316
int job_cancel_sync(Job *job, bool force);
317
318
-/** Synchronously force-cancels all jobs using job_cancel_sync(). */
319
+/* Same as job_cancel_sync, but called with job lock held. */
320
+int job_cancel_sync_locked(Job *job, bool force);
321
+
322
+/**
323
+ * Synchronously force-cancels all jobs using job_cancel_sync_locked().
324
+ *
325
+ * Called with job_lock *not* held.
326
+ */
327
void job_cancel_sync_all(void);
328
329
/**
330
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
331
*/
332
int job_complete_sync(Job *job, Error **errp);
333
334
+/* Same as job_complete_sync, but called with job lock held. */
335
+int job_complete_sync_locked(Job *job, Error **errp);
336
+
337
/**
338
* For a @job that has finished its work and is pending awaiting explicit
339
* acknowledgement to commit its work, this will commit that work.
340
@@ -XXX,XX +XXX,XX @@ int job_complete_sync(Job *job, Error **errp);
341
*/
342
void job_finalize(Job *job, Error **errp);
343
344
+/* Same as job_finalize(), but called with job lock held. */
345
+void job_finalize_locked(Job *job, Error **errp);
346
+
347
/**
348
* Remove the concluded @job from the query list and resets the passed pointer
349
* to %NULL. Returns an error if the job is not actually concluded.
350
*/
351
void job_dismiss(Job **job, Error **errp);
352
353
+/* Same as job_dismiss(), but called with job lock held. */
354
+void job_dismiss_locked(Job **job, Error **errp);
355
+
356
/**
357
* Synchronously finishes the given @job. If @finish is given, it is called to
358
* trigger completion or cancellation of the job.
359
@@ -XXX,XX +XXX,XX @@ void job_dismiss(Job **job, Error **errp);
360
*
361
* Callers must hold the AioContext lock of job->aio_context.
362
*/
363
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp);
364
+int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
365
+ Error **errp);
366
+
367
+/*
368
+ * Same as job_finish_sync(), but called with job lock held.
369
+ * Might release the lock temporarily.
370
+ */
371
+int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
372
+ Error **errp);
373
374
#endif
375
diff --git a/job.c b/job.c
33
index XXXXXXX..XXXXXXX 100644
376
index XXXXXXX..XXXXXXX 100644
34
--- a/block.c
377
--- a/job.c
35
+++ b/block.c
378
+++ b/job.c
36
@@ -XXX,XX +XXX,XX @@ void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)
379
@@ -XXX,XX +XXX,XX @@
37
380
*/
38
parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
381
QemuMutex job_mutex;
39
}
382
40
+
383
+/* Protected by job_mutex */
41
+int bdrv_make_empty(BdrvChild *c, Error **errp)
384
static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);
42
+{
385
43
+ BlockDriver *drv = c->bs->drv;
386
/* Job State Transition Table */
387
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void)
388
return txn;
389
}
390
391
-static void job_txn_ref(JobTxn *txn)
392
+/* Called with job_mutex held. */
393
+static void job_txn_ref_locked(JobTxn *txn)
394
{
395
txn->refcnt++;
396
}
397
398
-void job_txn_unref(JobTxn *txn)
399
+void job_txn_unref_locked(JobTxn *txn)
400
{
401
if (txn && --txn->refcnt == 0) {
402
g_free(txn);
403
}
404
}
405
406
+void job_txn_unref(JobTxn *txn)
407
+{
408
+ JOB_LOCK_GUARD();
409
+ job_txn_unref_locked(txn);
410
+}
411
+
412
/**
413
* @txn: The transaction (may be NULL)
414
* @job: Job to add to the transaction
415
@@ -XXX,XX +XXX,XX @@ void job_txn_unref(JobTxn *txn)
416
* the reference that is automatically grabbed here.
417
*
418
* If @txn is NULL, the function does nothing.
419
+ *
420
+ * Called with job_mutex held.
421
*/
422
-static void job_txn_add_job(JobTxn *txn, Job *job)
423
+static void job_txn_add_job_locked(JobTxn *txn, Job *job)
424
{
425
if (!txn) {
426
return;
427
@@ -XXX,XX +XXX,XX @@ static void job_txn_add_job(JobTxn *txn, Job *job)
428
job->txn = txn;
429
430
QLIST_INSERT_HEAD(&txn->jobs, job, txn_list);
431
- job_txn_ref(txn);
432
+ job_txn_ref_locked(txn);
433
}
434
435
-static void job_txn_del_job(Job *job)
436
+/* Called with job_mutex held. */
437
+static void job_txn_del_job_locked(Job *job)
438
{
439
if (job->txn) {
440
QLIST_REMOVE(job, txn_list);
441
- job_txn_unref(job->txn);
442
+ job_txn_unref_locked(job->txn);
443
job->txn = NULL;
444
}
445
}
446
447
-static int job_txn_apply(Job *job, int fn(Job *))
448
+/* Called with job_mutex held, but releases it temporarily. */
449
+static int job_txn_apply_locked(Job *job, int fn(Job *))
450
{
451
AioContext *inner_ctx;
452
Job *other_job, *next;
453
@@ -XXX,XX +XXX,XX @@ static int job_txn_apply(Job *job, int fn(Job *))
454
* we need to release it here to avoid holding the lock twice - which would
455
* break AIO_WAIT_WHILE from within fn.
456
*/
457
- job_ref(job);
458
+ job_ref_locked(job);
459
aio_context_release(job->aio_context);
460
461
QLIST_FOREACH_SAFE(other_job, &txn->jobs, txn_list, next) {
462
@@ -XXX,XX +XXX,XX @@ static int job_txn_apply(Job *job, int fn(Job *))
463
* can't use a local variable to cache it.
464
*/
465
aio_context_acquire(job->aio_context);
466
- job_unref(job);
467
+ job_unref_locked(job);
468
return rc;
469
}
470
471
@@ -XXX,XX +XXX,XX @@ bool job_is_internal(Job *job)
472
return (job->id == NULL);
473
}
474
475
-static void job_state_transition(Job *job, JobStatus s1)
476
+/* Called with job_mutex held. */
477
+static void job_state_transition_locked(Job *job, JobStatus s1)
478
{
479
JobStatus s0 = job->status;
480
assert(s1 >= 0 && s1 < JOB_STATUS__MAX);
481
@@ -XXX,XX +XXX,XX @@ static void job_state_transition(Job *job, JobStatus s1)
482
}
483
}
484
485
-int job_apply_verb(Job *job, JobVerb verb, Error **errp)
486
+int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp)
487
{
488
JobStatus s0 = job->status;
489
assert(verb >= 0 && verb < JOB_VERB__MAX);
490
@@ -XXX,XX +XXX,XX @@ int job_apply_verb(Job *job, JobVerb verb, Error **errp)
491
return -EPERM;
492
}
493
494
+int job_apply_verb(Job *job, JobVerb verb, Error **errp)
495
+{
496
+ JOB_LOCK_GUARD();
497
+ return job_apply_verb_locked(job, verb, errp);
498
+}
499
+
500
JobType job_type(const Job *job)
501
{
502
return job->driver->job_type;
503
@@ -XXX,XX +XXX,XX @@ const char *job_type_str(const Job *job)
504
return JobType_str(job_type(job));
505
}
506
507
-bool job_is_cancelled(Job *job)
508
+bool job_is_cancelled_locked(Job *job)
509
{
510
/* force_cancel may be true only if cancelled is true, too */
511
assert(job->cancelled || !job->force_cancel);
512
return job->force_cancel;
513
}
514
515
-bool job_cancel_requested(Job *job)
516
+bool job_is_cancelled(Job *job)
517
+{
518
+ JOB_LOCK_GUARD();
519
+ return job_is_cancelled_locked(job);
520
+}
521
+
522
+/* Called with job_mutex held. */
523
+static bool job_cancel_requested_locked(Job *job)
524
{
525
return job->cancelled;
526
}
527
528
-bool job_is_ready(Job *job)
529
+bool job_cancel_requested(Job *job)
530
+{
531
+ JOB_LOCK_GUARD();
532
+ return job_cancel_requested_locked(job);
533
+}
534
+
535
+bool job_is_ready_locked(Job *job)
536
{
537
switch (job->status) {
538
case JOB_STATUS_UNDEFINED:
539
@@ -XXX,XX +XXX,XX @@ bool job_is_ready(Job *job)
540
return false;
541
}
542
543
-bool job_is_completed(Job *job)
544
+bool job_is_ready(Job *job)
545
+{
546
+ JOB_LOCK_GUARD();
547
+ return job_is_ready_locked(job);
548
+}
549
+
550
+bool job_is_completed_locked(Job *job)
551
{
552
switch (job->status) {
553
case JOB_STATUS_UNDEFINED:
554
@@ -XXX,XX +XXX,XX @@ bool job_is_completed(Job *job)
555
return false;
556
}
557
558
-static bool job_started(Job *job)
559
+bool job_is_completed(Job *job)
560
+{
561
+ JOB_LOCK_GUARD();
562
+ return job_is_completed_locked(job);
563
+}
564
+
565
+static bool job_started_locked(Job *job)
566
{
567
return job->co;
568
}
569
570
-static bool job_should_pause(Job *job)
571
+/* Called with job_mutex held. */
572
+static bool job_should_pause_locked(Job *job)
573
{
574
return job->pause_count > 0;
575
}
576
577
-Job *job_next(Job *job)
578
+Job *job_next_locked(Job *job)
579
{
580
if (!job) {
581
return QLIST_FIRST(&jobs);
582
@@ -XXX,XX +XXX,XX @@ Job *job_next(Job *job)
583
return QLIST_NEXT(job, job_list);
584
}
585
586
-Job *job_get(const char *id)
587
+Job *job_next(Job *job)
588
+{
589
+ JOB_LOCK_GUARD();
590
+ return job_next_locked(job);
591
+}
592
+
593
+Job *job_get_locked(const char *id)
594
{
595
Job *job;
596
597
@@ -XXX,XX +XXX,XX @@ Job *job_get(const char *id)
598
return NULL;
599
}
600
601
+Job *job_get(const char *id)
602
+{
603
+ JOB_LOCK_GUARD();
604
+ return job_get_locked(id);
605
+}
606
+
607
+/* Called with job_mutex *not* held. */
608
static void job_sleep_timer_cb(void *opaque)
609
{
610
Job *job = opaque;
611
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
612
{
613
Job *job;
614
615
+ JOB_LOCK_GUARD();
616
+
617
if (job_id) {
618
if (flags & JOB_INTERNAL) {
619
error_setg(errp, "Cannot specify job ID for internal job");
620
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
621
error_setg(errp, "Invalid job ID '%s'", job_id);
622
return NULL;
623
}
624
- if (job_get(job_id)) {
625
+ if (job_get_locked(job_id)) {
626
error_setg(errp, "Job ID '%s' already in use", job_id);
627
return NULL;
628
}
629
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
630
notifier_list_init(&job->on_ready);
631
notifier_list_init(&job->on_idle);
632
633
- job_state_transition(job, JOB_STATUS_CREATED);
634
+ job_state_transition_locked(job, JOB_STATUS_CREATED);
635
aio_timer_init(qemu_get_aio_context(), &job->sleep_timer,
636
QEMU_CLOCK_REALTIME, SCALE_NS,
637
job_sleep_timer_cb, job);
638
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
639
* consolidating the job management logic */
640
if (!txn) {
641
txn = job_txn_new();
642
- job_txn_add_job(txn, job);
643
- job_txn_unref(txn);
644
+ job_txn_add_job_locked(txn, job);
645
+ job_txn_unref_locked(txn);
646
} else {
647
- job_txn_add_job(txn, job);
648
+ job_txn_add_job_locked(txn, job);
649
}
650
651
return job;
652
}
653
654
-void job_ref(Job *job)
655
+void job_ref_locked(Job *job)
656
{
657
++job->refcnt;
658
}
659
660
-void job_unref(Job *job)
661
+void job_ref(Job *job)
662
+{
663
+ JOB_LOCK_GUARD();
664
+ job_ref_locked(job);
665
+}
666
+
667
+void job_unref_locked(Job *job)
668
{
669
GLOBAL_STATE_CODE();
670
671
@@ -XXX,XX +XXX,XX @@ void job_unref(Job *job)
672
assert(!job->txn);
673
674
if (job->driver->free) {
675
+ job_unlock();
676
job->driver->free(job);
677
+ job_lock();
678
}
679
680
QLIST_REMOVE(job, job_list);
681
@@ -XXX,XX +XXX,XX @@ void job_unref(Job *job)
682
}
683
}
684
685
+void job_unref(Job *job)
686
+{
687
+ JOB_LOCK_GUARD();
688
+ job_unref_locked(job);
689
+}
690
+
691
void job_progress_update(Job *job, uint64_t done)
692
{
693
progress_work_done(&job->progress, done);
694
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta)
695
696
/**
697
* To be called when a cancelled job is finalised.
698
+ * Called with job_mutex held.
699
*/
700
-static void job_event_cancelled(Job *job)
701
+static void job_event_cancelled_locked(Job *job)
702
{
703
notifier_list_notify(&job->on_finalize_cancelled, job);
704
}
705
706
/**
707
* To be called when a successfully completed job is finalised.
708
+ * Called with job_mutex held.
709
*/
710
-static void job_event_completed(Job *job)
711
+static void job_event_completed_locked(Job *job)
712
{
713
notifier_list_notify(&job->on_finalize_completed, job);
714
}
715
716
-static void job_event_pending(Job *job)
717
+/* Called with job_mutex held. */
718
+static void job_event_pending_locked(Job *job)
719
{
720
notifier_list_notify(&job->on_pending, job);
721
}
722
723
-static void job_event_ready(Job *job)
724
+/* Called with job_mutex held. */
725
+static void job_event_ready_locked(Job *job)
726
{
727
notifier_list_notify(&job->on_ready, job);
728
}
729
730
-static void job_event_idle(Job *job)
731
+/* Called with job_mutex held. */
732
+static void job_event_idle_locked(Job *job)
733
{
734
notifier_list_notify(&job->on_idle, job);
735
}
736
737
-void job_enter_cond(Job *job, bool(*fn)(Job *job))
738
+void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
739
{
740
- if (!job_started(job)) {
741
+ if (!job_started_locked(job)) {
742
return;
743
}
744
if (job->deferred_to_main_loop) {
745
@@ -XXX,XX +XXX,XX @@ void job_enter_cond(Job *job, bool(*fn)(Job *job))
746
timer_del(&job->sleep_timer);
747
job->busy = true;
748
real_job_unlock();
749
+ job_unlock();
750
aio_co_enter(job->aio_context, job->co);
751
+ job_lock();
752
+}
753
+
754
+void job_enter_cond(Job *job, bool(*fn)(Job *job))
755
+{
756
+ JOB_LOCK_GUARD();
757
+ job_enter_cond_locked(job, fn);
758
}
759
760
void job_enter(Job *job)
761
{
762
- job_enter_cond(job, NULL);
763
+ JOB_LOCK_GUARD();
764
+ job_enter_cond_locked(job, NULL);
765
}
766
767
/* Yield, and schedule a timer to reenter the coroutine after @ns nanoseconds.
768
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job)
769
* is allowed and cancels the timer.
770
*
771
* If @ns is (uint64_t) -1, no timer is scheduled and job_enter() must be
772
- * called explicitly. */
773
-static void coroutine_fn job_do_yield(Job *job, uint64_t ns)
774
+ * called explicitly.
775
+ *
776
+ * Called with job_mutex held, but releases it temporarily.
777
+ */
778
+static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
779
{
780
real_job_lock();
781
if (ns != -1) {
782
timer_mod(&job->sleep_timer, ns);
783
}
784
job->busy = false;
785
- job_event_idle(job);
786
+ job_event_idle_locked(job);
787
real_job_unlock();
788
+ job_unlock();
789
qemu_coroutine_yield();
790
+ job_lock();
791
792
/* Set by job_enter_cond() before re-entering the coroutine. */
793
assert(job->busy);
794
}
795
796
-void coroutine_fn job_pause_point(Job *job)
797
+/* Called with job_mutex held, but releases it temporarily. */
798
+static void coroutine_fn job_pause_point_locked(Job *job)
799
{
800
- assert(job && job_started(job));
801
+ assert(job && job_started_locked(job));
802
803
- if (!job_should_pause(job)) {
804
+ if (!job_should_pause_locked(job)) {
805
return;
806
}
807
- if (job_is_cancelled(job)) {
808
+ if (job_is_cancelled_locked(job)) {
809
return;
810
}
811
812
if (job->driver->pause) {
813
+ job_unlock();
814
job->driver->pause(job);
815
+ job_lock();
816
}
817
818
- if (job_should_pause(job) && !job_is_cancelled(job)) {
819
+ if (job_should_pause_locked(job) && !job_is_cancelled_locked(job)) {
820
JobStatus status = job->status;
821
- job_state_transition(job, status == JOB_STATUS_READY
822
- ? JOB_STATUS_STANDBY
823
- : JOB_STATUS_PAUSED);
824
+ job_state_transition_locked(job, status == JOB_STATUS_READY
825
+ ? JOB_STATUS_STANDBY
826
+ : JOB_STATUS_PAUSED);
827
job->paused = true;
828
- job_do_yield(job, -1);
829
+ job_do_yield_locked(job, -1);
830
job->paused = false;
831
- job_state_transition(job, status);
832
+ job_state_transition_locked(job, status);
833
}
834
835
if (job->driver->resume) {
836
+ job_unlock();
837
job->driver->resume(job);
838
+ job_lock();
839
}
840
}
841
842
-void coroutine_fn job_yield(Job *job)
843
+void coroutine_fn job_pause_point(Job *job)
844
+{
845
+ JOB_LOCK_GUARD();
846
+ job_pause_point_locked(job);
847
+}
848
+
849
+static void coroutine_fn job_yield_locked(Job *job)
850
{
851
assert(job->busy);
852
853
/* Check cancellation *before* setting busy = false, too! */
854
- if (job_is_cancelled(job)) {
855
+ if (job_is_cancelled_locked(job)) {
856
return;
857
}
858
859
- if (!job_should_pause(job)) {
860
- job_do_yield(job, -1);
861
+ if (!job_should_pause_locked(job)) {
862
+ job_do_yield_locked(job, -1);
863
}
864
865
- job_pause_point(job);
866
+ job_pause_point_locked(job);
867
+}
868
+
869
+void coroutine_fn job_yield(Job *job)
870
+{
871
+ JOB_LOCK_GUARD();
872
+ job_yield_locked(job);
873
}
874
875
void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
876
{
877
+ JOB_LOCK_GUARD();
878
assert(job->busy);
879
880
/* Check cancellation *before* setting busy = false, too! */
881
- if (job_is_cancelled(job)) {
882
+ if (job_is_cancelled_locked(job)) {
883
return;
884
}
885
886
- if (!job_should_pause(job)) {
887
- job_do_yield(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns);
888
+ if (!job_should_pause_locked(job)) {
889
+ job_do_yield_locked(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns);
890
}
891
892
- job_pause_point(job);
893
+ job_pause_point_locked(job);
894
}
895
896
-/* Assumes the block_job_mutex is held */
897
-static bool job_timer_not_pending(Job *job)
898
+/* Assumes the job_mutex is held */
899
+static bool job_timer_not_pending_locked(Job *job)
900
{
901
return !timer_pending(&job->sleep_timer);
902
}
903
904
-void job_pause(Job *job)
905
+void job_pause_locked(Job *job)
906
{
907
job->pause_count++;
908
if (!job->paused) {
909
- job_enter(job);
910
+ job_enter_cond_locked(job, NULL);
911
}
912
}
913
914
-void job_resume(Job *job)
915
+void job_pause(Job *job)
916
+{
917
+ JOB_LOCK_GUARD();
918
+ job_pause_locked(job);
919
+}
920
+
921
+void job_resume_locked(Job *job)
922
{
923
assert(job->pause_count > 0);
924
job->pause_count--;
925
@@ -XXX,XX +XXX,XX @@ void job_resume(Job *job)
926
}
927
928
/* kick only if no timer is pending */
929
- job_enter_cond(job, job_timer_not_pending);
930
+ job_enter_cond_locked(job, job_timer_not_pending_locked);
931
}
932
933
-void job_user_pause(Job *job, Error **errp)
934
+void job_resume(Job *job)
935
{
936
- if (job_apply_verb(job, JOB_VERB_PAUSE, errp)) {
937
+ JOB_LOCK_GUARD();
938
+ job_resume_locked(job);
939
+}
940
+
941
+void job_user_pause_locked(Job *job, Error **errp)
942
+{
943
+ if (job_apply_verb_locked(job, JOB_VERB_PAUSE, errp)) {
944
return;
945
}
946
if (job->user_paused) {
947
@@ -XXX,XX +XXX,XX @@ void job_user_pause(Job *job, Error **errp)
948
return;
949
}
950
job->user_paused = true;
951
- job_pause(job);
952
+ job_pause_locked(job);
953
}
954
955
-bool job_user_paused(Job *job)
956
+void job_user_pause(Job *job, Error **errp)
957
+{
958
+ JOB_LOCK_GUARD();
959
+ job_user_pause_locked(job, errp);
960
+}
961
+
962
+bool job_user_paused_locked(Job *job)
963
{
964
return job->user_paused;
965
}
966
967
-void job_user_resume(Job *job, Error **errp)
968
+bool job_user_paused(Job *job)
969
+{
970
+ JOB_LOCK_GUARD();
971
+ return job_user_paused_locked(job);
972
+}
973
+
974
+void job_user_resume_locked(Job *job, Error **errp)
975
{
976
assert(job);
977
GLOBAL_STATE_CODE();
978
@@ -XXX,XX +XXX,XX @@ void job_user_resume(Job *job, Error **errp)
979
error_setg(errp, "Can't resume a job that was not paused");
980
return;
981
}
982
- if (job_apply_verb(job, JOB_VERB_RESUME, errp)) {
983
+ if (job_apply_verb_locked(job, JOB_VERB_RESUME, errp)) {
984
return;
985
}
986
if (job->driver->user_resume) {
987
+ job_unlock();
988
job->driver->user_resume(job);
989
+ job_lock();
990
}
991
job->user_paused = false;
992
- job_resume(job);
993
+ job_resume_locked(job);
994
}
995
996
-static void job_do_dismiss(Job *job)
997
+void job_user_resume(Job *job, Error **errp)
998
+{
999
+ JOB_LOCK_GUARD();
1000
+ job_user_resume_locked(job, errp);
1001
+}
1002
+
1003
+/* Called with job_mutex held, but releases it temporarily. */
1004
+static void job_do_dismiss_locked(Job *job)
1005
{
1006
assert(job);
1007
job->busy = false;
1008
job->paused = false;
1009
job->deferred_to_main_loop = true;
1010
1011
- job_txn_del_job(job);
1012
+ job_txn_del_job_locked(job);
1013
1014
- job_state_transition(job, JOB_STATUS_NULL);
1015
- job_unref(job);
1016
+ job_state_transition_locked(job, JOB_STATUS_NULL);
1017
+ job_unref_locked(job);
1018
}
1019
1020
-void job_dismiss(Job **jobptr, Error **errp)
1021
+void job_dismiss_locked(Job **jobptr, Error **errp)
1022
{
1023
Job *job = *jobptr;
1024
/* similarly to _complete, this is QMP-interface only. */
1025
assert(job->id);
1026
- if (job_apply_verb(job, JOB_VERB_DISMISS, errp)) {
1027
+ if (job_apply_verb_locked(job, JOB_VERB_DISMISS, errp)) {
1028
return;
1029
}
1030
1031
- job_do_dismiss(job);
1032
+ job_do_dismiss_locked(job);
1033
*jobptr = NULL;
1034
}
1035
1036
+void job_dismiss(Job **jobptr, Error **errp)
1037
+{
1038
+ JOB_LOCK_GUARD();
1039
+ job_dismiss_locked(jobptr, errp);
1040
+}
1041
+
1042
void job_early_fail(Job *job)
1043
{
1044
+ JOB_LOCK_GUARD();
1045
assert(job->status == JOB_STATUS_CREATED);
1046
- job_do_dismiss(job);
1047
+ job_do_dismiss_locked(job);
1048
}
1049
1050
-static void job_conclude(Job *job)
1051
+/* Called with job_mutex held. */
1052
+static void job_conclude_locked(Job *job)
1053
{
1054
- job_state_transition(job, JOB_STATUS_CONCLUDED);
1055
- if (job->auto_dismiss || !job_started(job)) {
1056
- job_do_dismiss(job);
1057
+ job_state_transition_locked(job, JOB_STATUS_CONCLUDED);
1058
+ if (job->auto_dismiss || !job_started_locked(job)) {
1059
+ job_do_dismiss_locked(job);
1060
}
1061
}
1062
1063
-static void job_update_rc(Job *job)
1064
+/* Called with job_mutex held. */
1065
+static void job_update_rc_locked(Job *job)
1066
{
1067
- if (!job->ret && job_is_cancelled(job)) {
1068
+ if (!job->ret && job_is_cancelled_locked(job)) {
1069
job->ret = -ECANCELED;
1070
}
1071
if (job->ret) {
1072
if (!job->err) {
1073
error_setg(&job->err, "%s", strerror(-job->ret));
1074
}
1075
- job_state_transition(job, JOB_STATUS_ABORTING);
1076
+ job_state_transition_locked(job, JOB_STATUS_ABORTING);
1077
}
1078
}
1079
1080
@@ -XXX,XX +XXX,XX @@ static void job_clean(Job *job)
1081
}
1082
}
1083
1084
-static int job_finalize_single(Job *job)
1085
+/* Called with job_mutex held, but releases it temporarily */
1086
+static int job_finalize_single_locked(Job *job)
1087
{
1088
- assert(job_is_completed(job));
1089
+ int job_ret;
1090
+
1091
+ assert(job_is_completed_locked(job));
1092
1093
/* Ensure abort is called for late-transactional failures */
1094
- job_update_rc(job);
1095
+ job_update_rc_locked(job);
1096
+
1097
+ job_ret = job->ret;
1098
+ job_unlock();
1099
1100
- if (!job->ret) {
1101
+ if (!job_ret) {
1102
job_commit(job);
1103
} else {
1104
job_abort(job);
1105
}
1106
job_clean(job);
1107
1108
+ job_lock();
1109
+
1110
if (job->cb) {
1111
- job->cb(job->opaque, job->ret);
1112
+ job_ret = job->ret;
1113
+ job_unlock();
1114
+ job->cb(job->opaque, job_ret);
1115
+ job_lock();
1116
}
1117
1118
/* Emit events only if we actually started */
1119
- if (job_started(job)) {
1120
- if (job_is_cancelled(job)) {
1121
- job_event_cancelled(job);
1122
+ if (job_started_locked(job)) {
1123
+ if (job_is_cancelled_locked(job)) {
1124
+ job_event_cancelled_locked(job);
1125
} else {
1126
- job_event_completed(job);
1127
+ job_event_completed_locked(job);
1128
}
1129
}
1130
1131
- job_txn_del_job(job);
1132
- job_conclude(job);
1133
+ job_txn_del_job_locked(job);
1134
+ job_conclude_locked(job);
1135
return 0;
1136
}
1137
1138
-static void job_cancel_async(Job *job, bool force)
1139
+/* Called with job_mutex held, but releases it temporarily */
1140
+static void job_cancel_async_locked(Job *job, bool force)
1141
{
1142
GLOBAL_STATE_CODE();
1143
if (job->driver->cancel) {
1144
+ job_unlock();
1145
force = job->driver->cancel(job, force);
1146
+ job_lock();
1147
} else {
1148
/* No .cancel() means the job will behave as if force-cancelled */
1149
force = true;
1150
@@ -XXX,XX +XXX,XX @@ static void job_cancel_async(Job *job, bool force)
1151
if (job->user_paused) {
1152
/* Do not call job_enter here, the caller will handle it. */
1153
if (job->driver->user_resume) {
1154
+ job_unlock();
1155
job->driver->user_resume(job);
1156
+ job_lock();
1157
}
1158
job->user_paused = false;
1159
assert(job->pause_count > 0);
1160
@@ -XXX,XX +XXX,XX @@ static void job_cancel_async(Job *job, bool force)
1161
}
1162
}
1163
1164
-static void job_completed_txn_abort(Job *job)
1165
+/* Called with job_mutex held, but releases it temporarily. */
1166
+static void job_completed_txn_abort_locked(Job *job)
1167
{
1168
AioContext *ctx;
1169
JobTxn *txn = job->txn;
1170
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
1171
return;
1172
}
1173
txn->aborting = true;
1174
- job_txn_ref(txn);
1175
+ job_txn_ref_locked(txn);
1176
1177
/*
1178
* We can only hold the single job's AioContext lock while calling
1179
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
1180
* calls of AIO_WAIT_WHILE(), which could deadlock otherwise.
1181
* Note that the job's AioContext may change when it is finalized.
1182
*/
1183
- job_ref(job);
1184
+ job_ref_locked(job);
1185
aio_context_release(job->aio_context);
1186
1187
/* Other jobs are effectively cancelled by us, set the status for
1188
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
1189
* Therefore, pass force=true to terminate all other jobs as quickly
1190
* as possible.
1191
*/
1192
- job_cancel_async(other_job, true);
1193
+ job_cancel_async_locked(other_job, true);
1194
aio_context_release(ctx);
1195
}
1196
}
1197
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
1198
*/
1199
ctx = other_job->aio_context;
1200
aio_context_acquire(ctx);
1201
- if (!job_is_completed(other_job)) {
1202
- assert(job_cancel_requested(other_job));
1203
- job_finish_sync(other_job, NULL, NULL);
1204
+ if (!job_is_completed_locked(other_job)) {
1205
+ assert(job_cancel_requested_locked(other_job));
1206
+ job_finish_sync_locked(other_job, NULL, NULL);
1207
}
1208
- job_finalize_single(other_job);
1209
+ job_finalize_single_locked(other_job);
1210
aio_context_release(ctx);
1211
}
1212
1213
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
1214
* even if the job went away during job_finalize_single().
1215
*/
1216
aio_context_acquire(job->aio_context);
1217
- job_unref(job);
1218
+ job_unref_locked(job);
1219
1220
- job_txn_unref(txn);
1221
+ job_txn_unref_locked(txn);
1222
}
1223
1224
-static int job_prepare(Job *job)
1225
+/* Called with job_mutex held, but releases it temporarily */
1226
+static int job_prepare_locked(Job *job)
1227
{
44
+ int ret;
1228
+ int ret;
45
+
1229
+
46
+ assert(c->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED));
1230
GLOBAL_STATE_CODE();
47
+
1231
if (job->ret == 0 && job->driver->prepare) {
48
+ if (!drv->bdrv_make_empty) {
1232
- job->ret = job->driver->prepare(job);
49
+ error_setg(errp, "%s does not support emptying nodes",
1233
- job_update_rc(job);
50
+ drv->format_name);
1234
+ job_unlock();
51
+ return -ENOTSUP;
1235
+ ret = job->driver->prepare(job);
1236
+ job_lock();
1237
+ job->ret = ret;
1238
+ job_update_rc_locked(job);
1239
}
1240
return job->ret;
1241
}
1242
1243
-static int job_needs_finalize(Job *job)
1244
+/* Called with job_mutex held */
1245
+static int job_needs_finalize_locked(Job *job)
1246
{
1247
return !job->auto_finalize;
1248
}
1249
1250
-static void job_do_finalize(Job *job)
1251
+/* Called with job_mutex held */
1252
+static void job_do_finalize_locked(Job *job)
1253
{
1254
int rc;
1255
assert(job && job->txn);
1256
1257
/* prepare the transaction to complete */
1258
- rc = job_txn_apply(job, job_prepare);
1259
+ rc = job_txn_apply_locked(job, job_prepare_locked);
1260
if (rc) {
1261
- job_completed_txn_abort(job);
1262
+ job_completed_txn_abort_locked(job);
1263
} else {
1264
- job_txn_apply(job, job_finalize_single);
1265
+ job_txn_apply_locked(job, job_finalize_single_locked);
1266
}
1267
}
1268
1269
-void job_finalize(Job *job, Error **errp)
1270
+void job_finalize_locked(Job *job, Error **errp)
1271
{
1272
assert(job && job->id);
1273
- if (job_apply_verb(job, JOB_VERB_FINALIZE, errp)) {
1274
+ if (job_apply_verb_locked(job, JOB_VERB_FINALIZE, errp)) {
1275
return;
1276
}
1277
- job_do_finalize(job);
1278
+ job_do_finalize_locked(job);
1279
}
1280
1281
-static int job_transition_to_pending(Job *job)
1282
+void job_finalize(Job *job, Error **errp)
1283
{
1284
- job_state_transition(job, JOB_STATUS_PENDING);
1285
+ JOB_LOCK_GUARD();
1286
+ job_finalize_locked(job, errp);
1287
+}
1288
+
1289
+/* Called with job_mutex held. */
1290
+static int job_transition_to_pending_locked(Job *job)
1291
+{
1292
+ job_state_transition_locked(job, JOB_STATUS_PENDING);
1293
if (!job->auto_finalize) {
1294
- job_event_pending(job);
1295
+ job_event_pending_locked(job);
1296
}
1297
return 0;
1298
}
1299
1300
void job_transition_to_ready(Job *job)
1301
{
1302
- job_state_transition(job, JOB_STATUS_READY);
1303
- job_event_ready(job);
1304
+ JOB_LOCK_GUARD();
1305
+ job_state_transition_locked(job, JOB_STATUS_READY);
1306
+ job_event_ready_locked(job);
1307
}
1308
1309
-static void job_completed_txn_success(Job *job)
1310
+/* Called with job_mutex held. */
1311
+static void job_completed_txn_success_locked(Job *job)
1312
{
1313
JobTxn *txn = job->txn;
1314
Job *other_job;
1315
1316
- job_state_transition(job, JOB_STATUS_WAITING);
1317
+ job_state_transition_locked(job, JOB_STATUS_WAITING);
1318
1319
/*
1320
* Successful completion, see if there are other running jobs in this
1321
* txn.
1322
*/
1323
QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
1324
- if (!job_is_completed(other_job)) {
1325
+ if (!job_is_completed_locked(other_job)) {
1326
return;
1327
}
1328
assert(other_job->ret == 0);
1329
}
1330
1331
- job_txn_apply(job, job_transition_to_pending);
1332
+ job_txn_apply_locked(job, job_transition_to_pending_locked);
1333
1334
/* If no jobs need manual finalization, automatically do so */
1335
- if (job_txn_apply(job, job_needs_finalize) == 0) {
1336
- job_do_finalize(job);
1337
+ if (job_txn_apply_locked(job, job_needs_finalize_locked) == 0) {
1338
+ job_do_finalize_locked(job);
1339
}
1340
}
1341
1342
-static void job_completed(Job *job)
1343
+/* Called with job_mutex held. */
1344
+static void job_completed_locked(Job *job)
1345
{
1346
- assert(job && job->txn && !job_is_completed(job));
1347
+ assert(job && job->txn && !job_is_completed_locked(job));
1348
1349
- job_update_rc(job);
1350
+ job_update_rc_locked(job);
1351
trace_job_completed(job, job->ret);
1352
if (job->ret) {
1353
- job_completed_txn_abort(job);
1354
+ job_completed_txn_abort_locked(job);
1355
} else {
1356
- job_completed_txn_success(job);
1357
+ job_completed_txn_success_locked(job);
1358
}
1359
}
1360
1361
-/** Useful only as a type shim for aio_bh_schedule_oneshot. */
1362
+/**
1363
+ * Useful only as a type shim for aio_bh_schedule_oneshot.
1364
+ * Called with job_mutex *not* held.
1365
+ */
1366
static void job_exit(void *opaque)
1367
{
1368
Job *job = (Job *)opaque;
1369
AioContext *ctx;
1370
+ JOB_LOCK_GUARD();
1371
1372
- job_ref(job);
1373
+ job_ref_locked(job);
1374
aio_context_acquire(job->aio_context);
1375
1376
/* This is a lie, we're not quiescent, but still doing the completion
1377
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
1378
* drain block nodes, and if .drained_poll still returned true, we would
1379
* deadlock. */
1380
job->busy = false;
1381
- job_event_idle(job);
1382
+ job_event_idle_locked(job);
1383
1384
- job_completed(job);
1385
+ job_completed_locked(job);
1386
1387
/*
1388
* Note that calling job_completed can move the job to a different
1389
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
1390
* the job underneath us.
1391
*/
1392
ctx = job->aio_context;
1393
- job_unref(job);
1394
+ job_unref_locked(job);
1395
aio_context_release(ctx);
1396
}
1397
1398
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
1399
static void coroutine_fn job_co_entry(void *opaque)
1400
{
1401
Job *job = opaque;
1402
+ int ret;
1403
1404
assert(job && job->driver && job->driver->run);
1405
- assert(job->aio_context == qemu_get_current_aio_context());
1406
- job_pause_point(job);
1407
- job->ret = job->driver->run(job, &job->err);
1408
- job->deferred_to_main_loop = true;
1409
- job->busy = true;
1410
+ WITH_JOB_LOCK_GUARD() {
1411
+ assert(job->aio_context == qemu_get_current_aio_context());
1412
+ job_pause_point_locked(job);
52
+ }
1413
+ }
53
+
1414
+ ret = job->driver->run(job, &job->err);
54
+ ret = drv->bdrv_make_empty(c->bs);
1415
+ WITH_JOB_LOCK_GUARD() {
55
+ if (ret < 0) {
1416
+ job->ret = ret;
56
+ error_setg_errno(errp, -ret, "Failed to empty %s",
1417
+ job->deferred_to_main_loop = true;
57
+ c->bs->filename);
1418
+ job->busy = true;
58
+ return ret;
59
+ }
1419
+ }
60
+
1420
aio_bh_schedule_oneshot(qemu_get_aio_context(), job_exit, job);
61
+ return 0;
1421
}
1422
1423
void job_start(Job *job)
1424
{
1425
- assert(job && !job_started(job) && job->paused &&
1426
- job->driver && job->driver->run);
1427
- job->co = qemu_coroutine_create(job_co_entry, job);
1428
- job->pause_count--;
1429
- job->busy = true;
1430
- job->paused = false;
1431
- job_state_transition(job, JOB_STATUS_RUNNING);
1432
+ assert(qemu_in_main_thread());
1433
+
1434
+ WITH_JOB_LOCK_GUARD() {
1435
+ assert(job && !job_started_locked(job) && job->paused &&
1436
+ job->driver && job->driver->run);
1437
+ job->co = qemu_coroutine_create(job_co_entry, job);
1438
+ job->pause_count--;
1439
+ job->busy = true;
1440
+ job->paused = false;
1441
+ job_state_transition_locked(job, JOB_STATUS_RUNNING);
1442
+ }
1443
aio_co_enter(job->aio_context, job->co);
1444
}
1445
1446
-void job_cancel(Job *job, bool force)
1447
+void job_cancel_locked(Job *job, bool force)
1448
{
1449
if (job->status == JOB_STATUS_CONCLUDED) {
1450
- job_do_dismiss(job);
1451
+ job_do_dismiss_locked(job);
1452
return;
1453
}
1454
- job_cancel_async(job, force);
1455
- if (!job_started(job)) {
1456
- job_completed(job);
1457
+ job_cancel_async_locked(job, force);
1458
+ if (!job_started_locked(job)) {
1459
+ job_completed_locked(job);
1460
} else if (job->deferred_to_main_loop) {
1461
/*
1462
* job_cancel_async() ignores soft-cancel requests for jobs
1463
@@ -XXX,XX +XXX,XX @@ void job_cancel(Job *job, bool force)
1464
* choose to call job_is_cancelled() to show that we invoke
1465
* job_completed_txn_abort() only for force-cancelled jobs.)
1466
*/
1467
- if (job_is_cancelled(job)) {
1468
- job_completed_txn_abort(job);
1469
+ if (job_is_cancelled_locked(job)) {
1470
+ job_completed_txn_abort_locked(job);
1471
}
1472
} else {
1473
- job_enter(job);
1474
+ job_enter_cond_locked(job, NULL);
1475
}
1476
}
1477
1478
-void job_user_cancel(Job *job, bool force, Error **errp)
1479
+void job_cancel(Job *job, bool force)
1480
{
1481
- if (job_apply_verb(job, JOB_VERB_CANCEL, errp)) {
1482
+ JOB_LOCK_GUARD();
1483
+ job_cancel_locked(job, force);
1484
+}
1485
+
1486
+void job_user_cancel_locked(Job *job, bool force, Error **errp)
1487
+{
1488
+ if (job_apply_verb_locked(job, JOB_VERB_CANCEL, errp)) {
1489
return;
1490
}
1491
- job_cancel(job, force);
1492
+ job_cancel_locked(job, force);
1493
+}
1494
+
1495
+void job_user_cancel(Job *job, bool force, Error **errp)
1496
+{
1497
+ JOB_LOCK_GUARD();
1498
+ job_user_cancel_locked(job, force, errp);
1499
}
1500
1501
/* A wrapper around job_cancel() taking an Error ** parameter so it may be
1502
* used with job_finish_sync() without the need for (rather nasty) function
1503
- * pointer casts there. */
1504
-static void job_cancel_err(Job *job, Error **errp)
1505
+ * pointer casts there.
1506
+ *
1507
+ * Called with job_mutex held.
1508
+ */
1509
+static void job_cancel_err_locked(Job *job, Error **errp)
1510
{
1511
- job_cancel(job, false);
1512
+ job_cancel_locked(job, false);
1513
}
1514
1515
/**
1516
* Same as job_cancel_err(), but force-cancel.
1517
+ * Called with job_mutex held.
1518
*/
1519
-static void job_force_cancel_err(Job *job, Error **errp)
1520
+static void job_force_cancel_err_locked(Job *job, Error **errp)
1521
{
1522
- job_cancel(job, true);
1523
+ job_cancel_locked(job, true);
1524
}
1525
1526
-int job_cancel_sync(Job *job, bool force)
1527
+int job_cancel_sync_locked(Job *job, bool force)
1528
{
1529
if (force) {
1530
- return job_finish_sync(job, &job_force_cancel_err, NULL);
1531
+ return job_finish_sync_locked(job, &job_force_cancel_err_locked, NULL);
1532
} else {
1533
- return job_finish_sync(job, &job_cancel_err, NULL);
1534
+ return job_finish_sync_locked(job, &job_cancel_err_locked, NULL);
1535
}
1536
}
1537
1538
+int job_cancel_sync(Job *job, bool force)
1539
+{
1540
+ JOB_LOCK_GUARD();
1541
+ return job_cancel_sync_locked(job, force);
1542
+}
1543
+
1544
void job_cancel_sync_all(void)
1545
{
1546
Job *job;
1547
AioContext *aio_context;
1548
+ JOB_LOCK_GUARD();
1549
1550
- while ((job = job_next(NULL))) {
1551
+ while ((job = job_next_locked(NULL))) {
1552
aio_context = job->aio_context;
1553
aio_context_acquire(aio_context);
1554
- job_cancel_sync(job, true);
1555
+ job_cancel_sync_locked(job, true);
1556
aio_context_release(aio_context);
1557
}
1558
}
1559
1560
+int job_complete_sync_locked(Job *job, Error **errp)
1561
+{
1562
+ return job_finish_sync_locked(job, job_complete_locked, errp);
1563
+}
1564
+
1565
int job_complete_sync(Job *job, Error **errp)
1566
{
1567
- return job_finish_sync(job, job_complete, errp);
1568
+ JOB_LOCK_GUARD();
1569
+ return job_complete_sync_locked(job, errp);
1570
}
1571
1572
-void job_complete(Job *job, Error **errp)
1573
+void job_complete_locked(Job *job, Error **errp)
1574
{
1575
/* Should not be reachable via external interface for internal jobs */
1576
assert(job->id);
1577
GLOBAL_STATE_CODE();
1578
- if (job_apply_verb(job, JOB_VERB_COMPLETE, errp)) {
1579
+ if (job_apply_verb_locked(job, JOB_VERB_COMPLETE, errp)) {
1580
return;
1581
}
1582
- if (job_cancel_requested(job) || !job->driver->complete) {
1583
+ if (job_cancel_requested_locked(job) || !job->driver->complete) {
1584
error_setg(errp, "The active block job '%s' cannot be completed",
1585
job->id);
1586
return;
1587
}
1588
1589
+ job_unlock();
1590
job->driver->complete(job, errp);
1591
+ job_lock();
1592
}
1593
1594
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
1595
+void job_complete(Job *job, Error **errp)
1596
+{
1597
+ JOB_LOCK_GUARD();
1598
+ job_complete_locked(job, errp);
1599
+}
1600
+
1601
+int job_finish_sync_locked(Job *job,
1602
+ void (*finish)(Job *, Error **errp),
1603
+ Error **errp)
1604
{
1605
Error *local_err = NULL;
1606
int ret;
1607
1608
- job_ref(job);
1609
+ job_ref_locked(job);
1610
1611
if (finish) {
1612
finish(job, &local_err);
1613
}
1614
if (local_err) {
1615
error_propagate(errp, local_err);
1616
- job_unref(job);
1617
+ job_unref_locked(job);
1618
return -EBUSY;
1619
}
1620
1621
+ job_unlock();
1622
AIO_WAIT_WHILE(job->aio_context,
1623
(job_enter(job), !job_is_completed(job)));
1624
+ job_lock();
1625
1626
- ret = (job_is_cancelled(job) && job->ret == 0) ? -ECANCELED : job->ret;
1627
- job_unref(job);
1628
+ ret = (job_is_cancelled_locked(job) && job->ret == 0)
1629
+ ? -ECANCELED : job->ret;
1630
+ job_unref_locked(job);
1631
return ret;
1632
}
1633
+
1634
+int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
1635
+{
1636
+ JOB_LOCK_GUARD();
1637
+ return job_finish_sync_locked(job, finish, errp);
62
+}
1638
+}
63
--
1639
--
64
2.25.4
1640
2.37.3
65
66
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
After the series this patch belongs to, we want to have a common
3
This comment applies more on job, it was left in blockjob as in the past
4
BdrvChildClass that encompasses all of child_file, child_format, and
4
the whole job logic was implemented there.
5
child_backing. Such a single class needs a single .inherit_options()
6
implementation, and this patch introduces it.
7
5
8
The next patch will show how the existing implementations can fall back
6
Note: at this stage, job_{lock/unlock} and job lock guard macros
9
to it just by passing appropriate BdrvChildRole and parent_is_format
7
are *nop*.
10
values.
11
8
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
No functional change intended.
13
Message-Id: <20200513110544.176672-11-mreitz@redhat.com>
10
14
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20220926093214.506243-7-eesposit@redhat.com>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
---
17
block.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
18
blockjob.c | 20 --------------------
18
1 file changed, 81 insertions(+)
19
job.c | 16 ++++++++++++++++
20
2 files changed, 16 insertions(+), 20 deletions(-)
19
21
20
diff --git a/block.c b/block.c
22
diff --git a/blockjob.c b/blockjob.c
21
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
22
--- a/block.c
24
--- a/blockjob.c
23
+++ b/block.c
25
+++ b/blockjob.c
24
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_backing = {
26
@@ -XXX,XX +XXX,XX @@
25
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
27
#include "qemu/main-loop.h"
26
};
28
#include "qemu/timer.h"
29
30
-/*
31
- * The block job API is composed of two categories of functions.
32
- *
33
- * The first includes functions used by the monitor. The monitor is
34
- * peculiar in that it accesses the block job list with block_job_get, and
35
- * therefore needs consistency across block_job_get and the actual operation
36
- * (e.g. block_job_set_speed). The consistency is achieved with
37
- * aio_context_acquire/release. These functions are declared in blockjob.h.
38
- *
39
- * The second includes functions used by the block job drivers and sometimes
40
- * by the core block layer. These do not care about locking, because the
41
- * whole coroutine runs under the AioContext lock, and are declared in
42
- * blockjob_int.h.
43
- */
44
-
45
static bool is_block_job(Job *job)
46
{
47
return job_type(job) == JOB_TYPE_BACKUP ||
48
@@ -XXX,XX +XXX,XX @@ static void block_job_event_ready(Notifier *n, void *opaque)
49
}
50
51
52
-/*
53
- * API for block job drivers and the block layer. These functions are
54
- * declared in blockjob_int.h.
55
- */
56
-
57
void *block_job_create(const char *job_id, const BlockJobDriver *driver,
58
JobTxn *txn, BlockDriverState *bs, uint64_t perm,
59
uint64_t shared_perm, int64_t speed, int flags,
60
diff --git a/job.c b/job.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/job.c
63
+++ b/job.c
64
@@ -XXX,XX +XXX,XX @@
65
#include "trace/trace-root.h"
66
#include "qapi/qapi-events-job.h"
27
67
28
+/*
68
+/*
29
+ * Returns the options and flags that a generic child of a BDS should
69
+ * The job API is composed of two categories of functions.
30
+ * get, based on the given options and flags for the parent BDS.
70
+ *
71
+ * The first includes functions used by the monitor. The monitor is
72
+ * peculiar in that it accesses the job list with job_get, and
73
+ * therefore needs consistency across job_get and the actual operation
74
+ * (e.g. job_user_cancel). To achieve this consistency, the caller
75
+ * calls job_lock/job_unlock itself around the whole operation.
76
+ *
77
+ *
78
+ * The second includes functions used by the job drivers and sometimes
79
+ * by the core block layer. These delegate the locking to the callee instead.
80
+ *
81
+ * TODO Actually make this true
31
+ */
82
+ */
32
+static void __attribute__((unused))
33
+ bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
34
+ int *child_flags, QDict *child_options,
35
+ int parent_flags, QDict *parent_options)
36
+{
37
+ int flags = parent_flags;
38
+
83
+
39
+ /*
84
/*
40
+ * First, decide whether to set, clear, or leave BDRV_O_PROTOCOL.
85
* job_mutex protects the jobs list, but also makes the
41
+ * Generally, the question to answer is: Should this child be
86
* struct job fields thread-safe.
42
+ * format-probed by default?
43
+ */
44
+
45
+ /*
46
+ * Pure and non-filtered data children of non-format nodes should
47
+ * be probed by default (even when the node itself has BDRV_O_PROTOCOL
48
+ * set). This only affects a very limited set of drivers (namely
49
+ * quorum and blkverify when this comment was written).
50
+ * Force-clear BDRV_O_PROTOCOL then.
51
+ */
52
+ if (!parent_is_format &&
53
+ (role & BDRV_CHILD_DATA) &&
54
+ !(role & (BDRV_CHILD_METADATA | BDRV_CHILD_FILTERED)))
55
+ {
56
+ flags &= ~BDRV_O_PROTOCOL;
57
+ }
58
+
59
+ /*
60
+ * All children of format nodes (except for COW children) and all
61
+ * metadata children in general should never be format-probed.
62
+ * Force-set BDRV_O_PROTOCOL then.
63
+ */
64
+ if ((parent_is_format && !(role & BDRV_CHILD_COW)) ||
65
+ (role & BDRV_CHILD_METADATA))
66
+ {
67
+ flags |= BDRV_O_PROTOCOL;
68
+ }
69
+
70
+ /*
71
+ * If the cache mode isn't explicitly set, inherit direct and no-flush from
72
+ * the parent.
73
+ */
74
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
75
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
76
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
77
+
78
+ if (role & BDRV_CHILD_COW) {
79
+ /* backing files are opened read-only by default */
80
+ qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
81
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
82
+ } else {
83
+ /* Inherit the read-only option from the parent if it's not set */
84
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
85
+ qdict_copy_default(child_options, parent_options,
86
+ BDRV_OPT_AUTO_READ_ONLY);
87
+ }
88
+
89
+ /*
90
+ * bdrv_co_pdiscard() respects unmap policy for the parent, so we
91
+ * can default to enable it on lower layers regardless of the
92
+ * parent option.
93
+ */
94
+ qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");
95
+
96
+ /* Clear flags that only apply to the top layer */
97
+ flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
98
+
99
+ if (role & BDRV_CHILD_METADATA) {
100
+ flags &= ~BDRV_O_NO_IO;
101
+ }
102
+ if (role & BDRV_CHILD_COW) {
103
+ flags &= ~BDRV_O_TEMPORARY;
104
+ }
105
+
106
+ *child_flags = flags;
107
+}
108
+
109
static int bdrv_open_flags(BlockDriverState *bs, int flags)
110
{
111
int open_flags = flags;
112
--
87
--
113
2.25.4
88
2.37.3
114
115
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Make all parents of backing files pass the appropriate BdrvChildRole.
3
Just as done with job.h, create _locked() functions in blockjob.h
4
By doing so, we can switch their BdrvChildClass over to the generic
4
5
child_of_bds, which will do the right thing when given a correct
5
These functions will be later useful when caller has already taken
6
BdrvChildRole.
6
the lock. All blockjob _locked functions call job _locked functions.
7
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Note: at this stage, job_{lock/unlock} and job lock guard macros
9
Message-Id: <20200513110544.176672-24-mreitz@redhat.com>
9
are *nop*.
10
Reviewed-by: Eric Blake <eblake@redhat.com>
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Message-Id: <20220926093214.506243-8-eesposit@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
17
---
13
block.c | 26 ++++++++++++++++++++------
18
include/block/blockjob.h | 18 ++++++++++++++
14
block/backup-top.c | 2 +-
19
blockjob.c | 52 ++++++++++++++++++++++++++++++++--------
15
block/vvfat.c | 3 ++-
20
2 files changed, 60 insertions(+), 10 deletions(-)
16
tests/test-bdrv-drain.c | 13 +++++++------
21
17
4 files changed, 30 insertions(+), 14 deletions(-)
22
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
18
19
diff --git a/block.c b/block.c
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/block.c
24
--- a/include/block/blockjob.h
22
+++ b/block.c
25
+++ b/include/block/blockjob.h
23
@@ -XXX,XX +XXX,XX @@ static bool bdrv_inherits_from_recursive(BlockDriverState *child,
26
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJob {
24
return child != NULL;
27
*/
25
}
28
BlockJob *block_job_next(BlockJob *job);
29
30
+/* Same as block_job_next(), but called with job lock held. */
31
+BlockJob *block_job_next_locked(BlockJob *job);
32
+
33
/**
34
* block_job_get:
35
* @id: The id of the block job.
36
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_next(BlockJob *job);
37
*/
38
BlockJob *block_job_get(const char *id);
39
40
+/* Same as block_job_get(), but called with job lock held. */
41
+BlockJob *block_job_get_locked(const char *id);
42
+
43
/**
44
* block_job_add_bdrv:
45
* @job: A block job
46
@@ -XXX,XX +XXX,XX @@ bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs);
47
*/
48
bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
26
49
27
+/*
50
+/*
28
+ * Return the BdrvChildRole for @bs's backing child. bs->backing is
51
+ * Same as block_job_set_speed(), but called with job lock held.
29
+ * mostly used for COW backing children (role = COW), but also for
52
+ * Might release the lock temporarily.
30
+ * filtered children (role = FILTERED | PRIMARY).
31
+ */
53
+ */
32
+static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
54
+bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp);
33
+{
55
+
34
+ if (bs->drv && bs->drv->is_filter) {
56
/**
35
+ return BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
57
* block_job_query:
36
+ } else {
58
* @job: The job to get information about.
37
+ return BDRV_CHILD_COW;
59
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
38
+ }
60
*/
39
+}
61
BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
62
63
+/* Same as block_job_query(), but called with job lock held. */
64
+BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp);
65
+
66
/**
67
* block_job_iostatus_reset:
68
* @job: The job whose I/O status should be reset.
69
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
70
*/
71
void block_job_iostatus_reset(BlockJob *job);
72
73
+/* Same as block_job_iostatus_reset(), but called with job lock held. */
74
+void block_job_iostatus_reset_locked(BlockJob *job);
40
+
75
+
41
/*
76
/*
42
* Sets the backing file link of a BDS. A new reference is created; callers
77
* block_job_get_aio_context:
43
* which don't need their own reference any more must call bdrv_unref().
78
*
44
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
79
diff --git a/blockjob.c b/blockjob.c
45
goto out;
46
}
47
48
- bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
49
- 0, errp);
50
+ bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_of_bds,
51
+ bdrv_backing_role(bs), errp);
52
/* If backing_hd was already part of bs's backing chain, and
53
* inherits_from pointed recursively to bs then let's update it to
54
* point directly to bs (else it will become NULL). */
55
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
56
}
57
58
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
59
- &child_backing, 0, errp);
60
+ &child_of_bds, bdrv_backing_role(bs), errp);
61
if (!backing_hd) {
62
bs->open_flags |= BDRV_O_NO_BACKING;
63
error_prepend(errp, "Could not open backing file: ");
64
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
65
if (state->replace_backing_bs && state->new_backing_bs) {
66
uint64_t nperm, nshared;
67
bdrv_child_perm(state->bs, state->new_backing_bs,
68
- NULL, &child_backing, 0, bs_queue,
69
- state->perm, state->shared_perm,
70
+ NULL, &child_of_bds, bdrv_backing_role(state->bs),
71
+ bs_queue, state->perm, state->shared_perm,
72
&nperm, &nshared);
73
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
74
nperm, nshared, NULL, NULL, errp);
75
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
76
drv->bdrv_gather_child_options(bs, opts, backing_overridden);
77
} else {
78
QLIST_FOREACH(child, &bs->children, next) {
79
- if (child->klass == &child_backing && !backing_overridden) {
80
+ if (child == bs->backing && !backing_overridden) {
81
/* We can skip the backing BDS if it has not been overridden */
82
continue;
83
}
84
diff --git a/block/backup-top.c b/block/backup-top.c
85
index XXXXXXX..XXXXXXX 100644
80
index XXXXXXX..XXXXXXX 100644
86
--- a/block/backup-top.c
81
--- a/blockjob.c
87
+++ b/block/backup-top.c
82
+++ b/blockjob.c
88
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
83
@@ -XXX,XX +XXX,XX @@ static bool is_block_job(Job *job)
89
return;
84
job_type(job) == JOB_TYPE_STREAM;
90
}
85
}
91
86
92
- if (child_class == &child_file) {
87
-BlockJob *block_job_next(BlockJob *bjob)
93
+ if (!(role & BDRV_CHILD_FILTERED)) {
88
+BlockJob *block_job_next_locked(BlockJob *bjob)
94
/*
89
{
95
* Target child
90
Job *job = bjob ? &bjob->job : NULL;
96
*
91
GLOBAL_STATE_CODE();
97
diff --git a/block/vvfat.c b/block/vvfat.c
92
98
index XXXXXXX..XXXXXXX 100644
93
do {
99
--- a/block/vvfat.c
94
- job = job_next(job);
100
+++ b/block/vvfat.c
95
+ job = job_next_locked(job);
101
@@ -XXX,XX +XXX,XX @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
96
} while (job && !is_block_job(job));
102
{
97
103
BDRVVVFATState *s = bs->opaque;
98
return job ? container_of(job, BlockJob, job) : NULL;
104
99
}
105
- assert(c == s->qcow || child_class == &child_backing);
100
106
+ assert(c == s->qcow ||
101
-BlockJob *block_job_get(const char *id)
107
+ (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
102
+BlockJob *block_job_next(BlockJob *bjob)
108
103
{
109
if (c == s->qcow) {
104
- Job *job = job_get(id);
110
/* This is a private node, nobody should try to attach to it */
105
+ JOB_LOCK_GUARD();
111
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
106
+ return block_job_next_locked(bjob);
112
index XXXXXXX..XXXXXXX 100644
107
+}
113
--- a/tests/test-bdrv-drain.c
108
+
114
+++ b/tests/test-bdrv-drain.c
109
+BlockJob *block_job_get_locked(const char *id)
115
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
110
+{
116
* bdrv_format_default_perms() accepts only these two, so disguise
111
+ Job *job = job_get_locked(id);
117
* detach_by_driver_cb_parent as one of them.
112
GLOBAL_STATE_CODE();
118
*/
113
119
- if (child_class != &child_file && child_class != &child_backing) {
114
if (job && is_block_job(job)) {
120
+ if (child_class != &child_file && child_class != &child_of_bds) {
115
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_get(const char *id)
121
child_class = &child_file;
116
}
122
}
117
}
123
118
124
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
119
+BlockJob *block_job_get(const char *id)
125
bdrv_ref(a);
120
+{
126
child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0,
121
+ JOB_LOCK_GUARD();
127
&error_abort);
122
+ return block_job_get_locked(id);
128
- child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, 0,
123
+}
129
- &error_abort);
124
+
130
+ child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds,
125
void block_job_free(Job *job)
131
+ BDRV_CHILD_COW, &error_abort);
126
{
132
127
BlockJob *bjob = container_of(job, BlockJob, job);
133
bdrv_ref(a);
128
@@ -XXX,XX +XXX,XX @@ static bool job_timer_pending(Job *job)
134
bdrv_attach_child(parent_a, a, "PA-A",
129
return timer_pending(&job->sleep_timer);
135
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
130
}
136
int i;
131
137
int ret;
132
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
138
133
+bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp)
139
- chain_child_class = child_backing;
134
{
140
+ chain_child_class = child_of_bds;
135
const BlockJobDriver *drv = block_job_driver(job);
141
chain_child_class.update_filename = drop_intermediate_poll_update_filename;
136
int64_t old_speed = job->speed;
142
137
143
for (i = 0; i < 3; i++) {
138
GLOBAL_STATE_CODE();
144
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
139
145
/* Takes the reference to chain[i - 1] */
140
- if (job_apply_verb(&job->job, JOB_VERB_SET_SPEED, errp) < 0) {
146
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
141
+ if (job_apply_verb_locked(&job->job, JOB_VERB_SET_SPEED, errp) < 0) {
147
"chain", &chain_child_class,
142
return false;
148
- 0, &error_abort);
143
}
149
+ BDRV_CHILD_COW, &error_abort);
144
if (speed < 0) {
150
}
145
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
151
}
146
job->speed = speed;
152
147
153
@@ -XXX,XX +XXX,XX @@ static void do_test_replace_child_mid_drain(int old_drain_count,
148
if (drv->set_speed) {
154
149
+ job_unlock();
155
bdrv_ref(old_child_bs);
150
drv->set_speed(job, speed);
156
parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
151
+ job_lock();
157
- &child_backing, 0, &error_abort);
152
}
158
+ &child_of_bds, BDRV_CHILD_COW,
153
159
+ &error_abort);
154
if (speed && speed <= old_speed) {
160
155
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
161
for (i = 0; i < old_drain_count; i++) {
156
}
162
bdrv_drained_begin(old_child_bs);
157
158
/* kick only if a timer is pending */
159
- job_enter_cond(&job->job, job_timer_pending);
160
+ job_enter_cond_locked(&job->job, job_timer_pending);
161
162
return true;
163
}
164
165
+bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
166
+{
167
+ JOB_LOCK_GUARD();
168
+ return block_job_set_speed_locked(job, speed, errp);
169
+}
170
+
171
int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
172
{
173
IO_CODE();
174
return ratelimit_calculate_delay(&job->limit, n);
175
}
176
177
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
178
+BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
179
{
180
BlockJobInfo *info;
181
uint64_t progress_current, progress_total;
182
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
183
info->len = progress_total;
184
info->speed = job->speed;
185
info->io_status = job->iostatus;
186
- info->ready = job_is_ready(&job->job),
187
+ info->ready = job_is_ready_locked(&job->job),
188
info->status = job->job.status;
189
info->auto_finalize = job->job.auto_finalize;
190
info->auto_dismiss = job->job.auto_dismiss;
191
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
192
return info;
193
}
194
195
+BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
196
+{
197
+ JOB_LOCK_GUARD();
198
+ return block_job_query_locked(job, errp);
199
+}
200
+
201
static void block_job_iostatus_set_err(BlockJob *job, int error)
202
{
203
if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
204
@@ -XXX,XX +XXX,XX @@ fail:
205
return NULL;
206
}
207
208
-void block_job_iostatus_reset(BlockJob *job)
209
+void block_job_iostatus_reset_locked(BlockJob *job)
210
{
211
GLOBAL_STATE_CODE();
212
if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
213
@@ -XXX,XX +XXX,XX @@ void block_job_iostatus_reset(BlockJob *job)
214
job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
215
}
216
217
+void block_job_iostatus_reset(BlockJob *job)
218
+{
219
+ JOB_LOCK_GUARD();
220
+ block_job_iostatus_reset_locked(job);
221
+}
222
+
223
void block_job_user_resume(Job *job)
224
{
225
BlockJob *bjob = container_of(job, BlockJob, job);
163
--
226
--
164
2.25.4
227
2.37.3
165
166
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
block_copy_do_copy() is static, only used in block_copy_task_entry
3
Both blockdev.c and job-qmp.c have TOC/TOU conditions, because
4
with the error_is_read argument set. No need to check for it,
4
they first search for the job and then perform an action on it.
5
simplify.
5
Therefore, we need to do the search + action under the same
6
job mutex critical section.
6
7
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Note: at this stage, job_{lock/unlock} and job lock guard macros
8
Message-Id: <20200507121129.29760-3-philmd@redhat.com>
9
are *nop*.
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Message-Id: <20220926093214.506243-9-eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
17
---
12
block/block-copy.c | 12 +++---------
18
blockdev.c | 67 +++++++++++++++++++++++++++++++++++++-----------------
13
1 file changed, 3 insertions(+), 9 deletions(-)
19
job-qmp.c | 57 ++++++++++++++++++++++++++++++++--------------
20
2 files changed, 86 insertions(+), 38 deletions(-)
14
21
15
diff --git a/block/block-copy.c b/block/block-copy.c
22
diff --git a/blockdev.c b/blockdev.c
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/block/block-copy.c
24
--- a/blockdev.c
18
+++ b/block/block-copy.c
25
+++ b/blockdev.c
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
26
@@ -XXX,XX +XXX,XX @@ out:
20
~BDRV_REQ_WRITE_COMPRESSED);
27
aio_context_release(aio_context);
21
if (ret < 0) {
28
}
22
trace_block_copy_write_zeroes_fail(s, offset, ret);
29
23
- if (error_is_read) {
30
-/* Get a block job using its ID and acquire its AioContext */
24
- *error_is_read = false;
31
-static BlockJob *find_block_job(const char *id, AioContext **aio_context,
25
- }
32
- Error **errp)
26
+ *error_is_read = false;
33
+/*
27
}
34
+ * Get a block job using its ID and acquire its AioContext.
28
return ret;
35
+ * Called with job_mutex held.
29
}
36
+ */
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
37
+static BlockJob *find_block_job_locked(const char *id,
31
ret = bdrv_co_pread(s->source, offset, nbytes, bounce_buffer, 0);
38
+ AioContext **aio_context,
32
if (ret < 0) {
39
+ Error **errp)
33
trace_block_copy_read_fail(s, offset, ret);
40
{
34
- if (error_is_read) {
41
BlockJob *job;
35
- *error_is_read = true;
42
36
- }
43
@@ -XXX,XX +XXX,XX @@ static BlockJob *find_block_job(const char *id, AioContext **aio_context,
37
+ *error_is_read = true;
44
45
*aio_context = NULL;
46
47
- job = block_job_get(id);
48
+ job = block_job_get_locked(id);
49
50
if (!job) {
51
error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE,
52
@@ -XXX,XX +XXX,XX @@ static BlockJob *find_block_job(const char *id, AioContext **aio_context,
53
void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
54
{
55
AioContext *aio_context;
56
- BlockJob *job = find_block_job(device, &aio_context, errp);
57
+ BlockJob *job;
58
+
59
+ JOB_LOCK_GUARD();
60
+ job = find_block_job_locked(device, &aio_context, errp);
61
62
if (!job) {
63
return;
64
}
65
66
- block_job_set_speed(job, speed, errp);
67
+ block_job_set_speed_locked(job, speed, errp);
68
aio_context_release(aio_context);
69
}
70
71
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_cancel(const char *device,
72
bool has_force, bool force, Error **errp)
73
{
74
AioContext *aio_context;
75
- BlockJob *job = find_block_job(device, &aio_context, errp);
76
+ BlockJob *job;
77
+
78
+ JOB_LOCK_GUARD();
79
+ job = find_block_job_locked(device, &aio_context, errp);
80
81
if (!job) {
82
return;
83
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_cancel(const char *device,
84
force = false;
85
}
86
87
- if (job_user_paused(&job->job) && !force) {
88
+ if (job_user_paused_locked(&job->job) && !force) {
89
error_setg(errp, "The block job for device '%s' is currently paused",
90
device);
38
goto out;
91
goto out;
39
}
92
}
40
93
41
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
94
trace_qmp_block_job_cancel(job);
42
s->write_flags);
95
- job_user_cancel(&job->job, force, errp);
43
if (ret < 0) {
96
+ job_user_cancel_locked(&job->job, force, errp);
44
trace_block_copy_write_fail(s, offset, ret);
97
out:
45
- if (error_is_read) {
98
aio_context_release(aio_context);
46
- *error_is_read = false;
99
}
47
- }
100
@@ -XXX,XX +XXX,XX @@ out:
48
+ *error_is_read = false;
101
void qmp_block_job_pause(const char *device, Error **errp)
49
goto out;
102
{
50
}
103
AioContext *aio_context;
104
- BlockJob *job = find_block_job(device, &aio_context, errp);
105
+ BlockJob *job;
106
+
107
+ JOB_LOCK_GUARD();
108
+ job = find_block_job_locked(device, &aio_context, errp);
109
110
if (!job) {
111
return;
112
}
113
114
trace_qmp_block_job_pause(job);
115
- job_user_pause(&job->job, errp);
116
+ job_user_pause_locked(&job->job, errp);
117
aio_context_release(aio_context);
118
}
119
120
void qmp_block_job_resume(const char *device, Error **errp)
121
{
122
AioContext *aio_context;
123
- BlockJob *job = find_block_job(device, &aio_context, errp);
124
+ BlockJob *job;
125
+
126
+ JOB_LOCK_GUARD();
127
+ job = find_block_job_locked(device, &aio_context, errp);
128
129
if (!job) {
130
return;
131
}
132
133
trace_qmp_block_job_resume(job);
134
- job_user_resume(&job->job, errp);
135
+ job_user_resume_locked(&job->job, errp);
136
aio_context_release(aio_context);
137
}
138
139
void qmp_block_job_complete(const char *device, Error **errp)
140
{
141
AioContext *aio_context;
142
- BlockJob *job = find_block_job(device, &aio_context, errp);
143
+ BlockJob *job;
144
+
145
+ JOB_LOCK_GUARD();
146
+ job = find_block_job_locked(device, &aio_context, errp);
147
148
if (!job) {
149
return;
150
}
151
152
trace_qmp_block_job_complete(job);
153
- job_complete(&job->job, errp);
154
+ job_complete_locked(&job->job, errp);
155
aio_context_release(aio_context);
156
}
157
158
void qmp_block_job_finalize(const char *id, Error **errp)
159
{
160
AioContext *aio_context;
161
- BlockJob *job = find_block_job(id, &aio_context, errp);
162
+ BlockJob *job;
163
+
164
+ JOB_LOCK_GUARD();
165
+ job = find_block_job_locked(id, &aio_context, errp);
166
167
if (!job) {
168
return;
169
}
170
171
trace_qmp_block_job_finalize(job);
172
- job_ref(&job->job);
173
- job_finalize(&job->job, errp);
174
+ job_ref_locked(&job->job);
175
+ job_finalize_locked(&job->job, errp);
176
177
/*
178
* Job's context might have changed via job_finalize (and job_txn_apply
179
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_finalize(const char *id, Error **errp)
180
* one.
181
*/
182
aio_context = block_job_get_aio_context(job);
183
- job_unref(&job->job);
184
+ job_unref_locked(&job->job);
185
aio_context_release(aio_context);
186
}
187
188
void qmp_block_job_dismiss(const char *id, Error **errp)
189
{
190
AioContext *aio_context;
191
- BlockJob *bjob = find_block_job(id, &aio_context, errp);
192
+ BlockJob *bjob;
193
Job *job;
194
195
+ JOB_LOCK_GUARD();
196
+ bjob = find_block_job_locked(id, &aio_context, errp);
197
+
198
if (!bjob) {
199
return;
200
}
201
202
trace_qmp_block_job_dismiss(bjob);
203
job = &bjob->job;
204
- job_dismiss(&job, errp);
205
+ job_dismiss_locked(&job, errp);
206
aio_context_release(aio_context);
207
}
208
209
diff --git a/job-qmp.c b/job-qmp.c
210
index XXXXXXX..XXXXXXX 100644
211
--- a/job-qmp.c
212
+++ b/job-qmp.c
213
@@ -XXX,XX +XXX,XX @@
214
#include "qapi/error.h"
215
#include "trace/trace-root.h"
216
217
-/* Get a job using its ID and acquire its AioContext */
218
-static Job *find_job(const char *id, AioContext **aio_context, Error **errp)
219
+/*
220
+ * Get a job using its ID and acquire its AioContext.
221
+ * Called with job_mutex held.
222
+ */
223
+static Job *find_job_locked(const char *id,
224
+ AioContext **aio_context,
225
+ Error **errp)
226
{
227
Job *job;
228
229
*aio_context = NULL;
230
231
- job = job_get(id);
232
+ job = job_get_locked(id);
233
if (!job) {
234
error_setg(errp, "Job not found");
235
return NULL;
236
@@ -XXX,XX +XXX,XX @@ static Job *find_job(const char *id, AioContext **aio_context, Error **errp)
237
void qmp_job_cancel(const char *id, Error **errp)
238
{
239
AioContext *aio_context;
240
- Job *job = find_job(id, &aio_context, errp);
241
+ Job *job;
242
+
243
+ JOB_LOCK_GUARD();
244
+ job = find_job_locked(id, &aio_context, errp);
245
246
if (!job) {
247
return;
248
}
249
250
trace_qmp_job_cancel(job);
251
- job_user_cancel(job, true, errp);
252
+ job_user_cancel_locked(job, true, errp);
253
aio_context_release(aio_context);
254
}
255
256
void qmp_job_pause(const char *id, Error **errp)
257
{
258
AioContext *aio_context;
259
- Job *job = find_job(id, &aio_context, errp);
260
+ Job *job;
261
+
262
+ JOB_LOCK_GUARD();
263
+ job = find_job_locked(id, &aio_context, errp);
264
265
if (!job) {
266
return;
267
}
268
269
trace_qmp_job_pause(job);
270
- job_user_pause(job, errp);
271
+ job_user_pause_locked(job, errp);
272
aio_context_release(aio_context);
273
}
274
275
void qmp_job_resume(const char *id, Error **errp)
276
{
277
AioContext *aio_context;
278
- Job *job = find_job(id, &aio_context, errp);
279
+ Job *job;
280
+
281
+ JOB_LOCK_GUARD();
282
+ job = find_job_locked(id, &aio_context, errp);
283
284
if (!job) {
285
return;
286
}
287
288
trace_qmp_job_resume(job);
289
- job_user_resume(job, errp);
290
+ job_user_resume_locked(job, errp);
291
aio_context_release(aio_context);
292
}
293
294
void qmp_job_complete(const char *id, Error **errp)
295
{
296
AioContext *aio_context;
297
- Job *job = find_job(id, &aio_context, errp);
298
+ Job *job;
299
+
300
+ JOB_LOCK_GUARD();
301
+ job = find_job_locked(id, &aio_context, errp);
302
303
if (!job) {
304
return;
305
}
306
307
trace_qmp_job_complete(job);
308
- job_complete(job, errp);
309
+ job_complete_locked(job, errp);
310
aio_context_release(aio_context);
311
}
312
313
void qmp_job_finalize(const char *id, Error **errp)
314
{
315
AioContext *aio_context;
316
- Job *job = find_job(id, &aio_context, errp);
317
+ Job *job;
318
+
319
+ JOB_LOCK_GUARD();
320
+ job = find_job_locked(id, &aio_context, errp);
321
322
if (!job) {
323
return;
324
}
325
326
trace_qmp_job_finalize(job);
327
- job_ref(job);
328
- job_finalize(job, errp);
329
+ job_ref_locked(job);
330
+ job_finalize_locked(job, errp);
331
332
/*
333
* Job's context might have changed via job_finalize (and job_txn_apply
334
@@ -XXX,XX +XXX,XX @@ void qmp_job_finalize(const char *id, Error **errp)
335
* one.
336
*/
337
aio_context = job->aio_context;
338
- job_unref(job);
339
+ job_unref_locked(job);
340
aio_context_release(aio_context);
341
}
342
343
void qmp_job_dismiss(const char *id, Error **errp)
344
{
345
AioContext *aio_context;
346
- Job *job = find_job(id, &aio_context, errp);
347
+ Job *job;
348
+
349
+ JOB_LOCK_GUARD();
350
+ job = find_job_locked(id, &aio_context, errp);
351
352
if (!job) {
353
return;
354
}
355
356
trace_qmp_job_dismiss(job);
357
- job_dismiss(&job, errp);
358
+ job_dismiss_locked(&job, errp);
359
aio_context_release(aio_context);
360
}
51
361
52
--
362
--
53
2.25.4
363
2.37.3
54
55
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
bdrv_commit() already has a BlockBackend pointing to the BDS that we
3
Add missing job synchronization in the unit tests, with
4
want to empty, it just has the wrong permissions.
4
explicit locks.
5
5
6
qemu-img commit has no BlockBackend pointing to the old backing file
6
We are deliberately using _locked functions wrapped by a guard
7
yet, but introducing one is simple.
7
instead of a normal call because the normal call will be removed
8
8
in future, as the only usage is limited to the tests.
9
After this commit, bdrv_make_empty() is the only remaining caller of
9
10
BlockDriver.bdrv_make_empty().
10
In other words, if a function like job_pause() is/will be only used
11
11
in tests to avoid:
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
13
Message-Id: <20200429141126.85159-5-mreitz@redhat.com>
13
WITH_JOB_LOCK_GUARD(){
14
Reviewed-by: Eric Blake <eblake@redhat.com>
14
job_pause_locked();
15
[kwolf: Fixed up reference output for 098]
15
}
16
17
then it is not worth keeping job_pause(), and just use the guard.
18
19
Note: at this stage, job_{lock/unlock} and job lock guard macros
20
are *nop*.
21
22
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
23
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
24
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
25
Message-Id: <20220926093214.506243-10-eesposit@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
27
---
18
block/commit.c | 16 +++++++++-------
28
tests/unit/test-bdrv-drain.c | 76 ++++++++++++--------
19
qemu-img.c | 19 ++++++++++++++-----
29
tests/unit/test-block-iothread.c | 8 ++-
20
tests/qemu-iotests/098.out | 8 ++++----
30
tests/unit/test-blockjob-txn.c | 24 ++++---
21
3 files changed, 27 insertions(+), 16 deletions(-)
31
tests/unit/test-blockjob.c | 115 +++++++++++++++++++------------
22
32
4 files changed, 140 insertions(+), 83 deletions(-)
23
diff --git a/block/commit.c b/block/commit.c
33
34
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
24
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
25
--- a/block/commit.c
36
--- a/tests/unit/test-bdrv-drain.c
26
+++ b/block/commit.c
37
+++ b/tests/unit/test-bdrv-drain.c
27
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
38
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
28
}
29
30
ctx = bdrv_get_aio_context(bs);
31
- src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
32
+ /* WRITE_UNCHANGED is required for bdrv_make_empty() */
33
+ src = blk_new(ctx, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED,
34
+ BLK_PERM_ALL);
35
backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
36
37
ret = blk_insert_bs(src, bs, &local_err);
38
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
39
}
39
}
40
}
40
}
41
41
42
- if (drv->bdrv_make_empty) {
42
- g_assert_cmpint(job->job.pause_count, ==, 0);
43
- ret = drv->bdrv_make_empty(bs);
43
- g_assert_false(job->job.paused);
44
- if (ret < 0) {
44
- g_assert_true(tjob->running);
45
- goto ro_cleanup;
45
- g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
46
- }
46
+ WITH_JOB_LOCK_GUARD() {
47
- blk_flush(src);
47
+ g_assert_cmpint(job->job.pause_count, ==, 0);
48
+ ret = blk_make_empty(src, NULL);
48
+ g_assert_false(job->job.paused);
49
+ /* Ignore -ENOTSUP */
49
+ g_assert_true(tjob->running);
50
+ if (ret < 0 && ret != -ENOTSUP) {
50
+ g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
51
+ goto ro_cleanup;
51
+ }
52
}
52
53
53
do_drain_begin_unlocked(drain_type, drain_bs);
54
+ blk_flush(src);
54
55
- if (drain_type == BDRV_DRAIN_ALL) {
56
- /* bdrv_drain_all() drains both src and target */
57
- g_assert_cmpint(job->job.pause_count, ==, 2);
58
- } else {
59
- g_assert_cmpint(job->job.pause_count, ==, 1);
60
+ WITH_JOB_LOCK_GUARD() {
61
+ if (drain_type == BDRV_DRAIN_ALL) {
62
+ /* bdrv_drain_all() drains both src and target */
63
+ g_assert_cmpint(job->job.pause_count, ==, 2);
64
+ } else {
65
+ g_assert_cmpint(job->job.pause_count, ==, 1);
66
+ }
67
+ g_assert_true(job->job.paused);
68
+ g_assert_false(job->job.busy); /* The job is paused */
69
}
70
- g_assert_true(job->job.paused);
71
- g_assert_false(job->job.busy); /* The job is paused */
72
73
do_drain_end_unlocked(drain_type, drain_bs);
74
75
if (use_iothread) {
76
- /* paused is reset in the I/O thread, wait for it */
77
+ /*
78
+ * Here we are waiting for the paused status to change,
79
+ * so don't bother protecting the read every time.
80
+ *
81
+ * paused is reset in the I/O thread, wait for it
82
+ */
83
while (job->job.paused) {
84
aio_poll(qemu_get_aio_context(), false);
85
}
86
}
87
88
- g_assert_cmpint(job->job.pause_count, ==, 0);
89
- g_assert_false(job->job.paused);
90
- g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
91
+ WITH_JOB_LOCK_GUARD() {
92
+ g_assert_cmpint(job->job.pause_count, ==, 0);
93
+ g_assert_false(job->job.paused);
94
+ g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
95
+ }
96
97
do_drain_begin_unlocked(drain_type, target);
98
99
- if (drain_type == BDRV_DRAIN_ALL) {
100
- /* bdrv_drain_all() drains both src and target */
101
- g_assert_cmpint(job->job.pause_count, ==, 2);
102
- } else {
103
- g_assert_cmpint(job->job.pause_count, ==, 1);
104
+ WITH_JOB_LOCK_GUARD() {
105
+ if (drain_type == BDRV_DRAIN_ALL) {
106
+ /* bdrv_drain_all() drains both src and target */
107
+ g_assert_cmpint(job->job.pause_count, ==, 2);
108
+ } else {
109
+ g_assert_cmpint(job->job.pause_count, ==, 1);
110
+ }
111
+ g_assert_true(job->job.paused);
112
+ g_assert_false(job->job.busy); /* The job is paused */
113
}
114
- g_assert_true(job->job.paused);
115
- g_assert_false(job->job.busy); /* The job is paused */
116
117
do_drain_end_unlocked(drain_type, target);
118
119
if (use_iothread) {
120
- /* paused is reset in the I/O thread, wait for it */
121
+ /*
122
+ * Here we are waiting for the paused status to change,
123
+ * so don't bother protecting the read every time.
124
+ *
125
+ * paused is reset in the I/O thread, wait for it
126
+ */
127
while (job->job.paused) {
128
aio_poll(qemu_get_aio_context(), false);
129
}
130
}
131
132
- g_assert_cmpint(job->job.pause_count, ==, 0);
133
- g_assert_false(job->job.paused);
134
- g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
135
+ WITH_JOB_LOCK_GUARD() {
136
+ g_assert_cmpint(job->job.pause_count, ==, 0);
137
+ g_assert_false(job->job.paused);
138
+ g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
139
+ }
140
141
aio_context_acquire(ctx);
142
- ret = job_complete_sync(&job->job, &error_abort);
143
+ WITH_JOB_LOCK_GUARD() {
144
+ ret = job_complete_sync_locked(&job->job, &error_abort);
145
+ }
146
g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO));
147
148
if (use_iothread) {
149
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/tests/unit/test-block-iothread.c
152
+++ b/tests/unit/test-block-iothread.c
153
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
154
}
155
156
aio_context_acquire(ctx);
157
- job_complete_sync(&tjob->common.job, &error_abort);
158
+ WITH_JOB_LOCK_GUARD() {
159
+ job_complete_sync_locked(&tjob->common.job, &error_abort);
160
+ }
161
blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
162
aio_context_release(ctx);
163
164
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
165
BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
166
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
167
&error_abort);
168
- job = job_get("job0");
169
+ WITH_JOB_LOCK_GUARD() {
170
+ job = job_get_locked("job0");
171
+ }
172
filter = bdrv_find_node("filter_node");
173
174
/* Change the AioContext of src */
175
diff --git a/tests/unit/test-blockjob-txn.c b/tests/unit/test-blockjob-txn.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/tests/unit/test-blockjob-txn.c
178
+++ b/tests/unit/test-blockjob-txn.c
179
@@ -XXX,XX +XXX,XX @@ static void test_single_job(int expected)
180
job = test_block_job_start(1, true, expected, &result, txn);
181
job_start(&job->job);
182
183
- if (expected == -ECANCELED) {
184
- job_cancel(&job->job, false);
185
+ WITH_JOB_LOCK_GUARD() {
186
+ if (expected == -ECANCELED) {
187
+ job_cancel_locked(&job->job, false);
188
+ }
189
}
190
191
while (result == -EINPROGRESS) {
192
@@ -XXX,XX +XXX,XX @@ static void test_pair_jobs(int expected1, int expected2)
193
/* Release our reference now to trigger as many nice
194
* use-after-free bugs as possible.
195
*/
196
- job_txn_unref(txn);
197
+ WITH_JOB_LOCK_GUARD() {
198
+ job_txn_unref_locked(txn);
199
200
- if (expected1 == -ECANCELED) {
201
- job_cancel(&job1->job, false);
202
- }
203
- if (expected2 == -ECANCELED) {
204
- job_cancel(&job2->job, false);
205
+ if (expected1 == -ECANCELED) {
206
+ job_cancel_locked(&job1->job, false);
207
+ }
208
+ if (expected2 == -ECANCELED) {
209
+ job_cancel_locked(&job2->job, false);
210
+ }
211
}
212
213
while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
214
@@ -XXX,XX +XXX,XX @@ static void test_pair_jobs_fail_cancel_race(void)
215
job_start(&job1->job);
216
job_start(&job2->job);
217
218
- job_cancel(&job1->job, false);
219
+ WITH_JOB_LOCK_GUARD() {
220
+ job_cancel_locked(&job1->job, false);
221
+ }
222
223
/* Now make job2 finish before the main loop kicks jobs. This simulates
224
* the race between a pending kick and another job completing.
225
diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/tests/unit/test-blockjob.c
228
+++ b/tests/unit/test-blockjob.c
229
@@ -XXX,XX +XXX,XX @@ static CancelJob *create_common(Job **pjob)
230
bjob = mk_job(blk, "Steve", &test_cancel_driver, true,
231
JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS);
232
job = &bjob->job;
233
- job_ref(job);
234
- assert(job->status == JOB_STATUS_CREATED);
235
+ WITH_JOB_LOCK_GUARD() {
236
+ job_ref_locked(job);
237
+ assert(job->status == JOB_STATUS_CREATED);
238
+ }
55
+
239
+
56
/*
240
s = container_of(bjob, CancelJob, common);
57
* Make sure all data we wrote to the backing device is actually
241
s->blk = blk;
58
* stable on disk.
242
59
diff --git a/qemu-img.c b/qemu-img.c
243
@@ -XXX,XX +XXX,XX @@ static void cancel_common(CancelJob *s)
60
index XXXXXXX..XXXXXXX 100644
244
aio_context_acquire(ctx);
61
--- a/qemu-img.c
245
62
+++ b/qemu-img.c
246
job_cancel_sync(&job->job, true);
63
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
247
- if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) {
64
goto unref_backing;
248
- Job *dummy = &job->job;
65
}
249
- job_dismiss(&dummy, &error_abort);
66
250
+ WITH_JOB_LOCK_GUARD() {
67
- if (!drop && bs->drv->bdrv_make_empty) {
251
+ if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) {
68
- ret = bs->drv->bdrv_make_empty(bs);
252
+ Job *dummy = &job->job;
69
- if (ret) {
253
+ job_dismiss_locked(&dummy, &error_abort);
70
- error_setg_errno(&local_err, -ret, "Could not empty %s",
254
+ }
71
- filename);
255
+ assert(job->job.status == JOB_STATUS_NULL);
72
+ if (!drop) {
256
+ job_unref_locked(&job->job);
73
+ BlockBackend *old_backing_blk;
257
}
258
- assert(job->job.status == JOB_STATUS_NULL);
259
- job_unref(&job->job);
260
destroy_blk(blk);
261
262
aio_context_release(ctx);
263
@@ -XXX,XX +XXX,XX @@ static void test_cancel_created(void)
264
cancel_common(s);
265
}
266
267
+static void assert_job_status_is(Job *job, int status)
268
+{
269
+ WITH_JOB_LOCK_GUARD() {
270
+ assert(job->status == status);
271
+ }
272
+}
74
+
273
+
75
+ old_backing_blk = blk_new_with_bs(bs, BLK_PERM_WRITE, BLK_PERM_ALL,
274
static void test_cancel_running(void)
76
+ &local_err);
275
{
77
+ if (!old_backing_blk) {
276
Job *job;
78
+ goto unref_backing;
277
@@ -XXX,XX +XXX,XX @@ static void test_cancel_running(void)
79
+ }
278
s = create_common(&job);
80
+ ret = blk_make_empty(old_backing_blk, &local_err);
279
81
+ blk_unref(old_backing_blk);
280
job_start(job);
82
+ if (ret == -ENOTSUP) {
281
- assert(job->status == JOB_STATUS_RUNNING);
83
+ error_free(local_err);
282
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
84
+ local_err = NULL;
283
85
+ } else if (ret < 0) {
284
cancel_common(s);
86
goto unref_backing;
285
}
87
}
286
@@ -XXX,XX +XXX,XX @@ static void test_cancel_paused(void)
88
}
287
s = create_common(&job);
89
diff --git a/tests/qemu-iotests/098.out b/tests/qemu-iotests/098.out
288
90
index XXXXXXX..XXXXXXX 100644
289
job_start(job);
91
--- a/tests/qemu-iotests/098.out
290
- assert(job->status == JOB_STATUS_RUNNING);
92
+++ b/tests/qemu-iotests/098.out
291
-
93
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
292
- job_user_pause(job, &error_abort);
94
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
293
+ WITH_JOB_LOCK_GUARD() {
95
wrote 65536/65536 bytes at offset 0
294
+ assert(job->status == JOB_STATUS_RUNNING);
96
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
295
+ job_user_pause_locked(job, &error_abort);
97
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
296
+ }
98
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
297
job_enter(job);
99
No errors were found on the image.
298
- assert(job->status == JOB_STATUS_PAUSED);
100
299
+ assert_job_status_is(job, JOB_STATUS_PAUSED);
101
=== empty_image_prepare ===
300
102
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
301
cancel_common(s);
103
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
302
}
104
wrote 65536/65536 bytes at offset 0
303
@@ -XXX,XX +XXX,XX @@ static void test_cancel_ready(void)
105
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
304
s = create_common(&job);
106
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
305
107
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
306
job_start(job);
108
Leaked cluster 4 refcount=1 reference=0
307
- assert(job->status == JOB_STATUS_RUNNING);
109
Leaked cluster 5 refcount=1 reference=0
308
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
110
Repairing cluster 4 refcount=1 reference=0
309
111
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
310
s->should_converge = true;
112
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
311
job_enter(job);
113
wrote 65536/65536 bytes at offset 0
312
- assert(job->status == JOB_STATUS_READY);
114
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
313
+ assert_job_status_is(job, JOB_STATUS_READY);
115
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
314
116
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
315
cancel_common(s);
117
ERROR cluster 0 refcount=0 reference=1
316
}
118
ERROR cluster 1 refcount=0 reference=1
317
@@ -XXX,XX +XXX,XX @@ static void test_cancel_standby(void)
119
ERROR cluster 3 refcount=0 reference=1
318
s = create_common(&job);
120
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
319
121
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
320
job_start(job);
122
wrote 65536/65536 bytes at offset 0
321
- assert(job->status == JOB_STATUS_RUNNING);
123
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
124
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
323
125
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
324
s->should_converge = true;
126
ERROR cluster 0 refcount=0 reference=1
325
job_enter(job);
127
ERROR cluster 1 refcount=0 reference=1
326
- assert(job->status == JOB_STATUS_READY);
128
ERROR cluster 3 refcount=0 reference=1
327
-
328
- job_user_pause(job, &error_abort);
329
+ WITH_JOB_LOCK_GUARD() {
330
+ assert(job->status == JOB_STATUS_READY);
331
+ job_user_pause_locked(job, &error_abort);
332
+ }
333
job_enter(job);
334
- assert(job->status == JOB_STATUS_STANDBY);
335
+ assert_job_status_is(job, JOB_STATUS_STANDBY);
336
337
cancel_common(s);
338
}
339
@@ -XXX,XX +XXX,XX @@ static void test_cancel_pending(void)
340
s = create_common(&job);
341
342
job_start(job);
343
- assert(job->status == JOB_STATUS_RUNNING);
344
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
345
346
s->should_converge = true;
347
job_enter(job);
348
- assert(job->status == JOB_STATUS_READY);
349
-
350
- job_complete(job, &error_abort);
351
+ WITH_JOB_LOCK_GUARD() {
352
+ assert(job->status == JOB_STATUS_READY);
353
+ job_complete_locked(job, &error_abort);
354
+ }
355
job_enter(job);
356
while (!job->deferred_to_main_loop) {
357
aio_poll(qemu_get_aio_context(), true);
358
}
359
- assert(job->status == JOB_STATUS_READY);
360
+ assert_job_status_is(job, JOB_STATUS_READY);
361
aio_poll(qemu_get_aio_context(), true);
362
- assert(job->status == JOB_STATUS_PENDING);
363
+ assert_job_status_is(job, JOB_STATUS_PENDING);
364
365
cancel_common(s);
366
}
367
@@ -XXX,XX +XXX,XX @@ static void test_cancel_concluded(void)
368
s = create_common(&job);
369
370
job_start(job);
371
- assert(job->status == JOB_STATUS_RUNNING);
372
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
373
374
s->should_converge = true;
375
job_enter(job);
376
- assert(job->status == JOB_STATUS_READY);
377
-
378
- job_complete(job, &error_abort);
379
+ WITH_JOB_LOCK_GUARD() {
380
+ assert(job->status == JOB_STATUS_READY);
381
+ job_complete_locked(job, &error_abort);
382
+ }
383
job_enter(job);
384
while (!job->deferred_to_main_loop) {
385
aio_poll(qemu_get_aio_context(), true);
386
}
387
- assert(job->status == JOB_STATUS_READY);
388
+ assert_job_status_is(job, JOB_STATUS_READY);
389
aio_poll(qemu_get_aio_context(), true);
390
- assert(job->status == JOB_STATUS_PENDING);
391
+ assert_job_status_is(job, JOB_STATUS_PENDING);
392
393
aio_context_acquire(job->aio_context);
394
- job_finalize(job, &error_abort);
395
+ WITH_JOB_LOCK_GUARD() {
396
+ job_finalize_locked(job, &error_abort);
397
+ }
398
aio_context_release(job->aio_context);
399
- assert(job->status == JOB_STATUS_CONCLUDED);
400
+ assert_job_status_is(job, JOB_STATUS_CONCLUDED);
401
402
cancel_common(s);
403
}
404
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
405
bjob = mk_job(blk, "job", &test_yielding_driver, true,
406
JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS);
407
job = &bjob->job;
408
- assert(job->status == JOB_STATUS_CREATED);
409
+ assert_job_status_is(job, JOB_STATUS_CREATED);
410
411
/* Wait for the job to become READY */
412
job_start(job);
413
aio_context_acquire(ctx);
414
+ /*
415
+ * Here we are waiting for the status to change, so don't bother
416
+ * protecting the read every time.
417
+ */
418
AIO_WAIT_WHILE(ctx, job->status != JOB_STATUS_READY);
419
aio_context_release(ctx);
420
421
/* Begin the drained section, pausing the job */
422
bdrv_drain_all_begin();
423
- assert(job->status == JOB_STATUS_STANDBY);
424
+ assert_job_status_is(job, JOB_STATUS_STANDBY);
425
+
426
/* Lock the IO thread to prevent the job from being run */
427
aio_context_acquire(ctx);
428
/* This will schedule the job to resume it */
429
bdrv_drain_all_end();
430
431
- /* But the job cannot run, so it will remain on standby */
432
- assert(job->status == JOB_STATUS_STANDBY);
433
+ WITH_JOB_LOCK_GUARD() {
434
+ /* But the job cannot run, so it will remain on standby */
435
+ assert(job->status == JOB_STATUS_STANDBY);
436
437
- /* Even though the job is on standby, this should work */
438
- job_complete(job, &error_abort);
439
+ /* Even though the job is on standby, this should work */
440
+ job_complete_locked(job, &error_abort);
441
442
- /* The test is done now, clean up. */
443
- job_finish_sync(job, NULL, &error_abort);
444
- assert(job->status == JOB_STATUS_PENDING);
445
+ /* The test is done now, clean up. */
446
+ job_finish_sync_locked(job, NULL, &error_abort);
447
+ assert(job->status == JOB_STATUS_PENDING);
448
449
- job_finalize(job, &error_abort);
450
- assert(job->status == JOB_STATUS_CONCLUDED);
451
+ job_finalize_locked(job, &error_abort);
452
+ assert(job->status == JOB_STATUS_CONCLUDED);
453
454
- job_dismiss(&job, &error_abort);
455
+ job_dismiss_locked(&job, &error_abort);
456
+ }
457
458
destroy_blk(blk);
459
aio_context_release(ctx);
129
--
460
--
130
2.25.4
461
2.37.3
131
132
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
The commit, mirror, and blkreplay block nodes are filters, so they should
3
Once job lock is used and aiocontext is removed, mirror has
4
be marked as such.
4
to perform job operations under the same critical section,
5
Note: at this stage, job_{lock/unlock} and job lock guard macros
6
are *nop*.
5
7
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Message-Id: <20200513110544.176672-2-mreitz@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Message-Id: <20220926093214.506243-11-eesposit@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
13
---
10
block/blkreplay.c | 1 +
14
block/mirror.c | 13 +++++++++----
11
block/commit.c | 2 ++
15
1 file changed, 9 insertions(+), 4 deletions(-)
12
block/mirror.c | 2 ++
13
3 files changed, 5 insertions(+)
14
16
15
diff --git a/block/blkreplay.c b/block/blkreplay.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/blkreplay.c
18
+++ b/block/blkreplay.c
19
@@ -XXX,XX +XXX,XX @@ static int blkreplay_snapshot_goto(BlockDriverState *bs,
20
static BlockDriver bdrv_blkreplay = {
21
.format_name = "blkreplay",
22
.instance_size = 0,
23
+ .is_filter = true,
24
25
.bdrv_open = blkreplay_open,
26
.bdrv_child_perm = bdrv_filter_default_perms,
27
diff --git a/block/commit.c b/block/commit.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/commit.c
30
+++ b/block/commit.c
31
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_commit_top = {
32
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
33
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
34
.bdrv_child_perm = bdrv_commit_top_child_perm,
35
+
36
+ .is_filter = true,
37
};
38
39
void commit_start(const char *job_id, BlockDriverState *bs,
40
diff --git a/block/mirror.c b/block/mirror.c
17
diff --git a/block/mirror.c b/block/mirror.c
41
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
42
--- a/block/mirror.c
19
--- a/block/mirror.c
43
+++ b/block/mirror.c
20
+++ b/block/mirror.c
44
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
21
@@ -XXX,XX +XXX,XX @@ static void mirror_complete(Job *job, Error **errp)
45
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
22
s->should_complete = true;
46
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
23
47
.bdrv_child_perm = bdrv_mirror_top_child_perm,
24
/* If the job is paused, it will be re-entered when it is resumed */
48
+
25
- if (!job->paused) {
49
+ .is_filter = true,
26
- job_enter(job);
50
};
27
+ WITH_JOB_LOCK_GUARD() {
51
28
+ if (!job->paused) {
52
static BlockJob *mirror_start_job(
29
+ job_enter_cond_locked(job, NULL);
30
+ }
31
}
32
}
33
34
@@ -XXX,XX +XXX,XX @@ static bool mirror_drained_poll(BlockJob *job)
35
* from one of our own drain sections, to avoid a deadlock waiting for
36
* ourselves.
37
*/
38
- if (!s->common.job.paused && !job_is_cancelled(&job->job) && !s->in_drain) {
39
- return true;
40
+ WITH_JOB_LOCK_GUARD() {
41
+ if (!s->common.job.paused && !job_is_cancelled_locked(&job->job)
42
+ && !s->in_drain) {
43
+ return true;
44
+ }
45
}
46
47
return !!s->in_flight;
53
--
48
--
54
2.25.4
49
2.37.3
55
56
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Right now, bdrv_format_default_perms() is used by format parents
3
Now that the API offers also _locked() functions, take advantage
4
(generally). We want to switch to a model where most parents use a
4
of it and give also the caller control to take the lock and call
5
single BdrvChildClass, which then decides the permissions based on the
5
_locked functions.
6
child role. To do so, we have to split bdrv_format_default_perms() into
6
7
separate functions for each such role.
7
This makes sense especially when we have for loops, because it
8
8
makes no sense to have:
9
Note that bdrv_default_perms_for_storage() currently handles all DATA |
9
10
METADATA children. A follow-up patch is going to split it further into
10
for(job = job_next(); ...)
11
one function for each case.
11
12
12
where each job_next() takes the lock internally.
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Instead we want
14
Reviewed-by: Eric Blake <eblake@redhat.com>
14
15
Message-Id: <20200513110544.176672-18-mreitz@redhat.com>
15
JOB_LOCK_GUARD();
16
for(job = job_next_locked(); ...)
17
18
In addition, protect also direct field accesses, by either creating a
19
new critical section or widening the existing ones.
20
21
Note: at this stage, job_{lock/unlock} and job lock guard macros
22
are *nop*.
23
24
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
25
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
26
Message-Id: <20220926093214.506243-12-eesposit@redhat.com>
27
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
29
---
18
block.c | 71 +++++++++++++++++++++++++++++++++++++--------------------
30
block.c | 17 ++++++++++-------
19
1 file changed, 46 insertions(+), 25 deletions(-)
31
blockdev.c | 14 ++++++++++----
32
blockjob.c | 35 ++++++++++++++++++++++-------------
33
job-qmp.c | 9 ++++++---
34
monitor/qmp-cmds.c | 7 +++++--
35
qemu-img.c | 15 ++++++++++-----
36
6 files changed, 63 insertions(+), 34 deletions(-)
20
37
21
diff --git a/block.c b/block.c
38
diff --git a/block.c b/block.c
22
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
23
--- a/block.c
40
--- a/block.c
24
+++ b/block.c
41
+++ b/block.c
25
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
42
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
26
*nshared = shared;
43
44
void bdrv_close_all(void)
45
{
46
- assert(job_next(NULL) == NULL);
47
GLOBAL_STATE_CODE();
48
+ assert(job_next(NULL) == NULL);
49
50
/* Drop references from requests still in flight, such as canceled block
51
* jobs whose AIO context has not been polled yet */
52
@@ -XXX,XX +XXX,XX @@ XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp)
53
}
54
}
55
56
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
57
- GSList *el;
58
+ WITH_JOB_LOCK_GUARD() {
59
+ for (job = block_job_next_locked(NULL); job;
60
+ job = block_job_next_locked(job)) {
61
+ GSList *el;
62
63
- xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
64
- job->job.id);
65
- for (el = job->nodes; el; el = el->next) {
66
- xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
67
+ xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
68
+ job->job.id);
69
+ for (el = job->nodes; el; el = el->next) {
70
+ xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
71
+ }
72
}
73
}
74
75
diff --git a/blockdev.c b/blockdev.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/blockdev.c
78
+++ b/blockdev.c
79
@@ -XXX,XX +XXX,XX @@ void blockdev_mark_auto_del(BlockBackend *blk)
80
return;
81
}
82
83
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
84
+ JOB_LOCK_GUARD();
85
+
86
+ for (job = block_job_next_locked(NULL); job;
87
+ job = block_job_next_locked(job)) {
88
if (block_job_has_bdrv(job, blk_bs(blk))) {
89
AioContext *aio_context = job->job.aio_context;
90
aio_context_acquire(aio_context);
91
92
- job_cancel(&job->job, false);
93
+ job_cancel_locked(&job->job, false);
94
95
aio_context_release(aio_context);
96
}
97
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
98
BlockJobInfoList *head = NULL, **tail = &head;
99
BlockJob *job;
100
101
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
102
+ JOB_LOCK_GUARD();
103
+
104
+ for (job = block_job_next_locked(NULL); job;
105
+ job = block_job_next_locked(job)) {
106
BlockJobInfo *value;
107
AioContext *aio_context;
108
109
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
110
}
111
aio_context = block_job_get_aio_context(job);
112
aio_context_acquire(aio_context);
113
- value = block_job_query(job, errp);
114
+ value = block_job_query_locked(job, errp);
115
aio_context_release(aio_context);
116
if (!value) {
117
qapi_free_BlockJobInfoList(head);
118
diff --git a/blockjob.c b/blockjob.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/blockjob.c
121
+++ b/blockjob.c
122
@@ -XXX,XX +XXX,XX @@ static bool child_job_drained_poll(BdrvChild *c)
123
/* An inactive or completed job doesn't have any pending requests. Jobs
124
* with !job->busy are either already paused or have a pause point after
125
* being reentered, so no job driver code will run before they pause. */
126
- if (!job->busy || job_is_completed(job)) {
127
- return false;
128
+ WITH_JOB_LOCK_GUARD() {
129
+ if (!job->busy || job_is_completed_locked(job)) {
130
+ return false;
131
+ }
132
}
133
134
/* Otherwise, assume that it isn't fully stopped yet, but allow the job to
135
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
136
job->ready_notifier.notify = block_job_event_ready;
137
job->idle_notifier.notify = block_job_on_idle;
138
139
- notifier_list_add(&job->job.on_finalize_cancelled,
140
- &job->finalize_cancelled_notifier);
141
- notifier_list_add(&job->job.on_finalize_completed,
142
- &job->finalize_completed_notifier);
143
- notifier_list_add(&job->job.on_pending, &job->pending_notifier);
144
- notifier_list_add(&job->job.on_ready, &job->ready_notifier);
145
- notifier_list_add(&job->job.on_idle, &job->idle_notifier);
146
+ WITH_JOB_LOCK_GUARD() {
147
+ notifier_list_add(&job->job.on_finalize_cancelled,
148
+ &job->finalize_cancelled_notifier);
149
+ notifier_list_add(&job->job.on_finalize_completed,
150
+ &job->finalize_completed_notifier);
151
+ notifier_list_add(&job->job.on_pending, &job->pending_notifier);
152
+ notifier_list_add(&job->job.on_ready, &job->ready_notifier);
153
+ notifier_list_add(&job->job.on_idle, &job->idle_notifier);
154
+ }
155
156
error_setg(&job->blocker, "block device is in use by block job: %s",
157
job_type_str(&job->job));
158
@@ -XXX,XX +XXX,XX @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
159
action);
160
}
161
if (action == BLOCK_ERROR_ACTION_STOP) {
162
- if (!job->job.user_paused) {
163
- job_pause(&job->job);
164
- /* make the pause user visible, which will be resumed from QMP. */
165
- job->job.user_paused = true;
166
+ WITH_JOB_LOCK_GUARD() {
167
+ if (!job->job.user_paused) {
168
+ job_pause_locked(&job->job);
169
+ /*
170
+ * make the pause user visible, which will be
171
+ * resumed from QMP.
172
+ */
173
+ job->job.user_paused = true;
174
+ }
175
}
176
block_job_iostatus_set_err(job, error);
177
}
178
diff --git a/job-qmp.c b/job-qmp.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/job-qmp.c
181
+++ b/job-qmp.c
182
@@ -XXX,XX +XXX,XX @@ void qmp_job_dismiss(const char *id, Error **errp)
183
aio_context_release(aio_context);
27
}
184
}
28
185
29
+static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
186
-static JobInfo *job_query_single(Job *job, Error **errp)
30
+ const BdrvChildClass *child_class,
187
+/* Called with job_mutex held. */
31
+ BdrvChildRole role,
188
+static JobInfo *job_query_single_locked(Job *job, Error **errp)
32
+ BlockReopenQueue *reopen_queue,
189
{
33
+ uint64_t perm, uint64_t shared,
190
JobInfo *info;
34
+ uint64_t *nperm, uint64_t *nshared)
191
uint64_t progress_current;
35
+{
192
@@ -XXX,XX +XXX,XX @@ JobInfoList *qmp_query_jobs(Error **errp)
36
+ int flags;
193
JobInfoList *head = NULL, **tail = &head;
194
Job *job;
195
196
- for (job = job_next(NULL); job; job = job_next(job)) {
197
+ JOB_LOCK_GUARD();
37
+
198
+
38
+ assert(child_class == &child_file ||
199
+ for (job = job_next_locked(NULL); job; job = job_next_locked(job)) {
39
+ (child_class == &child_of_bds &&
200
JobInfo *value;
40
+ (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA))));
201
AioContext *aio_context;
41
+
202
42
+ flags = bdrv_reopen_get_flags(reopen_queue, bs);
203
@@ -XXX,XX +XXX,XX @@ JobInfoList *qmp_query_jobs(Error **errp)
43
+
204
}
44
+ /*
205
aio_context = job->aio_context;
45
+ * Apart from the modifications below, the same permissions are
206
aio_context_acquire(aio_context);
46
+ * forwarded and left alone as for filters
207
- value = job_query_single(job, errp);
47
+ */
208
+ value = job_query_single_locked(job, errp);
48
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
209
aio_context_release(aio_context);
49
+ perm, shared, &perm, &shared);
210
if (!value) {
50
+
211
qapi_free_JobInfoList(head);
51
+ /* Format drivers may touch metadata even if the guest doesn't write */
212
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
52
+ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
213
index XXXXXXX..XXXXXXX 100644
53
+ perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
214
--- a/monitor/qmp-cmds.c
54
+ }
215
+++ b/monitor/qmp-cmds.c
55
+
216
@@ -XXX,XX +XXX,XX @@ void qmp_cont(Error **errp)
56
+ /*
217
blk_iostatus_reset(blk);
57
+ * bs->file always needs to be consistent because of the metadata. We
218
}
58
+ * can never allow other users to resize or write to it.
219
59
+ */
220
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
60
+ if (!(flags & BDRV_O_NO_IO)) {
221
- block_job_iostatus_reset(job);
61
+ perm |= BLK_PERM_CONSISTENT_READ;
222
+ WITH_JOB_LOCK_GUARD() {
62
+ }
223
+ for (job = block_job_next_locked(NULL); job;
63
+ shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
224
+ job = block_job_next_locked(job)) {
64
+
225
+ block_job_iostatus_reset_locked(job);
65
+ if (bs->open_flags & BDRV_O_INACTIVE) {
226
+ }
66
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
227
}
67
+ }
228
68
+
229
/* Continuing after completed migration. Images have been inactivated to
69
+ *nperm = perm;
230
diff --git a/qemu-img.c b/qemu-img.c
70
+ *nshared = shared;
231
index XXXXXXX..XXXXXXX 100644
71
+}
232
--- a/qemu-img.c
72
+
233
+++ b/qemu-img.c
73
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
234
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
74
const BdrvChildClass *child_class,
235
int ret = 0;
75
BdrvChildRole role,
236
76
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
237
aio_context_acquire(aio_context);
77
assert(child_class == &child_backing || child_class == &child_file);
238
- job_ref(&job->job);
78
239
+ job_lock();
79
if (!backing) {
240
+ job_ref_locked(&job->job);
80
- int flags = bdrv_reopen_get_flags(reopen_queue, bs);
241
do {
81
-
242
float progress = 0.0f;
82
- /* Apart from the modifications below, the same permissions are
243
+ job_unlock();
83
- * forwarded and left alone as for filters */
244
aio_poll(aio_context, true);
84
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
245
85
- perm, shared, &perm, &shared);
246
progress_get_snapshot(&job->job.progress, &progress_current,
86
-
247
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
87
- /* Format drivers may touch metadata even if the guest doesn't write */
248
progress = (float)progress_current / progress_total * 100.f;
88
- if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
249
}
89
- perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
250
qemu_progress_print(progress, 0);
90
- }
251
- } while (!job_is_ready(&job->job) && !job_is_completed(&job->job));
91
-
252
+ job_lock();
92
- /* bs->file always needs to be consistent because of the metadata. We
253
+ } while (!job_is_ready_locked(&job->job) &&
93
- * can never allow other users to resize or write to it. */
254
+ !job_is_completed_locked(&job->job));
94
- if (!(flags & BDRV_O_NO_IO)) {
255
95
- perm |= BLK_PERM_CONSISTENT_READ;
256
- if (!job_is_completed(&job->job)) {
96
- }
257
- ret = job_complete_sync(&job->job, errp);
97
- shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
258
+ if (!job_is_completed_locked(&job->job)) {
98
-
259
+ ret = job_complete_sync_locked(&job->job, errp);
99
- if (bs->open_flags & BDRV_O_INACTIVE) {
100
- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
101
- }
102
-
103
- *nperm = perm;
104
- *nshared = shared;
105
+ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
106
+ perm, shared, nperm, nshared);
107
} else {
260
} else {
108
bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
261
ret = job->job.ret;
109
perm, shared, nperm, nshared);
262
}
263
- job_unref(&job->job);
264
+ job_unref_locked(&job->job);
265
+ job_unlock();
266
aio_context_release(aio_context);
267
268
/* publish completion progress only when success */
110
--
269
--
111
2.25.4
270
2.37.3
112
113
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Right now, bdrv_format_default_perms() is used by format parents
3
We want to make sure access of job->aio_context is always done
4
(generally). We want to switch to a model where most parents use a
4
under either BQL or job_mutex. The problem is that using
5
single BdrvChildClass, which then decides the permissions based on the
5
aio_co_enter(job->aiocontext, job->co) in job_start and job_enter_cond
6
child role. To do so, we have to split bdrv_format_default_perms() into
6
makes the coroutine immediately resume, so we can't hold the job lock.
7
separate functions for each such role.
7
And caching it is not safe either, as it might change.
8
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
job_start is under BQL, so it can freely read job->aiocontext, but
10
Message-Id: <20200513110544.176672-17-mreitz@redhat.com>
10
job_enter_cond is not.
11
Reviewed-by: Eric Blake <eblake@redhat.com>
11
We want to avoid reading job->aio_context in job_enter_cond, therefore:
12
1) use aio_co_wake(), since it doesn't want an aiocontext as argument
13
but uses job->co->ctx
14
2) detect possible discrepancy between job->co->ctx and job->aio_context
15
by checking right after the coroutine resumes back from yielding if
16
job->aio_context has changed. If so, reschedule the coroutine to the
17
new context.
18
19
Calling bdrv_try_set_aio_context() will issue the following calls
20
(simplified):
21
* in terms of bdrv callbacks:
22
.drained_begin -> .set_aio_context -> .drained_end
23
* in terms of child_job functions:
24
child_job_drained_begin -> child_job_set_aio_context -> child_job_drained_end
25
* in terms of job functions:
26
job_pause_locked -> job_set_aio_context -> job_resume_locked
27
28
We can see that after setting the new aio_context, job_resume_locked
29
calls again job_enter_cond, which then invokes aio_co_wake(). But
30
while job->aiocontext has been set in job_set_aio_context,
31
job->co->ctx has not changed, so the coroutine would be entering in
32
the wrong aiocontext.
33
34
Using aio_co_schedule in job_resume_locked() might seem as a valid
35
alternative, but the problem is that the bh resuming the coroutine
36
is not scheduled immediately, and if in the meanwhile another
37
bdrv_try_set_aio_context() is run (see test_propagate_mirror() in
38
test-block-iothread.c), we would have the first schedule in the
39
wrong aiocontext, and the second set of drains won't even manage
40
to schedule the coroutine, as job->busy would still be true from
41
the previous job_resume_locked().
42
43
The solution is to stick with aio_co_wake() and detect every time
44
the coroutine resumes back from yielding if job->aio_context
45
has changed. If so, we can reschedule it to the new context.
46
47
Check for the aiocontext change in job_do_yield_locked because:
48
1) aio_co_reschedule_self requires to be in the running coroutine
49
2) since child_job_set_aio_context allows changing the aiocontext only
50
while the job is paused, this is the exact place where the coroutine
51
resumes, before running JobDriver's code.
52
53
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
54
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
55
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
56
Message-Id: <20220926093214.506243-13-eesposit@redhat.com>
57
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
58
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
59
---
14
block.c | 62 +++++++++++++++++++++++++++++++++++++--------------------
60
job.c | 19 +++++++++++++++++--
15
1 file changed, 40 insertions(+), 22 deletions(-)
61
1 file changed, 17 insertions(+), 2 deletions(-)
16
62
17
diff --git a/block.c b/block.c
63
diff --git a/job.c b/job.c
18
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
65
--- a/job.c
20
+++ b/block.c
66
+++ b/job.c
21
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
67
@@ -XXX,XX +XXX,XX @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
22
*nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED;
68
job->busy = true;
69
real_job_unlock();
70
job_unlock();
71
- aio_co_enter(job->aio_context, job->co);
72
+ aio_co_wake(job->co);
73
job_lock();
23
}
74
}
24
75
25
+static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
76
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job)
26
+ const BdrvChildClass *child_class,
77
*/
27
+ BdrvChildRole role,
78
static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
28
+ BlockReopenQueue *reopen_queue,
79
{
29
+ uint64_t perm, uint64_t shared,
80
+ AioContext *next_aio_context;
30
+ uint64_t *nperm, uint64_t *nshared)
31
+{
32
+ assert(child_class == &child_backing ||
33
+ (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
34
+
81
+
82
real_job_lock();
83
if (ns != -1) {
84
timer_mod(&job->sleep_timer, ns);
85
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
86
qemu_coroutine_yield();
87
job_lock();
88
89
- /* Set by job_enter_cond() before re-entering the coroutine. */
90
+ next_aio_context = job->aio_context;
35
+ /*
91
+ /*
36
+ * We want consistent read from backing files if the parent needs it.
92
+ * Coroutine has resumed, but in the meanwhile the job AioContext
37
+ * No other operations are performed on backing files.
93
+ * might have changed via bdrv_try_set_aio_context(), so we need to move
94
+ * the coroutine too in the new aiocontext.
38
+ */
95
+ */
39
+ perm &= BLK_PERM_CONSISTENT_READ;
96
+ while (qemu_get_current_aio_context() != next_aio_context) {
40
+
97
+ job_unlock();
41
+ /*
98
+ aio_co_reschedule_self(next_aio_context);
42
+ * If the parent can deal with changing data, we're okay with a
99
+ job_lock();
43
+ * writable and resizable backing file.
100
+ next_aio_context = job->aio_context;
44
+ * TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too?
45
+ */
46
+ if (shared & BLK_PERM_WRITE) {
47
+ shared = BLK_PERM_WRITE | BLK_PERM_RESIZE;
48
+ } else {
49
+ shared = 0;
50
+ }
101
+ }
51
+
102
+
52
+ shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
103
+ /* Set by job_enter_cond_locked() before re-entering the coroutine. */
53
+ BLK_PERM_WRITE_UNCHANGED;
104
assert(job->busy);
54
+
55
+ if (bs->open_flags & BDRV_O_INACTIVE) {
56
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
57
+ }
58
+
59
+ *nperm = perm;
60
+ *nshared = shared;
61
+}
62
+
63
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
64
const BdrvChildClass *child_class,
65
BdrvChildRole role,
66
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
67
*nperm = perm;
68
*nshared = shared;
69
} else {
70
- /* We want consistent read from backing files if the parent needs it.
71
- * No other operations are performed on backing files. */
72
- perm &= BLK_PERM_CONSISTENT_READ;
73
-
74
- /* If the parent can deal with changing data, we're okay with a
75
- * writable and resizable backing file. */
76
- /* TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too? */
77
- if (shared & BLK_PERM_WRITE) {
78
- shared = BLK_PERM_WRITE | BLK_PERM_RESIZE;
79
- } else {
80
- shared = 0;
81
- }
82
-
83
- shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
84
- BLK_PERM_WRITE_UNCHANGED;
85
-
86
- if (bs->open_flags & BDRV_O_INACTIVE) {
87
- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
88
- }
89
-
90
- *nperm = perm;
91
- *nshared = shared;
92
+ bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
93
+ perm, shared, nperm, nshared);
94
}
95
}
105
}
96
106
97
--
107
--
98
2.25.4
108
2.37.3
99
100
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
For now, it is always set to 0. Later patches in this series will
3
In order to make it thread safe, implement a "fake rwlock",
4
ensure that all callers pass an appropriate combination of flags.
4
where we allow reads under BQL *or* job_mutex held, but
5
writes only under BQL *and* job_mutex.
5
6
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
The only write we have is in child_job_set_aio_ctx, which always
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
happens under drain (so the job is paused).
8
Message-Id: <20200513110544.176672-6-mreitz@redhat.com>
9
For this reason, introduce job_set_aio_context and make sure that
10
the context is set under BQL, job_mutex and drain.
11
Also make sure all other places where the aiocontext is read
12
are protected.
13
14
The reads in commit.c and mirror.c are actually safe, because always
15
done under BQL.
16
17
Note: at this stage, job_{lock/unlock} and job lock guard macros
18
are *nop*.
19
20
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
21
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
22
Message-Id: <20220926093214.506243-14-eesposit@redhat.com>
23
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
24
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
26
---
11
include/block/block.h | 2 ++
27
include/qemu/job.h | 23 ++++++++++++++++++++---
12
include/block/block_int.h | 2 ++
28
block/replication.c | 1 +
13
block.c | 11 ++++++++---
29
blockjob.c | 3 ++-
14
block/backup-top.c | 3 ++-
30
job.c | 12 ++++++++++++
15
block/blkdebug.c | 2 +-
31
4 files changed, 35 insertions(+), 4 deletions(-)
16
block/blklogwrites.c | 6 +++---
17
block/blkreplay.c | 2 +-
18
block/blkverify.c | 4 ++--
19
block/block-backend.c | 4 ++--
20
block/bochs.c | 2 +-
21
block/cloop.c | 2 +-
22
block/copy-on-read.c | 2 +-
23
block/crypto.c | 2 +-
24
block/dmg.c | 2 +-
25
block/filter-compress.c | 2 +-
26
block/parallels.c | 2 +-
27
block/qcow.c | 2 +-
28
block/qcow2.c | 6 +++---
29
block/qed.c | 2 +-
30
block/quorum.c | 4 ++--
31
block/raw-format.c | 2 +-
32
block/replication.c | 2 +-
33
block/throttle.c | 2 +-
34
block/vdi.c | 2 +-
35
block/vhdx.c | 2 +-
36
block/vmdk.c | 4 ++--
37
block/vpc.c | 2 +-
38
block/vvfat.c | 2 +-
39
blockjob.c | 5 +++--
40
tests/test-bdrv-drain.c | 20 +++++++++++---------
41
tests/test-bdrv-graph-mod.c | 4 ++--
42
31 files changed, 62 insertions(+), 49 deletions(-)
43
32
44
diff --git a/include/block/block.h b/include/block/block.h
33
diff --git a/include/qemu/job.h b/include/qemu/job.h
45
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block.h
35
--- a/include/qemu/job.h
47
+++ b/include/block/block.h
36
+++ b/include/qemu/job.h
48
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
37
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
49
QDict *options, const char *bdref_key,
38
/* ProgressMeter API is thread-safe */
50
BlockDriverState* parent,
39
ProgressMeter progress;
51
const BdrvChildClass *child_class,
40
52
+ BdrvChildRole child_role,
41
+ /**
53
bool allow_none, Error **errp);
42
+ * AioContext to run the job coroutine in.
54
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
43
+ * The job Aiocontext can be read when holding *either*
55
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
44
+ * the BQL (so we are in the main loop) or the job_mutex.
56
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
45
+ * It can only be written when we hold *both* BQL
57
BlockDriverState *child_bs,
46
+ * and the job_mutex.
58
const char *child_name,
47
+ */
59
const BdrvChildClass *child_class,
48
+ AioContext *aio_context;
60
+ BdrvChildRole child_role,
49
61
Error **errp);
50
- /** Protected by AioContext lock */
62
51
63
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
52
- /** AioContext to run the job coroutine in */
64
diff --git a/include/block/block_int.h b/include/block/block_int.h
53
- AioContext *aio_context;
65
index XXXXXXX..XXXXXXX 100644
54
+ /** Protected by AioContext lock */
66
--- a/include/block/block_int.h
55
67
+++ b/include/block/block_int.h
56
/** Reference count of the block job */
68
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
57
int refcnt;
69
BlockDriverState *bs;
58
@@ -XXX,XX +XXX,XX @@ int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
70
char *name;
59
int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
71
const BdrvChildClass *klass;
60
Error **errp);
72
+ BdrvChildRole role;
61
73
void *opaque;
62
+/**
74
63
+ * Sets the @job->aio_context.
75
/**
64
+ * Called with job_mutex *not* held.
76
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
65
+ *
77
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
66
+ * This function must run in the main thread to protect against
78
const char *child_name,
67
+ * concurrent read in job_finish_sync_locked(), takes the job_mutex
79
const BdrvChildClass *child_class,
68
+ * lock to protect against the read in job_do_yield_locked(), and must
80
+ BdrvChildRole child_role,
69
+ * be called when the job is quiescent.
81
AioContext *ctx,
70
+ */
82
uint64_t perm, uint64_t shared_perm,
71
+void job_set_aio_context(Job *job, AioContext *ctx);
83
void *opaque, Error **errp);
72
+
84
diff --git a/block.c b/block.c
73
#endif
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block.c
87
+++ b/block.c
88
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
89
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
90
const char *child_name,
91
const BdrvChildClass *child_class,
92
+ BdrvChildRole child_role,
93
AioContext *ctx,
94
uint64_t perm, uint64_t shared_perm,
95
void *opaque, Error **errp)
96
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
97
.bs = NULL,
98
.name = g_strdup(child_name),
99
.klass = child_class,
100
+ .role = child_role,
101
.perm = perm,
102
.shared_perm = shared_perm,
103
.opaque = opaque,
104
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
105
BlockDriverState *child_bs,
106
const char *child_name,
107
const BdrvChildClass *child_class,
108
+ BdrvChildRole child_role,
109
Error **errp)
110
{
111
BdrvChild *child;
112
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
113
perm, shared_perm, &perm, &shared_perm);
114
115
child = bdrv_root_attach_child(child_bs, child_name, child_class,
116
- bdrv_get_aio_context(parent_bs),
117
+ child_role, bdrv_get_aio_context(parent_bs),
118
perm, shared_perm, parent_bs, errp);
119
if (child == NULL) {
120
return NULL;
121
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
122
}
123
124
bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
125
- errp);
126
+ 0, errp);
127
/* If backing_hd was already part of bs's backing chain, and
128
* inherits_from pointed recursively to bs then let's update it to
129
* point directly to bs (else it will become NULL). */
130
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
131
QDict *options, const char *bdref_key,
132
BlockDriverState *parent,
133
const BdrvChildClass *child_class,
134
+ BdrvChildRole child_role,
135
bool allow_none, Error **errp)
136
{
137
BlockDriverState *bs;
138
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
139
return NULL;
140
}
141
142
- return bdrv_attach_child(parent, bs, bdref_key, child_class, errp);
143
+ return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
144
+ errp);
145
}
146
147
/*
148
diff --git a/block/backup-top.c b/block/backup-top.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/block/backup-top.c
151
+++ b/block/backup-top.c
152
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
153
source->supported_zero_flags);
154
155
bdrv_ref(target);
156
- state->target = bdrv_attach_child(top, target, "target", &child_file, errp);
157
+ state->target = bdrv_attach_child(top, target, "target", &child_file, 0,
158
+ errp);
159
if (!state->target) {
160
bdrv_unref(target);
161
bdrv_unref(top);
162
diff --git a/block/blkdebug.c b/block/blkdebug.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/block/blkdebug.c
165
+++ b/block/blkdebug.c
166
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
167
168
/* Open the image file */
169
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
170
- bs, &child_file, false, &local_err);
171
+ bs, &child_file, 0, false, &local_err);
172
if (local_err) {
173
ret = -EINVAL;
174
error_propagate(errp, local_err);
175
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/block/blklogwrites.c
178
+++ b/block/blklogwrites.c
179
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
180
}
181
182
/* Open the file */
183
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
184
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
185
&local_err);
186
if (local_err) {
187
ret = -EINVAL;
188
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
189
}
190
191
/* Open the log file */
192
- s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, false,
193
- &local_err);
194
+ s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, 0,
195
+ false, &local_err);
196
if (local_err) {
197
ret = -EINVAL;
198
error_propagate(errp, local_err);
199
diff --git a/block/blkreplay.c b/block/blkreplay.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/block/blkreplay.c
202
+++ b/block/blkreplay.c
203
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
204
205
/* Open the image file */
206
bs->file = bdrv_open_child(NULL, options, "image",
207
- bs, &child_file, false, &local_err);
208
+ bs, &child_file, 0, false, &local_err);
209
if (local_err) {
210
ret = -EINVAL;
211
error_propagate(errp, local_err);
212
diff --git a/block/blkverify.c b/block/blkverify.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/block/blkverify.c
215
+++ b/block/blkverify.c
216
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
217
218
/* Open the raw file */
219
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
220
- bs, &child_file, false, &local_err);
221
+ bs, &child_file, 0, false, &local_err);
222
if (local_err) {
223
ret = -EINVAL;
224
error_propagate(errp, local_err);
225
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
226
227
/* Open the test file */
228
s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options,
229
- "test", bs, &child_format, false,
230
+ "test", bs, &child_format, 0, false,
231
&local_err);
232
if (local_err) {
233
ret = -EINVAL;
234
diff --git a/block/block-backend.c b/block/block-backend.c
235
index XXXXXXX..XXXXXXX 100644
236
--- a/block/block-backend.c
237
+++ b/block/block-backend.c
238
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
239
return NULL;
240
}
241
242
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
243
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
244
perm, BLK_PERM_ALL, blk, errp);
245
if (!blk->root) {
246
blk_unref(blk);
247
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
248
{
249
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
250
bdrv_ref(bs);
251
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
252
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
253
blk->perm, blk->shared_perm, blk, errp);
254
if (blk->root == NULL) {
255
return -EPERM;
256
diff --git a/block/bochs.c b/block/bochs.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/bochs.c
259
+++ b/block/bochs.c
260
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
261
return ret;
262
}
263
264
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
265
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
266
false, errp);
267
if (!bs->file) {
268
return -EINVAL;
269
diff --git a/block/cloop.c b/block/cloop.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/cloop.c
272
+++ b/block/cloop.c
273
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
274
return ret;
275
}
276
277
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
278
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
279
false, errp);
280
if (!bs->file) {
281
return -EINVAL;
282
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/copy-on-read.c
285
+++ b/block/copy-on-read.c
286
@@ -XXX,XX +XXX,XX @@
287
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
288
Error **errp)
289
{
290
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
291
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
292
errp);
293
if (!bs->file) {
294
return -EINVAL;
295
diff --git a/block/crypto.c b/block/crypto.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/block/crypto.c
298
+++ b/block/crypto.c
299
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
300
unsigned int cflags = 0;
301
QDict *cryptoopts = NULL;
302
303
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
304
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
305
false, errp);
306
if (!bs->file) {
307
return -EINVAL;
308
diff --git a/block/dmg.c b/block/dmg.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/block/dmg.c
311
+++ b/block/dmg.c
312
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
313
return ret;
314
}
315
316
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
317
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
318
false, errp);
319
if (!bs->file) {
320
return -EINVAL;
321
diff --git a/block/filter-compress.c b/block/filter-compress.c
322
index XXXXXXX..XXXXXXX 100644
323
--- a/block/filter-compress.c
324
+++ b/block/filter-compress.c
325
@@ -XXX,XX +XXX,XX @@
326
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
327
Error **errp)
328
{
329
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
330
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
331
errp);
332
if (!bs->file) {
333
return -EINVAL;
334
diff --git a/block/parallels.c b/block/parallels.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/block/parallels.c
337
+++ b/block/parallels.c
338
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
339
Error *local_err = NULL;
340
char *buf;
341
342
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
343
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
344
false, errp);
345
if (!bs->file) {
346
return -EINVAL;
347
diff --git a/block/qcow.c b/block/qcow.c
348
index XXXXXXX..XXXXXXX 100644
349
--- a/block/qcow.c
350
+++ b/block/qcow.c
351
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
352
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
353
encryptfmt = qdict_get_try_str(encryptopts, "format");
354
355
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
356
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
357
false, errp);
358
if (!bs->file) {
359
ret = -EINVAL;
360
diff --git a/block/qcow2.c b/block/qcow2.c
361
index XXXXXXX..XXXXXXX 100644
362
--- a/block/qcow2.c
363
+++ b/block/qcow2.c
364
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
365
366
/* Open external data file */
367
s->data_file = bdrv_open_child(NULL, options, "data-file", bs, &child_file,
368
- true, &local_err);
369
+ 0, true, &local_err);
370
if (local_err) {
371
error_propagate(errp, local_err);
372
ret = -EINVAL;
373
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
374
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
375
if (!s->data_file && s->image_data_file) {
376
s->data_file = bdrv_open_child(s->image_data_file, options,
377
- "data-file", bs, &child_file,
378
+ "data-file", bs, &child_file, 0,
379
false, errp);
380
if (!s->data_file) {
381
ret = -EINVAL;
382
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
383
.ret = -EINPROGRESS
384
};
385
386
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
387
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
388
false, errp);
389
if (!bs->file) {
390
return -EINVAL;
391
diff --git a/block/qed.c b/block/qed.c
392
index XXXXXXX..XXXXXXX 100644
393
--- a/block/qed.c
394
+++ b/block/qed.c
395
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
396
.ret = -EINPROGRESS
397
};
398
399
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
400
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
401
false, errp);
402
if (!bs->file) {
403
return -EINVAL;
404
diff --git a/block/quorum.c b/block/quorum.c
405
index XXXXXXX..XXXXXXX 100644
406
--- a/block/quorum.c
407
+++ b/block/quorum.c
408
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
409
assert(ret < 32);
410
411
s->children[i] = bdrv_open_child(NULL, options, indexstr, bs,
412
- &child_format, false, &local_err);
413
+ &child_format, 0, false, &local_err);
414
if (local_err) {
415
ret = -EINVAL;
416
goto close_exit;
417
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
418
/* We can safely add the child now */
419
bdrv_ref(child_bs);
420
421
- child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, errp);
422
+ child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, 0, errp);
423
if (child == NULL) {
424
s->next_child_index--;
425
goto out;
426
diff --git a/block/raw-format.c b/block/raw-format.c
427
index XXXXXXX..XXXXXXX 100644
428
--- a/block/raw-format.c
429
+++ b/block/raw-format.c
430
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
431
BDRVRawState *s = bs->opaque;
432
int ret;
433
434
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
435
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
436
false, errp);
437
if (!bs->file) {
438
return -EINVAL;
439
diff --git a/block/replication.c b/block/replication.c
74
diff --git a/block/replication.c b/block/replication.c
440
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
441
--- a/block/replication.c
76
--- a/block/replication.c
442
+++ b/block/replication.c
77
+++ b/block/replication.c
443
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
78
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
444
const char *mode;
79
{
445
const char *top_id;
80
BDRVReplicationState *s = bs->opaque;
446
81
Job *commit_job;
447
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
82
+ GLOBAL_STATE_CODE();
448
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
83
449
false, errp);
84
if (s->stage == BLOCK_REPLICATION_RUNNING) {
450
if (!bs->file) {
85
replication_stop(s->rs, false, NULL);
451
return -EINVAL;
452
diff --git a/block/throttle.c b/block/throttle.c
453
index XXXXXXX..XXXXXXX 100644
454
--- a/block/throttle.c
455
+++ b/block/throttle.c
456
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
457
int ret;
458
459
bs->file = bdrv_open_child(NULL, options, "file", bs,
460
- &child_file, false, errp);
461
+ &child_file, 0, false, errp);
462
if (!bs->file) {
463
return -EINVAL;
464
}
465
diff --git a/block/vdi.c b/block/vdi.c
466
index XXXXXXX..XXXXXXX 100644
467
--- a/block/vdi.c
468
+++ b/block/vdi.c
469
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
470
Error *local_err = NULL;
471
QemuUUID uuid_link, uuid_parent;
472
473
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
474
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
475
false, errp);
476
if (!bs->file) {
477
return -EINVAL;
478
diff --git a/block/vhdx.c b/block/vhdx.c
479
index XXXXXXX..XXXXXXX 100644
480
--- a/block/vhdx.c
481
+++ b/block/vhdx.c
482
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
483
uint64_t signature;
484
Error *local_err = NULL;
485
486
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
487
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
488
false, errp);
489
if (!bs->file) {
490
return -EINVAL;
491
diff --git a/block/vmdk.c b/block/vmdk.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/block/vmdk.c
494
+++ b/block/vmdk.c
495
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
496
assert(ret < 32);
497
498
extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,
499
- bs, &child_file, false, &local_err);
500
+ bs, &child_file, 0, false, &local_err);
501
g_free(extent_path);
502
if (local_err) {
503
error_propagate(errp, local_err);
504
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
505
uint32_t magic;
506
Error *local_err = NULL;
507
508
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
509
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
510
false, errp);
511
if (!bs->file) {
512
return -EINVAL;
513
diff --git a/block/vpc.c b/block/vpc.c
514
index XXXXXXX..XXXXXXX 100644
515
--- a/block/vpc.c
516
+++ b/block/vpc.c
517
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
518
int ret;
519
int64_t bs_size;
520
521
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
522
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
523
false, errp);
524
if (!bs->file) {
525
return -EINVAL;
526
diff --git a/block/vvfat.c b/block/vvfat.c
527
index XXXXXXX..XXXXXXX 100644
528
--- a/block/vvfat.c
529
+++ b/block/vvfat.c
530
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
531
options = qdict_new();
532
qdict_put_str(options, "write-target.driver", "qcow");
533
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
534
- &child_vvfat_qcow, false, errp);
535
+ &child_vvfat_qcow, 0, false, errp);
536
qobject_unref(options);
537
if (!s->qcow) {
538
ret = -EINVAL;
539
diff --git a/blockjob.c b/blockjob.c
86
diff --git a/blockjob.c b/blockjob.c
540
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
541
--- a/blockjob.c
88
--- a/blockjob.c
542
+++ b/blockjob.c
89
+++ b/blockjob.c
543
@@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
90
@@ -XXX,XX +XXX,XX @@ static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
544
if (job->job.aio_context != qemu_get_aio_context()) {
91
bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
545
aio_context_release(job->job.aio_context);
546
}
92
}
547
- c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context,
93
548
- perm, shared_perm, job, errp);
94
- job->job.aio_context = ctx;
549
+ c = bdrv_root_attach_child(bs, name, &child_job, 0,
95
+ job_set_aio_context(&job->job, ctx);
550
+ job->job.aio_context, perm, shared_perm, job,
96
}
551
+ errp);
97
552
if (job->job.aio_context != qemu_get_aio_context()) {
98
static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
553
aio_context_acquire(job->job.aio_context);
99
{
554
}
100
BlockJob *job = c->opaque;
555
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
101
+ GLOBAL_STATE_CODE();
102
103
return job->job.aio_context;
104
}
105
diff --git a/job.c b/job.c
556
index XXXXXXX..XXXXXXX 100644
106
index XXXXXXX..XXXXXXX 100644
557
--- a/tests/test-bdrv-drain.c
107
--- a/job.c
558
+++ b/tests/test-bdrv-drain.c
108
+++ b/job.c
559
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
109
@@ -XXX,XX +XXX,XX @@ Job *job_get(const char *id)
560
110
return job_get_locked(id);
561
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
562
&error_abort);
563
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort);
564
+ bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
565
566
/* This child will be the one to pass to requests through to, and
567
* it will stall until a drain occurs */
568
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
569
child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS;
570
/* Takes our reference to child_bs */
571
tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", &child_file,
572
- &error_abort);
573
+ 0, &error_abort);
574
575
/* This child is just there to be deleted
576
* (for detach_instead_of_delete == true) */
577
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
578
&error_abort);
579
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort);
580
+ bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
581
582
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
583
blk_insert_bs(blk, bs, &error_abort);
584
@@ -XXX,XX +XXX,XX @@ static void detach_indirect_bh(void *opaque)
585
586
bdrv_ref(data->c);
587
data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C",
588
- &child_file, &error_abort);
589
+ &child_file, 0, &error_abort);
590
}
111
}
591
112
592
static void detach_by_parent_aio_cb(void *opaque, int ret)
113
+void job_set_aio_context(Job *job, AioContext *ctx)
593
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
114
+{
594
/* Set child relationships */
115
+ /* protect against read in job_finish_sync_locked and job_start */
595
bdrv_ref(b);
116
+ GLOBAL_STATE_CODE();
596
bdrv_ref(a);
117
+ /* protect against read in job_do_yield_locked */
597
- child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, &error_abort);
118
+ JOB_LOCK_GUARD();
598
- child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, &error_abort);
119
+ /* ensure the job is quiescent while the AioContext is changed */
599
+ child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0,
120
+ assert(job->paused || job_is_completed_locked(job));
600
+ &error_abort);
121
+ job->aio_context = ctx;
601
+ child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, 0,
122
+}
602
+ &error_abort);
123
+
603
124
/* Called with job_mutex *not* held. */
604
bdrv_ref(a);
125
static void job_sleep_timer_cb(void *opaque)
605
bdrv_attach_child(parent_a, a, "PA-A",
126
{
606
by_parent_cb ? &child_file : &detach_by_driver_cb_class,
127
@@ -XXX,XX +XXX,XX @@ int job_finish_sync_locked(Job *job,
607
- &error_abort);
128
{
608
+ 0, &error_abort);
129
Error *local_err = NULL;
609
130
int ret;
610
g_assert_cmpint(parent_a->refcnt, ==, 1);
131
+ GLOBAL_STATE_CODE();
611
g_assert_cmpint(parent_b->refcnt, ==, 1);
132
612
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
133
job_ref_locked(job);
613
/* Takes the reference to chain[i - 1] */
614
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
615
"chain", &chain_child_class,
616
- &error_abort);
617
+ 0, &error_abort);
618
}
619
}
620
621
@@ -XXX,XX +XXX,XX @@ static void do_test_replace_child_mid_drain(int old_drain_count,
622
623
bdrv_ref(old_child_bs);
624
parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
625
- &child_backing, &error_abort);
626
+ &child_backing, 0, &error_abort);
627
628
for (i = 0; i < old_drain_count; i++) {
629
bdrv_drained_begin(old_child_bs);
630
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
631
index XXXXXXX..XXXXXXX 100644
632
--- a/tests/test-bdrv-graph-mod.c
633
+++ b/tests/test-bdrv-graph-mod.c
634
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
635
636
blk_insert_bs(root, bs, &error_abort);
637
638
- bdrv_attach_child(filter, bs, "child", &child_file, &error_abort);
639
+ bdrv_attach_child(filter, bs, "child", &child_file, 0, &error_abort);
640
641
bdrv_append(filter, bs, &local_err);
642
643
@@ -XXX,XX +XXX,XX @@ static void test_should_update_child(void)
644
bdrv_set_backing_hd(target, bs, &error_abort);
645
646
g_assert(target->backing->bs == bs);
647
- bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
648
+ bdrv_attach_child(filter, target, "target", &child_file, 0, &error_abort);
649
bdrv_append(filter, bs, &error_abort);
650
g_assert(target->backing->bs == bs);
651
134
652
--
135
--
653
2.25.4
136
2.37.3
654
655
diff view generated by jsdifflib
1
We need to fix only a few places so that iotests.py can pass
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
mypy --disallow-incomplete-defs, which seems to be a desirable option to
3
have enabled in the long run.
4
2
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
The same job lock is being used also to protect some of blockjob fields.
6
Message-Id: <20200511163529.349329-2-kwolf@redhat.com>
4
Categorize them just as done in job.h.
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
8
Reviewed-by: John Snow <jsnow@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Message-Id: <20220926093214.506243-15-eesposit@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
---
11
tests/qemu-iotests/iotests.py | 8 ++++----
12
include/block/blockjob.h | 32 ++++++++++++++++++++++++++------
12
1 file changed, 4 insertions(+), 4 deletions(-)
13
1 file changed, 26 insertions(+), 6 deletions(-)
13
14
14
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
15
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/iotests.py
17
--- a/include/block/blockjob.h
17
+++ b/tests/qemu-iotests/iotests.py
18
+++ b/include/block/blockjob.h
18
@@ -XXX,XX +XXX,XX @@ def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None:
19
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJobDriver BlockJobDriver;
19
if supported_cache_modes and (cachemode not in supported_cache_modes):
20
* Long-running operation on a BlockDriverState.
20
notrun('not suitable for this cache mode: %s' % cachemode)
21
*/
21
22
typedef struct BlockJob {
22
-def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()):
23
- /** Data belonging to the generic Job infrastructure */
23
+def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()) -> None:
24
+ /**
24
if supported_aio_modes and (aiomode not in supported_aio_modes):
25
+ * Data belonging to the generic Job infrastructure.
25
notrun('not suitable for this aio mode: %s' % aiomode)
26
+ * Protected by job mutex.
26
27
+ */
27
@@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=(), read_only=False):
28
Job job;
28
'''Skip Test Decorator
29
29
Runs the test if all the required formats are whitelisted'''
30
- /** Status that is published by the query-block-jobs QMP API */
30
def skip_test_decorator(func):
31
+ /**
31
- def func_wrapper(test_case: QMPTestCase, *args, **kwargs):
32
+ * Status that is published by the query-block-jobs QMP API.
32
+ def func_wrapper(test_case: QMPTestCase, *args: List[Any],
33
+ * Protected by job mutex.
33
+ **kwargs: Dict[str, Any]) -> None:
34
+ */
34
if callable(required_formats):
35
BlockDeviceIoStatus iostatus;
35
fmts = required_formats(test_case)
36
36
else:
37
- /** Speed that was set with @block_job_set_speed. */
37
@@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=(), read_only=False):
38
+ /**
38
if usf_list:
39
+ * Speed that was set with @block_job_set_speed.
39
msg = f'{test_case}: formats {usf_list} are not whitelisted'
40
+ * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE).
40
test_case.case_skip(msg)
41
+ */
41
- return None
42
int64_t speed;
42
else:
43
43
- return func(test_case, *args, **kwargs)
44
- /** Rate limiting data structure for implementing @speed. */
44
+ func(test_case, *args, **kwargs)
45
+ /**
45
return func_wrapper
46
+ * Rate limiting data structure for implementing @speed.
46
return skip_test_decorator
47
+ * RateLimit API is thread-safe.
48
+ */
49
RateLimit limit;
50
51
- /** Block other operations when block job is running */
52
+ /**
53
+ * Block other operations when block job is running.
54
+ * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE).
55
+ */
56
Error *blocker;
57
58
+ /** All notifiers are set once in block_job_create() and never modified. */
59
+
60
/** Called when a cancelled job is finalised. */
61
Notifier finalize_cancelled_notifier;
62
63
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJob {
64
/** Called when the job coroutine yields or terminates */
65
Notifier idle_notifier;
66
67
- /** BlockDriverStates that are involved in this block job */
68
+ /**
69
+ * BlockDriverStates that are involved in this block job.
70
+ * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE).
71
+ */
72
GSList *nodes;
73
} BlockJob;
47
74
48
--
75
--
49
2.25.4
76
2.37.3
50
51
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We plan to unify the generic .inherit_options() functions. The
3
They all are called with job_lock held, in job_event_*_locked()
4
resulting common function will need to decide whether to force-enable
5
format probing, force-disable it, or leave it as-is. To make this
6
decision, it will need to know whether the parent node is a format node
7
or not (because we never want format probing if the parent is a format
8
node already (except for the backing chain)).
9
4
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
12
Message-Id: <20200513110544.176672-9-mreitz@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Message-Id: <20220926093214.506243-16-eesposit@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
11
---
15
include/block/block_int.h | 2 +-
12
blockjob.c | 25 +++++++++++++++----------
16
block.c | 37 +++++++++++++++++++++++++++----------
13
1 file changed, 15 insertions(+), 10 deletions(-)
17
block/block-backend.c | 2 +-
18
block/vvfat.c | 2 +-
19
4 files changed, 30 insertions(+), 13 deletions(-)
20
14
21
diff --git a/include/block/block_int.h b/include/block/block_int.h
15
diff --git a/blockjob.c b/blockjob.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block_int.h
17
--- a/blockjob.c
24
+++ b/include/block/block_int.h
18
+++ b/blockjob.c
25
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
19
@@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
26
* non-BDS parents. */
20
return 0;
27
bool parent_is_bds;
21
}
28
22
29
- void (*inherit_options)(BdrvChildRole role,
23
-static void block_job_on_idle(Notifier *n, void *opaque)
30
+ void (*inherit_options)(BdrvChildRole role, bool parent_is_format,
24
+/* Called with job_mutex lock held. */
31
int *child_flags, QDict *child_options,
25
+static void block_job_on_idle_locked(Notifier *n, void *opaque)
32
int parent_flags, QDict *parent_options);
33
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
37
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
39
* Returns the options and flags that bs->file should get if a protocol driver
40
* is expected, based on the given options and flags for the parent BDS
41
*/
42
-static void bdrv_inherited_options(BdrvChildRole role,
43
+static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
44
int *child_flags, QDict *child_options,
45
int parent_flags, QDict *parent_options)
46
{
26
{
47
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_file = {
27
aio_wait_kick();
48
* flags for the parent BDS
28
}
49
*/
29
@@ -XXX,XX +XXX,XX @@ static void block_job_iostatus_set_err(BlockJob *job, int error)
50
static void bdrv_inherited_fmt_options(BdrvChildRole role,
30
}
51
+ bool parent_is_format,
31
}
52
int *child_flags, QDict *child_options,
32
53
int parent_flags, QDict *parent_options)
33
-static void block_job_event_cancelled(Notifier *n, void *opaque)
34
+/* Called with job_mutex lock held. */
35
+static void block_job_event_cancelled_locked(Notifier *n, void *opaque)
54
{
36
{
55
- child_file.inherit_options(role, child_flags, child_options,
37
BlockJob *job = opaque;
56
+ child_file.inherit_options(role, parent_is_format,
38
uint64_t progress_current, progress_total;
57
+ child_flags, child_options,
39
@@ -XXX,XX +XXX,XX @@ static void block_job_event_cancelled(Notifier *n, void *opaque)
58
parent_flags, parent_options);
40
job->speed);
59
41
}
60
*child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
42
61
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
43
-static void block_job_event_completed(Notifier *n, void *opaque)
62
* Returns the options and flags that bs->backing should get, based on the
44
+/* Called with job_mutex lock held. */
63
* given options and flags for the parent BDS
45
+static void block_job_event_completed_locked(Notifier *n, void *opaque)
64
*/
65
-static void bdrv_backing_options(BdrvChildRole role,
66
+static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format,
67
int *child_flags, QDict *child_options,
68
int parent_flags, QDict *parent_options)
69
{
46
{
70
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
47
BlockJob *job = opaque;
71
bs->explicit_options = qdict_clone_shallow(options);
48
const char *msg = NULL;
72
49
@@ -XXX,XX +XXX,XX @@ static void block_job_event_completed(Notifier *n, void *opaque)
73
if (child_class) {
50
msg);
74
+ bool parent_is_format;
51
}
75
+
52
76
+ if (parent->drv) {
53
-static void block_job_event_pending(Notifier *n, void *opaque)
77
+ parent_is_format = parent->drv->is_format;
54
+/* Called with job_mutex lock held. */
78
+ } else {
55
+static void block_job_event_pending_locked(Notifier *n, void *opaque)
79
+ /*
80
+ * parent->drv is not set yet because this node is opened for
81
+ * (potential) format probing. That means that @parent is going
82
+ * to be a format node.
83
+ */
84
+ parent_is_format = true;
85
+ }
86
+
87
bs->inherits_from = parent;
88
- child_class->inherit_options(child_role, &flags, options,
89
+ child_class->inherit_options(child_role, parent_is_format,
90
+ &flags, options,
91
parent->open_flags, parent->options);
92
}
93
94
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
95
flags, options);
96
/* Let bdrv_backing_options() override "read-only" */
97
qdict_del(options, BDRV_OPT_READ_ONLY);
98
- bdrv_backing_options(0, &flags, options, flags, options);
99
+ bdrv_backing_options(0, true, &flags, options, flags, options);
100
}
101
102
bs->open_flags = flags;
103
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
104
QDict *options,
105
const BdrvChildClass *klass,
106
BdrvChildRole role,
107
+ bool parent_is_format,
108
QDict *parent_options,
109
int parent_flags,
110
bool keep_old_opts)
111
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
112
/* Inherit from parent node */
113
if (parent_options) {
114
flags = 0;
115
- klass->inherit_options(role, &flags, options,
116
+ klass->inherit_options(role, parent_is_format, &flags, options,
117
parent_flags, parent_options);
118
} else {
119
flags = bdrv_get_flags(bs);
120
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
121
}
122
123
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
124
- child->klass, child->role, options, flags,
125
- child_keep_old);
126
+ child->klass, child->role, bs->drv->is_format,
127
+ options, flags, child_keep_old);
128
}
129
130
return bs_queue;
131
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
132
BlockDriverState *bs,
133
QDict *options, bool keep_old_opts)
134
{
56
{
135
- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, NULL, 0,
57
BlockJob *job = opaque;
136
- keep_old_opts);
58
137
+ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, false,
59
@@ -XXX,XX +XXX,XX @@ static void block_job_event_pending(Notifier *n, void *opaque)
138
+ NULL, 0, keep_old_opts);
60
job->job.id);
139
}
61
}
140
62
141
/*
63
-static void block_job_event_ready(Notifier *n, void *opaque)
142
diff --git a/block/block-backend.c b/block/block-backend.c
64
+/* Called with job_mutex lock held. */
143
index XXXXXXX..XXXXXXX 100644
65
+static void block_job_event_ready_locked(Notifier *n, void *opaque)
144
--- a/block/block-backend.c
145
+++ b/block/block-backend.c
146
@@ -XXX,XX +XXX,XX @@ static QTAILQ_HEAD(, BlockBackend) block_backends =
147
static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
148
QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
149
150
-static void blk_root_inherit_options(BdrvChildRole role,
151
+static void blk_root_inherit_options(BdrvChildRole role, bool parent_is_format,
152
int *child_flags, QDict *child_options,
153
int parent_flags, QDict *parent_options)
154
{
66
{
155
diff --git a/block/vvfat.c b/block/vvfat.c
67
BlockJob *job = opaque;
156
index XXXXXXX..XXXXXXX 100644
68
uint64_t progress_current, progress_total;
157
--- a/block/vvfat.c
69
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
158
+++ b/block/vvfat.c
70
159
@@ -XXX,XX +XXX,XX @@ static BlockDriver vvfat_write_target = {
71
ratelimit_init(&job->limit);
160
.bdrv_co_pwritev = write_target_commit,
72
161
};
73
- job->finalize_cancelled_notifier.notify = block_job_event_cancelled;
162
74
- job->finalize_completed_notifier.notify = block_job_event_completed;
163
-static void vvfat_qcow_options(BdrvChildRole role,
75
- job->pending_notifier.notify = block_job_event_pending;
164
+static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
76
- job->ready_notifier.notify = block_job_event_ready;
165
int *child_flags, QDict *child_options,
77
- job->idle_notifier.notify = block_job_on_idle;
166
int parent_flags, QDict *parent_options)
78
+ job->finalize_cancelled_notifier.notify = block_job_event_cancelled_locked;
167
{
79
+ job->finalize_completed_notifier.notify = block_job_event_completed_locked;
80
+ job->pending_notifier.notify = block_job_event_pending_locked;
81
+ job->ready_notifier.notify = block_job_event_ready_locked;
82
+ job->idle_notifier.notify = block_job_on_idle_locked;
83
84
WITH_JOB_LOCK_GUARD() {
85
notifier_list_add(&job->job.on_finalize_cancelled,
168
--
86
--
169
2.25.4
87
2.37.3
170
171
diff view generated by jsdifflib
1
If the target is shorter than the source, mirror would copy data until
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
it reaches the end of the target and then fail with an I/O error when
3
trying to write past the end.
4
2
5
If the target is longer than the source, the mirror job would complete
3
iostatus is the only field (together with .job) that needs
6
successfully, but the target wouldn't actually be an accurate copy of
4
protection using the job mutex.
7
the source image (it would contain some additional garbage at the end).
8
5
9
Fix this by checking that both images have the same size when the job
6
It is set in the main loop (GLOBAL_STATE functions) but read
10
starts.
7
in I/O code (block_job_error_action).
11
8
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
In order to protect it, change block_job_iostatus_set_err
13
Reviewed-by: Eric Blake <eblake@redhat.com>
10
to block_job_iostatus_set_err_locked(), always called under
14
Message-Id: <20200511135825.219437-4-kwolf@redhat.com>
11
job lock.
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
16
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
16
Message-Id: <20220926093214.506243-17-eesposit@redhat.com>
17
[kwolf: Fixed up type of iostatus]
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
---
19
block/mirror.c | 21 ++++++++++++---------
20
block/mirror.c | 6 +++++-
20
1 file changed, 12 insertions(+), 9 deletions(-)
21
blockjob.c | 5 +++--
22
2 files changed, 8 insertions(+), 3 deletions(-)
21
23
22
diff --git a/block/mirror.c b/block/mirror.c
24
diff --git a/block/mirror.c b/block/mirror.c
23
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
24
--- a/block/mirror.c
26
--- a/block/mirror.c
25
+++ b/block/mirror.c
27
+++ b/block/mirror.c
26
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
29
BlockDriverState *bs = s->mirror_top_bs->backing->bs;
27
BlockDriverState *target_bs = blk_bs(s->target);
30
BlockDriverState *target_bs = blk_bs(s->target);
28
bool need_drain = true;
31
bool need_drain = true;
32
+ BlockDeviceIoStatus iostatus;
29
int64_t length;
33
int64_t length;
30
+ int64_t target_length;
34
int64_t target_length;
31
BlockDriverInfo bdi;
35
BlockDriverInfo bdi;
32
char backing_filename[2]; /* we only need 2 characters because we are only
33
checking for a NULL string */
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
36
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
35
goto immediate_exit;
37
* We do so every BLKOCK_JOB_SLICE_TIME nanoseconds, or when there is
38
* an error, or when the source is clean, whichever comes first. */
39
delta = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->last_pause_ns;
40
+ WITH_JOB_LOCK_GUARD() {
41
+ iostatus = s->common.iostatus;
42
+ }
43
if (delta < BLOCK_JOB_SLICE_TIME &&
44
- s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
45
+ iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
46
if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 ||
47
(cnt == 0 && s->in_flight > 0)) {
48
trace_mirror_yield(s, cnt, s->buf_free_count, s->in_flight);
49
diff --git a/blockjob.c b/blockjob.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/blockjob.c
52
+++ b/blockjob.c
53
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
54
return block_job_query_locked(job, errp);
55
}
56
57
-static void block_job_iostatus_set_err(BlockJob *job, int error)
58
+/* Called with job lock held */
59
+static void block_job_iostatus_set_err_locked(BlockJob *job, int error)
60
{
61
if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
62
job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
63
@@ -XXX,XX +XXX,XX @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
64
*/
65
job->job.user_paused = true;
66
}
67
+ block_job_iostatus_set_err_locked(job, error);
68
}
69
- block_job_iostatus_set_err(job, error);
36
}
70
}
37
71
return action;
38
+ target_length = blk_getlength(s->target);
72
}
39
+ if (target_length < 0) {
40
+ ret = target_length;
41
+ goto immediate_exit;
42
+ }
43
+
44
/* Active commit must resize the base image if its size differs from the
45
* active layer. */
46
if (s->base == blk_bs(s->target)) {
47
- int64_t base_length;
48
-
49
- base_length = blk_getlength(s->target);
50
- if (base_length < 0) {
51
- ret = base_length;
52
- goto immediate_exit;
53
- }
54
-
55
- if (s->bdev_length > base_length) {
56
+ if (s->bdev_length > target_length) {
57
ret = blk_truncate(s->target, s->bdev_length, false,
58
PREALLOC_MODE_OFF, 0, NULL);
59
if (ret < 0) {
60
goto immediate_exit;
61
}
62
}
63
+ } else if (s->bdev_length != target_length) {
64
+ error_setg(errp, "Source and target image have different sizes");
65
+ ret = -EINVAL;
66
+ goto immediate_exit;
67
}
68
69
if (s->bdev_length == 0) {
70
--
73
--
71
2.25.4
74
2.37.3
72
73
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Some callbacks implementation use bdrv_* APIs that assume the
4
Reviewed-by: Eric Blake <eblake@redhat.com>
4
AioContext lock is held. Make sure this invariant is documented.
5
Message-Id: <20200513110544.176672-23-mreitz@redhat.com>
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
8
Message-Id: <20220926093214.506243-18-eesposit@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
11
---
8
include/block/block_int.h | 1 -
12
include/qemu/job.h | 27 +++++++++++++++++++++++++--
9
block.c | 29 -----------------------------
13
1 file changed, 25 insertions(+), 2 deletions(-)
10
2 files changed, 30 deletions(-)
11
14
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
15
diff --git a/include/qemu/job.h b/include/qemu/job.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/include/block/block_int.h
17
--- a/include/qemu/job.h
15
+++ b/include/block/block_int.h
18
+++ b/include/qemu/job.h
16
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
19
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
17
20
/** True if this job should automatically dismiss itself */
18
extern const BdrvChildClass child_of_bds;
21
bool auto_dismiss;
19
extern const BdrvChildClass child_file;
22
20
-extern const BdrvChildClass child_format;
23
- /** The completion function that will be called when the job completes. */
21
extern const BdrvChildClass child_backing;
24
+ /**
22
25
+ * The completion function that will be called when the job completes.
23
struct BdrvChild {
26
+ * Called with AioContext lock held, since many callback implementations
24
diff --git a/block.c b/block.c
27
+ * use bdrv_* functions that require to hold the lock.
25
index XXXXXXX..XXXXXXX 100644
28
+ */
26
--- a/block.c
29
BlockCompletionFunc *cb;
27
+++ b/block.c
30
28
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_file = {
31
/** The opaque value that is passed to the completion function. */
29
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
32
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
33
*
34
* This callback will not be invoked if the job has already failed.
35
* If it fails, abort and then clean will be called.
36
+ *
37
+ * Called with AioContext lock held, since many callbacs implementations
38
+ * use bdrv_* functions that require to hold the lock.
39
*/
40
int (*prepare)(Job *job);
41
42
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
43
*
44
* All jobs will complete with a call to either .commit() or .abort() but
45
* never both.
46
+ *
47
+ * Called with AioContext lock held, since many callback implementations
48
+ * use bdrv_* functions that require to hold the lock.
49
*/
50
void (*commit)(Job *job);
51
52
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
53
*
54
* All jobs will complete with a call to either .commit() or .abort() but
55
* never both.
56
+ *
57
+ * Called with AioContext lock held, since many callback implementations
58
+ * use bdrv_* functions that require to hold the lock.
59
*/
60
void (*abort)(Job *job);
61
62
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
63
* .commit() or .abort(). Regardless of which callback is invoked after
64
* completion, .clean() will always be called, even if the job does not
65
* belong to a transaction group.
66
+ *
67
+ * Called with AioContext lock held, since many callbacs implementations
68
+ * use bdrv_* functions that require to hold the lock.
69
*/
70
void (*clean)(Job *job);
71
72
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
73
* READY).
74
* (If the callback is NULL, the job is assumed to terminate
75
* without I/O.)
76
+ *
77
+ * Called with AioContext lock held, since many callback implementations
78
+ * use bdrv_* functions that require to hold the lock.
79
*/
80
bool (*cancel)(Job *job, bool force);
81
82
83
- /** Called when the job is freed */
84
+ /**
85
+ * Called when the job is freed.
86
+ * Called with AioContext lock held, since many callback implementations
87
+ * use bdrv_* functions that require to hold the lock.
88
+ */
89
void (*free)(Job *job);
30
};
90
};
31
91
32
-/*
33
- * Returns the options and flags that bs->file should get if the use of formats
34
- * (and not only protocols) is permitted for it, based on the given options and
35
- * flags for the parent BDS
36
- */
37
-static void bdrv_inherited_fmt_options(BdrvChildRole role,
38
- bool parent_is_format,
39
- int *child_flags, QDict *child_options,
40
- int parent_flags, QDict *parent_options)
41
-{
42
- bdrv_inherited_options(BDRV_CHILD_DATA, false,
43
- child_flags, child_options,
44
- parent_flags, parent_options);
45
-}
46
-
47
-const BdrvChildClass child_format = {
48
- .parent_is_bds = true,
49
- .get_parent_desc = bdrv_child_get_parent_desc,
50
- .inherit_options = bdrv_inherited_fmt_options,
51
- .drained_begin = bdrv_child_cb_drained_begin,
52
- .drained_poll = bdrv_child_cb_drained_poll,
53
- .drained_end = bdrv_child_cb_drained_end,
54
- .attach = bdrv_child_cb_attach,
55
- .detach = bdrv_child_cb_detach,
56
- .inactivate = bdrv_child_cb_inactivate,
57
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
58
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
59
-};
60
-
61
static void bdrv_backing_attach(BdrvChild *c)
62
{
63
BlockDriverState *parent = c->opaque;
64
--
92
--
65
2.25.4
93
2.37.3
66
67
diff view generated by jsdifflib
1
From: Lukas Straub <lukasstraub2@web.de>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
If qemu in colo secondary mode is stopped, it crashes because
3
Change the job_{lock/unlock} and macros to use job_mutex.
4
s->backup_job is canceled twice: First with job_cancel_sync_all()
5
in qemu_cleanup() and then in replication_stop().
6
4
7
Fix this by assigning NULL to s->backup_job when the job completes
5
Now that they are not nop anymore, remove the aiocontext
8
so replication_stop() and replication_do_checkpoint() won't touch
6
to avoid deadlocks.
9
the job.
10
7
11
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
8
Therefore:
12
Message-Id: <20200511090801.7ed5d8f3@luklap>
9
- when possible, remove completely the aiocontext lock/unlock pair
10
- if it is used by some other function too, reduce the locking
11
section as much as possible, leaving the job API outside.
12
- change AIO_WAIT_WHILE in AIO_WAIT_WHILE_UNLOCKED, since we
13
are not using the aiocontext lock anymore
14
15
The only functions that still need the aiocontext lock are:
16
- the JobDriver callbacks, already documented in job.h
17
- job_cancel_sync() in replication.c is called with aio_context_lock
18
taken, but now job is using AIO_WAIT_WHILE_UNLOCKED so we need to
19
release the lock.
20
21
Reduce the locking section to only cover the callback invocation
22
and document the functions that take the AioContext lock,
23
to avoid taking it twice.
24
25
Also remove real_job_{lock/unlock}, as they are replaced by the
26
public functions.
27
28
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
29
Message-Id: <20220926093214.506243-19-eesposit@redhat.com>
30
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
32
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
33
---
15
block/replication.c | 2 ++
34
include/qemu/job.h | 17 ++---
16
1 file changed, 2 insertions(+)
35
block/replication.c | 2 +
36
blockdev.c | 72 +++-----------------
37
job-qmp.c | 46 +++----------
38
job.c | 111 +++++++++----------------------
39
qemu-img.c | 2 -
40
tests/unit/test-bdrv-drain.c | 4 +-
41
tests/unit/test-block-iothread.c | 2 +-
42
tests/unit/test-blockjob.c | 19 +++---
43
9 files changed, 72 insertions(+), 203 deletions(-)
17
44
45
diff --git a/include/qemu/job.h b/include/qemu/job.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/qemu/job.h
48
+++ b/include/qemu/job.h
49
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
50
AioContext *aio_context;
51
52
53
- /** Protected by AioContext lock */
54
+ /** Protected by job_mutex */
55
56
/** Reference count of the block job */
57
int refcnt;
58
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
59
/**
60
* Set to false by the job while the coroutine has yielded and may be
61
* re-entered by job_enter(). There may still be I/O or event loop activity
62
- * pending. Accessed under block_job_mutex (in blockjob.c).
63
+ * pending. Accessed under job_mutex.
64
*
65
* When the job is deferred to the main loop, busy is true as long as the
66
* bottom half is still pending.
67
@@ -XXX,XX +XXX,XX @@ typedef enum JobCreateFlags {
68
69
extern QemuMutex job_mutex;
70
71
-#define JOB_LOCK_GUARD() /* QEMU_LOCK_GUARD(&job_mutex) */
72
+#define JOB_LOCK_GUARD() QEMU_LOCK_GUARD(&job_mutex)
73
74
-#define WITH_JOB_LOCK_GUARD() /* WITH_QEMU_LOCK_GUARD(&job_mutex) */
75
+#define WITH_JOB_LOCK_GUARD() WITH_QEMU_LOCK_GUARD(&job_mutex)
76
77
/**
78
* job_lock:
79
@@ -XXX,XX +XXX,XX @@ void job_ref_locked(Job *job);
80
/**
81
* Release a reference that was previously acquired with job_ref() or
82
* job_create(). If it's the last reference to the object, it will be freed.
83
+ *
84
+ * Takes AioContext lock internally to invoke a job->driver callback.
85
*/
86
void job_unref(Job *job);
87
88
@@ -XXX,XX +XXX,XX @@ void job_user_cancel_locked(Job *job, bool force, Error **errp);
89
* Returns the return value from the job if the job actually completed
90
* during the call, or -ECANCELED if it was canceled.
91
*
92
- * Callers must hold the AioContext lock of job->aio_context.
93
+ * Called with job_lock *not* held.
94
*/
95
int job_cancel_sync(Job *job, bool force);
96
97
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
98
* function).
99
*
100
* Returns the return value from the job.
101
- *
102
- * Callers must hold the AioContext lock of job->aio_context.
103
+ * Called with job_lock *not* held.
104
*/
105
int job_complete_sync(Job *job, Error **errp);
106
107
@@ -XXX,XX +XXX,XX @@ void job_dismiss_locked(Job **job, Error **errp);
108
* Returns 0 if the job is successfully completed, -ECANCELED if the job was
109
* cancelled before completing, and -errno in other error cases.
110
*
111
- * Callers must hold the AioContext lock of job->aio_context.
112
+ * Called with job_lock *not* held.
113
*/
114
int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
115
Error **errp);
18
diff --git a/block/replication.c b/block/replication.c
116
diff --git a/block/replication.c b/block/replication.c
19
index XXXXXXX..XXXXXXX 100644
117
index XXXXXXX..XXXXXXX 100644
20
--- a/block/replication.c
118
--- a/block/replication.c
21
+++ b/block/replication.c
119
+++ b/block/replication.c
22
@@ -XXX,XX +XXX,XX @@ static void backup_job_cleanup(BlockDriverState *bs)
120
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
23
BDRVReplicationState *s = bs->opaque;
121
* disk, secondary disk in backup_job_completed().
24
BlockDriverState *top_bs;
122
*/
25
123
if (s->backup_job) {
26
+ s->backup_job = NULL;
124
+ aio_context_release(aio_context);
125
job_cancel_sync(&s->backup_job->job, true);
126
+ aio_context_acquire(aio_context);
127
}
128
129
if (!failover) {
130
diff --git a/blockdev.c b/blockdev.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/blockdev.c
133
+++ b/blockdev.c
134
@@ -XXX,XX +XXX,XX @@ void blockdev_mark_auto_del(BlockBackend *blk)
135
for (job = block_job_next_locked(NULL); job;
136
job = block_job_next_locked(job)) {
137
if (block_job_has_bdrv(job, blk_bs(blk))) {
138
- AioContext *aio_context = job->job.aio_context;
139
- aio_context_acquire(aio_context);
140
-
141
job_cancel_locked(&job->job, false);
142
-
143
- aio_context_release(aio_context);
144
}
145
}
146
147
@@ -XXX,XX +XXX,XX @@ static void drive_backup_abort(BlkActionState *common)
148
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
149
150
if (state->job) {
151
- AioContext *aio_context;
152
-
153
- aio_context = bdrv_get_aio_context(state->bs);
154
- aio_context_acquire(aio_context);
155
-
156
job_cancel_sync(&state->job->job, true);
157
-
158
- aio_context_release(aio_context);
159
}
160
}
161
162
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_abort(BlkActionState *common)
163
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
164
165
if (state->job) {
166
- AioContext *aio_context;
167
-
168
- aio_context = bdrv_get_aio_context(state->bs);
169
- aio_context_acquire(aio_context);
170
-
171
job_cancel_sync(&state->job->job, true);
172
-
173
- aio_context_release(aio_context);
174
}
175
}
176
177
@@ -XXX,XX +XXX,XX @@ out:
178
}
179
180
/*
181
- * Get a block job using its ID and acquire its AioContext.
182
- * Called with job_mutex held.
183
+ * Get a block job using its ID. Called with job_mutex held.
184
*/
185
-static BlockJob *find_block_job_locked(const char *id,
186
- AioContext **aio_context,
187
- Error **errp)
188
+static BlockJob *find_block_job_locked(const char *id, Error **errp)
189
{
190
BlockJob *job;
191
192
assert(id != NULL);
193
194
- *aio_context = NULL;
195
-
196
job = block_job_get_locked(id);
197
198
if (!job) {
199
@@ -XXX,XX +XXX,XX @@ static BlockJob *find_block_job_locked(const char *id,
200
return NULL;
201
}
202
203
- *aio_context = block_job_get_aio_context(job);
204
- aio_context_acquire(*aio_context);
205
-
206
return job;
207
}
208
209
void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
210
{
211
- AioContext *aio_context;
212
BlockJob *job;
213
214
JOB_LOCK_GUARD();
215
- job = find_block_job_locked(device, &aio_context, errp);
216
+ job = find_block_job_locked(device, errp);
217
218
if (!job) {
219
return;
220
}
221
222
block_job_set_speed_locked(job, speed, errp);
223
- aio_context_release(aio_context);
224
}
225
226
void qmp_block_job_cancel(const char *device,
227
bool has_force, bool force, Error **errp)
228
{
229
- AioContext *aio_context;
230
BlockJob *job;
231
232
JOB_LOCK_GUARD();
233
- job = find_block_job_locked(device, &aio_context, errp);
234
+ job = find_block_job_locked(device, errp);
235
236
if (!job) {
237
return;
238
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_cancel(const char *device,
239
if (job_user_paused_locked(&job->job) && !force) {
240
error_setg(errp, "The block job for device '%s' is currently paused",
241
device);
242
- goto out;
243
+ return;
244
}
245
246
trace_qmp_block_job_cancel(job);
247
job_user_cancel_locked(&job->job, force, errp);
248
-out:
249
- aio_context_release(aio_context);
250
}
251
252
void qmp_block_job_pause(const char *device, Error **errp)
253
{
254
- AioContext *aio_context;
255
BlockJob *job;
256
257
JOB_LOCK_GUARD();
258
- job = find_block_job_locked(device, &aio_context, errp);
259
+ job = find_block_job_locked(device, errp);
260
261
if (!job) {
262
return;
263
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_pause(const char *device, Error **errp)
264
265
trace_qmp_block_job_pause(job);
266
job_user_pause_locked(&job->job, errp);
267
- aio_context_release(aio_context);
268
}
269
270
void qmp_block_job_resume(const char *device, Error **errp)
271
{
272
- AioContext *aio_context;
273
BlockJob *job;
274
275
JOB_LOCK_GUARD();
276
- job = find_block_job_locked(device, &aio_context, errp);
277
+ job = find_block_job_locked(device, errp);
278
279
if (!job) {
280
return;
281
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_resume(const char *device, Error **errp)
282
283
trace_qmp_block_job_resume(job);
284
job_user_resume_locked(&job->job, errp);
285
- aio_context_release(aio_context);
286
}
287
288
void qmp_block_job_complete(const char *device, Error **errp)
289
{
290
- AioContext *aio_context;
291
BlockJob *job;
292
293
JOB_LOCK_GUARD();
294
- job = find_block_job_locked(device, &aio_context, errp);
295
+ job = find_block_job_locked(device, errp);
296
297
if (!job) {
298
return;
299
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_complete(const char *device, Error **errp)
300
301
trace_qmp_block_job_complete(job);
302
job_complete_locked(&job->job, errp);
303
- aio_context_release(aio_context);
304
}
305
306
void qmp_block_job_finalize(const char *id, Error **errp)
307
{
308
- AioContext *aio_context;
309
BlockJob *job;
310
311
JOB_LOCK_GUARD();
312
- job = find_block_job_locked(id, &aio_context, errp);
313
+ job = find_block_job_locked(id, errp);
314
315
if (!job) {
316
return;
317
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_finalize(const char *id, Error **errp)
318
job_ref_locked(&job->job);
319
job_finalize_locked(&job->job, errp);
320
321
- /*
322
- * Job's context might have changed via job_finalize (and job_txn_apply
323
- * automatically acquires the new one), so make sure we release the correct
324
- * one.
325
- */
326
- aio_context = block_job_get_aio_context(job);
327
job_unref_locked(&job->job);
328
- aio_context_release(aio_context);
329
}
330
331
void qmp_block_job_dismiss(const char *id, Error **errp)
332
{
333
- AioContext *aio_context;
334
BlockJob *bjob;
335
Job *job;
336
337
JOB_LOCK_GUARD();
338
- bjob = find_block_job_locked(id, &aio_context, errp);
339
+ bjob = find_block_job_locked(id, errp);
340
341
if (!bjob) {
342
return;
343
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_dismiss(const char *id, Error **errp)
344
trace_qmp_block_job_dismiss(bjob);
345
job = &bjob->job;
346
job_dismiss_locked(&job, errp);
347
- aio_context_release(aio_context);
348
}
349
350
void qmp_change_backing_file(const char *device,
351
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
352
for (job = block_job_next_locked(NULL); job;
353
job = block_job_next_locked(job)) {
354
BlockJobInfo *value;
355
- AioContext *aio_context;
356
357
if (block_job_is_internal(job)) {
358
continue;
359
}
360
- aio_context = block_job_get_aio_context(job);
361
- aio_context_acquire(aio_context);
362
value = block_job_query_locked(job, errp);
363
- aio_context_release(aio_context);
364
if (!value) {
365
qapi_free_BlockJobInfoList(head);
366
return NULL;
367
diff --git a/job-qmp.c b/job-qmp.c
368
index XXXXXXX..XXXXXXX 100644
369
--- a/job-qmp.c
370
+++ b/job-qmp.c
371
@@ -XXX,XX +XXX,XX @@
372
#include "trace/trace-root.h"
373
374
/*
375
- * Get a job using its ID and acquire its AioContext.
376
- * Called with job_mutex held.
377
+ * Get a job using its ID. Called with job_mutex held.
378
*/
379
-static Job *find_job_locked(const char *id,
380
- AioContext **aio_context,
381
- Error **errp)
382
+static Job *find_job_locked(const char *id, Error **errp)
383
{
384
Job *job;
385
386
- *aio_context = NULL;
387
-
388
job = job_get_locked(id);
389
if (!job) {
390
error_setg(errp, "Job not found");
391
return NULL;
392
}
393
394
- *aio_context = job->aio_context;
395
- aio_context_acquire(*aio_context);
396
-
397
return job;
398
}
399
400
void qmp_job_cancel(const char *id, Error **errp)
401
{
402
- AioContext *aio_context;
403
Job *job;
404
405
JOB_LOCK_GUARD();
406
- job = find_job_locked(id, &aio_context, errp);
407
+ job = find_job_locked(id, errp);
408
409
if (!job) {
410
return;
411
@@ -XXX,XX +XXX,XX @@ void qmp_job_cancel(const char *id, Error **errp)
412
413
trace_qmp_job_cancel(job);
414
job_user_cancel_locked(job, true, errp);
415
- aio_context_release(aio_context);
416
}
417
418
void qmp_job_pause(const char *id, Error **errp)
419
{
420
- AioContext *aio_context;
421
Job *job;
422
423
JOB_LOCK_GUARD();
424
- job = find_job_locked(id, &aio_context, errp);
425
+ job = find_job_locked(id, errp);
426
427
if (!job) {
428
return;
429
@@ -XXX,XX +XXX,XX @@ void qmp_job_pause(const char *id, Error **errp)
430
431
trace_qmp_job_pause(job);
432
job_user_pause_locked(job, errp);
433
- aio_context_release(aio_context);
434
}
435
436
void qmp_job_resume(const char *id, Error **errp)
437
{
438
- AioContext *aio_context;
439
Job *job;
440
441
JOB_LOCK_GUARD();
442
- job = find_job_locked(id, &aio_context, errp);
443
+ job = find_job_locked(id, errp);
444
445
if (!job) {
446
return;
447
@@ -XXX,XX +XXX,XX @@ void qmp_job_resume(const char *id, Error **errp)
448
449
trace_qmp_job_resume(job);
450
job_user_resume_locked(job, errp);
451
- aio_context_release(aio_context);
452
}
453
454
void qmp_job_complete(const char *id, Error **errp)
455
{
456
- AioContext *aio_context;
457
Job *job;
458
459
JOB_LOCK_GUARD();
460
- job = find_job_locked(id, &aio_context, errp);
461
+ job = find_job_locked(id, errp);
462
463
if (!job) {
464
return;
465
@@ -XXX,XX +XXX,XX @@ void qmp_job_complete(const char *id, Error **errp)
466
467
trace_qmp_job_complete(job);
468
job_complete_locked(job, errp);
469
- aio_context_release(aio_context);
470
}
471
472
void qmp_job_finalize(const char *id, Error **errp)
473
{
474
- AioContext *aio_context;
475
Job *job;
476
477
JOB_LOCK_GUARD();
478
- job = find_job_locked(id, &aio_context, errp);
479
+ job = find_job_locked(id, errp);
480
481
if (!job) {
482
return;
483
@@ -XXX,XX +XXX,XX @@ void qmp_job_finalize(const char *id, Error **errp)
484
job_ref_locked(job);
485
job_finalize_locked(job, errp);
486
487
- /*
488
- * Job's context might have changed via job_finalize (and job_txn_apply
489
- * automatically acquires the new one), so make sure we release the correct
490
- * one.
491
- */
492
- aio_context = job->aio_context;
493
job_unref_locked(job);
494
- aio_context_release(aio_context);
495
}
496
497
void qmp_job_dismiss(const char *id, Error **errp)
498
{
499
- AioContext *aio_context;
500
Job *job;
501
502
JOB_LOCK_GUARD();
503
- job = find_job_locked(id, &aio_context, errp);
504
+ job = find_job_locked(id, errp);
505
506
if (!job) {
507
return;
508
@@ -XXX,XX +XXX,XX @@ void qmp_job_dismiss(const char *id, Error **errp)
509
510
trace_qmp_job_dismiss(job);
511
job_dismiss_locked(&job, errp);
512
- aio_context_release(aio_context);
513
}
514
515
/* Called with job_mutex held. */
516
@@ -XXX,XX +XXX,XX @@ JobInfoList *qmp_query_jobs(Error **errp)
517
518
for (job = job_next_locked(NULL); job; job = job_next_locked(job)) {
519
JobInfo *value;
520
- AioContext *aio_context;
521
522
if (job_is_internal(job)) {
523
continue;
524
}
525
- aio_context = job->aio_context;
526
- aio_context_acquire(aio_context);
527
value = job_query_single_locked(job, errp);
528
- aio_context_release(aio_context);
529
if (!value) {
530
qapi_free_JobInfoList(head);
531
return NULL;
532
diff --git a/job.c b/job.c
533
index XXXXXXX..XXXXXXX 100644
534
--- a/job.c
535
+++ b/job.c
536
@@ -XXX,XX +XXX,XX @@
537
*
538
* The second includes functions used by the job drivers and sometimes
539
* by the core block layer. These delegate the locking to the callee instead.
540
- *
541
- * TODO Actually make this true
542
*/
543
544
/*
545
@@ -XXX,XX +XXX,XX @@ struct JobTxn {
546
};
547
548
void job_lock(void)
549
-{
550
- /* nop */
551
-}
552
-
553
-void job_unlock(void)
554
-{
555
- /* nop */
556
-}
557
-
558
-static void real_job_lock(void)
559
{
560
qemu_mutex_lock(&job_mutex);
561
}
562
563
-static void real_job_unlock(void)
564
+void job_unlock(void)
565
{
566
qemu_mutex_unlock(&job_mutex);
567
}
568
@@ -XXX,XX +XXX,XX @@ static void job_txn_del_job_locked(Job *job)
569
/* Called with job_mutex held, but releases it temporarily. */
570
static int job_txn_apply_locked(Job *job, int fn(Job *))
571
{
572
- AioContext *inner_ctx;
573
Job *other_job, *next;
574
JobTxn *txn = job->txn;
575
int rc = 0;
576
@@ -XXX,XX +XXX,XX @@ static int job_txn_apply_locked(Job *job, int fn(Job *))
577
* break AIO_WAIT_WHILE from within fn.
578
*/
579
job_ref_locked(job);
580
- aio_context_release(job->aio_context);
581
582
QLIST_FOREACH_SAFE(other_job, &txn->jobs, txn_list, next) {
583
- inner_ctx = other_job->aio_context;
584
- aio_context_acquire(inner_ctx);
585
rc = fn(other_job);
586
- aio_context_release(inner_ctx);
587
if (rc) {
588
break;
589
}
590
}
591
592
- /*
593
- * Note that job->aio_context might have been changed by calling fn, so we
594
- * can't use a local variable to cache it.
595
- */
596
- aio_context_acquire(job->aio_context);
597
job_unref_locked(job);
598
return rc;
599
}
600
@@ -XXX,XX +XXX,XX @@ void job_unref_locked(Job *job)
601
assert(!job->txn);
602
603
if (job->driver->free) {
604
+ AioContext *aio_context = job->aio_context;
605
job_unlock();
606
+ /* FIXME: aiocontext lock is required because cb calls blk_unref */
607
+ aio_context_acquire(aio_context);
608
job->driver->free(job);
609
+ aio_context_release(aio_context);
610
job_lock();
611
}
612
613
@@ -XXX,XX +XXX,XX @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
614
return;
615
}
616
617
- real_job_lock();
618
if (job->busy) {
619
- real_job_unlock();
620
return;
621
}
622
623
if (fn && !fn(job)) {
624
- real_job_unlock();
625
return;
626
}
627
628
assert(!job->deferred_to_main_loop);
629
timer_del(&job->sleep_timer);
630
job->busy = true;
631
- real_job_unlock();
632
job_unlock();
633
aio_co_wake(job->co);
634
job_lock();
635
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
636
{
637
AioContext *next_aio_context;
638
639
- real_job_lock();
640
if (ns != -1) {
641
timer_mod(&job->sleep_timer, ns);
642
}
643
job->busy = false;
644
job_event_idle_locked(job);
645
- real_job_unlock();
646
job_unlock();
647
qemu_coroutine_yield();
648
job_lock();
649
@@ -XXX,XX +XXX,XX @@ static void job_clean(Job *job)
650
}
651
}
652
653
-/* Called with job_mutex held, but releases it temporarily */
654
+/*
655
+ * Called with job_mutex held, but releases it temporarily.
656
+ * Takes AioContext lock internally to invoke a job->driver callback.
657
+ */
658
static int job_finalize_single_locked(Job *job)
659
{
660
int job_ret;
661
+ AioContext *ctx = job->aio_context;
662
663
assert(job_is_completed_locked(job));
664
665
@@ -XXX,XX +XXX,XX @@ static int job_finalize_single_locked(Job *job)
666
667
job_ret = job->ret;
668
job_unlock();
669
+ aio_context_acquire(ctx);
670
671
if (!job_ret) {
672
job_commit(job);
673
@@ -XXX,XX +XXX,XX @@ static int job_finalize_single_locked(Job *job)
674
}
675
job_clean(job);
676
677
- job_lock();
678
-
679
if (job->cb) {
680
- job_ret = job->ret;
681
- job_unlock();
682
job->cb(job->opaque, job_ret);
683
- job_lock();
684
}
685
686
+ aio_context_release(ctx);
687
+ job_lock();
27
+
688
+
28
top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL);
689
/* Emit events only if we actually started */
29
if (!top_bs) {
690
if (job_started_locked(job)) {
30
return;
691
if (job_is_cancelled_locked(job)) {
692
@@ -XXX,XX +XXX,XX @@ static int job_finalize_single_locked(Job *job)
693
return 0;
694
}
695
696
-/* Called with job_mutex held, but releases it temporarily */
697
+/*
698
+ * Called with job_mutex held, but releases it temporarily.
699
+ * Takes AioContext lock internally to invoke a job->driver callback.
700
+ */
701
static void job_cancel_async_locked(Job *job, bool force)
702
{
703
+ AioContext *ctx = job->aio_context;
704
GLOBAL_STATE_CODE();
705
if (job->driver->cancel) {
706
job_unlock();
707
+ aio_context_acquire(ctx);
708
force = job->driver->cancel(job, force);
709
+ aio_context_release(ctx);
710
job_lock();
711
} else {
712
/* No .cancel() means the job will behave as if force-cancelled */
713
@@ -XXX,XX +XXX,XX @@ static void job_cancel_async_locked(Job *job, bool force)
714
}
715
}
716
717
-/* Called with job_mutex held, but releases it temporarily. */
718
+/*
719
+ * Called with job_mutex held, but releases it temporarily.
720
+ * Takes AioContext lock internally to invoke a job->driver callback.
721
+ */
722
static void job_completed_txn_abort_locked(Job *job)
723
{
724
- AioContext *ctx;
725
JobTxn *txn = job->txn;
726
Job *other_job;
727
728
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort_locked(Job *job)
729
txn->aborting = true;
730
job_txn_ref_locked(txn);
731
732
- /*
733
- * We can only hold the single job's AioContext lock while calling
734
- * job_finalize_single() because the finalization callbacks can involve
735
- * calls of AIO_WAIT_WHILE(), which could deadlock otherwise.
736
- * Note that the job's AioContext may change when it is finalized.
737
- */
738
job_ref_locked(job);
739
- aio_context_release(job->aio_context);
740
741
/* Other jobs are effectively cancelled by us, set the status for
742
* them; this job, however, may or may not be cancelled, depending
743
* on the caller, so leave it. */
744
QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
745
if (other_job != job) {
746
- ctx = other_job->aio_context;
747
- aio_context_acquire(ctx);
748
/*
749
* This is a transaction: If one job failed, no result will matter.
750
* Therefore, pass force=true to terminate all other jobs as quickly
751
* as possible.
752
*/
753
job_cancel_async_locked(other_job, true);
754
- aio_context_release(ctx);
755
}
756
}
757
while (!QLIST_EMPTY(&txn->jobs)) {
758
other_job = QLIST_FIRST(&txn->jobs);
759
- /*
760
- * The job's AioContext may change, so store it in @ctx so we
761
- * release the same context that we have acquired before.
762
- */
763
- ctx = other_job->aio_context;
764
- aio_context_acquire(ctx);
765
if (!job_is_completed_locked(other_job)) {
766
assert(job_cancel_requested_locked(other_job));
767
job_finish_sync_locked(other_job, NULL, NULL);
768
}
769
job_finalize_single_locked(other_job);
770
- aio_context_release(ctx);
771
}
772
773
- /*
774
- * Use job_ref()/job_unref() so we can read the AioContext here
775
- * even if the job went away during job_finalize_single().
776
- */
777
- aio_context_acquire(job->aio_context);
778
job_unref_locked(job);
779
-
780
job_txn_unref_locked(txn);
781
}
782
783
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort_locked(Job *job)
784
static int job_prepare_locked(Job *job)
785
{
786
int ret;
787
+ AioContext *ctx = job->aio_context;
788
789
GLOBAL_STATE_CODE();
790
+
791
if (job->ret == 0 && job->driver->prepare) {
792
job_unlock();
793
+ aio_context_acquire(ctx);
794
ret = job->driver->prepare(job);
795
+ aio_context_release(ctx);
796
job_lock();
797
job->ret = ret;
798
job_update_rc_locked(job);
799
}
800
+
801
return job->ret;
802
}
803
804
@@ -XXX,XX +XXX,XX @@ static void job_completed_locked(Job *job)
805
static void job_exit(void *opaque)
806
{
807
Job *job = (Job *)opaque;
808
- AioContext *ctx;
809
JOB_LOCK_GUARD();
810
-
811
job_ref_locked(job);
812
- aio_context_acquire(job->aio_context);
813
814
/* This is a lie, we're not quiescent, but still doing the completion
815
* callbacks. However, completion callbacks tend to involve operations that
816
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
817
job_event_idle_locked(job);
818
819
job_completed_locked(job);
820
-
821
- /*
822
- * Note that calling job_completed can move the job to a different
823
- * aio_context, so we cannot cache from above. job_txn_apply takes care of
824
- * acquiring the new lock, and we ref/unref to avoid job_completed freeing
825
- * the job underneath us.
826
- */
827
- ctx = job->aio_context;
828
job_unref_locked(job);
829
- aio_context_release(ctx);
830
}
831
832
/**
833
@@ -XXX,XX +XXX,XX @@ int job_cancel_sync(Job *job, bool force)
834
void job_cancel_sync_all(void)
835
{
836
Job *job;
837
- AioContext *aio_context;
838
JOB_LOCK_GUARD();
839
840
while ((job = job_next_locked(NULL))) {
841
- aio_context = job->aio_context;
842
- aio_context_acquire(aio_context);
843
job_cancel_sync_locked(job, true);
844
- aio_context_release(aio_context);
845
}
846
}
847
848
@@ -XXX,XX +XXX,XX @@ int job_finish_sync_locked(Job *job,
849
}
850
851
job_unlock();
852
- AIO_WAIT_WHILE(job->aio_context,
853
- (job_enter(job), !job_is_completed(job)));
854
+ AIO_WAIT_WHILE_UNLOCKED(job->aio_context,
855
+ (job_enter(job), !job_is_completed(job)));
856
job_lock();
857
858
ret = (job_is_cancelled_locked(job) && job->ret == 0)
859
diff --git a/qemu-img.c b/qemu-img.c
860
index XXXXXXX..XXXXXXX 100644
861
--- a/qemu-img.c
862
+++ b/qemu-img.c
863
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
864
AioContext *aio_context = block_job_get_aio_context(job);
865
int ret = 0;
866
867
- aio_context_acquire(aio_context);
868
job_lock();
869
job_ref_locked(&job->job);
870
do {
871
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
872
}
873
job_unref_locked(&job->job);
874
job_unlock();
875
- aio_context_release(aio_context);
876
877
/* publish completion progress only when success */
878
if (!ret) {
879
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
880
index XXXXXXX..XXXXXXX 100644
881
--- a/tests/unit/test-bdrv-drain.c
882
+++ b/tests/unit/test-bdrv-drain.c
883
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
884
tjob->prepare_ret = -EIO;
885
break;
886
}
887
+ aio_context_release(ctx);
888
889
job_start(&job->job);
890
- aio_context_release(ctx);
891
892
if (use_iothread) {
893
/* job_co_entry() is run in the I/O thread, wait for the actual job
894
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
895
g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
896
}
897
898
- aio_context_acquire(ctx);
899
WITH_JOB_LOCK_GUARD() {
900
ret = job_complete_sync_locked(&job->job, &error_abort);
901
}
902
g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO));
903
904
+ aio_context_acquire(ctx);
905
if (use_iothread) {
906
blk_set_aio_context(blk_src, qemu_get_aio_context(), &error_abort);
907
assert(blk_get_aio_context(blk_target) == qemu_get_aio_context());
908
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
909
index XXXXXXX..XXXXXXX 100644
910
--- a/tests/unit/test-block-iothread.c
911
+++ b/tests/unit/test-block-iothread.c
912
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
913
aio_poll(qemu_get_aio_context(), false);
914
}
915
916
- aio_context_acquire(ctx);
917
WITH_JOB_LOCK_GUARD() {
918
job_complete_sync_locked(&tjob->common.job, &error_abort);
919
}
920
+ aio_context_acquire(ctx);
921
blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
922
aio_context_release(ctx);
923
924
diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c
925
index XXXXXXX..XXXXXXX 100644
926
--- a/tests/unit/test-blockjob.c
927
+++ b/tests/unit/test-blockjob.c
928
@@ -XXX,XX +XXX,XX @@ static void cancel_common(CancelJob *s)
929
BlockJob *job = &s->common;
930
BlockBackend *blk = s->blk;
931
JobStatus sts = job->job.status;
932
- AioContext *ctx;
933
-
934
- ctx = job->job.aio_context;
935
- aio_context_acquire(ctx);
936
+ AioContext *ctx = job->job.aio_context;
937
938
job_cancel_sync(&job->job, true);
939
WITH_JOB_LOCK_GUARD() {
940
@@ -XXX,XX +XXX,XX @@ static void cancel_common(CancelJob *s)
941
assert(job->job.status == JOB_STATUS_NULL);
942
job_unref_locked(&job->job);
943
}
944
- destroy_blk(blk);
945
946
+ aio_context_acquire(ctx);
947
+ destroy_blk(blk);
948
aio_context_release(ctx);
949
+
950
}
951
952
static void test_cancel_created(void)
953
@@ -XXX,XX +XXX,XX @@ static void test_cancel_concluded(void)
954
aio_poll(qemu_get_aio_context(), true);
955
assert_job_status_is(job, JOB_STATUS_PENDING);
956
957
- aio_context_acquire(job->aio_context);
958
WITH_JOB_LOCK_GUARD() {
959
job_finalize_locked(job, &error_abort);
960
+ assert(job->status == JOB_STATUS_CONCLUDED);
961
}
962
- aio_context_release(job->aio_context);
963
- assert_job_status_is(job, JOB_STATUS_CONCLUDED);
964
965
cancel_common(s);
966
}
967
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
968
969
/* Wait for the job to become READY */
970
job_start(job);
971
- aio_context_acquire(ctx);
972
/*
973
* Here we are waiting for the status to change, so don't bother
974
* protecting the read every time.
975
*/
976
- AIO_WAIT_WHILE(ctx, job->status != JOB_STATUS_READY);
977
- aio_context_release(ctx);
978
+ AIO_WAIT_WHILE_UNLOCKED(ctx, job->status != JOB_STATUS_READY);
979
980
/* Begin the drained section, pausing the job */
981
bdrv_drain_all_begin();
982
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
983
aio_context_acquire(ctx);
984
/* This will schedule the job to resume it */
985
bdrv_drain_all_end();
986
+ aio_context_release(ctx);
987
988
WITH_JOB_LOCK_GUARD() {
989
/* But the job cannot run, so it will remain on standby */
990
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
991
job_dismiss_locked(&job, &error_abort);
992
}
993
994
+ aio_context_acquire(ctx);
995
destroy_blk(blk);
996
aio_context_release(ctx);
997
iothread_join(iothread);
31
--
998
--
32
2.25.4
999
2.37.3
33
34
diff view generated by jsdifflib
1
We made sure that iotests.py passes pylint. It would be a shame if we
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
allowed new patches in that break this again, so let's just add a
3
meta-test case that runs pylint on it.
4
2
5
While we don't pass mypy --strict yet, we can already run it with a few
3
Not sure what the atomic here was supposed to do, since job.busy
6
options that would be part of --strict to make sure that we won't
4
is protected by the job lock. Since the whole function
7
regress on these aspects at least until we can enable the full thing.
5
is called under job_mutex, just remove the atomic.
8
6
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Message-Id: <20200511163529.349329-3-kwolf@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Message-Id: <20220926093214.506243-20-eesposit@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
tests/qemu-iotests/297 | 44 ++++++++++++++++++++++++++++++++++++++
14
blockjob.c | 2 +-
16
tests/qemu-iotests/297.out | 3 +++
15
1 file changed, 1 insertion(+), 1 deletion(-)
17
tests/qemu-iotests/group | 1 +
18
3 files changed, 48 insertions(+)
19
create mode 100755 tests/qemu-iotests/297
20
create mode 100644 tests/qemu-iotests/297.out
21
16
22
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
17
diff --git a/blockjob.c b/blockjob.c
23
new file mode 100755
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/tests/qemu-iotests/297
27
@@ -XXX,XX +XXX,XX @@
28
+#!/usr/bin/env bash
29
+#
30
+# Copyright (C) 2020 Red Hat, Inc.
31
+#
32
+# This program is free software; you can redistribute it and/or modify
33
+# it under the terms of the GNU General Public License as published by
34
+# the Free Software Foundation; either version 2 of the License, or
35
+# (at your option) any later version.
36
+#
37
+# This program is distributed in the hope that it will be useful,
38
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
39
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40
+# GNU General Public License for more details.
41
+#
42
+# You should have received a copy of the GNU General Public License
43
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
44
+
45
+seq=$(basename $0)
46
+echo "QA output created by $seq"
47
+
48
+status=1    # failure is the default!
49
+
50
+# get standard environment
51
+. ./common.rc
52
+
53
+if ! type -p "pylint-3" > /dev/null; then
54
+ _notrun "pylint-3 not found"
55
+fi
56
+if ! type -p "mypy" > /dev/null; then
57
+ _notrun "mypy not found"
58
+fi
59
+
60
+pylint-3 --score=n iotests.py
61
+
62
+MYPYPATH=../../python/ mypy --warn-unused-configs --disallow-subclassing-any \
63
+ --disallow-any-generics --disallow-incomplete-defs \
64
+ --disallow-untyped-decorators --no-implicit-optional \
65
+ --warn-redundant-casts --warn-unused-ignores \
66
+ --no-implicit-reexport iotests.py
67
+
68
+# success, all done
69
+echo "*** done"
70
+rm -f $seq.full
71
+status=0
72
diff --git a/tests/qemu-iotests/297.out b/tests/qemu-iotests/297.out
73
new file mode 100644
74
index XXXXXXX..XXXXXXX
75
--- /dev/null
76
+++ b/tests/qemu-iotests/297.out
77
@@ -XXX,XX +XXX,XX @@
78
+QA output created by 297
79
+Success: no issues found in 1 source file
80
+*** done
81
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
82
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
83
--- a/tests/qemu-iotests/group
19
--- a/blockjob.c
84
+++ b/tests/qemu-iotests/group
20
+++ b/blockjob.c
85
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
86
289 rw quick
22
info = g_new0(BlockJobInfo, 1);
87
290 rw auto quick
23
info->type = g_strdup(job_type_str(&job->job));
88
292 rw auto quick
24
info->device = g_strdup(job->job.id);
89
+297 meta
25
- info->busy = qatomic_read(&job->job.busy);
26
+ info->busy = job->job.busy;
27
info->paused = job->job.pause_count > 0;
28
info->offset = progress_current;
29
info->len = progress_total;
90
--
30
--
91
2.25.4
31
2.37.3
92
93
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
These public functions are not used anywhere, thus can be dropped.
4
Message-Id: <20200513110544.176672-25-mreitz@redhat.com>
4
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
Message-Id: <20220926093214.506243-21-eesposit@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
11
---
8
include/block/block_int.h | 1 -
12
include/block/blockjob.h | 31 ++++++++++++-------------------
9
block.c | 60 ++-------------------------------------
13
blockjob.c | 16 ++--------------
10
2 files changed, 3 insertions(+), 58 deletions(-)
14
2 files changed, 14 insertions(+), 33 deletions(-)
11
15
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
16
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/include/block/block_int.h
18
--- a/include/block/blockjob.h
15
+++ b/include/block/block_int.h
19
+++ b/include/block/blockjob.h
16
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
20
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJob {
17
21
*/
18
extern const BdrvChildClass child_of_bds;
22
19
extern const BdrvChildClass child_file;
23
/**
20
-extern const BdrvChildClass child_backing;
24
- * block_job_next:
21
25
+ * block_job_next_locked:
22
struct BdrvChild {
26
* @job: A block job, or %NULL.
23
BlockDriverState *bs;
27
*
24
diff --git a/block.c b/block.c
28
* Get the next element from the list of block jobs after @job, or the
29
* first one if @job is %NULL.
30
*
31
* Returns the requested job, or %NULL if there are no more jobs left.
32
+ * Called with job lock held.
33
*/
34
-BlockJob *block_job_next(BlockJob *job);
35
-
36
-/* Same as block_job_next(), but called with job lock held. */
37
BlockJob *block_job_next_locked(BlockJob *job);
38
39
/**
40
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_next_locked(BlockJob *job);
41
* Get the block job identified by @id (which must not be %NULL).
42
*
43
* Returns the requested job, or %NULL if it doesn't exist.
44
+ * Called with job lock *not* held.
45
*/
46
BlockJob *block_job_get(const char *id);
47
48
@@ -XXX,XX +XXX,XX @@ void block_job_remove_all_bdrv(BlockJob *job);
49
bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs);
50
51
/**
52
- * block_job_set_speed:
53
+ * block_job_set_speed_locked:
54
* @job: The job to set the speed for.
55
* @speed: The new value
56
* @errp: Error object.
57
*
58
* Set a rate-limiting parameter for the job; the actual meaning may
59
* vary depending on the job type.
60
- */
61
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
62
-
63
-/*
64
- * Same as block_job_set_speed(), but called with job lock held.
65
- * Might release the lock temporarily.
66
+ *
67
+ * Called with job lock held, but might release it temporarily.
68
*/
69
bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp);
70
71
/**
72
- * block_job_query:
73
+ * block_job_query_locked:
74
* @job: The job to get information about.
75
*
76
* Return information about a job.
77
+ *
78
+ * Called with job lock held.
79
*/
80
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
81
-
82
-/* Same as block_job_query(), but called with job lock held. */
83
BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp);
84
85
/**
86
- * block_job_iostatus_reset:
87
+ * block_job_iostatus_reset_locked:
88
* @job: The job whose I/O status should be reset.
89
*
90
* Reset I/O status on @job and on BlockDriverState objects it uses,
91
* other than job->blk.
92
+ *
93
+ * Called with job lock held.
94
*/
95
-void block_job_iostatus_reset(BlockJob *job);
96
-
97
-/* Same as block_job_iostatus_reset(), but called with job lock held. */
98
void block_job_iostatus_reset_locked(BlockJob *job);
99
100
/*
101
diff --git a/blockjob.c b/blockjob.c
25
index XXXXXXX..XXXXXXX 100644
102
index XXXXXXX..XXXXXXX 100644
26
--- a/block.c
103
--- a/blockjob.c
27
+++ b/block.c
104
+++ b/blockjob.c
28
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
105
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_next_locked(BlockJob *bjob)
29
parent->backing_blocker);
106
return job ? container_of(job, BlockJob, job) : NULL;
30
}
107
}
31
108
32
-/* XXX: Will be removed along with child_backing */
109
-BlockJob *block_job_next(BlockJob *bjob)
33
-static void bdrv_child_cb_attach_backing(BdrvChild *c)
34
-{
110
-{
35
- if (!(c->role & BDRV_CHILD_COW)) {
111
- JOB_LOCK_GUARD();
36
- bdrv_backing_attach(c);
112
- return block_job_next_locked(bjob);
37
- }
38
- bdrv_child_cb_attach(c);
39
-}
113
-}
40
-
114
-
41
static void bdrv_backing_detach(BdrvChild *c)
115
BlockJob *block_job_get_locked(const char *id)
42
{
116
{
43
BlockDriverState *parent = c->opaque;
117
Job *job = job_get_locked(id);
44
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
118
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp)
45
parent->backing_blocker = NULL;
119
return true;
46
}
120
}
47
121
48
-/* XXX: Will be removed along with child_backing */
122
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
49
-static void bdrv_child_cb_detach_backing(BdrvChild *c)
123
+static bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
124
{
125
JOB_LOCK_GUARD();
126
return block_job_set_speed_locked(job, speed, errp);
127
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
128
return info;
129
}
130
131
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
50
-{
132
-{
51
- if (!(c->role & BDRV_CHILD_COW)) {
133
- JOB_LOCK_GUARD();
52
- bdrv_backing_detach(c);
134
- return block_job_query_locked(job, errp);
53
- }
54
- bdrv_child_cb_detach(c);
55
-}
135
-}
56
-
136
-
57
-/*
137
/* Called with job lock held */
58
- * Returns the options and flags that bs->backing should get, based on the
138
static void block_job_iostatus_set_err_locked(BlockJob *job, int error)
59
- * given options and flags for the parent BDS
60
- */
61
-static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format,
62
- int *child_flags, QDict *child_options,
63
- int parent_flags, QDict *parent_options)
64
-{
65
- bdrv_inherited_options(BDRV_CHILD_COW, true,
66
- child_flags, child_options,
67
- parent_flags, parent_options);
68
-}
69
-
70
static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
71
const char *filename, Error **errp)
72
{
139
{
73
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
140
@@ -XXX,XX +XXX,XX @@ void block_job_iostatus_reset_locked(BlockJob *job)
74
return ret;
141
job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
75
}
142
}
76
143
77
-const BdrvChildClass child_backing = {
144
-void block_job_iostatus_reset(BlockJob *job)
78
- .parent_is_bds = true,
145
+static void block_job_iostatus_reset(BlockJob *job)
79
- .get_parent_desc = bdrv_child_get_parent_desc,
80
- .attach = bdrv_child_cb_attach_backing,
81
- .detach = bdrv_child_cb_detach_backing,
82
- .inherit_options = bdrv_backing_options,
83
- .drained_begin = bdrv_child_cb_drained_begin,
84
- .drained_poll = bdrv_child_cb_drained_poll,
85
- .drained_end = bdrv_child_cb_drained_end,
86
- .inactivate = bdrv_child_cb_inactivate,
87
- .update_filename = bdrv_backing_update_filename,
88
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
89
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
90
-};
91
-
92
/*
93
* Returns the options and flags that a generic child of a BDS should
94
* get, based on the given options and flags for the parent BDS.
95
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
96
uint64_t perm, uint64_t shared,
97
uint64_t *nperm, uint64_t *nshared)
98
{
146
{
99
- assert(child_class == &child_backing ||
147
JOB_LOCK_GUARD();
100
- (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
148
block_job_iostatus_reset_locked(job);
101
+ assert(child_class == &child_of_bds && (role & BDRV_CHILD_COW));
102
103
/*
104
* We want consistent read from backing files if the parent needs it.
105
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
106
uint64_t perm, uint64_t shared,
107
uint64_t *nperm, uint64_t *nshared)
108
{
109
- bool backing = (child_class == &child_backing);
110
-
111
if (child_class == &child_of_bds) {
112
bdrv_default_perms(bs, c, child_class, role, reopen_queue,
113
perm, shared, nperm, nshared);
114
return;
115
}
116
117
- assert(child_class == &child_backing || child_class == &child_file);
118
+ assert(child_class == &child_file);
119
120
- if (!backing) {
121
- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
122
- perm, shared, nperm, nshared);
123
- } else {
124
- bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
125
+ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
126
perm, shared, nperm, nshared);
127
- }
128
}
129
130
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
131
--
149
--
132
2.25.4
150
2.37.3
133
134
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
For now, all callers (effectively) pass 0 and no callee evaluates thie
3
These public functions are not used anywhere, thus can be dropped.
4
value. Later patches will change both.
4
Also, since this is the final job API that doesn't use AioContext
5
lock and replaces it with job_lock, adjust all remaining function
6
documentation to clearly specify if the job lock is taken or not.
5
7
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Also document the locking requirements for a few functions
7
Reviewed-by: Eric Blake <eblake@redhat.com>
9
where the second version is not removed.
8
Message-Id: <20200513110544.176672-8-mreitz@redhat.com>
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20220926093214.506243-22-eesposit@redhat.com>
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
17
---
11
include/block/block_int.h | 3 ++-
18
include/qemu/job.h | 110 +++++++++++++------------------------
12
block.c | 40 +++++++++++++++++++++++----------------
19
job.c | 107 ++----------------------------------
13
block/block-backend.c | 3 ++-
20
tests/unit/test-blockjob.c | 4 +-
14
block/vvfat.c | 3 ++-
21
3 files changed, 46 insertions(+), 175 deletions(-)
15
4 files changed, 30 insertions(+), 19 deletions(-)
16
22
17
diff --git a/include/block/block_int.h b/include/block/block_int.h
23
diff --git a/include/qemu/job.h b/include/qemu/job.h
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block_int.h
25
--- a/include/qemu/job.h
20
+++ b/include/block/block_int.h
26
+++ b/include/qemu/job.h
21
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
27
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void);
22
* non-BDS parents. */
28
/**
23
bool parent_is_bds;
29
* Release a reference that was previously acquired with job_txn_add_job or
24
30
* job_txn_new. If it's the last reference to the object, it will be freed.
25
- void (*inherit_options)(int *child_flags, QDict *child_options,
31
+ *
26
+ void (*inherit_options)(BdrvChildRole role,
32
+ * Called with job lock *not* held.
27
+ int *child_flags, QDict *child_options,
33
*/
28
int parent_flags, QDict *parent_options);
34
void job_txn_unref(JobTxn *txn);
29
35
30
void (*change_media)(BdrvChild *child, bool load);
36
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
31
diff --git a/block.c b/block.c
37
/**
38
* Add a reference to Job refcnt, it will be decreased with job_unref, and then
39
* be freed if it comes to be the last reference.
40
+ *
41
+ * Called with job lock held.
42
*/
43
-void job_ref(Job *job);
44
-
45
-/* Same as job_ref(), but called with job lock held. */
46
void job_ref_locked(Job *job);
47
48
/**
49
- * Release a reference that was previously acquired with job_ref() or
50
+ * Release a reference that was previously acquired with job_ref_locked() or
51
* job_create(). If it's the last reference to the object, it will be freed.
52
*
53
* Takes AioContext lock internally to invoke a job->driver callback.
54
+ * Called with job lock held.
55
*/
56
-void job_unref(Job *job);
57
-
58
-/* Same as job_unref(), but called with job lock held. */
59
void job_unref_locked(Job *job);
60
61
/**
62
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta);
63
* Conditionally enter the job coroutine if the job is ready to run, not
64
* already busy and fn() returns true. fn() is called while under the job_lock
65
* critical section.
66
- */
67
-void job_enter_cond(Job *job, bool(*fn)(Job *job));
68
-
69
-/*
70
- * Same as job_enter_cond(), but called with job lock held.
71
- * Might release the lock temporarily.
72
+ *
73
+ * Called with job lock held, but might release it temporarily.
74
*/
75
void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
76
77
@@ -XXX,XX +XXX,XX @@ bool job_cancel_requested(Job *job);
78
79
/**
80
* Returns whether the job is in a completed state.
81
- * Called with job_mutex *not* held.
82
+ * Called with job lock held.
83
*/
84
-bool job_is_completed(Job *job);
85
-
86
-/* Same as job_is_completed(), but called with job lock held. */
87
bool job_is_completed_locked(Job *job);
88
89
/**
90
@@ -XXX,XX +XXX,XX @@ bool job_is_ready_locked(Job *job);
91
/**
92
* Request @job to pause at the next pause point. Must be paired with
93
* job_resume(). If the job is supposed to be resumed by user action, call
94
- * job_user_pause() instead.
95
+ * job_user_pause_locked() instead.
96
+ *
97
+ * Called with job lock *not* held.
98
*/
99
void job_pause(Job *job);
100
101
/* Same as job_pause(), but called with job lock held. */
102
void job_pause_locked(Job *job);
103
104
-/** Resumes a @job paused with job_pause. */
105
+/** Resumes a @job paused with job_pause. Called with job lock *not* held. */
106
void job_resume(Job *job);
107
108
/*
109
@@ -XXX,XX +XXX,XX @@ void job_resume_locked(Job *job);
110
/**
111
* Asynchronously pause the specified @job.
112
* Do not allow a resume until a matching call to job_user_resume.
113
+ * Called with job lock held.
114
*/
115
-void job_user_pause(Job *job, Error **errp);
116
-
117
-/* Same as job_user_pause(), but called with job lock held. */
118
void job_user_pause_locked(Job *job, Error **errp);
119
120
-/** Returns true if the job is user-paused. */
121
-bool job_user_paused(Job *job);
122
-
123
-/* Same as job_user_paused(), but called with job lock held. */
124
+/**
125
+ * Returns true if the job is user-paused.
126
+ * Called with job lock held.
127
+ */
128
bool job_user_paused_locked(Job *job);
129
130
/**
131
* Resume the specified @job.
132
- * Must be paired with a preceding job_user_pause.
133
- */
134
-void job_user_resume(Job *job, Error **errp);
135
-
136
-/*
137
- * Same as job_user_resume(), but called with job lock held.
138
- * Might release the lock temporarily.
139
+ * Must be paired with a preceding job_user_pause_locked.
140
+ * Called with job lock held, but might release it temporarily.
141
*/
142
void job_user_resume_locked(Job *job, Error **errp);
143
144
@@ -XXX,XX +XXX,XX @@ void job_user_resume_locked(Job *job, Error **errp);
145
* first one if @job is %NULL.
146
*
147
* Returns the requested job, or %NULL if there are no more jobs left.
148
+ * Called with job lock *not* held.
149
*/
150
Job *job_next(Job *job);
151
152
@@ -XXX,XX +XXX,XX @@ Job *job_next_locked(Job *job);
153
* Get the job identified by @id (which must not be %NULL).
154
*
155
* Returns the requested job, or %NULL if it doesn't exist.
156
+ * Called with job lock held.
157
*/
158
-Job *job_get(const char *id);
159
-
160
-/* Same as job_get(), but called with job lock held. */
161
Job *job_get_locked(const char *id);
162
163
/**
164
* Check whether the verb @verb can be applied to @job in its current state.
165
* Returns 0 if the verb can be applied; otherwise errp is set and -EPERM
166
* returned.
167
+ *
168
+ * Called with job lock held.
169
*/
170
-int job_apply_verb(Job *job, JobVerb verb, Error **errp);
171
-
172
-/* Same as job_apply_verb, but called with job lock held. */
173
int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp);
174
175
/**
176
@@ -XXX,XX +XXX,XX @@ void job_early_fail(Job *job);
177
*/
178
void job_transition_to_ready(Job *job);
179
180
-/** Asynchronously complete the specified @job. */
181
-void job_complete(Job *job, Error **errp);
182
-
183
-/*
184
- * Same as job_complete(), but called with job lock held.
185
- * Might release the lock temporarily.
186
+/**
187
+ * Asynchronously complete the specified @job.
188
+ * Called with job lock held, but might release it temporarily.
189
*/
190
void job_complete_locked(Job *job, Error **errp);
191
192
/**
193
* Asynchronously cancel the specified @job. If @force is true, the job should
194
* be cancelled immediately without waiting for a consistent state.
195
+ * Called with job lock held.
196
*/
197
-void job_cancel(Job *job, bool force);
198
-
199
-/* Same as job_cancel(), but called with job lock held. */
200
void job_cancel_locked(Job *job, bool force);
201
202
/**
203
- * Cancels the specified job like job_cancel(), but may refuse to do so if the
204
- * operation isn't meaningful in the current state of the job.
205
+ * Cancels the specified job like job_cancel_locked(), but may refuse
206
+ * to do so if the operation isn't meaningful in the current state of the job.
207
+ * Called with job lock held.
208
*/
209
-void job_user_cancel(Job *job, bool force, Error **errp);
210
-
211
-/* Same as job_user_cancel(), but called with job lock held. */
212
void job_user_cancel_locked(Job *job, bool force, Error **errp);
213
214
/**
215
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
216
217
/**
218
* @job: The job to be completed.
219
- * @errp: Error object which may be set by job_complete(); this is not
220
+ * @errp: Error object which may be set by job_complete_locked(); this is not
221
* necessarily set on every error, the job return value has to be
222
* checked as well.
223
*
224
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
225
* function).
226
*
227
* Returns the return value from the job.
228
- * Called with job_lock *not* held.
229
+ * Called with job_lock held.
230
*/
231
-int job_complete_sync(Job *job, Error **errp);
232
-
233
-/* Same as job_complete_sync, but called with job lock held. */
234
int job_complete_sync_locked(Job *job, Error **errp);
235
236
/**
237
@@ -XXX,XX +XXX,XX @@ int job_complete_sync_locked(Job *job, Error **errp);
238
* FIXME: Make the below statement universally true:
239
* For jobs that support the manual workflow mode, all graph changes that occur
240
* as a result will occur after this command and before a successful reply.
241
+ *
242
+ * Called with job lock held.
243
*/
244
-void job_finalize(Job *job, Error **errp);
245
-
246
-/* Same as job_finalize(), but called with job lock held. */
247
void job_finalize_locked(Job *job, Error **errp);
248
249
/**
250
* Remove the concluded @job from the query list and resets the passed pointer
251
* to %NULL. Returns an error if the job is not actually concluded.
252
+ *
253
+ * Called with job lock held.
254
*/
255
-void job_dismiss(Job **job, Error **errp);
256
-
257
-/* Same as job_dismiss(), but called with job lock held. */
258
void job_dismiss_locked(Job **job, Error **errp);
259
260
/**
261
@@ -XXX,XX +XXX,XX @@ void job_dismiss_locked(Job **job, Error **errp);
262
* Returns 0 if the job is successfully completed, -ECANCELED if the job was
263
* cancelled before completing, and -errno in other error cases.
264
*
265
- * Called with job_lock *not* held.
266
- */
267
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
268
- Error **errp);
269
-
270
-/*
271
- * Same as job_finish_sync(), but called with job lock held.
272
- * Might release the lock temporarily.
273
+ * Called with job_lock held, but might release it temporarily.
274
*/
275
int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
276
Error **errp);
277
diff --git a/job.c b/job.c
32
index XXXXXXX..XXXXXXX 100644
278
index XXXXXXX..XXXXXXX 100644
33
--- a/block.c
279
--- a/job.c
34
+++ b/block.c
280
+++ b/job.c
35
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
281
@@ -XXX,XX +XXX,XX @@ int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp)
36
QDict *options, int flags,
282
return -EPERM;
37
BlockDriverState *parent,
283
}
38
const BdrvChildClass *child_class,
284
39
+ BdrvChildRole child_role,
285
-int job_apply_verb(Job *job, JobVerb verb, Error **errp)
40
Error **errp);
286
-{
41
287
- JOB_LOCK_GUARD();
42
/* If non-zero, use only whitelisted block drivers */
288
- return job_apply_verb_locked(job, verb, errp);
43
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
289
-}
44
* Returns the options and flags that bs->file should get if a protocol driver
290
-
45
* is expected, based on the given options and flags for the parent BDS
291
JobType job_type(const Job *job)
46
*/
292
{
47
-static void bdrv_inherited_options(int *child_flags, QDict *child_options,
293
return job->driver->job_type;
48
+static void bdrv_inherited_options(BdrvChildRole role,
294
@@ -XXX,XX +XXX,XX @@ bool job_is_completed_locked(Job *job)
49
+ int *child_flags, QDict *child_options,
295
return false;
50
int parent_flags, QDict *parent_options)
296
}
51
{
297
52
int flags = parent_flags;
298
-bool job_is_completed(Job *job)
53
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_file = {
299
+static bool job_is_completed(Job *job)
54
* (and not only protocols) is permitted for it, based on the given options and
300
{
55
* flags for the parent BDS
301
JOB_LOCK_GUARD();
56
*/
302
return job_is_completed_locked(job);
57
-static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options,
303
@@ -XXX,XX +XXX,XX @@ Job *job_get_locked(const char *id)
58
+static void bdrv_inherited_fmt_options(BdrvChildRole role,
304
return NULL;
59
+ int *child_flags, QDict *child_options,
305
}
60
int parent_flags, QDict *parent_options)
306
61
{
307
-Job *job_get(const char *id)
62
- child_file.inherit_options(child_flags, child_options,
308
-{
63
+ child_file.inherit_options(role, child_flags, child_options,
309
- JOB_LOCK_GUARD();
64
parent_flags, parent_options);
310
- return job_get_locked(id);
65
311
-}
66
*child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
312
-
67
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
313
void job_set_aio_context(Job *job, AioContext *ctx)
68
* Returns the options and flags that bs->backing should get, based on the
314
{
69
* given options and flags for the parent BDS
315
/* protect against read in job_finish_sync_locked and job_start */
70
*/
316
@@ -XXX,XX +XXX,XX @@ void job_ref_locked(Job *job)
71
-static void bdrv_backing_options(int *child_flags, QDict *child_options,
317
++job->refcnt;
72
+static void bdrv_backing_options(BdrvChildRole role,
318
}
73
+ int *child_flags, QDict *child_options,
319
74
int parent_flags, QDict *parent_options)
320
-void job_ref(Job *job)
75
{
321
-{
76
int flags = parent_flags;
322
- JOB_LOCK_GUARD();
77
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
323
- job_ref_locked(job);
324
-}
325
-
326
void job_unref_locked(Job *job)
327
{
328
GLOBAL_STATE_CODE();
329
@@ -XXX,XX +XXX,XX @@ void job_unref_locked(Job *job)
78
}
330
}
79
331
}
80
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
332
81
- &child_backing, errp);
333
-void job_unref(Job *job)
82
+ &child_backing, 0, errp);
334
-{
83
if (!backing_hd) {
335
- JOB_LOCK_GUARD();
84
bs->open_flags |= BDRV_O_NO_BACKING;
336
- job_unref_locked(job);
85
error_prepend(errp, "Could not open backing file: ");
337
-}
86
@@ -XXX,XX +XXX,XX @@ free_exit:
338
-
87
static BlockDriverState *
339
void job_progress_update(Job *job, uint64_t done)
88
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
340
{
89
BlockDriverState *parent, const BdrvChildClass *child_class,
341
progress_work_done(&job->progress, done);
90
- bool allow_none, Error **errp)
342
@@ -XXX,XX +XXX,XX @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
91
+ BdrvChildRole child_role, bool allow_none, Error **errp)
343
job_lock();
92
{
344
}
93
BlockDriverState *bs = NULL;
345
94
QDict *image_options;
346
-void job_enter_cond(Job *job, bool(*fn)(Job *job))
95
@@ -XXX,XX +XXX,XX @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
347
-{
348
- JOB_LOCK_GUARD();
349
- job_enter_cond_locked(job, fn);
350
-}
351
-
352
void job_enter(Job *job)
353
{
354
JOB_LOCK_GUARD();
355
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job)
356
job_pause_point_locked(job);
357
}
358
359
-static void coroutine_fn job_yield_locked(Job *job)
360
+void coroutine_fn job_yield(Job *job)
361
{
362
+ JOB_LOCK_GUARD();
363
assert(job->busy);
364
365
/* Check cancellation *before* setting busy = false, too! */
366
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_yield_locked(Job *job)
367
job_pause_point_locked(job);
368
}
369
370
-void coroutine_fn job_yield(Job *job)
371
-{
372
- JOB_LOCK_GUARD();
373
- job_yield_locked(job);
374
-}
375
-
376
void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
377
{
378
JOB_LOCK_GUARD();
379
@@ -XXX,XX +XXX,XX @@ void job_user_pause_locked(Job *job, Error **errp)
380
job_pause_locked(job);
381
}
382
383
-void job_user_pause(Job *job, Error **errp)
384
-{
385
- JOB_LOCK_GUARD();
386
- job_user_pause_locked(job, errp);
387
-}
388
-
389
bool job_user_paused_locked(Job *job)
390
{
391
return job->user_paused;
392
}
393
394
-bool job_user_paused(Job *job)
395
-{
396
- JOB_LOCK_GUARD();
397
- return job_user_paused_locked(job);
398
-}
399
-
400
void job_user_resume_locked(Job *job, Error **errp)
401
{
402
assert(job);
403
@@ -XXX,XX +XXX,XX @@ void job_user_resume_locked(Job *job, Error **errp)
404
job_resume_locked(job);
405
}
406
407
-void job_user_resume(Job *job, Error **errp)
408
-{
409
- JOB_LOCK_GUARD();
410
- job_user_resume_locked(job, errp);
411
-}
412
-
413
/* Called with job_mutex held, but releases it temporarily. */
414
static void job_do_dismiss_locked(Job *job)
415
{
416
@@ -XXX,XX +XXX,XX @@ void job_dismiss_locked(Job **jobptr, Error **errp)
417
*jobptr = NULL;
418
}
419
420
-void job_dismiss(Job **jobptr, Error **errp)
421
-{
422
- JOB_LOCK_GUARD();
423
- job_dismiss_locked(jobptr, errp);
424
-}
425
-
426
void job_early_fail(Job *job)
427
{
428
JOB_LOCK_GUARD();
429
@@ -XXX,XX +XXX,XX @@ void job_finalize_locked(Job *job, Error **errp)
430
job_do_finalize_locked(job);
431
}
432
433
-void job_finalize(Job *job, Error **errp)
434
-{
435
- JOB_LOCK_GUARD();
436
- job_finalize_locked(job, errp);
437
-}
438
-
439
/* Called with job_mutex held. */
440
static int job_transition_to_pending_locked(Job *job)
441
{
442
@@ -XXX,XX +XXX,XX @@ void job_cancel_locked(Job *job, bool force)
96
}
443
}
97
444
}
98
bs = bdrv_open_inherit(filename, reference, image_options, 0,
445
99
- parent, child_class, errp);
446
-void job_cancel(Job *job, bool force)
100
+ parent, child_class, child_role, errp);
447
-{
101
if (!bs) {
448
- JOB_LOCK_GUARD();
102
goto done;
449
- job_cancel_locked(job, force);
103
}
450
-}
104
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
451
-
105
BlockDriverState *bs;
452
void job_user_cancel_locked(Job *job, bool force, Error **errp)
106
453
{
107
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
454
if (job_apply_verb_locked(job, JOB_VERB_CANCEL, errp)) {
108
- allow_none, errp);
455
@@ -XXX,XX +XXX,XX @@ void job_user_cancel_locked(Job *job, bool force, Error **errp)
109
+ child_role, allow_none, errp);
456
job_cancel_locked(job, force);
110
if (bs == NULL) {
457
}
111
return NULL;
458
112
}
459
-void job_user_cancel(Job *job, bool force, Error **errp)
113
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
460
-{
114
461
- JOB_LOCK_GUARD();
115
}
462
- job_user_cancel_locked(job, force, errp);
116
463
-}
117
- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
464
-
118
+ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
465
-/* A wrapper around job_cancel() taking an Error ** parameter so it may be
119
obj = NULL;
466
- * used with job_finish_sync() without the need for (rather nasty) function
120
qobject_unref(obj);
467
- * pointer casts there.
121
visit_free(v);
468
+/* A wrapper around job_cancel_locked() taking an Error ** parameter so it may
122
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
469
+ * be used with job_finish_sync_locked() without the need for (rather nasty)
123
QDict *options, int flags,
470
+ * function pointer casts there.
124
BlockDriverState *parent,
471
*
125
const BdrvChildClass *child_class,
472
* Called with job_mutex held.
126
+ BdrvChildRole child_role,
473
*/
127
Error **errp)
474
@@ -XXX,XX +XXX,XX @@ int job_complete_sync_locked(Job *job, Error **errp)
128
{
475
return job_finish_sync_locked(job, job_complete_locked, errp);
129
int ret;
476
}
130
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
477
131
478
-int job_complete_sync(Job *job, Error **errp)
132
if (child_class) {
479
-{
133
bs->inherits_from = parent;
480
- JOB_LOCK_GUARD();
134
- child_class->inherit_options(&flags, options,
481
- return job_complete_sync_locked(job, errp);
135
+ child_class->inherit_options(child_role, &flags, options,
482
-}
136
parent->open_flags, parent->options);
483
-
137
}
484
void job_complete_locked(Job *job, Error **errp)
138
485
{
139
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
486
/* Should not be reachable via external interface for internal jobs */
140
flags, options);
487
@@ -XXX,XX +XXX,XX @@ void job_complete_locked(Job *job, Error **errp)
141
/* Let bdrv_backing_options() override "read-only" */
488
job_lock();
142
qdict_del(options, BDRV_OPT_READ_ONLY);
489
}
143
- bdrv_backing_options(&flags, options, flags, options);
490
144
+ bdrv_backing_options(0, &flags, options, flags, options);
491
-void job_complete(Job *job, Error **errp)
145
}
492
-{
146
493
- JOB_LOCK_GUARD();
147
bs->open_flags = flags;
494
- job_complete_locked(job, errp);
148
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
495
-}
149
BlockDriverState *file_bs;
496
-
150
497
int job_finish_sync_locked(Job *job,
151
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
498
void (*finish)(Job *, Error **errp),
152
- &child_file, true, &local_err);
499
Error **errp)
153
+ &child_file, 0, true, &local_err);
500
@@ -XXX,XX +XXX,XX @@ int job_finish_sync_locked(Job *job,
154
if (local_err) {
501
job_unref_locked(job);
155
goto fail;
502
return ret;
156
}
503
}
157
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
504
-
158
QDict *options, int flags, Error **errp)
505
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
159
{
506
-{
160
return bdrv_open_inherit(filename, reference, options, flags, NULL,
507
- JOB_LOCK_GUARD();
161
- NULL, errp);
508
- return job_finish_sync_locked(job, finish, errp);
162
+ NULL, 0, errp);
509
-}
163
}
510
diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c
164
165
/* Return true if the NULL-terminated @list contains @str */
166
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
167
BlockDriverState *bs,
168
QDict *options,
169
const BdrvChildClass *klass,
170
+ BdrvChildRole role,
171
QDict *parent_options,
172
int parent_flags,
173
bool keep_old_opts)
174
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
175
/* Inherit from parent node */
176
if (parent_options) {
177
flags = 0;
178
- klass->inherit_options(&flags, options, parent_flags, parent_options);
179
+ klass->inherit_options(role, &flags, options,
180
+ parent_flags, parent_options);
181
} else {
182
flags = bdrv_get_flags(bs);
183
}
184
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
185
}
186
187
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
188
- child->klass, options, flags, child_keep_old);
189
+ child->klass, child->role, options, flags,
190
+ child_keep_old);
191
}
192
193
return bs_queue;
194
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
195
BlockDriverState *bs,
196
QDict *options, bool keep_old_opts)
197
{
198
- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0,
199
+ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, NULL, 0,
200
keep_old_opts);
201
}
202
203
diff --git a/block/block-backend.c b/block/block-backend.c
204
index XXXXXXX..XXXXXXX 100644
511
index XXXXXXX..XXXXXXX 100644
205
--- a/block/block-backend.c
512
--- a/tests/unit/test-blockjob.c
206
+++ b/block/block-backend.c
513
+++ b/tests/unit/test-blockjob.c
207
@@ -XXX,XX +XXX,XX @@ static QTAILQ_HEAD(, BlockBackend) block_backends =
514
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver test_yielding_driver = {
208
static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
209
QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
210
211
-static void blk_root_inherit_options(int *child_flags, QDict *child_options,
212
+static void blk_root_inherit_options(BdrvChildRole role,
213
+ int *child_flags, QDict *child_options,
214
int parent_flags, QDict *parent_options)
215
{
216
/* We're not supposed to call this function for root nodes */
217
diff --git a/block/vvfat.c b/block/vvfat.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/block/vvfat.c
220
+++ b/block/vvfat.c
221
@@ -XXX,XX +XXX,XX @@ static BlockDriver vvfat_write_target = {
222
.bdrv_co_pwritev = write_target_commit,
223
};
515
};
224
516
225
-static void vvfat_qcow_options(int *child_flags, QDict *child_options,
517
/*
226
+static void vvfat_qcow_options(BdrvChildRole role,
518
- * Test that job_complete() works even on jobs that are in a paused
227
+ int *child_flags, QDict *child_options,
519
+ * Test that job_complete_locked() works even on jobs that are in a paused
228
int parent_flags, QDict *parent_options)
520
* state (i.e., STANDBY).
229
{
521
*
230
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
522
* To do this, run YieldingJob in an IO thread, get it into the READY
523
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver test_yielding_driver = {
524
* acquire the context so the job will not be entered and will thus
525
* remain on STANDBY.
526
*
527
- * job_complete() should still work without error.
528
+ * job_complete_locked() should still work without error.
529
*
530
* Note that on the QMP interface, it is impossible to lock an IO
531
* thread before a drained section ends. In practice, the
231
--
532
--
232
2.25.4
533
2.37.3
233
234
diff view generated by jsdifflib
1
This tests that the mirror job catches situations where the target node
1
The field is unused (only ever set, but never read) since commit
2
has a different size than the source node. It must also forbid resize
2
ac9185603. Additionally, the commit message of commit 34fa110e already
3
operations when the job is already running.
3
explained earlier why it's unreliable. Remove it.
4
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-Id: <20220923142838.91043-1-kwolf@redhat.com>
7
Message-Id: <20200511135825.219437-5-kwolf@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
8
---
12
tests/qemu-iotests/041 | 45 ++++++++++++++++++++++++++++++++++++++
9
block/file-posix.c | 9 ---------
13
tests/qemu-iotests/041.out | 4 ++--
10
1 file changed, 9 deletions(-)
14
2 files changed, 47 insertions(+), 2 deletions(-)
15
11
16
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
12
diff --git a/block/file-posix.c b/block/file-posix.c
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/041
19
+++ b/tests/qemu-iotests/041
20
@@ -XXX,XX +XXX,XX @@ class TestSingleBlockdev(TestSingleDrive):
21
target=self.qmp_target)
22
self.assert_qmp(result, 'error/class', 'GenericError')
23
24
+ def do_test_resize(self, device, node):
25
+ def pre_finalize():
26
+ if device:
27
+ result = self.vm.qmp('block_resize', device=device, size=65536)
28
+ self.assert_qmp(result, 'error/class', 'GenericError')
29
+
30
+ result = self.vm.qmp('block_resize', node_name=node, size=65536)
31
+ self.assert_qmp(result, 'error/class', 'GenericError')
32
+
33
+ result = self.vm.qmp(self.qmp_cmd, job_id='job0', device='drive0',
34
+ sync='full', target=self.qmp_target,
35
+ auto_finalize=False, auto_dismiss=False)
36
+ self.assert_qmp(result, 'return', {})
37
+
38
+ result = self.vm.run_job('job0', auto_finalize=False,
39
+ pre_finalize=pre_finalize)
40
+ self.assertEqual(result, None)
41
+
42
+ def test_source_resize(self):
43
+ self.do_test_resize('drive0', 'top')
44
+
45
+ def test_target_resize(self):
46
+ self.do_test_resize(None, self.qmp_target)
47
+
48
+ def do_test_target_size(self, size):
49
+ result = self.vm.qmp('block_resize', node_name=self.qmp_target,
50
+ size=size)
51
+ self.assert_qmp(result, 'return', {})
52
+
53
+ result = self.vm.qmp(self.qmp_cmd, job_id='job0',
54
+ device='drive0', sync='full', auto_dismiss=False,
55
+ target=self.qmp_target)
56
+ self.assert_qmp(result, 'return', {})
57
+
58
+ result = self.vm.run_job('job0')
59
+ self.assertEqual(result, 'Source and target image have different sizes')
60
+
61
+ def test_small_target(self):
62
+ self.do_test_target_size(self.image_len // 2)
63
+
64
+ def test_large_target(self):
65
+ self.do_test_target_size(self.image_len * 2)
66
+
67
test_large_cluster = None
68
test_image_not_found = None
69
test_small_buffer2 = None
70
@@ -XXX,XX +XXX,XX @@ class TestSingleDriveZeroLength(TestSingleDrive):
71
72
class TestSingleBlockdevZeroLength(TestSingleBlockdev):
73
image_len = 0
74
+ test_small_target = None
75
+ test_large_target = None
76
77
class TestSingleDriveUnalignedLength(TestSingleDrive):
78
image_len = 1025 * 1024
79
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
80
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
81
--- a/tests/qemu-iotests/041.out
14
--- a/block/file-posix.c
82
+++ b/tests/qemu-iotests/041.out
15
+++ b/block/file-posix.c
83
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
84
-..............................................................................................
17
85
+........................................................................................................
18
bool has_discard:1;
86
----------------------------------------------------------------------
19
bool has_write_zeroes:1;
87
-Ran 94 tests
20
- bool discard_zeroes:1;
88
+Ran 104 tests
21
bool use_linux_aio:1;
89
22
bool use_linux_io_uring:1;
90
OK
23
int page_cache_inconsistent; /* errno from fdatasync failure */
24
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
25
ret = -EINVAL;
26
goto fail;
27
} else {
28
- s->discard_zeroes = true;
29
s->has_fallocate = true;
30
}
31
} else {
32
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
33
}
34
35
if (S_ISBLK(st.st_mode)) {
36
-#ifdef BLKDISCARDZEROES
37
- unsigned int arg;
38
- if (ioctl(s->fd, BLKDISCARDZEROES, &arg) == 0 && arg) {
39
- s->discard_zeroes = true;
40
- }
41
-#endif
42
#ifdef __linux__
43
/* On Linux 3.10, BLKDISCARD leaves stale data in the page cache. Do
44
* not rely on the contents of discarded blocks unless using O_DIRECT.
45
* Same for BLKZEROOUT.
46
*/
47
if (!(bs->open_flags & BDRV_O_NOCACHE)) {
48
- s->discard_zeroes = false;
49
s->has_write_zeroes = false;
50
}
51
#endif
91
--
52
--
92
2.25.4
53
2.37.3
93
94
diff view generated by jsdifflib