X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/cf3129323f900ef5ddbccbe86e4fa801e88c566e..1b5c15cebd5cc7595337a8a7cf14f6a707605e99:/blockjob.c diff --git a/blockjob.c b/blockjob.c index 73d9f1ba2b..c6e20e2fcd 100644 --- a/blockjob.c +++ b/blockjob.c @@ -33,6 +33,7 @@ #include "qapi/qapi-events-block-core.h" #include "qapi/qmp/qerror.h" #include "qemu/coroutine.h" +#include "qemu/main-loop.h" #include "qemu/timer.h" /* @@ -89,18 +90,6 @@ void block_job_free(Job *job) error_free(bjob->blocker); } -void block_job_drain(Job *job) -{ - BlockJob *bjob = container_of(job, BlockJob, job); - const JobDriver *drv = job->driver; - BlockJobDriver *bjdrv = container_of(drv, BlockJobDriver, job_driver); - - blk_drain(bjob->blk); - if (bjdrv->drain) { - bjdrv->drain(bjob); - } -} - static char *child_job_get_parent_desc(BdrvChild *c) { BlockJob *job = c->opaque; @@ -186,14 +175,23 @@ static const BdrvChildRole child_job = { void block_job_remove_all_bdrv(BlockJob *job) { - GSList *l; - for (l = job->nodes; l; l = l->next) { + /* + * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(), + * which will also traverse job->nodes, so consume the list one by + * one to make sure that such a concurrent access does not attempt + * to process an already freed BdrvChild. + */ + while (job->nodes) { + GSList *l = job->nodes; BdrvChild *c = l->data; + + job->nodes = l->next; + bdrv_op_unblock_all(c->bs, job->blocker); bdrv_root_unref_child(c); + + g_slist_free_1(l); } - g_slist_free(job->nodes); - job->nodes = NULL; } bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs) @@ -421,7 +419,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, assert(is_block_job(&job->job)); assert(job->job.driver->free == &block_job_free); assert(job->job.driver->user_resume == &block_job_user_resume); - assert(job->job.driver->drain == &block_job_drain); job->blk = blk;