From: Emanuele Giuseppe Esposito Date: Tue, 25 Oct 2022 08:49:45 +0000 (-0400) Subject: bdrv_change_aio_context: use hash table instead of list of visited nodes X-Git-Tag: v7.2.0-rc0~32^2~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e08cc001d502958040565636e19a42c06e1ae8b7;p=thirdparty%2Fqemu.git bdrv_change_aio_context: use hash table instead of list of visited nodes Minor performance improvement, but given that we have hash tables available, avoid iterating in the visited nodes list every time just to check if a node has been already visited. The data structure is not actually a proper hash map, but an hash set, as we are just adding nodes and not key,value pairs. Suggested-by: Hanna Reitz Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Kevin Wolf Message-Id: <20221025084952.2139888-4-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- diff --git a/block.c b/block.c index 38e5d831ca8..59319d9b0fa 100644 --- a/block.c +++ b/block.c @@ -105,7 +105,7 @@ static void bdrv_reopen_abort(BDRVReopenState *reopen_state); static bool bdrv_backing_overridden(BlockDriverState *bs); static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx, - GSList **visited, Transaction *tran, + GHashTable *visited, Transaction *tran, Error **errp); /* If non-zero, use only whitelisted block drivers */ @@ -7315,14 +7315,15 @@ typedef struct BdrvStateSetAioContext { } BdrvStateSetAioContext; static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx, - GSList **visited, Transaction *tran, + GHashTable *visited, + Transaction *tran, Error **errp) { GLOBAL_STATE_CODE(); - if (g_slist_find(*visited, c)) { + if (g_hash_table_contains(visited, c)) { return true; } - *visited = g_slist_prepend(*visited, c); + g_hash_table_add(visited, c); /* * A BdrvChildClass that doesn't handle AioContext changes cannot @@ -7353,14 +7354,14 @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx, } bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx, - GSList **visited, Transaction *tran, + GHashTable *visited, Transaction *tran, Error **errp) { GLOBAL_STATE_CODE(); - if (g_slist_find(*visited, c)) { + if (g_hash_table_contains(visited, c)) { return true; } - *visited = g_slist_prepend(*visited, c); + g_hash_table_add(visited, c); return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp); } @@ -7445,7 +7446,7 @@ static TransactionActionDrv set_aio_context = { * responsible for freeing the list afterwards. */ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx, - GSList **visited, Transaction *tran, + GHashTable *visited, Transaction *tran, Error **errp) { BdrvChild *c; @@ -7524,7 +7525,7 @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx, BdrvChild *ignore_child, Error **errp) { Transaction *tran; - GSList *visited; + GHashTable *visited; int ret; AioContext *old_context = bdrv_get_aio_context(bs); GLOBAL_STATE_CODE(); @@ -7536,9 +7537,12 @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx, * is successful (the transaction itself). */ tran = tran_new(); - visited = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL; - ret = bdrv_change_aio_context(bs, ctx, &visited, tran, errp); - g_slist_free(visited); + visited = g_hash_table_new(NULL, NULL); + if (ignore_child) { + g_hash_table_add(visited, ignore_child); + } + ret = bdrv_change_aio_context(bs, ctx, visited, tran, errp); + g_hash_table_destroy(visited); /* * Linear phase: go through all callbacks collected in the transaction. diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h index 7b0095b419d..e7372ec541b 100644 --- a/include/block/block-global-state.h +++ b/include/block/block-global-state.h @@ -233,7 +233,7 @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx, AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c); bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx, - GSList **visited, Transaction *tran, + GHashTable *visited, Transaction *tran, Error **errp); int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx, BdrvChild *ignore_child, Error **errp); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 9067a99249b..7ccbbdae05d 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -911,7 +911,8 @@ struct BdrvChildClass { void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore); bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx, - GSList **visited, Transaction *tran, Error **errp); + GHashTable *visited, Transaction *tran, + Error **errp); AioContext *(*get_parent_aio_context)(BdrvChild *child);