aboutsummaryrefslogtreecommitdiff
path: root/blockjob.c
diff options
context:
space:
mode:
authorAlberto Garcia <berto@igalia.com>2016-10-28 10:08:04 +0300
committerKevin Wolf <kwolf@redhat.com>2016-10-31 16:52:38 +0100
commit23d402d42beb975b97303beb3d9d4f60f4a1a883 (patch)
tree93d21dba765ab21fd555ea8630d504e48e92964b /blockjob.c
parent40840e419be31e6a32e6ea24511c74b389d5e0e4 (diff)
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 <berto@igalia.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'blockjob.c')
-rw-r--r--blockjob.c17
1 files changed, 15 insertions, 2 deletions
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);