From patchwork Fri Aug 17 19:04:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 959084 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41sXvK4qVGz9s2P for ; Sat, 18 Aug 2018 05:14:37 +1000 (AEST) Received: from localhost ([::1]:36047 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqkCh-00068H-5u for incoming@patchwork.ozlabs.org; Fri, 17 Aug 2018 15:14:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36687) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk90-0001Ib-7R for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:10:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqk3i-0006mL-2I for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:05:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50264) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqk3e-0006hQ-OY; Fri, 17 Aug 2018 15:05:14 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 21F0A307D914; Fri, 17 Aug 2018 19:05:14 +0000 (UTC) Received: from probe.redhat.com (ovpn-123-11.rdu2.redhat.com [10.10.123.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id EB5DE1948B; Fri, 17 Aug 2018 19:05:12 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 17 Aug 2018 15:04:51 -0400 Message-Id: <20180817190457.8292-2-jsnow@redhat.com> In-Reply-To: <20180817190457.8292-1-jsnow@redhat.com> References: <20180817190457.8292-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Fri, 17 Aug 2018 19:05:14 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 1/7] jobs: change start callback to run callback X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , Jeff Cody , jtc@redhat.com, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Presently we codify the entry point for a job as the "start" callback, but a more apt name would be "run" to clarify the idea that when this function returns we consider the job to have "finished," except for any cleanup which occurs in separate callbacks later. As part of this clarification, change the signature to include an error object and a return code. The error ptr is not yet used, and the return code while captured, will be overwritten by actions in the job_completed function. Signed-off-by: John Snow Reviewed-by: Eric Blake --- block/backup.c | 7 ++++--- block/commit.c | 7 ++++--- block/create.c | 8 +++++--- block/mirror.c | 10 ++++++---- block/stream.c | 7 ++++--- include/qemu/job.h | 2 +- job.c | 6 +++--- tests/test-bdrv-drain.c | 7 ++++--- tests/test-blockjob-txn.c | 16 ++++++++-------- tests/test-blockjob.c | 7 ++++--- 10 files changed, 43 insertions(+), 34 deletions(-) diff --git a/block/backup.c b/block/backup.c index 8630d32926..5d47781840 100644 --- a/block/backup.c +++ b/block/backup.c @@ -480,9 +480,9 @@ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job) bdrv_dirty_iter_free(dbi); } -static void coroutine_fn backup_run(void *opaque) +static int coroutine_fn backup_run(Job *opaque_job, Error **errp) { - BackupBlockJob *job = opaque; + BackupBlockJob *job = container_of(opaque_job, BackupBlockJob, common.job); BackupCompleteData *data; BlockDriverState *bs = blk_bs(job->common.blk); int64_t offset, nb_clusters; @@ -587,6 +587,7 @@ static void coroutine_fn backup_run(void *opaque) data = g_malloc(sizeof(*data)); data->ret = ret; job_defer_to_main_loop(&job->common.job, backup_complete, data); + return ret; } static const BlockJobDriver backup_job_driver = { @@ -596,7 +597,7 @@ static const BlockJobDriver backup_job_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .drain = block_job_drain, - .start = backup_run, + .run = backup_run, .commit = backup_commit, .abort = backup_abort, .clean = backup_clean, diff --git a/block/commit.c b/block/commit.c index eb414579bd..a0ea86ff64 100644 --- a/block/commit.c +++ b/block/commit.c @@ -134,9 +134,9 @@ static void commit_complete(Job *job, void *opaque) bdrv_unref(top); } -static void coroutine_fn commit_run(void *opaque) +static int coroutine_fn commit_run(Job *job, Error **errp) { - CommitBlockJob *s = opaque; + CommitBlockJob *s = container_of(job, CommitBlockJob, common.job); CommitCompleteData *data; int64_t offset; uint64_t delay_ns = 0; @@ -213,6 +213,7 @@ out: data = g_malloc(sizeof(*data)); data->ret = ret; job_defer_to_main_loop(&s->common.job, commit_complete, data); + return ret; } static const BlockJobDriver commit_job_driver = { @@ -222,7 +223,7 @@ static const BlockJobDriver commit_job_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .drain = block_job_drain, - .start = commit_run, + .run = commit_run, }, }; diff --git a/block/create.c b/block/create.c index 915cd41bcc..04733c3618 100644 --- a/block/create.c +++ b/block/create.c @@ -45,9 +45,9 @@ static void blockdev_create_complete(Job *job, void *opaque) job_completed(job, s->ret, s->err); } -static void coroutine_fn blockdev_create_run(void *opaque) +static int coroutine_fn blockdev_create_run(Job *job, Error **errp) { - BlockdevCreateJob *s = opaque; + BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common); job_progress_set_remaining(&s->common, 1); s->ret = s->drv->bdrv_co_create(s->opts, &s->err); @@ -55,12 +55,14 @@ static void coroutine_fn blockdev_create_run(void *opaque) qapi_free_BlockdevCreateOptions(s->opts); job_defer_to_main_loop(&s->common, blockdev_create_complete, NULL); + + return s->ret; } static const JobDriver blockdev_create_job_driver = { .instance_size = sizeof(BlockdevCreateJob), .job_type = JOB_TYPE_CREATE, - .start = blockdev_create_run, + .run = blockdev_create_run, }; void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, diff --git a/block/mirror.c b/block/mirror.c index 6cc10df5c9..691763db41 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -812,9 +812,9 @@ static int mirror_flush(MirrorBlockJob *s) return ret; } -static void coroutine_fn mirror_run(void *opaque) +static int coroutine_fn mirror_run(Job *job, Error **errp) { - MirrorBlockJob *s = opaque; + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); MirrorExitData *data; BlockDriverState *bs = s->mirror_top_bs->backing->bs; BlockDriverState *target_bs = blk_bs(s->target); @@ -1041,7 +1041,9 @@ immediate_exit: if (need_drain) { bdrv_drained_begin(bs); } + job_defer_to_main_loop(&s->common.job, mirror_exit, data); + return ret; } static void mirror_complete(Job *job, Error **errp) @@ -1138,7 +1140,7 @@ static const BlockJobDriver mirror_job_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .drain = block_job_drain, - .start = mirror_run, + .run = mirror_run, .pause = mirror_pause, .complete = mirror_complete, }, @@ -1154,7 +1156,7 @@ static const BlockJobDriver commit_active_job_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .drain = block_job_drain, - .start = mirror_run, + .run = mirror_run, .pause = mirror_pause, .complete = mirror_complete, }, diff --git a/block/stream.c b/block/stream.c index 9264b68a1e..b4b987df7e 100644 --- a/block/stream.c +++ b/block/stream.c @@ -97,9 +97,9 @@ out: g_free(data); } -static void coroutine_fn stream_run(void *opaque) +static int coroutine_fn stream_run(Job *job, Error **errp) { - StreamBlockJob *s = opaque; + StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); StreamCompleteData *data; BlockBackend *blk = s->common.blk; BlockDriverState *bs = blk_bs(blk); @@ -206,6 +206,7 @@ out: data = g_malloc(sizeof(*data)); data->ret = ret; job_defer_to_main_loop(&s->common.job, stream_complete, data); + return ret; } static const BlockJobDriver stream_job_driver = { @@ -213,7 +214,7 @@ static const BlockJobDriver stream_job_driver = { .instance_size = sizeof(StreamBlockJob), .job_type = JOB_TYPE_STREAM, .free = block_job_free, - .start = stream_run, + .run = stream_run, .user_resume = block_job_user_resume, .drain = block_job_drain, }, diff --git a/include/qemu/job.h b/include/qemu/job.h index 18c9223e31..9cf463d228 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -169,7 +169,7 @@ struct JobDriver { JobType job_type; /** Mandatory: Entrypoint for the Coroutine. */ - CoroutineEntry *start; + int coroutine_fn (*run)(Job *job, Error **errp); /** * If the callback is not NULL, it will be invoked when the job transitions diff --git a/job.c b/job.c index fa671b431a..898260b2b3 100644 --- a/job.c +++ b/job.c @@ -544,16 +544,16 @@ static void coroutine_fn job_co_entry(void *opaque) { Job *job = opaque; - assert(job && job->driver && job->driver->start); + assert(job && job->driver && job->driver->run); job_pause_point(job); - job->driver->start(job); + job->ret = job->driver->run(job, NULL); } void job_start(Job *job) { assert(job && !job_started(job) && job->paused && - job->driver && job->driver->start); + job->driver && job->driver->run); job->co = qemu_coroutine_create(job_co_entry, job); job->pause_count--; job->busy = true; diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c index 17bb8508ae..a7533861f6 100644 --- a/tests/test-bdrv-drain.c +++ b/tests/test-bdrv-drain.c @@ -757,9 +757,9 @@ static void test_job_completed(Job *job, void *opaque) job_completed(job, 0, NULL); } -static void coroutine_fn test_job_start(void *opaque) +static int coroutine_fn test_job_run(Job *job, Error **errp) { - TestBlockJob *s = opaque; + TestBlockJob *s = container_of(job, TestBlockJob, common.job); job_transition_to_ready(&s->common.job); while (!s->should_complete) { @@ -771,6 +771,7 @@ static void coroutine_fn test_job_start(void *opaque) } job_defer_to_main_loop(&s->common.job, test_job_completed, NULL); + return 0; } static void test_job_complete(Job *job, Error **errp) @@ -785,7 +786,7 @@ BlockJobDriver test_job_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .drain = block_job_drain, - .start = test_job_start, + .run = test_job_run, .complete = test_job_complete, }, }; diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c index 58d9b87fb2..3194924071 100644 --- a/tests/test-blockjob-txn.c +++ b/tests/test-blockjob-txn.c @@ -38,25 +38,25 @@ static void test_block_job_complete(Job *job, void *opaque) bdrv_unref(bs); } -static void coroutine_fn test_block_job_run(void *opaque) +static int coroutine_fn test_block_job_run(Job *job, Error **errp) { - TestBlockJob *s = opaque; - BlockJob *job = &s->common; + TestBlockJob *s = container_of(job, TestBlockJob, common.job); while (s->iterations--) { if (s->use_timer) { - job_sleep_ns(&job->job, 0); + job_sleep_ns(job, 0); } else { - job_yield(&job->job); + job_yield(job); } - if (job_is_cancelled(&job->job)) { + if (job_is_cancelled(job)) { break; } } - job_defer_to_main_loop(&job->job, test_block_job_complete, + job_defer_to_main_loop(job, test_block_job_complete, (void *)(intptr_t)s->rc); + return s->rc; } typedef struct { @@ -80,7 +80,7 @@ static const BlockJobDriver test_block_job_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .drain = block_job_drain, - .start = test_block_job_run, + .run = test_block_job_run, }, }; diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c index cb42f06e61..b0462bfdec 100644 --- a/tests/test-blockjob.c +++ b/tests/test-blockjob.c @@ -176,9 +176,9 @@ static void cancel_job_complete(Job *job, Error **errp) s->should_complete = true; } -static void coroutine_fn cancel_job_start(void *opaque) +static int coroutine_fn cancel_job_run(Job *job, Error **errp) { - CancelJob *s = opaque; + CancelJob *s = container_of(job, CancelJob, common.job); while (!s->should_complete) { if (job_is_cancelled(&s->common.job)) { @@ -194,6 +194,7 @@ static void coroutine_fn cancel_job_start(void *opaque) defer: job_defer_to_main_loop(&s->common.job, cancel_job_completed, s); + return 0; } static const BlockJobDriver test_cancel_driver = { @@ -202,7 +203,7 @@ static const BlockJobDriver test_cancel_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .drain = block_job_drain, - .start = cancel_job_start, + .run = cancel_job_run, .complete = cancel_job_complete, }, }; From patchwork Fri Aug 17 19:04:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 959086 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41sY0F5Q5Mz9s5c for ; Sat, 18 Aug 2018 05:18:53 +1000 (AEST) Received: from localhost ([::1]:36083 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqkGp-00035Q-E2 for incoming@patchwork.ozlabs.org; Fri, 17 Aug 2018 15:18:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36708) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk90-0001Jh-I3 for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:10:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqk3i-0006mR-2J for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:05:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57902) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqk3g-0006i4-0x; Fri, 17 Aug 2018 15:05:16 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 553833084218; Fri, 17 Aug 2018 19:05:15 +0000 (UTC) Received: from probe.redhat.com (ovpn-123-11.rdu2.redhat.com [10.10.123.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4ACB916C66; Fri, 17 Aug 2018 19:05:14 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 17 Aug 2018 15:04:52 -0400 Message-Id: <20180817190457.8292-3-jsnow@redhat.com> In-Reply-To: <20180817190457.8292-1-jsnow@redhat.com> References: <20180817190457.8292-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Fri, 17 Aug 2018 19:05:15 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 2/7] jobs: canonize Error object X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , Jeff Cody , jtc@redhat.com, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Jobs presently use both an Error object in the case of the create job, and char strings in the case of generic errors elsewhere. Unify the two paths as just j->err, and remove the extra argument from job_completed. The integer error code for job_completed is kept for now for use by pre-emptive cancellation. Signed-off-by: John Snow Reviewed-by: Eric Blake --- block/backup.c | 2 +- block/commit.c | 2 +- block/create.c | 5 ++--- block/mirror.c | 2 +- block/stream.c | 2 +- include/qemu/job.h | 10 ++++------ job-qmp.c | 5 +++-- job.c | 19 ++++++------------- tests/test-bdrv-drain.c | 2 +- tests/test-blockjob-txn.c | 2 +- tests/test-blockjob.c | 2 +- 11 files changed, 22 insertions(+), 31 deletions(-) diff --git a/block/backup.c b/block/backup.c index 5d47781840..1e965d54e5 100644 --- a/block/backup.c +++ b/block/backup.c @@ -388,7 +388,7 @@ static void backup_complete(Job *job, void *opaque) { BackupCompleteData *data = opaque; - job_completed(job, data->ret, NULL); + job_completed(job, data->ret); g_free(data); } diff --git a/block/commit.c b/block/commit.c index a0ea86ff64..4a17bb73ec 100644 --- a/block/commit.c +++ b/block/commit.c @@ -117,7 +117,7 @@ static void commit_complete(Job *job, void *opaque) * bdrv_set_backing_hd() to fail. */ block_job_remove_all_bdrv(bjob); - job_completed(job, ret, NULL); + job_completed(job, ret); g_free(data); /* If bdrv_drop_intermediate() didn't already do that, remove the commit diff --git a/block/create.c b/block/create.c index 04733c3618..26a385c6c7 100644 --- a/block/create.c +++ b/block/create.c @@ -35,14 +35,13 @@ typedef struct BlockdevCreateJob { BlockDriver *drv; BlockdevCreateOptions *opts; int ret; - Error *err; } BlockdevCreateJob; static void blockdev_create_complete(Job *job, void *opaque) { BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common); - job_completed(job, s->ret, s->err); + job_completed(job, s->ret); } static int coroutine_fn blockdev_create_run(Job *job, Error **errp) @@ -50,7 +49,7 @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp) BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common); job_progress_set_remaining(&s->common, 1); - s->ret = s->drv->bdrv_co_create(s->opts, &s->err); + s->ret = s->drv->bdrv_co_create(s->opts, errp); job_progress_update(&s->common, 1); qapi_free_BlockdevCreateOptions(s->opts); diff --git a/block/mirror.c b/block/mirror.c index 691763db41..be5dc6b7b0 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -710,7 +710,7 @@ static void mirror_exit(Job *job, void *opaque) blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort); bs_opaque->job = NULL; - job_completed(job, data->ret, NULL); + job_completed(job, data->ret); g_free(data); bdrv_drained_end(src); diff --git a/block/stream.c b/block/stream.c index b4b987df7e..26a775386b 100644 --- a/block/stream.c +++ b/block/stream.c @@ -93,7 +93,7 @@ out: } g_free(s->backing_file_str); - job_completed(job, data->ret, NULL); + job_completed(job, data->ret); g_free(data); } diff --git a/include/qemu/job.h b/include/qemu/job.h index 9cf463d228..5c92c53ef0 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -124,12 +124,12 @@ typedef struct Job { /** Estimated progress_current value at the completion of the job */ int64_t progress_total; - /** Error string for a failed job (NULL if, and only if, job->ret == 0) */ - char *error; - /** ret code passed to job_completed. */ int ret; + /** Error object for a failed job **/ + Error *err; + /** The completion function that will be called when the job completes. */ BlockCompletionFunc *cb; @@ -484,15 +484,13 @@ void job_transition_to_ready(Job *job); /** * @job: The job being completed. * @ret: The status code. - * @error: The error message for a failing job (only with @ret < 0). If @ret is - * negative, but NULL is given for @error, strerror() is used. * * Marks @job as completed. If @ret is non-zero, the job transaction it is part * of is aborted. If @ret is zero, the job moves into the WAITING state. If it * is the last job to complete in its transaction, all jobs in the transaction * move from WAITING to PENDING. */ -void job_completed(Job *job, int ret, Error *error); +void job_completed(Job *job, int ret); /** Asynchronously complete the specified @job. */ void job_complete(Job *job, Error **errp); diff --git a/job-qmp.c b/job-qmp.c index 410775df61..a969b2bbf0 100644 --- a/job-qmp.c +++ b/job-qmp.c @@ -146,8 +146,9 @@ static JobInfo *job_query_single(Job *job, Error **errp) .status = job->status, .current_progress = job->progress_current, .total_progress = job->progress_total, - .has_error = !!job->error, - .error = g_strdup(job->error), + .has_error = !!job->err, + .error = job->err ? \ + g_strdup(error_get_pretty(job->err)) : NULL, }; return info; diff --git a/job.c b/job.c index 898260b2b3..c9de1af556 100644 --- a/job.c +++ b/job.c @@ -369,7 +369,7 @@ void job_unref(Job *job) QLIST_REMOVE(job, job_list); - g_free(job->error); + error_free(job->err); g_free(job->id); g_free(job); } @@ -535,7 +535,6 @@ void job_drain(Job *job) } } - /** * All jobs must allow a pause point before entering their job proper. This * ensures that jobs can be paused prior to being started, then resumed later. @@ -546,7 +545,7 @@ static void coroutine_fn job_co_entry(void *opaque) assert(job && job->driver && job->driver->run); job_pause_point(job); - job->ret = job->driver->run(job, NULL); + job->ret = job->driver->run(job, &job->err); } @@ -666,8 +665,8 @@ static void job_update_rc(Job *job) job->ret = -ECANCELED; } if (job->ret) { - if (!job->error) { - job->error = g_strdup(strerror(-job->ret)); + if (!job->err) { + error_setg_errno(&job->err, -job->ret, "job failed"); } job_state_transition(job, JOB_STATUS_ABORTING); } @@ -865,17 +864,11 @@ static void job_completed_txn_success(Job *job) } } -void job_completed(Job *job, int ret, Error *error) +void job_completed(Job *job, int ret) { assert(job && job->txn && !job_is_completed(job)); job->ret = ret; - if (error) { - assert(job->ret < 0); - job->error = g_strdup(error_get_pretty(error)); - error_free(error); - } - job_update_rc(job); trace_job_completed(job, ret, job->ret); if (job->ret) { @@ -893,7 +886,7 @@ void job_cancel(Job *job, bool force) } job_cancel_async(job, force); if (!job_started(job)) { - job_completed(job, -ECANCELED, NULL); + job_completed(job, -ECANCELED); } else if (job->deferred_to_main_loop) { job_completed_txn_abort(job); } else { diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c index a7533861f6..00604dfc0c 100644 --- a/tests/test-bdrv-drain.c +++ b/tests/test-bdrv-drain.c @@ -754,7 +754,7 @@ typedef struct TestBlockJob { static void test_job_completed(Job *job, void *opaque) { - job_completed(job, 0, NULL); + job_completed(job, 0); } static int coroutine_fn test_job_run(Job *job, Error **errp) diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c index 3194924071..82cedee78b 100644 --- a/tests/test-blockjob-txn.c +++ b/tests/test-blockjob-txn.c @@ -34,7 +34,7 @@ static void test_block_job_complete(Job *job, void *opaque) rc = -ECANCELED; } - job_completed(job, rc, NULL); + job_completed(job, rc); bdrv_unref(bs); } diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c index b0462bfdec..408a226939 100644 --- a/tests/test-blockjob.c +++ b/tests/test-blockjob.c @@ -167,7 +167,7 @@ static void cancel_job_completed(Job *job, void *opaque) { CancelJob *s = opaque; s->completed = true; - job_completed(job, 0, NULL); + job_completed(job, 0); } static void cancel_job_complete(Job *job, Error **errp) From patchwork Fri Aug 17 19:04:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 959085 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41sXy50hM1z9s3Z for ; Sat, 18 Aug 2018 05:16:59 +1000 (AEST) Received: from localhost ([::1]:36070 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqkEx-0001r9-3j for incoming@patchwork.ozlabs.org; Fri, 17 Aug 2018 15:16:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36602) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk8z-0001Dr-Qi for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:10:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqk3n-0006qB-PT for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:05:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38970) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqk3k-0006ny-DA; Fri, 17 Aug 2018 15:05:21 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B90AB5F741; Fri, 17 Aug 2018 19:05:19 +0000 (UTC) Received: from probe.redhat.com (ovpn-123-11.rdu2.redhat.com [10.10.123.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1B5731948B; Fri, 17 Aug 2018 19:05:15 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 17 Aug 2018 15:04:53 -0400 Message-Id: <20180817190457.8292-4-jsnow@redhat.com> In-Reply-To: <20180817190457.8292-1-jsnow@redhat.com> References: <20180817190457.8292-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 17 Aug 2018 19:05:19 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 3/7] jobs: add exit shim X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , Jeff Cody , jtc@redhat.com, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" All jobs do the same thing when they leave their running loop: - Store the return code in a structure - wait to receive this structure in the main thread - signal job completion via job_completed Few jobs do anything beyond exactly this. Consolidate this exit logic for a net reduction in SLOC. More seriously, when we utilize job_defer_to_main_loop_bh to call a function that calls job_completed, job_finalize_single will run in a context where it has recursively taken the aio_context lock, which can cause hangs if it puts down a reference that causes a flush. You can observe this in practice by looking at mirror_exit's careful placement of job_completed and bdrv_unref calls. If we centralize job exiting, we can signal job completion from outside of the aio_context, which should allow for job cleanup code to run with only one lock, which makes cleanup callbacks less tricky to write. Signed-off-by: John Snow Reviewed-by: Eric Blake --- include/qemu/job.h | 7 +++++++ job.c | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/qemu/job.h b/include/qemu/job.h index 5c92c53ef0..6f5b13751a 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -204,6 +204,13 @@ struct JobDriver { */ void (*drain)(Job *job); + /** + * If the callback is not NULL, exit will be invoked from the main thread + * when the job's coroutine has finished, but before transactional + * convergence; before @prepare or @abort. + */ + void (*exit)(Job *job); + /** * If the callback is not NULL, prepare will be invoked when all the jobs * belonging to the same transaction complete; or upon this job's completion diff --git a/job.c b/job.c index c9de1af556..fae8e6047c 100644 --- a/job.c +++ b/job.c @@ -535,6 +535,19 @@ void job_drain(Job *job) } } +static void job_exit(void *opaque) +{ + Job *job = (Job *)opaque; + AioContext *aio_context = job->aio_context; + + if (job->driver->exit) { + aio_context_acquire(aio_context); + job->driver->exit(job); + aio_context_release(aio_context); + } + job_completed(job, job->ret); +} + /** * All jobs must allow a pause point before entering their job proper. This * ensures that jobs can be paused prior to being started, then resumed later. @@ -546,6 +559,12 @@ static void coroutine_fn job_co_entry(void *opaque) assert(job && job->driver && job->driver->run); job_pause_point(job); job->ret = job->driver->run(job, &job->err); + if (!job->deferred_to_main_loop) { + job->deferred_to_main_loop = true; + aio_bh_schedule_oneshot(qemu_get_aio_context(), + job_exit, + job); + } } From patchwork Fri Aug 17 19:04:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 959083 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41sXv40kBDz9s2P for ; Sat, 18 Aug 2018 05:14:24 +1000 (AEST) Received: from localhost ([::1]:36044 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqkCT-0005wG-Jf for incoming@patchwork.ozlabs.org; Fri, 17 Aug 2018 15:14:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36602) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk8y-0001Dr-HK for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:10:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqk3z-0006uC-R3 for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:05:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56632) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqk3m-0006p4-09; Fri, 17 Aug 2018 15:05:22 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4E37F307C717; Fri, 17 Aug 2018 19:05:21 +0000 (UTC) Received: from probe.redhat.com (ovpn-123-11.rdu2.redhat.com [10.10.123.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3209816C66; Fri, 17 Aug 2018 19:05:20 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 17 Aug 2018 15:04:54 -0400 Message-Id: <20180817190457.8292-5-jsnow@redhat.com> In-Reply-To: <20180817190457.8292-1-jsnow@redhat.com> References: <20180817190457.8292-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Fri, 17 Aug 2018 19:05:21 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 4/7] block/commit: utilize job_exit shim X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , Jeff Cody , jtc@redhat.com, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Change the manual deferment to commit_complete into the implicit callback to job_exit, renaming commit_complete to commit_exit. This conversion does change the timing of when job_completed is called to after the bdrv_replace_node and bdrv_unref calls, which could have implications for bjob->blk which will now be put down after this cleanup. Kevin highlights that we did not take any permissions for that backend at job creation time, so it is safe to reorder these operations. Signed-off-by: John Snow --- block/commit.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/block/commit.c b/block/commit.c index 4a17bb73ec..93c3b6a39e 100644 --- a/block/commit.c +++ b/block/commit.c @@ -68,19 +68,13 @@ static int coroutine_fn commit_populate(BlockBackend *bs, BlockBackend *base, return 0; } -typedef struct { - int ret; -} CommitCompleteData; - -static void commit_complete(Job *job, void *opaque) +static void commit_exit(Job *job) { CommitBlockJob *s = container_of(job, CommitBlockJob, common.job); BlockJob *bjob = &s->common; - CommitCompleteData *data = opaque; BlockDriverState *top = blk_bs(s->top); BlockDriverState *base = blk_bs(s->base); BlockDriverState *commit_top_bs = s->commit_top_bs; - int ret = data->ret; bool remove_commit_top_bs = false; /* Make sure commit_top_bs and top stay around until bdrv_replace_node() */ @@ -93,8 +87,8 @@ static void commit_complete(Job *job, void *opaque) if (!job_is_cancelled(job) && ret == 0) { /* success */ - ret = bdrv_drop_intermediate(s->commit_top_bs, base, - s->backing_file_str); + job->ret = bdrv_drop_intermediate(s->commit_top_bs, base, + s->backing_file_str); } else { /* XXX Can (or should) we somehow keep 'consistent read' blocked even * after the failed/cancelled commit job is gone? If we already wrote @@ -117,9 +111,6 @@ static void commit_complete(Job *job, void *opaque) * bdrv_set_backing_hd() to fail. */ block_job_remove_all_bdrv(bjob); - job_completed(job, ret); - g_free(data); - /* If bdrv_drop_intermediate() didn't already do that, remove the commit * filter driver from the backing chain. Do this as the final step so that * the 'consistent read' permission can be granted. */ @@ -137,7 +128,6 @@ static void commit_complete(Job *job, void *opaque) static int coroutine_fn commit_run(Job *job, Error **errp) { CommitBlockJob *s = container_of(job, CommitBlockJob, common.job); - CommitCompleteData *data; int64_t offset; uint64_t delay_ns = 0; int ret = 0; @@ -210,9 +200,6 @@ static int coroutine_fn commit_run(Job *job, Error **errp) out: qemu_vfree(buf); - data = g_malloc(sizeof(*data)); - data->ret = ret; - job_defer_to_main_loop(&s->common.job, commit_complete, data); return ret; } @@ -224,6 +211,7 @@ static const BlockJobDriver commit_job_driver = { .user_resume = block_job_user_resume, .drain = block_job_drain, .run = commit_run, + .exit = commit_exit, }, }; From patchwork Fri Aug 17 19:04:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 959076 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41sXqp4j6tz9s5c for ; Sat, 18 Aug 2018 05:11:34 +1000 (AEST) Received: from localhost ([::1]:36028 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk9k-0001Ju-9D for incoming@patchwork.ozlabs.org; Fri, 17 Aug 2018 15:11:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36455) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk8x-0000x6-Tv for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:10:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqk3z-0006u3-Ov for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:05:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56642) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqk3p-0006qF-4k; Fri, 17 Aug 2018 15:05:25 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B60D0307C717; Fri, 17 Aug 2018 19:05:23 +0000 (UTC) Received: from probe.redhat.com (ovpn-123-11.rdu2.redhat.com [10.10.123.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5DAC019488; Fri, 17 Aug 2018 19:05:22 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 17 Aug 2018 15:04:55 -0400 Message-Id: <20180817190457.8292-6-jsnow@redhat.com> In-Reply-To: <20180817190457.8292-1-jsnow@redhat.com> References: <20180817190457.8292-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Fri, 17 Aug 2018 19:05:23 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 5/7] block/mirror: utilize job_exit shim X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , Jeff Cody , jtc@redhat.com, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Change the manual deferment to mirror_exit into the implicit callback to job_exit and the mirror_exit callback. This does change the order of some bdrv_unref calls and job_completed, but thanks to the new context in which we call .job_exit, this is safe to defer the possible flushing of any nodes to the job_finalize_single cleanup stage. Signed-off-by: John Snow --- block/mirror.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index be5dc6b7b0..57b4ac97d8 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -607,21 +607,17 @@ static void mirror_wait_for_all_io(MirrorBlockJob *s) } } -typedef struct { - int ret; -} MirrorExitData; - -static void mirror_exit(Job *job, void *opaque) +static void mirror_exit(Job *job) { MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); BlockJob *bjob = &s->common; - MirrorExitData *data = opaque; MirrorBDSOpaque *bs_opaque = s->mirror_top_bs->opaque; AioContext *replace_aio_context = NULL; BlockDriverState *src = s->mirror_top_bs->backing->bs; BlockDriverState *target_bs = blk_bs(s->target); BlockDriverState *mirror_top_bs = s->mirror_top_bs; Error *local_err = NULL; + int ret = job->ret; bdrv_release_dirty_bitmap(src, s->dirty_bitmap); @@ -652,7 +648,7 @@ static void mirror_exit(Job *job, void *opaque) bdrv_set_backing_hd(target_bs, backing, &local_err); if (local_err) { error_report_err(local_err); - data->ret = -EPERM; + ret = -EPERM; } } } @@ -662,7 +658,7 @@ static void mirror_exit(Job *job, void *opaque) aio_context_acquire(replace_aio_context); } - if (s->should_complete && data->ret == 0) { + if (s->should_complete && ret == 0) { BlockDriverState *to_replace = src; if (s->to_replace) { to_replace = s->to_replace; @@ -679,7 +675,7 @@ static void mirror_exit(Job *job, void *opaque) bdrv_drained_end(target_bs); if (local_err) { error_report_err(local_err); - data->ret = -EPERM; + ret = -EPERM; } } if (s->to_replace) { @@ -710,12 +706,12 @@ static void mirror_exit(Job *job, void *opaque) blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort); bs_opaque->job = NULL; - job_completed(job, data->ret); - g_free(data); bdrv_drained_end(src); bdrv_unref(mirror_top_bs); bdrv_unref(src); + + job->ret = ret; } static void mirror_throttle(MirrorBlockJob *s) @@ -815,7 +811,6 @@ static int mirror_flush(MirrorBlockJob *s) static int coroutine_fn mirror_run(Job *job, Error **errp) { MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); - MirrorExitData *data; BlockDriverState *bs = s->mirror_top_bs->backing->bs; BlockDriverState *target_bs = blk_bs(s->target); bool need_drain = true; @@ -1035,14 +1030,10 @@ immediate_exit: g_free(s->in_flight_bitmap); bdrv_dirty_iter_free(s->dbi); - data = g_malloc(sizeof(*data)); - data->ret = ret; - if (need_drain) { bdrv_drained_begin(bs); } - job_defer_to_main_loop(&s->common.job, mirror_exit, data); return ret; } @@ -1141,6 +1132,7 @@ static const BlockJobDriver mirror_job_driver = { .user_resume = block_job_user_resume, .drain = block_job_drain, .run = mirror_run, + .exit = mirror_exit, .pause = mirror_pause, .complete = mirror_complete, }, @@ -1157,6 +1149,7 @@ static const BlockJobDriver commit_active_job_driver = { .user_resume = block_job_user_resume, .drain = block_job_drain, .run = mirror_run, + .exit = mirror_exit, .pause = mirror_pause, .complete = mirror_complete, }, From patchwork Fri Aug 17 19:04:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 959077 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41sXqq4JTgz9s2P for ; Sat, 18 Aug 2018 05:11:35 +1000 (AEST) Received: from localhost ([::1]:36029 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk9l-0001KW-3m for incoming@patchwork.ozlabs.org; Fri, 17 Aug 2018 15:11:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36602) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk8v-0001Dr-7f for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:10:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqk43-0006wZ-7V for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:05:40 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45524) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqk3z-0006tS-Ox; Fri, 17 Aug 2018 15:05:35 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 787474E8A8; Fri, 17 Aug 2018 19:05:33 +0000 (UTC) Received: from probe.redhat.com (ovpn-123-11.rdu2.redhat.com [10.10.123.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id F245D19488; Fri, 17 Aug 2018 19:05:23 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 17 Aug 2018 15:04:56 -0400 Message-Id: <20180817190457.8292-7-jsnow@redhat.com> In-Reply-To: <20180817190457.8292-1-jsnow@redhat.com> References: <20180817190457.8292-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 17 Aug 2018 19:05:33 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 6/7] jobs: utilize job_exit shim X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , Jeff Cody , jtc@redhat.com, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Utilize the job_exit shim by not calling job_defer_to_main_loop, and where applicable, converting the deferred callback into the job_exit callback. This converts backup, stream, create, and the unit tests all at once. None of these jobs undergo and order of operations changes, so it should be a mechanical change. Signed-off-by: John Snow --- block/backup.c | 16 ---------------- block/create.c | 14 +++----------- block/stream.c | 22 +++++++--------------- tests/test-bdrv-drain.c | 6 ------ tests/test-blockjob-txn.c | 11 ++--------- tests/test-blockjob.c | 10 ++++------ 6 files changed, 16 insertions(+), 63 deletions(-) diff --git a/block/backup.c b/block/backup.c index 1e965d54e5..a67b7fa96b 100644 --- a/block/backup.c +++ b/block/backup.c @@ -380,18 +380,6 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job, } } -typedef struct { - int ret; -} BackupCompleteData; - -static void backup_complete(Job *job, void *opaque) -{ - BackupCompleteData *data = opaque; - - job_completed(job, data->ret); - g_free(data); -} - static bool coroutine_fn yield_and_check(BackupBlockJob *job) { uint64_t delay_ns; @@ -483,7 +471,6 @@ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job) static int coroutine_fn backup_run(Job *opaque_job, Error **errp) { BackupBlockJob *job = container_of(opaque_job, BackupBlockJob, common.job); - BackupCompleteData *data; BlockDriverState *bs = blk_bs(job->common.blk); int64_t offset, nb_clusters; int ret = 0; @@ -584,9 +571,6 @@ static int coroutine_fn backup_run(Job *opaque_job, Error **errp) qemu_co_rwlock_unlock(&job->flush_rwlock); hbitmap_free(job->copy_bitmap); - data = g_malloc(sizeof(*data)); - data->ret = ret; - job_defer_to_main_loop(&job->common.job, backup_complete, data); return ret; } diff --git a/block/create.c b/block/create.c index 26a385c6c7..95341219ef 100644 --- a/block/create.c +++ b/block/create.c @@ -34,28 +34,20 @@ typedef struct BlockdevCreateJob { Job common; BlockDriver *drv; BlockdevCreateOptions *opts; - int ret; } BlockdevCreateJob; -static void blockdev_create_complete(Job *job, void *opaque) -{ - BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common); - - job_completed(job, s->ret); -} - static int coroutine_fn blockdev_create_run(Job *job, Error **errp) { BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common); + int ret; job_progress_set_remaining(&s->common, 1); - s->ret = s->drv->bdrv_co_create(s->opts, errp); + ret = s->drv->bdrv_co_create(s->opts, errp); job_progress_update(&s->common, 1); qapi_free_BlockdevCreateOptions(s->opts); - job_defer_to_main_loop(&s->common, blockdev_create_complete, NULL); - return s->ret; + return ret; } static const JobDriver blockdev_create_job_driver = { diff --git a/block/stream.c b/block/stream.c index 26a775386b..67e1e72e23 100644 --- a/block/stream.c +++ b/block/stream.c @@ -54,20 +54,16 @@ static int coroutine_fn stream_populate(BlockBackend *blk, return blk_co_preadv(blk, offset, qiov.size, &qiov, BDRV_REQ_COPY_ON_READ); } -typedef struct { - int ret; -} StreamCompleteData; - -static void stream_complete(Job *job, void *opaque) +static void stream_exit(Job *job) { StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); BlockJob *bjob = &s->common; - StreamCompleteData *data = opaque; BlockDriverState *bs = blk_bs(bjob->blk); BlockDriverState *base = s->base; Error *local_err = NULL; + int ret = job->ret; - if (!job_is_cancelled(job) && bs->backing && data->ret == 0) { + if (!job_is_cancelled(job) && bs->backing && ret == 0) { const char *base_id = NULL, *base_fmt = NULL; if (base) { base_id = s->backing_file_str; @@ -75,11 +71,11 @@ static void stream_complete(Job *job, void *opaque) base_fmt = base->drv->format_name; } } - data->ret = bdrv_change_backing_file(bs, base_id, base_fmt); + ret = bdrv_change_backing_file(bs, base_id, base_fmt); bdrv_set_backing_hd(bs, base, &local_err); if (local_err) { error_report_err(local_err); - data->ret = -EPERM; + ret = -EPERM; goto out; } } @@ -93,14 +89,12 @@ out: } g_free(s->backing_file_str); - job_completed(job, data->ret); - g_free(data); + job->ret = ret; } static int coroutine_fn stream_run(Job *job, Error **errp) { StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); - StreamCompleteData *data; BlockBackend *blk = s->common.blk; BlockDriverState *bs = blk_bs(blk); BlockDriverState *base = s->base; @@ -203,9 +197,6 @@ static int coroutine_fn stream_run(Job *job, Error **errp) out: /* Modify backing chain and close BDSes in main loop */ - data = g_malloc(sizeof(*data)); - data->ret = ret; - job_defer_to_main_loop(&s->common.job, stream_complete, data); return ret; } @@ -215,6 +206,7 @@ static const BlockJobDriver stream_job_driver = { .job_type = JOB_TYPE_STREAM, .free = block_job_free, .run = stream_run, + .exit = stream_exit, .user_resume = block_job_user_resume, .drain = block_job_drain, }, diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c index 00604dfc0c..9bcb3c72af 100644 --- a/tests/test-bdrv-drain.c +++ b/tests/test-bdrv-drain.c @@ -752,11 +752,6 @@ typedef struct TestBlockJob { bool should_complete; } TestBlockJob; -static void test_job_completed(Job *job, void *opaque) -{ - job_completed(job, 0); -} - static int coroutine_fn test_job_run(Job *job, Error **errp) { TestBlockJob *s = container_of(job, TestBlockJob, common.job); @@ -770,7 +765,6 @@ static int coroutine_fn test_job_run(Job *job, Error **errp) job_pause_point(&s->common.job); } - job_defer_to_main_loop(&s->common.job, test_job_completed, NULL); return 0; } diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c index 82cedee78b..ef29f35e44 100644 --- a/tests/test-blockjob-txn.c +++ b/tests/test-blockjob-txn.c @@ -24,17 +24,11 @@ typedef struct { int *result; } TestBlockJob; -static void test_block_job_complete(Job *job, void *opaque) +static void test_block_job_exit(Job *job) { BlockJob *bjob = container_of(job, BlockJob, job); BlockDriverState *bs = blk_bs(bjob->blk); - int rc = (intptr_t)opaque; - if (job_is_cancelled(job)) { - rc = -ECANCELED; - } - - job_completed(job, rc); bdrv_unref(bs); } @@ -54,8 +48,6 @@ static int coroutine_fn test_block_job_run(Job *job, Error **errp) } } - job_defer_to_main_loop(job, test_block_job_complete, - (void *)(intptr_t)s->rc); return s->rc; } @@ -81,6 +73,7 @@ static const BlockJobDriver test_block_job_driver = { .user_resume = block_job_user_resume, .drain = block_job_drain, .run = test_block_job_run, + .exit = test_block_job_exit, }, }; diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c index 408a226939..ad4a65bc78 100644 --- a/tests/test-blockjob.c +++ b/tests/test-blockjob.c @@ -163,11 +163,10 @@ typedef struct CancelJob { bool completed; } CancelJob; -static void cancel_job_completed(Job *job, void *opaque) +static void cancel_job_exit(Job *job) { - CancelJob *s = opaque; + CancelJob *s = container_of(job, CancelJob, common.job); s->completed = true; - job_completed(job, 0); } static void cancel_job_complete(Job *job, Error **errp) @@ -182,7 +181,7 @@ static int coroutine_fn cancel_job_run(Job *job, Error **errp) while (!s->should_complete) { if (job_is_cancelled(&s->common.job)) { - goto defer; + return 0; } if (!job_is_ready(&s->common.job) && s->should_converge) { @@ -192,8 +191,6 @@ static int coroutine_fn cancel_job_run(Job *job, Error **errp) job_sleep_ns(&s->common.job, 100000); } - defer: - job_defer_to_main_loop(&s->common.job, cancel_job_completed, s); return 0; } @@ -204,6 +201,7 @@ static const BlockJobDriver test_cancel_driver = { .user_resume = block_job_user_resume, .drain = block_job_drain, .run = cancel_job_run, + .exit = cancel_job_exit, .complete = cancel_job_complete, }, }; From patchwork Fri Aug 17 19:04:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 959075 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41sXqm3phrz9s2P for ; Sat, 18 Aug 2018 05:11:32 +1000 (AEST) Received: from localhost ([::1]:36027 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk9i-0001JM-3V for incoming@patchwork.ozlabs.org; Fri, 17 Aug 2018 15:11:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36608) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fqk8v-0001EN-AW for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:10:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqk43-0006wU-4l for qemu-devel@nongnu.org; Fri, 17 Aug 2018 15:05:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50630) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqk3z-0006tm-QE; Fri, 17 Aug 2018 15:05:36 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1B19381109; Fri, 17 Aug 2018 19:05:35 +0000 (UTC) Received: from probe.redhat.com (ovpn-123-11.rdu2.redhat.com [10.10.123.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id E027819488; Fri, 17 Aug 2018 19:05:33 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 17 Aug 2018 15:04:57 -0400 Message-Id: <20180817190457.8292-8-jsnow@redhat.com> In-Reply-To: <20180817190457.8292-1-jsnow@redhat.com> References: <20180817190457.8292-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 17 Aug 2018 19:05:35 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 7/7] jobs: remove job_defer_to_main_loop X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , Jeff Cody , jtc@redhat.com, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Now that the job infrastructure is handling the job_completed call for all implemented jobs, we can remove the interface that allowed jobs to schedule their own completion. Signed-off-by: John Snow Reviewed-by: Max Reitz --- include/qemu/job.h | 17 ----------------- job.c | 40 ++-------------------------------------- 2 files changed, 2 insertions(+), 55 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index 6f5b13751a..8349702e3e 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -558,23 +558,6 @@ void job_finalize(Job *job, Error **errp); */ void job_dismiss(Job **job, Error **errp); -typedef void JobDeferToMainLoopFn(Job *job, void *opaque); - -/** - * @job: The job - * @fn: The function to run in the main loop - * @opaque: The opaque value that is passed to @fn - * - * This function must be called by the main job coroutine just before it - * returns. @fn is executed in the main loop with the job AioContext acquired. - * - * Block jobs must call bdrv_unref(), bdrv_close(), and anything that uses - * bdrv_drain_all() in the main loop. - * - * The @job AioContext is held while @fn executes. - */ -void job_defer_to_main_loop(Job *job, JobDeferToMainLoopFn *fn, void *opaque); - /** * Synchronously finishes the given @job. If @finish is given, it is called to * trigger completion or cancellation of the job. diff --git a/job.c b/job.c index fae8e6047c..dbb225e35d 100644 --- a/job.c +++ b/job.c @@ -559,12 +559,8 @@ static void coroutine_fn job_co_entry(void *opaque) assert(job && job->driver && job->driver->run); job_pause_point(job); job->ret = job->driver->run(job, &job->err); - if (!job->deferred_to_main_loop) { - job->deferred_to_main_loop = true; - aio_bh_schedule_oneshot(qemu_get_aio_context(), - job_exit, - job); - } + job->deferred_to_main_loop = true; + aio_bh_schedule_oneshot(qemu_get_aio_context(), job_exit, job); } @@ -968,38 +964,6 @@ void job_complete(Job *job, Error **errp) job->driver->complete(job, errp); } - -typedef struct { - Job *job; - JobDeferToMainLoopFn *fn; - void *opaque; -} JobDeferToMainLoopData; - -static void job_defer_to_main_loop_bh(void *opaque) -{ - JobDeferToMainLoopData *data = opaque; - Job *job = data->job; - AioContext *aio_context = job->aio_context; - - aio_context_acquire(aio_context); - data->fn(data->job, data->opaque); - aio_context_release(aio_context); - - g_free(data); -} - -void job_defer_to_main_loop(Job *job, JobDeferToMainLoopFn *fn, void *opaque) -{ - JobDeferToMainLoopData *data = g_malloc(sizeof(*data)); - data->job = job; - data->fn = fn; - data->opaque = opaque; - job->deferred_to_main_loop = true; - - aio_bh_schedule_oneshot(qemu_get_aio_context(), - job_defer_to_main_loop_bh, data); -} - int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp) { Error *local_err = NULL;