From 89cadc9dc0f7c6a48c243bf7d9ad983a9b667426 Mon Sep 17 00:00:00 2001 From: Ashijeet Acharya Date: Tue, 25 Oct 2016 18:33:58 +0530 Subject: util/qemu-sockets: Make inet_connect_saddr() public Make inet_connect_saddr() in util/qemu-sockets.c public in order to be able to use it with InetSocketAddress sockets outside of util/qemu-sockets.c independently. Signed-off-by: Ashijeet Acharya Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/qemu/sockets.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 9eb24707df..5589e6842b 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -34,6 +34,8 @@ typedef void NonBlockingConnectHandler(int fd, Error *err, void *opaque); InetSocketAddress *inet_parse(const char *str, Error **errp); int inet_connect(const char *str, Error **errp); +int inet_connect_saddr(InetSocketAddress *saddr, Error **errp, + NonBlockingConnectHandler *callback, void *opaque); NetworkAddressFamily inet_netfamily(int family); -- cgit v1.2.3-55-g7522 From c0778f6693213d0d6bfa7bee8045374a798db750 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Fri, 28 Oct 2016 10:08:02 +0300 Subject: block: Add bdrv_drain_all_{begin,end}() bdrv_drain_all() doesn't allow the caller to do anything after all pending requests have been completed but before block jobs are resumed. This patch splits bdrv_drain_all() into _begin() and _end() for that purpose. It also adds aio_{disable,enable}_external() calls to disable external clients in the meantime. An important restriction of this split is that no new block jobs or BlockDriverStates can be created between the bdrv_drain_all_begin() and bdrv_drain_all_end() calls. This is not a concern now because we'll only be using this in bdrv_reopen_multiple(), but it must be dealt with if we ever have other uses cases in the future. Signed-off-by: Alberto Garcia Cc: Paolo Bonzini Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/io.c | 27 ++++++++++++++++++++++++--- include/block/block.h | 2 ++ 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/block/io.c b/block/io.c index be0d862ca6..37749b680a 100644 --- a/block/io.c +++ b/block/io.c @@ -273,8 +273,14 @@ void bdrv_drain(BlockDriverState *bs) * * This function does not flush data to disk, use bdrv_flush_all() for that * after calling this function. + * + * This pauses all block jobs and disables external clients. It must + * be paired with bdrv_drain_all_end(). + * + * NOTE: no new block jobs or BlockDriverStates can be created between + * the bdrv_drain_all_begin() and bdrv_drain_all_end() calls. */ -void bdrv_drain_all(void) +void bdrv_drain_all_begin(void) { /* Always run first iteration so any pending completion BHs run */ bool waited = true; @@ -297,6 +303,7 @@ void bdrv_drain_all(void) aio_context_acquire(aio_context); bdrv_parent_drained_begin(bs); bdrv_io_unplugged_begin(bs); + aio_disable_external(aio_context); aio_context_release(aio_context); if (!g_slist_find(aio_ctxs, aio_context)) { @@ -326,17 +333,25 @@ void bdrv_drain_all(void) } } + g_slist_free(aio_ctxs); +} + +void bdrv_drain_all_end(void) +{ + BlockDriverState *bs; + BdrvNextIterator it; + BlockJob *job = NULL; + for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); + aio_enable_external(aio_context); bdrv_io_unplugged_end(bs); bdrv_parent_drained_end(bs); aio_context_release(aio_context); } - g_slist_free(aio_ctxs); - job = NULL; while ((job = block_job_next(job))) { AioContext *aio_context = blk_get_aio_context(job->blk); @@ -346,6 +361,12 @@ void bdrv_drain_all(void) } } +void bdrv_drain_all(void) +{ + bdrv_drain_all_begin(); + bdrv_drain_all_end(); +} + /** * Remove an active request from the tracked requests list * diff --git a/include/block/block.h b/include/block/block.h index b7dc7d54ae..b81a3e35ce 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -332,6 +332,8 @@ int bdrv_flush_all(void); void bdrv_close_all(void); void bdrv_drain(BlockDriverState *bs); void coroutine_fn bdrv_co_drain(BlockDriverState *bs); +void bdrv_drain_all_begin(void); +void bdrv_drain_all_end(void); void bdrv_drain_all(void); #define BDRV_POLL_WHILE(bs, cond) ({ \ -- cgit v1.2.3-55-g7522 From 23d402d42beb975b97303beb3d9d4f60f4a1a883 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Fri, 28 Oct 2016 10:08:04 +0300 Subject: block: Add block_job_add_bdrv() When a block job is created on a certain BlockDriverState, operations are blocked there while the job exists. However, some block jobs may involve additional BDSs, which must be blocked separately when the job is created and unblocked manually afterwards. This patch adds block_job_add_bdrv(), that simplifies this process by keeping a list of BDSs that are involved in the specified block job. Signed-off-by: Alberto Garcia Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- blockjob.c | 17 +++++++++++++++-- include/block/blockjob.h | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/blockjob.c b/blockjob.c index 7c88b30074..422851fde5 100644 --- a/blockjob.c +++ b/blockjob.c @@ -113,6 +113,13 @@ static void block_job_detach_aio_context(void *opaque) block_job_unref(job); } +void block_job_add_bdrv(BlockJob *job, BlockDriverState *bs) +{ + job->nodes = g_slist_prepend(job->nodes, bs); + bdrv_ref(bs); + bdrv_op_block_all(bs, job->blocker); +} + void *block_job_create(const char *job_id, const BlockJobDriver *driver, BlockDriverState *bs, int64_t speed, BlockCompletionFunc *cb, void *opaque, Error **errp) @@ -150,7 +157,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, job = g_malloc0(driver->instance_size); error_setg(&job->blocker, "block device is in use by block job: %s", BlockJobType_lookup[driver->job_type]); - bdrv_op_block_all(bs, job->blocker); + block_job_add_bdrv(job, bs); bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker); job->driver = driver; @@ -189,9 +196,15 @@ void block_job_ref(BlockJob *job) void block_job_unref(BlockJob *job) { if (--job->refcnt == 0) { + GSList *l; BlockDriverState *bs = blk_bs(job->blk); bs->job = NULL; - bdrv_op_unblock_all(bs, job->blocker); + for (l = job->nodes; l; l = l->next) { + bs = l->data; + bdrv_op_unblock_all(bs, job->blocker); + bdrv_unref(bs); + } + g_slist_free(job->nodes); blk_remove_aio_context_notifier(job->blk, block_job_attached_aio_context, block_job_detach_aio_context, job); diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 2bb39f4d29..4dfb16b43f 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -188,6 +188,9 @@ struct BlockJob { /** Block other operations when block job is running */ Error *blocker; + /** BlockDriverStates that are involved in this block job */ + GSList *nodes; + /** The opaque value that is passed to the completion function. */ void *opaque; @@ -252,6 +255,17 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, BlockDriverState *bs, int64_t speed, BlockCompletionFunc *cb, void *opaque, Error **errp); +/** + * block_job_add_bdrv: + * @job: A block job + * @bs: A BlockDriverState that is involved in @job + * + * Add @bs to the list of BlockDriverState that are involved in + * @job. This means that all operations will be blocked on @bs while + * @job exists. + */ +void block_job_add_bdrv(BlockJob *job, BlockDriverState *bs); + /** * block_job_sleep_ns: * @job: The job that calls the function. -- cgit v1.2.3-55-g7522