1
The following changes since commit 36f87b4513373b3cd79c87c9197d17face95d4ac:
1
The following changes since commit 6c769690ac845fa62642a5f93b4e4bd906adab95:
2
2
3
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.10-20170630' into staging (2017-06-30 11:58:49 +0100)
3
Merge remote-tracking branch 'remotes/vsementsov/tags/pull-simplebench-2021-05-04' into staging (2021-05-21 12:02:34 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://github.com/famz/qemu.git tags/block-pull-request
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to c61e684e44272f2acb2bef34cf2aa234582a73a9:
9
for you to fetch changes up to 0a6f0c76a030710780ce10d6347a70f098024d21:
10
10
11
block: Exploit BDRV_BLOCK_EOF for larger zero blocks (2017-06-30 21:48:06 +0800)
11
coroutine-sleep: introduce qemu_co_sleep (2021-05-21 18:22:33 +0100)
12
13
----------------------------------------------------------------
14
Pull request
15
16
(Resent due to an email preparation mistake.)
12
17
13
----------------------------------------------------------------
18
----------------------------------------------------------------
14
19
15
Hi Peter,
20
Paolo Bonzini (6):
21
coroutine-sleep: use a stack-allocated timer
22
coroutine-sleep: disallow NULL QemuCoSleepState** argument
23
coroutine-sleep: allow qemu_co_sleep_wake that wakes nothing
24
coroutine-sleep: move timer out of QemuCoSleepState
25
coroutine-sleep: replace QemuCoSleepState pointer with struct in the
26
API
27
coroutine-sleep: introduce qemu_co_sleep
16
28
17
Here are Eric Blake's enhancement to block layer API. Thanks!
29
Philippe Mathieu-Daudé (1):
30
bitops.h: Improve find_xxx_bit() documentation
18
31
19
----------------------------------------------------------------
32
Zenghui Yu (1):
33
multi-process: Initialize variables declared with g_auto*
20
34
21
Eric Blake (2):
35
include/qemu/bitops.h | 15 ++++++--
22
block: Add BDRV_BLOCK_EOF to bdrv_get_block_status()
36
include/qemu/coroutine.h | 27 ++++++++-----
23
block: Exploit BDRV_BLOCK_EOF for larger zero blocks
37
block/block-copy.c | 10 ++---
24
38
block/nbd.c | 14 +++----
25
block/io.c | 42 +++++++++++++++++++++++++++++++++---------
39
hw/remote/memory.c | 5 +--
26
include/block/block.h | 2 ++
40
hw/remote/proxy.c | 3 +-
27
tests/qemu-iotests/154 | 4 ----
41
util/qemu-coroutine-sleep.c | 75 +++++++++++++++++++------------------
28
tests/qemu-iotests/154.out | 12 ++++++------
42
7 files changed, 79 insertions(+), 70 deletions(-)
29
4 files changed, 41 insertions(+), 19 deletions(-)
30
43
31
--
44
--
32
2.9.4
45
2.31.1
33
46
34
diff view generated by jsdifflib
New patch
1
From: Zenghui Yu <yuzenghui@huawei.com>
1
2
3
Quote docs/devel/style.rst (section "Automatic memory deallocation"):
4
5
* Variables declared with g_auto* MUST always be initialized,
6
otherwise the cleanup function will use uninitialized stack memory
7
8
Initialize @name properly to get rid of the compilation error (using
9
gcc-7.3.0 on CentOS):
10
11
../hw/remote/proxy.c: In function 'pci_proxy_dev_realize':
12
/usr/include/glib-2.0/glib/glib-autocleanups.h:28:3: error: 'name' may be used uninitialized in this function [-Werror=maybe-uninitialized]
13
g_free (*pp);
14
^~~~~~~~~~~~
15
../hw/remote/proxy.c:350:30: note: 'name' was declared here
16
g_autofree char *name;
17
^~~~
18
19
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
20
Reviewed-by: Jagannathan Raman <jag.raman@oracle.com>
21
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
23
Message-id: 20210312112143.1369-1-yuzenghui@huawei.com
24
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
25
---
26
hw/remote/memory.c | 5 ++---
27
hw/remote/proxy.c | 3 +--
28
2 files changed, 3 insertions(+), 5 deletions(-)
29
30
diff --git a/hw/remote/memory.c b/hw/remote/memory.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/remote/memory.c
33
+++ b/hw/remote/memory.c
34
@@ -XXX,XX +XXX,XX @@ void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp)
35
36
remote_sysmem_reset();
37
38
- for (region = 0; region < msg->num_fds; region++) {
39
- g_autofree char *name;
40
+ for (region = 0; region < msg->num_fds; region++, suffix++) {
41
+ g_autofree char *name = g_strdup_printf("remote-mem-%u", suffix);
42
subregion = g_new(MemoryRegion, 1);
43
- name = g_strdup_printf("remote-mem-%u", suffix++);
44
memory_region_init_ram_from_fd(subregion, NULL,
45
name, sysmem_info->sizes[region],
46
true, msg->fds[region],
47
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/remote/proxy.c
50
+++ b/hw/remote/proxy.c
51
@@ -XXX,XX +XXX,XX @@ static void probe_pci_info(PCIDevice *dev, Error **errp)
52
PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY;
53
54
if (size) {
55
- g_autofree char *name;
56
+ g_autofree char *name = g_strdup_printf("bar-region-%d", i);
57
pdev->region[i].dev = pdev;
58
pdev->region[i].present = true;
59
if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) {
60
pdev->region[i].memory = true;
61
}
62
- name = g_strdup_printf("bar-region-%d", i);
63
memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev),
64
&proxy_mr_ops, &pdev->region[i],
65
name, size);
66
--
67
2.31.1
68
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
Document the following functions return the bitmap size
4
if no matching bit is found:
5
6
- find_first_bit
7
- find_next_bit
8
- find_last_bit
9
- find_first_zero_bit
10
- find_next_zero_bit
11
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Message-id: 20210510200758.2623154-2-philmd@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
18
include/qemu/bitops.h | 15 ++++++++++++---
19
1 file changed, 12 insertions(+), 3 deletions(-)
20
21
diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/qemu/bitops.h
24
+++ b/include/qemu/bitops.h
25
@@ -XXX,XX +XXX,XX @@ static inline int test_bit(long nr, const unsigned long *addr)
26
* @addr: The address to start the search at
27
* @size: The maximum size to search
28
*
29
- * Returns the bit number of the first set bit, or size.
30
+ * Returns the bit number of the last set bit,
31
+ * or @size if there is no set bit in the bitmap.
32
*/
33
unsigned long find_last_bit(const unsigned long *addr,
34
unsigned long size);
35
@@ -XXX,XX +XXX,XX @@ unsigned long find_last_bit(const unsigned long *addr,
36
* @addr: The address to base the search on
37
* @offset: The bitnumber to start searching at
38
* @size: The bitmap size in bits
39
+ *
40
+ * Returns the bit number of the next set bit,
41
+ * or @size if there are no further set bits in the bitmap.
42
*/
43
unsigned long find_next_bit(const unsigned long *addr,
44
unsigned long size,
45
@@ -XXX,XX +XXX,XX @@ unsigned long find_next_bit(const unsigned long *addr,
46
* @addr: The address to base the search on
47
* @offset: The bitnumber to start searching at
48
* @size: The bitmap size in bits
49
+ *
50
+ * Returns the bit number of the next cleared bit,
51
+ * or @size if there are no further clear bits in the bitmap.
52
*/
53
54
unsigned long find_next_zero_bit(const unsigned long *addr,
55
@@ -XXX,XX +XXX,XX @@ unsigned long find_next_zero_bit(const unsigned long *addr,
56
* @addr: The address to start the search at
57
* @size: The maximum size to search
58
*
59
- * Returns the bit number of the first set bit.
60
+ * Returns the bit number of the first set bit,
61
+ * or @size if there is no set bit in the bitmap.
62
*/
63
static inline unsigned long find_first_bit(const unsigned long *addr,
64
unsigned long size)
65
@@ -XXX,XX +XXX,XX @@ static inline unsigned long find_first_bit(const unsigned long *addr,
66
* @addr: The address to start the search at
67
* @size: The maximum size to search
68
*
69
- * Returns the bit number of the first cleared bit.
70
+ * Returns the bit number of the first cleared bit,
71
+ * or @size if there is no clear bit in the bitmap.
72
*/
73
static inline unsigned long find_first_zero_bit(const unsigned long *addr,
74
unsigned long size)
75
--
76
2.31.1
77
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
The lifetime of the timer is well-known (it cannot outlive
4
qemu_co_sleep_ns_wakeable, because it's deleted by the time the
5
coroutine resumes), so it is not necessary to place it on the heap.
6
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-id: 20210517100548.28806-2-pbonzini@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
util/qemu-coroutine-sleep.c | 9 ++++-----
13
1 file changed, 4 insertions(+), 5 deletions(-)
14
15
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/util/qemu-coroutine-sleep.c
18
+++ b/util/qemu-coroutine-sleep.c
19
@@ -XXX,XX +XXX,XX @@ static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns";
20
21
struct QemuCoSleepState {
22
Coroutine *co;
23
- QEMUTimer *ts;
24
+ QEMUTimer ts;
25
QemuCoSleepState **user_state_pointer;
26
};
27
28
@@ -XXX,XX +XXX,XX @@ void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
29
if (sleep_state->user_state_pointer) {
30
*sleep_state->user_state_pointer = NULL;
31
}
32
- timer_del(sleep_state->ts);
33
+ timer_del(&sleep_state->ts);
34
aio_co_wake(sleep_state->co);
35
}
36
37
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
38
AioContext *ctx = qemu_get_current_aio_context();
39
QemuCoSleepState state = {
40
.co = qemu_coroutine_self(),
41
- .ts = aio_timer_new(ctx, type, SCALE_NS, co_sleep_cb, &state),
42
.user_state_pointer = sleep_state,
43
};
44
45
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
46
abort();
47
}
48
49
+ aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, &state);
50
if (sleep_state) {
51
*sleep_state = &state;
52
}
53
- timer_mod(state.ts, qemu_clock_get_ns(type) + ns);
54
+ timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
55
qemu_coroutine_yield();
56
if (sleep_state) {
57
/*
58
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
59
*/
60
assert(*sleep_state == NULL);
61
}
62
- timer_free(state.ts);
63
}
64
--
65
2.31.1
66
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Simplify the code by removing conditionals. qemu_co_sleep_ns
4
can simply point the argument to an on-stack temporary.
5
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-id: 20210517100548.28806-3-pbonzini@redhat.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
include/qemu/coroutine.h | 5 +++--
12
util/qemu-coroutine-sleep.c | 18 +++++-------------
13
2 files changed, 8 insertions(+), 15 deletions(-)
14
15
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/qemu/coroutine.h
18
+++ b/include/qemu/coroutine.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct QemuCoSleepState QemuCoSleepState;
20
21
/**
22
* Yield the coroutine for a given duration. During this yield, @sleep_state
23
- * (if not NULL) is set to an opaque pointer, which may be used for
24
+ * is set to an opaque pointer, which may be used for
25
* qemu_co_sleep_wake(). Be careful, the pointer is set back to zero when the
26
* timer fires. Don't save the obtained value to other variables and don't call
27
* qemu_co_sleep_wake from another aio context.
28
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
29
QemuCoSleepState **sleep_state);
30
static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
31
{
32
- qemu_co_sleep_ns_wakeable(type, ns, NULL);
33
+ QemuCoSleepState *unused = NULL;
34
+ qemu_co_sleep_ns_wakeable(type, ns, &unused);
35
}
36
37
/**
38
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/util/qemu-coroutine-sleep.c
41
+++ b/util/qemu-coroutine-sleep.c
42
@@ -XXX,XX +XXX,XX @@ void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
43
qemu_co_sleep_ns__scheduled, NULL);
44
45
assert(scheduled == qemu_co_sleep_ns__scheduled);
46
- if (sleep_state->user_state_pointer) {
47
- *sleep_state->user_state_pointer = NULL;
48
- }
49
+ *sleep_state->user_state_pointer = NULL;
50
timer_del(&sleep_state->ts);
51
aio_co_wake(sleep_state->co);
52
}
53
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
54
}
55
56
aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, &state);
57
- if (sleep_state) {
58
- *sleep_state = &state;
59
- }
60
+ *sleep_state = &state;
61
timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
62
qemu_coroutine_yield();
63
- if (sleep_state) {
64
- /*
65
- * Note that *sleep_state is cleared during qemu_co_sleep_wake
66
- * before resuming this coroutine.
67
- */
68
- assert(*sleep_state == NULL);
69
- }
70
+
71
+ /* qemu_co_sleep_wake clears *sleep_state before resuming this coroutine. */
72
+ assert(*sleep_state == NULL);
73
}
74
--
75
2.31.1
76
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
All callers of qemu_co_sleep_wake are checking whether they are passing
4
a NULL argument inside the pointer-to-pointer: do the check in
5
qemu_co_sleep_wake itself.
6
7
As a side effect, qemu_co_sleep_wake can be called more than once and
8
it will only wake the coroutine once; after the first time, the argument
9
will be set to NULL via *sleep_state->user_state_pointer. However, this
10
would not be safe unless co_sleep_cb keeps using the QemuCoSleepState*
11
directly, so make it go through the pointer-to-pointer instead.
12
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-id: 20210517100548.28806-4-pbonzini@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
18
block/block-copy.c | 4 +---
19
block/nbd.c | 8 ++------
20
util/qemu-coroutine-sleep.c | 21 ++++++++++++---------
21
3 files changed, 15 insertions(+), 18 deletions(-)
22
23
diff --git a/block/block-copy.c b/block/block-copy.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/block-copy.c
26
+++ b/block/block-copy.c
27
@@ -XXX,XX +XXX,XX @@ out:
28
29
void block_copy_kick(BlockCopyCallState *call_state)
30
{
31
- if (call_state->sleep_state) {
32
- qemu_co_sleep_wake(call_state->sleep_state);
33
- }
34
+ qemu_co_sleep_wake(call_state->sleep_state);
35
}
36
37
/*
38
diff --git a/block/nbd.c b/block/nbd.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/nbd.c
41
+++ b/block/nbd.c
42
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nbd_client_co_drain_begin(BlockDriverState *bs)
43
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
44
45
s->drained = true;
46
- if (s->connection_co_sleep_ns_state) {
47
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
48
- }
49
+ qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
50
51
nbd_co_establish_connection_cancel(bs, false);
52
53
@@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs)
54
55
s->state = NBD_CLIENT_QUIT;
56
if (s->connection_co) {
57
- if (s->connection_co_sleep_ns_state) {
58
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
59
- }
60
+ qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
61
nbd_co_establish_connection_cancel(bs, true);
62
}
63
if (qemu_in_coroutine()) {
64
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/util/qemu-coroutine-sleep.c
67
+++ b/util/qemu-coroutine-sleep.c
68
@@ -XXX,XX +XXX,XX @@ struct QemuCoSleepState {
69
70
void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
71
{
72
- /* Write of schedule protected by barrier write in aio_co_schedule */
73
- const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled,
74
- qemu_co_sleep_ns__scheduled, NULL);
75
+ if (sleep_state) {
76
+ /* Write of schedule protected by barrier write in aio_co_schedule */
77
+ const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled,
78
+ qemu_co_sleep_ns__scheduled, NULL);
79
80
- assert(scheduled == qemu_co_sleep_ns__scheduled);
81
- *sleep_state->user_state_pointer = NULL;
82
- timer_del(&sleep_state->ts);
83
- aio_co_wake(sleep_state->co);
84
+ assert(scheduled == qemu_co_sleep_ns__scheduled);
85
+ *sleep_state->user_state_pointer = NULL;
86
+ timer_del(&sleep_state->ts);
87
+ aio_co_wake(sleep_state->co);
88
+ }
89
}
90
91
static void co_sleep_cb(void *opaque)
92
{
93
- qemu_co_sleep_wake(opaque);
94
+ QemuCoSleepState **sleep_state = opaque;
95
+ qemu_co_sleep_wake(*sleep_state);
96
}
97
98
void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
99
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
100
abort();
101
}
102
103
- aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, &state);
104
+ aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, sleep_state);
105
*sleep_state = &state;
106
timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
107
qemu_coroutine_yield();
108
--
109
2.31.1
110
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
This simplification is enabled by the previous patch. Now aio_co_wake
4
will only be called once, therefore we do not care about a spurious
5
firing of the timer after a qemu_co_sleep_wake.
6
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-id: 20210517100548.28806-5-pbonzini@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
util/qemu-coroutine-sleep.c | 8 ++++----
13
1 file changed, 4 insertions(+), 4 deletions(-)
14
15
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/util/qemu-coroutine-sleep.c
18
+++ b/util/qemu-coroutine-sleep.c
19
@@ -XXX,XX +XXX,XX @@ static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns";
20
21
struct QemuCoSleepState {
22
Coroutine *co;
23
- QEMUTimer ts;
24
QemuCoSleepState **user_state_pointer;
25
};
26
27
@@ -XXX,XX +XXX,XX @@ void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
28
29
assert(scheduled == qemu_co_sleep_ns__scheduled);
30
*sleep_state->user_state_pointer = NULL;
31
- timer_del(&sleep_state->ts);
32
aio_co_wake(sleep_state->co);
33
}
34
}
35
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
36
QemuCoSleepState **sleep_state)
37
{
38
AioContext *ctx = qemu_get_current_aio_context();
39
+ QEMUTimer ts;
40
QemuCoSleepState state = {
41
.co = qemu_coroutine_self(),
42
.user_state_pointer = sleep_state,
43
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
44
abort();
45
}
46
47
- aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, sleep_state);
48
+ aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, sleep_state);
49
*sleep_state = &state;
50
- timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
51
+ timer_mod(&ts, qemu_clock_get_ns(type) + ns);
52
qemu_coroutine_yield();
53
+ timer_del(&ts);
54
55
/* qemu_co_sleep_wake clears *sleep_state before resuming this coroutine. */
56
assert(*sleep_state == NULL);
57
--
58
2.31.1
59
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
When we have a BDS with unallocated clusters, but asking the status
3
Right now, users of qemu_co_sleep_ns_wakeable are simply passing
4
of its underlying bs->file or backing layer encounters an end-of-file
4
a pointer to QemuCoSleepState by reference to the function. But
5
condition, we know that the rest of the unallocated area will read as
5
QemuCoSleepState really is just a Coroutine*; making the
6
zeroes. However, pre-patch, this required two separate calls to
6
content of the struct public is just as efficient and lets us
7
bdrv_get_block_status(), as the first call stops at the point where
7
skip the user_state_pointer indirection.
8
the underlying file ends. Thanks to BDRV_BLOCK_EOF, we can now widen
8
9
the results of the primary status if the secondary status already
9
Since the usage is changed, take the occasion to rename the
10
includes BDRV_BLOCK_ZERO.
10
struct to QemuCoSleep.
11
11
12
In turn, this fixes a TODO mentioned in iotest 154, where we can now
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
see that all sectors in a partial cluster at the end of a file read
13
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
14
as zero when coupling the shorter backing file's status along with our
14
Message-id: 20210517100548.28806-6-pbonzini@redhat.com
15
knowledge that the remaining sectors came from an unallocated cluster.
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
17
Also, note that the loop in bdrv_co_get_block_status_above() had an
18
inefficent exit: in cases where the active layer sets BDRV_BLOCK_ZERO
19
but does NOT set BDRV_BLOCK_ALLOCATED (namely, where we know we read
20
zeroes merely because our unallocated clusters lie beyond the backing
21
file's shorter length), we still ended up probing the backing layer
22
even though we already had a good answer.
23
24
Signed-off-by: Eric Blake <eblake@redhat.com>
25
Message-Id: <20170505021500.19315-3-eblake@redhat.com>
26
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
27
Signed-off-by: Fam Zheng <famz@redhat.com>
28
---
16
---
29
block/io.c | 27 ++++++++++++++++++++++-----
17
include/qemu/coroutine.h | 23 +++++++++++----------
30
tests/qemu-iotests/154 | 4 ----
18
block/block-copy.c | 8 ++++----
31
tests/qemu-iotests/154.out | 12 ++++++------
19
block/nbd.c | 10 ++++-----
32
3 files changed, 28 insertions(+), 15 deletions(-)
20
util/qemu-coroutine-sleep.c | 41 ++++++++++++++++---------------------
33
21
4 files changed, 39 insertions(+), 43 deletions(-)
34
diff --git a/block/io.c b/block/io.c
22
35
index XXXXXXX..XXXXXXX 100644
23
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
36
--- a/block/io.c
24
index XXXXXXX..XXXXXXX 100644
37
+++ b/block/io.c
25
--- a/include/qemu/coroutine.h
38
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
26
+++ b/include/qemu/coroutine.h
39
/* Ignore errors. This is just providing extra information, it
27
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_wrlock(CoRwlock *lock);
40
* is useful but not necessary.
28
*/
41
*/
29
void qemu_co_rwlock_unlock(CoRwlock *lock);
42
- if (!file_pnum) {
30
43
- /* !file_pnum indicates an offset at or beyond the EOF; it is
31
-typedef struct QemuCoSleepState QemuCoSleepState;
44
- * perfectly valid for the format block driver to point to such
32
+typedef struct QemuCoSleep {
45
- * offsets, so catch it and mark everything as zero */
33
+ Coroutine *to_wake;
46
+ if (ret2 & BDRV_BLOCK_EOF &&
34
+} QemuCoSleep;
47
+ (!file_pnum || ret2 & BDRV_BLOCK_ZERO)) {
35
48
+ /*
36
/**
49
+ * It is valid for the format block driver to read
37
- * Yield the coroutine for a given duration. During this yield, @sleep_state
50
+ * beyond the end of the underlying file's current
38
- * is set to an opaque pointer, which may be used for
51
+ * size; such areas read as zero.
39
- * qemu_co_sleep_wake(). Be careful, the pointer is set back to zero when the
52
+ */
40
- * timer fires. Don't save the obtained value to other variables and don't call
53
ret |= BDRV_BLOCK_ZERO;
41
- * qemu_co_sleep_wake from another aio context.
54
} else {
42
+ * Yield the coroutine for a given duration. Initializes @w so that,
55
/* Limit request to the range reported by the protocol driver */
43
+ * during this yield, it can be passed to qemu_co_sleep_wake() to
56
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
44
+ * terminate the sleep.
57
{
45
*/
58
BlockDriverState *p;
46
-void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
59
int64_t ret = 0;
47
- QemuCoSleepState **sleep_state);
60
+ bool first = true;
48
+void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
61
49
+ QEMUClockType type, int64_t ns);
62
assert(bs != base);
50
+
63
for (p = bs; p != base; p = backing_bs(p)) {
51
static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
64
ret = bdrv_co_get_block_status(p, sector_num, nb_sectors, pnum, file);
52
{
65
- if (ret < 0 || ret & BDRV_BLOCK_ALLOCATED) {
53
- QemuCoSleepState *unused = NULL;
66
+ if (ret < 0) {
54
- qemu_co_sleep_ns_wakeable(type, ns, &unused);
67
+ break;
55
+ QemuCoSleep w = { 0 };
68
+ }
56
+ qemu_co_sleep_ns_wakeable(&w, type, ns);
69
+ if (ret & BDRV_BLOCK_ZERO && ret & BDRV_BLOCK_EOF && !first) {
57
}
70
+ /*
58
71
+ * Reading beyond the end of the file continues to read
59
/**
72
+ * zeroes, but we can only widen the result to the
60
@@ -XXX,XX +XXX,XX @@ static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
73
+ * unallocated length we learned from an earlier
61
* qemu_co_sleep_ns() and should be checked to be non-NULL before calling
74
+ * iteration.
62
* qemu_co_sleep_wake().
75
+ */
63
*/
76
+ *pnum = nb_sectors;
64
-void qemu_co_sleep_wake(QemuCoSleepState *sleep_state);
77
+ }
65
+void qemu_co_sleep_wake(QemuCoSleep *w);
78
+ if (ret & (BDRV_BLOCK_ZERO | BDRV_BLOCK_DATA)) {
66
79
break;
67
/**
80
}
68
* Yield until a file descriptor becomes readable
81
/* [sector_num, pnum] unallocated on this layer, which could be only
69
diff --git a/block/block-copy.c b/block/block-copy.c
82
* the first part of [sector_num, nb_sectors]. */
70
index XXXXXXX..XXXXXXX 100644
83
nb_sectors = MIN(nb_sectors, *pnum);
71
--- a/block/block-copy.c
84
+ first = false;
72
+++ b/block/block-copy.c
73
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState {
74
/* State */
75
int ret;
76
bool finished;
77
- QemuCoSleepState *sleep_state;
78
+ QemuCoSleep sleep;
79
bool cancelled;
80
81
/* OUT parameters */
82
@@ -XXX,XX +XXX,XX @@ block_copy_dirty_clusters(BlockCopyCallState *call_state)
83
if (ns > 0) {
84
block_copy_task_end(task, -EAGAIN);
85
g_free(task);
86
- qemu_co_sleep_ns_wakeable(QEMU_CLOCK_REALTIME, ns,
87
- &call_state->sleep_state);
88
+ qemu_co_sleep_ns_wakeable(&call_state->sleep,
89
+ QEMU_CLOCK_REALTIME, ns);
90
continue;
91
}
92
}
93
@@ -XXX,XX +XXX,XX @@ out:
94
95
void block_copy_kick(BlockCopyCallState *call_state)
96
{
97
- qemu_co_sleep_wake(call_state->sleep_state);
98
+ qemu_co_sleep_wake(&call_state->sleep);
99
}
100
101
/*
102
diff --git a/block/nbd.c b/block/nbd.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/block/nbd.c
105
+++ b/block/nbd.c
106
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVNBDState {
107
CoQueue free_sema;
108
Coroutine *connection_co;
109
Coroutine *teardown_co;
110
- QemuCoSleepState *connection_co_sleep_ns_state;
111
+ QemuCoSleep reconnect_sleep;
112
bool drained;
113
bool wait_drained_end;
114
int in_flight;
115
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nbd_client_co_drain_begin(BlockDriverState *bs)
116
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
117
118
s->drained = true;
119
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
120
+ qemu_co_sleep_wake(&s->reconnect_sleep);
121
122
nbd_co_establish_connection_cancel(bs, false);
123
124
@@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs)
125
126
s->state = NBD_CLIENT_QUIT;
127
if (s->connection_co) {
128
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
129
+ qemu_co_sleep_wake(&s->reconnect_sleep);
130
nbd_co_establish_connection_cancel(bs, true);
85
}
131
}
86
return ret;
132
if (qemu_in_coroutine()) {
87
}
133
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_co_reconnect_loop(BDRVNBDState *s)
88
diff --git a/tests/qemu-iotests/154 b/tests/qemu-iotests/154
134
}
89
index XXXXXXX..XXXXXXX 100755
135
bdrv_inc_in_flight(s->bs);
90
--- a/tests/qemu-iotests/154
136
} else {
91
+++ b/tests/qemu-iotests/154
137
- qemu_co_sleep_ns_wakeable(QEMU_CLOCK_REALTIME, timeout,
92
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
138
- &s->connection_co_sleep_ns_state);
93
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
139
+ qemu_co_sleep_ns_wakeable(&s->reconnect_sleep,
94
140
+ QEMU_CLOCK_REALTIME, timeout);
95
# Repeat with backing file holding unallocated cluster.
141
if (s->drained) {
96
-# TODO: Note that this forces an allocation, because we aren't yet able to
142
continue;
97
-# quickly detect that reads beyond EOF of the backing file are always zero
143
}
98
CLUSTER_SIZE=2048 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024))
144
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
99
145
index XXXXXXX..XXXXXXX 100644
100
# Write at the front: sector-wise, the request is:
146
--- a/util/qemu-coroutine-sleep.c
101
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
147
+++ b/util/qemu-coroutine-sleep.c
102
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
148
@@ -XXX,XX +XXX,XX @@
103
149
104
# Repeat with backing file holding zero'd cluster
150
static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns";
105
-# TODO: Note that this forces an allocation, because we aren't yet able to
151
106
-# quickly detect that reads beyond EOF of the backing file are always zero
152
-struct QemuCoSleepState {
107
$QEMU_IO -c "write -z $size 512" "$TEST_IMG.base" | _filter_qemu_io
153
+void qemu_co_sleep_wake(QemuCoSleep *w)
108
154
+{
109
# Write at the front: sector-wise, the request is:
155
Coroutine *co;
110
diff --git a/tests/qemu-iotests/154.out b/tests/qemu-iotests/154.out
156
- QemuCoSleepState **user_state_pointer;
111
index XXXXXXX..XXXXXXX 100644
157
-};
112
--- a/tests/qemu-iotests/154.out
158
113
+++ b/tests/qemu-iotests/154.out
159
-void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
114
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 134217728
160
-{
115
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
161
- if (sleep_state) {
116
2048/2048 bytes allocated at offset 128 MiB
162
+ co = w->to_wake;
117
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
163
+ w->to_wake = NULL;
118
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
164
+ if (co) {
119
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
165
/* Write of schedule protected by barrier write in aio_co_schedule */
120
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
166
- const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled,
121
wrote 512/512 bytes at offset 134219264
167
+ const char *scheduled = qatomic_cmpxchg(&co->scheduled,
122
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
qemu_co_sleep_ns__scheduled, NULL);
123
2048/2048 bytes allocated at offset 128 MiB
169
124
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
170
assert(scheduled == qemu_co_sleep_ns__scheduled);
125
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
171
- *sleep_state->user_state_pointer = NULL;
126
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
172
- aio_co_wake(sleep_state->co);
127
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
173
+ aio_co_wake(co);
128
wrote 1024/1024 bytes at offset 134218240
174
}
129
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
175
}
130
2048/2048 bytes allocated at offset 128 MiB
176
131
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
177
static void co_sleep_cb(void *opaque)
132
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
178
{
133
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
179
- QemuCoSleepState **sleep_state = opaque;
134
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
180
- qemu_co_sleep_wake(*sleep_state);
135
wrote 2048/2048 bytes at offset 134217728
181
+ QemuCoSleep *w = opaque;
136
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
182
+ qemu_co_sleep_wake(w);
137
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 134217728
183
}
138
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
184
139
2048/2048 bytes allocated at offset 128 MiB
185
-void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
140
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
186
- QemuCoSleepState **sleep_state)
141
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
187
+void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
142
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
188
+ QEMUClockType type, int64_t ns)
143
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
189
{
144
wrote 512/512 bytes at offset 134219264
190
+ Coroutine *co = qemu_coroutine_self();
145
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
191
AioContext *ctx = qemu_get_current_aio_context();
146
2048/2048 bytes allocated at offset 128 MiB
192
QEMUTimer ts;
147
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
193
- QemuCoSleepState state = {
148
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
194
- .co = qemu_coroutine_self(),
149
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
195
- .user_state_pointer = sleep_state,
150
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
196
- };
151
wrote 1024/1024 bytes at offset 134218240
197
152
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
198
- const char *scheduled = qatomic_cmpxchg(&state.co->scheduled, NULL,
153
2048/2048 bytes allocated at offset 128 MiB
199
- qemu_co_sleep_ns__scheduled);
154
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
200
+ const char *scheduled = qatomic_cmpxchg(&co->scheduled, NULL,
155
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
201
+ qemu_co_sleep_ns__scheduled);
156
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
202
if (scheduled) {
157
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
203
fprintf(stderr,
158
wrote 2048/2048 bytes at offset 134217728
204
"%s: Co-routine was already scheduled in '%s'\n",
159
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
205
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
206
abort();
207
}
208
209
- aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, sleep_state);
210
- *sleep_state = &state;
211
+ w->to_wake = co;
212
+ aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w),
213
timer_mod(&ts, qemu_clock_get_ns(type) + ns);
214
qemu_coroutine_yield();
215
timer_del(&ts);
216
217
- /* qemu_co_sleep_wake clears *sleep_state before resuming this coroutine. */
218
- assert(*sleep_state == NULL);
219
+ /* w->to_wake is cleared before resuming this coroutine. */
220
+ assert(w->to_wake == NULL);
221
}
160
--
222
--
161
2.9.4
223
2.31.1
162
224
163
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Just as the block layer already sets BDRV_BLOCK_ALLOCATED as a
3
Allow using QemuCoSleep to sleep forever until woken by qemu_co_sleep_wake.
4
shortcut for subsequent operations, there are also some optimizations
4
This makes the logic of qemu_co_sleep_ns_wakeable easy to understand.
5
that are made easier if we can quickly tell that *pnum will advance
6
us to the end of a file, via a new BDRV_BLOCK_EOF which gets set
7
by the block layer.
8
5
9
This just plumbs up the new bit; subsequent patches will make use
6
In the future we will introduce an API that can work even if the
10
of it.
7
sleep and wake happen from different threads. For now, initializing
8
w->to_wake after timer_mod is fine because the timer can only fire in
9
the same AioContext.
11
10
12
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Message-Id: <20170505021500.19315-2-eblake@redhat.com>
12
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: 20210517100548.28806-7-pbonzini@redhat.com
15
Signed-off-by: Fam Zheng <famz@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
15
---
17
block/io.c | 15 +++++++++++----
16
include/qemu/coroutine.h | 5 +++++
18
include/block/block.h | 2 ++
17
util/qemu-coroutine-sleep.c | 26 +++++++++++++++++++-------
19
2 files changed, 13 insertions(+), 4 deletions(-)
18
2 files changed, 24 insertions(+), 7 deletions(-)
20
19
21
diff --git a/block/io.c b/block/io.c
20
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/block/io.c
22
--- a/include/qemu/coroutine.h
24
+++ b/block/io.c
23
+++ b/include/qemu/coroutine.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvCoGetBlockStatusData {
24
@@ -XXX,XX +XXX,XX @@ typedef struct QemuCoSleep {
26
* Drivers not implementing the functionality are assumed to not support
25
void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
27
* backing files, hence all their sectors are reported as allocated.
26
QEMUClockType type, int64_t ns);
28
*
27
29
- * If 'sector_num' is beyond the end of the disk image the return value is 0
28
+/**
30
- * and 'pnum' is set to 0.
29
+ * Yield the coroutine until the next call to qemu_co_sleep_wake.
31
+ * If 'sector_num' is beyond the end of the disk image the return value is
30
+ */
32
+ * BDRV_BLOCK_EOF and 'pnum' is set to 0.
31
+void coroutine_fn qemu_co_sleep(QemuCoSleep *w);
33
*
32
+
34
* 'pnum' is set to the number of sectors (including and immediately following
33
static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
35
* the specified sector) that are known to be in the same
34
{
36
* allocated/unallocated state.
35
QemuCoSleep w = { 0 };
37
*
36
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
38
* 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
37
index XXXXXXX..XXXXXXX 100644
39
- * beyond the end of the disk image it will be clamped.
38
--- a/util/qemu-coroutine-sleep.c
40
+ * beyond the end of the disk image it will be clamped; if 'pnum' is set to
39
+++ b/util/qemu-coroutine-sleep.c
41
+ * the end of the image, then the returned value will include BDRV_BLOCK_EOF.
40
@@ -XXX,XX +XXX,XX @@ static void co_sleep_cb(void *opaque)
42
*
41
qemu_co_sleep_wake(w);
43
* If returned value is positive and BDRV_BLOCK_OFFSET_VALID bit is set, 'file'
42
}
44
* points to the BDS which the sector range is allocated in.
43
45
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
44
-void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
46
45
- QEMUClockType type, int64_t ns)
47
if (sector_num >= total_sectors) {
46
+void coroutine_fn qemu_co_sleep(QemuCoSleep *w)
48
*pnum = 0;
47
{
49
- return 0;
48
Coroutine *co = qemu_coroutine_self();
50
+ return BDRV_BLOCK_EOF;
49
- AioContext *ctx = qemu_get_current_aio_context();
50
- QEMUTimer ts;
51
52
const char *scheduled = qatomic_cmpxchg(&co->scheduled, NULL,
53
qemu_co_sleep_ns__scheduled);
54
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
51
}
55
}
52
56
53
n = total_sectors - sector_num;
57
w->to_wake = co;
54
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
58
- aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w),
55
if (!bs->drv->bdrv_co_get_block_status) {
59
- timer_mod(&ts, qemu_clock_get_ns(type) + ns);
56
*pnum = nb_sectors;
60
qemu_coroutine_yield();
57
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
61
- timer_del(&ts);
58
+ if (sector_num + nb_sectors == total_sectors) {
62
59
+ ret |= BDRV_BLOCK_EOF;
63
/* w->to_wake is cleared before resuming this coroutine. */
60
+ }
64
assert(w->to_wake == NULL);
61
if (bs->drv->protocol_name) {
62
ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
63
}
64
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
65
66
out:
67
bdrv_dec_in_flight(bs);
68
+ if (ret >= 0 && sector_num + *pnum == total_sectors) {
69
+ ret |= BDRV_BLOCK_EOF;
70
+ }
71
return ret;
72
}
65
}
73
66
+
74
diff --git a/include/block/block.h b/include/block/block.h
67
+void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
75
index XXXXXXX..XXXXXXX 100644
68
+ QEMUClockType type, int64_t ns)
76
--- a/include/block/block.h
69
+{
77
+++ b/include/block/block.h
70
+ AioContext *ctx = qemu_get_current_aio_context();
78
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
71
+ QEMUTimer ts;
79
* BDRV_BLOCK_OFFSET_VALID: an associated offset exists for accessing raw data
72
+
80
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
73
+ aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w);
81
* layer (short for DATA || ZERO), set by block layer
74
+ timer_mod(&ts, qemu_clock_get_ns(type) + ns);
82
+ * BDRV_BLOCK_EOF: the returned pnum covers through end of file for this layer
75
+
83
*
76
+ /*
84
* Internal flag:
77
+ * The timer will fire in the current AiOContext, so the callback
85
* BDRV_BLOCK_RAW: used internally to indicate that the request was
78
+ * must happen after qemu_co_sleep yields and there is no race
86
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
79
+ * between timer_mod and qemu_co_sleep.
87
#define BDRV_BLOCK_OFFSET_VALID 0x04
80
+ */
88
#define BDRV_BLOCK_RAW 0x08
81
+ qemu_co_sleep(w);
89
#define BDRV_BLOCK_ALLOCATED 0x10
82
+ timer_del(&ts);
90
+#define BDRV_BLOCK_EOF 0x20
83
+}
91
#define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK
92
93
typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
94
--
84
--
95
2.9.4
85
2.31.1
96
86
97
diff view generated by jsdifflib