mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 04:06:46 +00:00 
			
		
		
		
	 60f782b6b7
			
		
	
	
		60f782b6b7
		
	
	
	
	
		
			
			All callers now pass is_external=false to aio_set_fd_handler() and aio_set_event_notifier(). The aio_disable_external() API that temporarily disables fd handlers that were registered is_external=true is therefore dead code. Remove aio_disable_external(), aio_enable_external(), and the is_external arguments to aio_set_fd_handler() and aio_set_event_notifier(). The entire test-fdmon-epoll test is removed because its sole purpose was testing aio_disable_external(). Parts of this patch were generated using the following coccinelle (https://coccinelle.lip6.fr/) semantic patch: @@ expression ctx, fd, is_external, io_read, io_write, io_poll, io_poll_ready, opaque; @@ - aio_set_fd_handler(ctx, fd, is_external, io_read, io_write, io_poll, io_poll_ready, opaque) + aio_set_fd_handler(ctx, fd, io_read, io_write, io_poll, io_poll_ready, opaque) @@ expression ctx, notifier, is_external, io_read, io_poll, io_poll_ready; @@ - aio_set_event_notifier(ctx, notifier, is_external, io_read, io_poll, io_poll_ready) + aio_set_event_notifier(ctx, notifier, io_read, io_poll, io_poll_ready) Reviewed-by: Juan Quintela <quintela@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Message-Id: <20230516190238.8401-21-stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
		
			
				
	
	
		
			130 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0-or-later */
 | |
| /*
 | |
|  * Test that poll handlers are not re-entrant in nested aio_poll()
 | |
|  *
 | |
|  * Copyright Red Hat
 | |
|  *
 | |
|  * Poll handlers are usually level-triggered. That means they continue firing
 | |
|  * until the condition is reset (e.g. a virtqueue becomes empty). If a poll
 | |
|  * handler calls nested aio_poll() before the condition is reset, then infinite
 | |
|  * recursion occurs.
 | |
|  *
 | |
|  * aio_poll() is supposed to prevent this by disabling poll handlers in nested
 | |
|  * aio_poll() calls. This test case checks that this is indeed what happens.
 | |
|  */
 | |
| #include "qemu/osdep.h"
 | |
| #include "block/aio.h"
 | |
| #include "qapi/error.h"
 | |
| 
 | |
| typedef struct {
 | |
|     AioContext *ctx;
 | |
| 
 | |
|     /* This is the EventNotifier that drives the test */
 | |
|     EventNotifier poll_notifier;
 | |
| 
 | |
|     /* This EventNotifier is only used to wake aio_poll() */
 | |
|     EventNotifier dummy_notifier;
 | |
| 
 | |
|     bool nested;
 | |
| } TestData;
 | |
| 
 | |
| static void io_read(EventNotifier *notifier)
 | |
| {
 | |
|     fprintf(stderr, "%s %p\n", __func__, notifier);
 | |
|     event_notifier_test_and_clear(notifier);
 | |
| }
 | |
| 
 | |
| static bool io_poll_true(void *opaque)
 | |
| {
 | |
|     fprintf(stderr, "%s %p\n", __func__, opaque);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| static bool io_poll_false(void *opaque)
 | |
| {
 | |
|     fprintf(stderr, "%s %p\n", __func__, opaque);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| static void io_poll_ready(EventNotifier *notifier)
 | |
| {
 | |
|     TestData *td = container_of(notifier, TestData, poll_notifier);
 | |
| 
 | |
|     fprintf(stderr, "> %s\n", __func__);
 | |
| 
 | |
|     g_assert(!td->nested);
 | |
|     td->nested = true;
 | |
| 
 | |
|     /* Wake the following nested aio_poll() call */
 | |
|     event_notifier_set(&td->dummy_notifier);
 | |
| 
 | |
|     /* This nested event loop must not call io_poll()/io_poll_ready() */
 | |
|     g_assert(aio_poll(td->ctx, true));
 | |
| 
 | |
|     td->nested = false;
 | |
| 
 | |
|     fprintf(stderr, "< %s\n", __func__);
 | |
| }
 | |
| 
 | |
| /* dummy_notifier never triggers */
 | |
| static void io_poll_never_ready(EventNotifier *notifier)
 | |
| {
 | |
|     g_assert_not_reached();
 | |
| }
 | |
| 
 | |
| static void test(void)
 | |
| {
 | |
|     TestData td = {
 | |
|         .ctx = aio_context_new(&error_abort),
 | |
|     };
 | |
| 
 | |
|     qemu_set_current_aio_context(td.ctx);
 | |
| 
 | |
|     /* Enable polling */
 | |
|     aio_context_set_poll_params(td.ctx, 1000000, 2, 2, &error_abort);
 | |
| 
 | |
|     /*
 | |
|      * The GSource is unused but this has the side-effect of changing the fdmon
 | |
|      * that AioContext uses.
 | |
|      */
 | |
|     aio_get_g_source(td.ctx);
 | |
| 
 | |
|     /* Make the event notifier active (set) right away */
 | |
|     event_notifier_init(&td.poll_notifier, 1);
 | |
|     aio_set_event_notifier(td.ctx, &td.poll_notifier,
 | |
|                            io_read, io_poll_true, io_poll_ready);
 | |
| 
 | |
|     /* This event notifier will be used later */
 | |
|     event_notifier_init(&td.dummy_notifier, 0);
 | |
|     aio_set_event_notifier(td.ctx, &td.dummy_notifier,
 | |
|                            io_read, io_poll_false, io_poll_never_ready);
 | |
| 
 | |
|     /* Consume aio_notify() */
 | |
|     g_assert(!aio_poll(td.ctx, false));
 | |
| 
 | |
|     /*
 | |
|      * Run the io_read() handler. This has the side-effect of activating
 | |
|      * polling in future aio_poll() calls.
 | |
|      */
 | |
|     g_assert(aio_poll(td.ctx, true));
 | |
| 
 | |
|     /* The second time around the io_poll()/io_poll_ready() handler runs */
 | |
|     g_assert(aio_poll(td.ctx, true));
 | |
| 
 | |
|     /* Run io_poll()/io_poll_ready() one more time to show it keeps working */
 | |
|     g_assert(aio_poll(td.ctx, true));
 | |
| 
 | |
|     aio_set_event_notifier(td.ctx, &td.dummy_notifier, NULL, NULL, NULL);
 | |
|     aio_set_event_notifier(td.ctx, &td.poll_notifier, NULL, NULL, NULL);
 | |
|     event_notifier_cleanup(&td.dummy_notifier);
 | |
|     event_notifier_cleanup(&td.poll_notifier);
 | |
|     aio_context_unref(td.ctx);
 | |
| }
 | |
| 
 | |
| int main(int argc, char **argv)
 | |
| {
 | |
|     g_test_init(&argc, &argv, NULL);
 | |
|     g_test_add_func("/nested-aio-poll", test);
 | |
|     return g_test_run();
 | |
| }
 |