[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 05/38] block: Add no_coroutine_fn and coroutine_mixed_fn marker
From: |
Kevin Wolf |
Subject: |
[PULL 05/38] block: Add no_coroutine_fn and coroutine_mixed_fn marker |
Date: |
Fri, 20 Jan 2023 13:26:00 +0100 |
From: Alberto Faria <afaria@redhat.com>
Add more annotations to functions, describing valid and invalid
calls from coroutine to non-coroutine context.
When applied to a function, no_coroutine_fn advertises that it should
not be called from coroutine_fn functions. This can be because the
function blocks or, in the case of generated_co_wrapper, to enforce
that coroutine_fn functions directly call the coroutine_fn that backs
the generated_co_wrapper.
coroutine_mixed_fn instead is for function that can be called in
both coroutine and non-coroutine context, but will suspend when
called in coroutine context. Annotating them is a first step
towards enforcing that non-annotated functions are absolutely
not going to suspend.
These can be used for example with the vrc tool:
# find functions that *really* cannot be called from no_coroutine_fn
(vrc) load --loader clang
libblock.fa.p/meson-generated_.._block_block-gen.c.o
(vrc) paths [no_coroutine_fn,!coroutine_mixed_fn]
bdrv_remove_persistent_dirty_bitmap
bdrv_create
bdrv_can_store_new_dirty_bitmap
# find how coroutine_fns end up calling a mixed function
(vrc) load --loader clang --force libblock.fa.p/*.c.o
(vrc) paths [coroutine_fn] [!no_coroutine_fn]* [coroutine_mixed_fn]
...
bdrv_pread <- vhdx_log_write <- vhdx_log_write_and_flush <- vhdx_co_writev
...
Signed-off-by: Alberto Faria <afaria@redhat.com>
[Rebase, add coroutine_mixed_fn. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221216110758.559947-3-pbonzini@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
include/block/block-common.h | 11 ++++++----
include/qemu/coroutine.h | 39 ++++++++++++++++++++++++++++++++++++
2 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/include/block/block-common.h b/include/block/block-common.h
index 4749c46a5e..cce79bd001 100644
--- a/include/block/block-common.h
+++ b/include/block/block-common.h
@@ -50,11 +50,14 @@
* - co_wrapper_mixed_bdrv_rdlock are co_wrapper_mixed functions but
* automatically take and release the graph rdlock when creating a new
* coroutine.
+ *
+ * These functions should not be called from a coroutine_fn; instead,
+ * call the wrapped function directly.
*/
-#define co_wrapper
-#define co_wrapper_mixed
-#define co_wrapper_bdrv_rdlock
-#define co_wrapper_mixed_bdrv_rdlock
+#define co_wrapper no_coroutine_fn
+#define co_wrapper_mixed no_coroutine_fn coroutine_mixed_fn
+#define co_wrapper_bdrv_rdlock no_coroutine_fn
+#define co_wrapper_mixed_bdrv_rdlock no_coroutine_fn coroutine_mixed_fn
#include "block/dirty-bitmap.h"
#include "block/blockjob.h"
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index b0c97f6fb7..569d7a5331 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -48,6 +48,45 @@
#define coroutine_fn
#endif
+/**
+ * Mark a function that can suspend when executed in coroutine context,
+ * but can handle running in non-coroutine context too.
+ */
+#ifdef __clang__
+#define coroutine_mixed_fn __attribute__((__annotate__("coroutine_mixed_fn")))
+#else
+#define coroutine_mixed_fn
+#endif
+
+/**
+ * Mark a function that should not be called from a coroutine context.
+ * Usually there will be an analogous, coroutine_fn function that should
+ * be used instead.
+ *
+ * When the function is also marked as coroutine_mixed_fn, the function should
+ * only be called if the caller does not know whether it is in coroutine
+ * context.
+ *
+ * Functions that are only no_coroutine_fn, on the other hand, should not
+ * be called from within coroutines at all. This for example includes
+ * functions that block.
+ *
+ * In the future it would be nice to enable compiler or static checker
+ * support for catching such errors. This annotation is the first step
+ * towards this, and in the meantime it serves as documentation.
+ *
+ * For example:
+ *
+ * static void no_coroutine_fn foo(void) {
+ * ....
+ * }
+ */
+#ifdef __clang__
+#define no_coroutine_fn __attribute__((__annotate__("no_coroutine_fn")))
+#else
+#define no_coroutine_fn
+#endif
+
typedef struct Coroutine Coroutine;
/**
--
2.38.1
- [PULL 00/38] Block layer patches, Kevin Wolf, 2023/01/20
- [PULL 01/38] tests/qemu-iotests/312: Mark "quorum" as required driver, Kevin Wolf, 2023/01/20
- [PULL 04/38] coroutine: annotate coroutine_fn for libclang, Kevin Wolf, 2023/01/20
- [PULL 03/38] pflash: Only read non-zero parts of backend image, Kevin Wolf, 2023/01/20
- [PULL 02/38] tests/qemu-iotests/262: Check for availability of "blkverify" first, Kevin Wolf, 2023/01/20
- [PULL 06/38] qemu-io: do not reinvent the blk_pwrite_zeroes wheel, Kevin Wolf, 2023/01/20
- [PULL 07/38] block: remove bdrv_coroutine_enter, Kevin Wolf, 2023/01/20
- [PULL 08/38] qcow2: Fix theoretical corruption in store_bitmap() error path, Kevin Wolf, 2023/01/20
- [PULL 05/38] block: Add no_coroutine_fn and coroutine_mixed_fn marker,
Kevin Wolf <=
- [PULL 10/38] qemu-img bitmap: Report errors while closing the image, Kevin Wolf, 2023/01/20
- [PULL 11/38] qemu-iotests: Test qemu-img bitmap/commit exit code on error, Kevin Wolf, 2023/01/20
- [PULL 09/38] qemu-img commit: Report errors while closing the image, Kevin Wolf, 2023/01/20
- [PULL 13/38] block: Convert bdrv_io_plug() to co_wrapper, Kevin Wolf, 2023/01/20
- [PULL 12/38] block-coroutine-wrapper: support void functions, Kevin Wolf, 2023/01/20
- [PULL 14/38] block: Convert bdrv_io_unplug() to co_wrapper, Kevin Wolf, 2023/01/20
- [PULL 15/38] block: Convert bdrv_is_inserted() to co_wrapper, Kevin Wolf, 2023/01/20
- [PULL 20/38] block: Convert bdrv_get_allocated_file_size() to co_wrapper, Kevin Wolf, 2023/01/20
- [PULL 19/38] block: use bdrv_co_refresh_total_sectors when possible, Kevin Wolf, 2023/01/20
- [PULL 16/38] block: Rename refresh_total_sectors to bdrv_refresh_total_sectors, Kevin Wolf, 2023/01/20