Skip to contentSkip to conversation

Misc block job patches

PATCH In review Alberto Garcia 2 participants 10 messages May 27, 2016 Block layer

lore
Share & tools
lore
#1 lore raw

PATCH 1/4 block: use the block job list in bdrv_drain_all()

In reply to Alberto Garcia

bdrv_drain_all() pauses all block jobs by using bdrv_next() to iterate over all top-level BlockDriverStates. Therefore the code is unable to find block jobs in other nodes.

This patch uses block_job_next() to iterate over all block jobs.

---
 block/io.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
block/io.c +18 -6
index 2d832aa..c848b18 100644
@@ -289,15 +289,21 @@ void bdrv_drain_all(void)
     bool busy = true;
     BlockDriverState *bs;
     BdrvNextIterator it;
+    BlockJob *job = NULL;
     GSList *aio_ctxs = NULL, *ctx;
 
+    while ((job = block_job_next(job))) {
+        AioContext *aio_context = blk_get_aio_context(job->blk);
+
+        aio_context_acquire(aio_context);
+        block_job_pause(job);
+        aio_context_release(aio_context);
+    }
+
     for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
         AioContext *aio_context = bdrv_get_aio_context(bs);
 
         aio_context_acquire(aio_context);
-        if (bs->job) {
-            block_job_pause(bs->job);
-        }
         bdrv_parent_drained_begin(bs);
         bdrv_io_unplugged_begin(bs);
         bdrv_drain_recurse(bs);
@@ -340,12 +346,18 @@ void bdrv_drain_all(void)
         aio_context_acquire(aio_context);
         bdrv_io_unplugged_end(bs);
         bdrv_parent_drained_end(bs);
-        if (bs->job) {
-            block_job_resume(bs->job);
-        }
         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);
+
+        aio_context_acquire(aio_context);
+        block_job_resume(job);
+        aio_context_release(aio_context);
+    }
 }
 
 /**
Signature · 1 line
2.8.1
#3 lore raw

PATCH 2/4 block: use the block job list in qmp_query_block_jobs()

In reply to Alberto Garcia

qmp_query_block_jobs() uses bdrv_next() to look for block jobs, but this function can only find those in top-level BlockDriverStates.

This patch uses block_job_next() instead.

---
 blockdev.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)
blockdev.c +8 -12
index 717785e..ca7fa82 100644
@@ -4141,22 +4141,18 @@ void qmp_x_blockdev_change(const char *parent, bool has_child,
 BlockJobInfoList *qmp_query_block_jobs(Error **errp)
 {
     BlockJobInfoList *head = NULL, **p_next = &head;
-    BlockDriverState *bs;
-    BdrvNextIterator it;
+    BlockJob *job;
 
-    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
-        AioContext *aio_context = bdrv_get_aio_context(bs);
+    for (job = block_job_next(NULL); job; job = block_job_next(job)) {
+        BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
+        AioContext *aio_context = blk_get_aio_context(job->blk);
 
         aio_context_acquire(aio_context);
-
-        if (bs->job) {
-            BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
-            elem->value = block_job_query(bs->job);
-            *p_next = elem;
-            p_next = &elem->next;
-        }
-
+        elem->value = block_job_query(job);
         aio_context_release(aio_context);
+
+        *p_next = elem;
+        p_next = &elem->next;
     }
 
     return head;
Signature · 1 line
2.8.1
#5 lore raw

PATCH 3/4 block: Prevent sleeping jobs from resuming if they have been paused

In reply to Alberto Garcia

If we pause a block job and drain its BlockDriverState we want that the job remains inactive until we call block_job_resume() again.

However if we pause the job while it is sleeping then it will resume when the sleep timer fires.

This patch prevents that from happening by checking if the job has been paused after it comes back from sleeping.

---
 blockjob.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
blockjob.c +4 -2
index c095cc5..01b896b 100644
@@ -361,10 +361,12 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns)
     }
 
     job->busy = false;
+    if (!block_job_is_paused(job)) {
+        co_aio_sleep_ns(blk_get_aio_context(job->blk), type, ns);
+    }
+    /* The job can be paused while sleeping, so check this again */
     if (block_job_is_paused(job)) {
         qemu_coroutine_yield();
-    } else {
-        co_aio_sleep_ns(blk_get_aio_context(job->blk), type, ns);
     }
     job->busy = true;
 }
Signature · 1 line
2.8.1
#0 lore raw

cover Misc block job patches

Hi,

here's a few patches from my block-stream series that I think are ready to be merged now.

I don't think there's anything controversial here:

- Patches 1 and 2 simply use block_job_next() in places where bdrv_next() was being used to look for block jobs.

- Patch 3 is a fix that was already proposed in the list.

- Patch 4 is quite simple and it deals with the failure of block_job_create() in commit_start().

Regards,

Berto

Alberto Garcia (4):
block: use the block job list in bdrv_drain_all()
block: use the block job list in qmp_query_block_jobs()
block: Prevent sleeping jobs from resuming if they have been paused
block: Create the commit block job before reopening any image

 block/commit.c | 11 ++++++-----
 block/io.c     | 24 ++++++++++++++++++------
 blockdev.c     | 20 ++++++++------------
 blockjob.c     |  6 ++++--
 4 files changed, 36 insertions(+), 25 deletions(-)
Signature · 1 line
2.8.1
#7 lore raw

PATCH 4/4 block: Create the commit block job before reopening any image

If the base or overlay images need to be reopened in read-write mode but the block_job_create() call fails then no one will put those images back in read-only mode.

We can solve this problem easily by calling block_job_create() first.

---
 block/commit.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
block/commit.c +6 -5
index 8a00e11..444333b 100644
@@ -236,6 +236,11 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
         return;
     }
 
+    s = block_job_create(&commit_job_driver, bs, speed, cb, opaque, errp);
+    if (!s) {
+        return;
+    }
+
     orig_base_flags    = bdrv_get_flags(base);
     orig_overlay_flags = bdrv_get_flags(overlay_bs);
 
@@ -252,16 +257,12 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
         bdrv_reopen_multiple(reopen_queue, &local_err);
         if (local_err != NULL) {
             error_propagate(errp, local_err);
+            block_job_unref(&s->common);
             return;
         }
     }
 
 
-    s = block_job_create(&commit_job_driver, bs, speed, cb, opaque, errp);
-    if (!s) {
-        return;
-    }
-
     s->base = blk_new();
     blk_insert_bs(s->base, base);
 
Signature · 1 line
2.8.1
Reviewed-by on v1 1/4
#2 lore raw

Re: [Qemu-devel] [PATCH 1/4] block: use the block job list in bdrv_drain_all()

In reply to Alberto Garcia
Quoted 10 lines · Alberto Garcia

bdrv_drain_all() pauses all block jobs by using bdrv_next() to iterate over all top-level BlockDriverStates. Therefore the code is unable to find block jobs in other nodes.

This patch uses block_job_next() to iterate over all block jobs.

---
 block/io.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
Reviewed-by on v1 2/4
#4 lore raw

Re: [Qemu-devel] [PATCH 2/4] block: use the block job list in qmp_query_block_jobs()

In reply to Alberto Garcia
Quoted 9 lines · Alberto Garcia

qmp_query_block_jobs() uses bdrv_next() to look for block jobs, but this function can only find those in top-level BlockDriverStates.

This patch uses block_job_next() instead.

---
 blockdev.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)
Reviewed-by on v1 3/4
#6 lore raw

Re: [Qemu-devel] [PATCH 3/4] block: Prevent sleeping jobs from resuming if they have been paused

In reply to Alberto Garcia
Quoted 6 lines · Alberto Garcia

If we pause a block job and drain its BlockDriverState we want that the job remains inactive until we call block_job_resume() again.

However if we pause the job while it is sleeping then it will resume when the sleep timer fires.

Quoted 8 lines

This patch prevents that from happening by checking if the job has been paused after it comes back from sleeping.

---
 blockjob.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
Reviewed-by on v1 4/4
#8 lore raw

Re: [Qemu-devel] [PATCH 4/4] block: Create the commit block job before reopening any image

In reply to Alberto Garcia
Quoted 10 lines · Alberto Garcia

If the base or overlay images need to be reopened in read-write mode but the block_job_create() call fails then no one will put those images back in read-only mode.

We can solve this problem easily by calling block_job_create() first.

---
 block/commit.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
#9 lore raw
In reply to Alberto Garcia
Quoted 25 lines · Alberto Garcia

Hi,

here's a few patches from my block-stream series that I think are ready to be merged now.

I don't think there's anything controversial here:

- Patches 1 and 2 simply use block_job_next() in places where bdrv_next() was being used to look for block jobs.

- Patch 3 is a fix that was already proposed in the list.

- Patch 4 is quite simple and it deals with the failure of block_job_create() in commit_start().

Regards,

Berto

Alberto Garcia (4):
block: use the block job list in bdrv_drain_all()
block: use the block job list in qmp_query_block_jobs()
block: Prevent sleeping jobs from resuming if they have been paused
block: Create the commit block job before reopening any image

Quoted 5 lines
 block/commit.c | 11 ++++++-----
 block/io.c     | 24 ++++++++++++++++++------
 blockdev.c     | 20 ++++++++------------
 blockjob.c     |  6 ++++--
 4 files changed, 36 insertions(+), 25 deletions(-)

Thanks Berto, I've applied the series to my block branch:

https://github.com/XanClic/qemu/commits/block

Max