block.c (27633e740e784709f256f6ee70f2dd0b5a87279f) block.c (f8be48adf08641f43dfb34b6abf50f9bc21fc250)
1/*
2 * QEMU System Emulator block driver
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2020 Virtuozzo International GmbH.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal

--- 2910 unchanged lines hidden (view full) ---

2919 GLOBAL_STATE_CODE();
2920 bdrv_replace_child_noperm(s->child, NULL);
2921
2922 if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
2923 bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
2924 }
2925
2926 if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
1/*
2 * QEMU System Emulator block driver
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2020 Virtuozzo International GmbH.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal

--- 2910 unchanged lines hidden (view full) ---

2919 GLOBAL_STATE_CODE();
2920 bdrv_replace_child_noperm(s->child, NULL);
2921
2922 if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
2923 bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
2924 }
2925
2926 if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
2927 GSList *ignore;
2927 Transaction *tran;
2928 GHashTable *visited;
2929 bool ret;
2928
2930
2929 /* No need to ignore `child`, because it has been detached already */
2930 ignore = NULL;
2931 s->child->klass->can_set_aio_ctx(s->child, s->old_parent_ctx, &ignore,
2932 &error_abort);
2933 g_slist_free(ignore);
2931 tran = tran_new();
2934
2932
2935 ignore = NULL;
2936 s->child->klass->set_aio_ctx(s->child, s->old_parent_ctx, &ignore);
2937 g_slist_free(ignore);
2933 /* No need to visit `child`, because it has been detached already */
2934 visited = g_hash_table_new(NULL, NULL);
2935 ret = s->child->klass->change_aio_ctx(s->child, s->old_parent_ctx,
2936 visited, tran, &error_abort);
2937 g_hash_table_destroy(visited);
2938
2939 /* transaction is supposed to always succeed */
2940 assert(ret == true);
2941 tran_commit(tran);
2938 }
2939
2940 bdrv_unref(bs);
2941 bdrv_child_free(s->child);
2942}
2943
2944static TransactionActionDrv bdrv_attach_child_common_drv = {
2945 .abort = bdrv_attach_child_common_abort,

--- 38 unchanged lines hidden (view full) ---

2984 * child_bs into the AioContext of the new parent. If this doesn't work,
2985 * try moving the parent into the AioContext of child_bs instead.
2986 */
2987 parent_ctx = bdrv_child_get_parent_aio_context(new_child);
2988 if (child_ctx != parent_ctx) {
2989 Error *local_err = NULL;
2990 int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
2991
2942 }
2943
2944 bdrv_unref(bs);
2945 bdrv_child_free(s->child);
2946}
2947
2948static TransactionActionDrv bdrv_attach_child_common_drv = {
2949 .abort = bdrv_attach_child_common_abort,

--- 38 unchanged lines hidden (view full) ---

2988 * child_bs into the AioContext of the new parent. If this doesn't work,
2989 * try moving the parent into the AioContext of child_bs instead.
2990 */
2991 parent_ctx = bdrv_child_get_parent_aio_context(new_child);
2992 if (child_ctx != parent_ctx) {
2993 Error *local_err = NULL;
2994 int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
2995
2992 if (ret < 0 && child_class->can_set_aio_ctx) {
2993 GSList *ignore = g_slist_prepend(NULL, new_child);
2994 if (child_class->can_set_aio_ctx(new_child, child_ctx, &ignore,
2995 NULL))
2996 {
2996 if (ret < 0 && child_class->change_aio_ctx) {
2997 Transaction *tran = tran_new();
2998 GHashTable *visited = g_hash_table_new(NULL, NULL);
2999 bool ret_child;
3000
3001 g_hash_table_add(visited, new_child);
3002 ret_child = child_class->change_aio_ctx(new_child, child_ctx,
3003 visited, tran, NULL);
3004 if (ret_child == true) {
2997 error_free(local_err);
2998 ret = 0;
3005 error_free(local_err);
3006 ret = 0;
2999 g_slist_free(ignore);
3000 ignore = g_slist_prepend(NULL, new_child);
3001 child_class->set_aio_ctx(new_child, child_ctx, &ignore);
3002 }
3007 }
3003 g_slist_free(ignore);
3008 tran_finalize(tran, ret_child == true ? 0 : -1);
3009 g_hash_table_destroy(visited);
3004 }
3005
3006 if (ret < 0) {
3007 error_propagate(errp, local_err);
3008 bdrv_child_free(new_child);
3009 return NULL;
3010 }
3011 }

--- 4584 unchanged lines hidden (view full) ---

7596
7597 return 0;
7598}
7599
7600int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
7601 Error **errp)
7602{
7603 GLOBAL_STATE_CODE();
3010 }
3011
3012 if (ret < 0) {
3013 error_propagate(errp, local_err);
3014 bdrv_child_free(new_child);
3015 return NULL;
3016 }
3017 }

--- 4584 unchanged lines hidden (view full) ---

7602
7603 return 0;
7604}
7605
7606int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
7607 Error **errp)
7608{
7609 GLOBAL_STATE_CODE();
7604 return bdrv_child_try_set_aio_context(bs, ctx, NULL, errp);
7610 return bdrv_child_try_change_aio_context(bs, ctx, NULL, errp);
7605}
7606
7607void bdrv_add_aio_context_notifier(BlockDriverState *bs,
7608 void (*attached_aio_context)(AioContext *new_context, void *opaque),
7609 void (*detach_aio_context)(void *opaque), void *opaque)
7610{
7611 BdrvAioNotifier *ban = g_new(BdrvAioNotifier, 1);
7612 *ban = (BdrvAioNotifier){

--- 737 unchanged lines hidden ---
7611}
7612
7613void bdrv_add_aio_context_notifier(BlockDriverState *bs,
7614 void (*attached_aio_context)(AioContext *new_context, void *opaque),
7615 void (*detach_aio_context)(void *opaque), void *opaque)
7616{
7617 BdrvAioNotifier *ban = g_new(BdrvAioNotifier, 1);
7618 *ban = (BdrvAioNotifier){

--- 737 unchanged lines hidden ---