From nobody Wed Oct 29 22:55:03 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 152588446512219.854949421810034; Wed, 9 May 2018 09:47:45 -0700 (PDT) Received: from localhost ([::1]:57645 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fGSFj-00028K-V3 for importer@patchew.org; Wed, 09 May 2018 12:47:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52437) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fGRwO-0005eh-Op for qemu-devel@nongnu.org; Wed, 09 May 2018 12:27:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fGRwM-0002Gv-5k for qemu-devel@nongnu.org; Wed, 09 May 2018 12:27:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50608 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fGRwG-00022Q-65; Wed, 09 May 2018 12:27:36 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9601B4059FE1; Wed, 9 May 2018 16:27:35 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-193.ams2.redhat.com [10.36.117.193]) by smtp.corp.redhat.com (Postfix) with ESMTP id 47D3F2023433; Wed, 9 May 2018 16:27:34 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Wed, 9 May 2018 18:26:15 +0200 Message-Id: <20180509162637.15575-21-kwolf@redhat.com> In-Reply-To: <20180509162637.15575-1-kwolf@redhat.com> References: <20180509162637.15575-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Wed, 09 May 2018 16:27:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Wed, 09 May 2018 16:27:35 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH 20/42] job: Move pause/resume functions to Job 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, qemu-devel@nongnu.org, jcody@redhat.com, armbru@redhat.com, mreitz@redhat.com, jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" While we already moved the state related to job pausing to Job, the functions to do were still BlockJob only. This commit moves them over to Job. Signed-off-by: Kevin Wolf Reviewed-by: John Snow Reviewed-by: Max Reitz --- include/block/blockjob.h | 32 ------------------- include/block/blockjob_int.h | 7 +++++ include/qemu/job.h | 37 ++++++++++++++++++++++ block/backup.c | 1 + block/commit.c | 1 + block/mirror.c | 2 ++ block/stream.c | 1 + blockdev.c | 6 ++-- blockjob.c | 73 ++++++++++------------------------------= ---- job.c | 51 +++++++++++++++++++++++++++++++ tests/test-bdrv-drain.c | 1 + tests/test-blockjob-txn.c | 1 + tests/test-blockjob.c | 6 ++-- 13 files changed, 125 insertions(+), 94 deletions(-) diff --git a/include/block/blockjob.h b/include/block/blockjob.h index c0448206e2..ce136ff2ac 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -57,12 +57,6 @@ typedef struct BlockJob { bool force; =20 /** - * Set to true if the job is paused by user. Can be unpaused with the - * block-job-resume QMP command. - */ - bool user_paused; - - /** * Set to true when the job is ready to be completed. */ bool ready; @@ -248,32 +242,6 @@ void block_job_progress_set_remaining(BlockJob *job, u= int64_t remaining); BlockJobInfo *block_job_query(BlockJob *job, Error **errp); =20 /** - * block_job_user_pause: - * @job: The job to be paused. - * - * Asynchronously pause the specified job. - * Do not allow a resume until a matching call to block_job_user_resume. - */ -void block_job_user_pause(BlockJob *job, Error **errp); - -/** - * block_job_paused: - * @job: The job to query. - * - * Returns true if the job is user-paused. - */ -bool block_job_user_paused(BlockJob *job); - -/** - * block_job_user_resume: - * @job: The job to be resumed. - * - * Resume the specified job. - * Must be paired with a preceding block_job_user_pause. - */ -void block_job_user_resume(BlockJob *job, Error **errp); - -/** * block_job_user_cancel: * @job: The job to be cancelled. * @force: Quit a job without waiting for data to be in sync. diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h index 8937f5b163..7e705ae0e9 100644 --- a/include/block/blockjob_int.h +++ b/include/block/blockjob_int.h @@ -134,6 +134,13 @@ void *block_job_create(const char *job_id, const Block= JobDriver *driver, void block_job_free(Job *job); =20 /** + * block_job_user_resume: + * Callback to be used for JobDriver.user_resume in all block jobs. Resets= the + * iostatus when the user resumes @job. + */ +void block_job_user_resume(Job *job); + +/** * block_job_yield: * @job: The job that calls the function. * diff --git a/include/qemu/job.h b/include/qemu/job.h index ddfa824315..0ba6cb3161 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -83,6 +83,12 @@ typedef struct Job { bool paused; =20 /** + * Set to true if the job is paused by user. Can be unpaused with the + * block-job-resume QMP command. + */ + bool user_paused; + + /** * Set to true if the job should cancel itself. The flag must * always be tested just before toggling the busy flag from false * to true. After a job has been cancelled, it should only yield @@ -124,6 +130,12 @@ struct JobDriver { */ void coroutine_fn (*resume)(Job *job); =20 + /** + * Called when the job is resumed by the user (i.e. user_paused becomes + * false). .user_resume is called before .resume. + */ + void (*user_resume)(Job *job); + /** Called when the job is freed */ void (*free)(Job *job); }; @@ -203,6 +215,31 @@ const char *job_type_str(Job *job); bool job_is_cancelled(Job *job); =20 /** + * Request @job to pause at the next pause point. Must be paired with + * job_resume(). If the job is supposed to be resumed by user action, call + * job_user_pause() instead. + */ +void job_pause(Job *job); + +/** Resumes a @job paused with job_pause. */ +void job_resume(Job *job); + +/** + * Asynchronously pause the specified @job. + * Do not allow a resume until a matching call to job_user_resume. + */ +void job_user_pause(Job *job, Error **errp); + +/** Returns true if the job is user-paused. */ +bool job_user_paused(Job *job); + +/** + * Resume the specified @job. + * Must be paired with a preceding job_user_pause. + */ +void job_user_resume(Job *job, Error **errp); + +/** * Get the next element from the list of block jobs after @job, or the * first one if @job is %NULL. * diff --git a/block/backup.c b/block/backup.c index f3a4f7c898..4d011d5a5c 100644 --- a/block/backup.c +++ b/block/backup.c @@ -528,6 +528,7 @@ static const BlockJobDriver backup_job_driver =3D { .instance_size =3D sizeof(BackupBlockJob), .job_type =3D JOB_TYPE_BACKUP, .free =3D block_job_free, + .user_resume =3D block_job_user_resume, .start =3D backup_run, }, .commit =3D backup_commit, diff --git a/block/commit.c b/block/commit.c index 1c6cb6c298..c4a98e5804 100644 --- a/block/commit.c +++ b/block/commit.c @@ -220,6 +220,7 @@ static const BlockJobDriver commit_job_driver =3D { .instance_size =3D sizeof(CommitBlockJob), .job_type =3D JOB_TYPE_COMMIT, .free =3D block_job_free, + .user_resume =3D block_job_user_resume, .start =3D commit_run, }, }; diff --git a/block/mirror.c b/block/mirror.c index 6d54729557..80f068ca75 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -991,6 +991,7 @@ static const BlockJobDriver mirror_job_driver =3D { .instance_size =3D sizeof(MirrorBlockJob), .job_type =3D JOB_TYPE_MIRROR, .free =3D block_job_free, + .user_resume =3D block_job_user_resume, .start =3D mirror_run, .pause =3D mirror_pause, }, @@ -1004,6 +1005,7 @@ static const BlockJobDriver commit_active_job_driver = =3D { .instance_size =3D sizeof(MirrorBlockJob), .job_type =3D JOB_TYPE_COMMIT, .free =3D block_job_free, + .user_resume =3D block_job_user_resume, .start =3D mirror_run, .pause =3D mirror_pause, }, diff --git a/block/stream.c b/block/stream.c index 1faab02086..e81b488a22 100644 --- a/block/stream.c +++ b/block/stream.c @@ -214,6 +214,7 @@ static const BlockJobDriver stream_job_driver =3D { .job_type =3D JOB_TYPE_STREAM, .free =3D block_job_free, .start =3D stream_run, + .user_resume =3D block_job_user_resume, }, }; =20 diff --git a/blockdev.c b/blockdev.c index c551fdf39a..3533c0dd6a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3844,7 +3844,7 @@ void qmp_block_job_cancel(const char *device, force =3D false; } =20 - if (block_job_user_paused(job) && !force) { + if (job_user_paused(&job->job) && !force) { error_setg(errp, "The block job for device '%s' is currently pause= d", device); goto out; @@ -3866,7 +3866,7 @@ void qmp_block_job_pause(const char *device, Error **= errp) } =20 trace_qmp_block_job_pause(job); - block_job_user_pause(job, errp); + job_user_pause(&job->job, errp); aio_context_release(aio_context); } =20 @@ -3880,7 +3880,7 @@ void qmp_block_job_resume(const char *device, Error *= *errp) } =20 trace_qmp_block_job_resume(job); - block_job_user_resume(job, errp); + job_user_resume(&job->job, errp); aio_context_release(aio_context); } =20 diff --git a/blockjob.c b/blockjob.c index 342ec74f66..a2b6bfc975 100644 --- a/blockjob.c +++ b/blockjob.c @@ -141,21 +141,6 @@ static void block_job_txn_del_job(BlockJob *job) } } =20 -static void block_job_pause(BlockJob *job) -{ - job->job.pause_count++; -} - -static void block_job_resume(BlockJob *job) -{ - assert(job->job.pause_count > 0); - job->job.pause_count--; - if (job->job.pause_count) { - return; - } - block_job_enter(job); -} - static void block_job_attached_aio_context(AioContext *new_context, void *opaque); static void block_job_detach_aio_context(void *opaque); @@ -186,7 +171,7 @@ static void block_job_attached_aio_context(AioContext *= new_context, job->driver->attached_aio_context(job, new_context); } =20 - block_job_resume(job); + job_resume(&job->job); } =20 static void block_job_drain(BlockJob *job) @@ -207,7 +192,7 @@ static void block_job_detach_aio_context(void *opaque) /* In case the job terminates during aio_poll()... */ job_ref(&job->job); =20 - block_job_pause(job); + job_pause(&job->job); =20 while (!job->job.paused && !job->completed) { block_job_drain(job); @@ -226,13 +211,13 @@ static char *child_job_get_parent_desc(BdrvChild *c) static void child_job_drained_begin(BdrvChild *c) { BlockJob *job =3D c->opaque; - block_job_pause(job); + job_pause(&job->job); } =20 static void child_job_drained_end(BdrvChild *c) { BlockJob *job =3D c->opaque; - block_job_resume(job); + job_resume(&job->job); } =20 static const BdrvChildRole child_job =3D { @@ -389,9 +374,9 @@ static void block_job_cancel_async(BlockJob *job, bool = force) if (job->iostatus !=3D BLOCK_DEVICE_IO_STATUS_OK) { block_job_iostatus_reset(job); } - if (job->user_paused) { + if (job->job.user_paused) { /* Do not call block_job_enter here, the caller will handle it. */ - job->user_paused =3D false; + job->job.user_paused =3D false; job->job.pause_count--; } job->job.cancelled =3D true; @@ -621,39 +606,6 @@ void block_job_dismiss(BlockJob **jobptr, Error **errp) *jobptr =3D NULL; } =20 -void block_job_user_pause(BlockJob *job, Error **errp) -{ - if (job_apply_verb(&job->job, JOB_VERB_PAUSE, errp)) { - return; - } - if (job->user_paused) { - error_setg(errp, "Job is already paused"); - return; - } - job->user_paused =3D true; - block_job_pause(job); -} - -bool block_job_user_paused(BlockJob *job) -{ - return job->user_paused; -} - -void block_job_user_resume(BlockJob *job, Error **errp) -{ - assert(job); - if (!job->user_paused || job->job.pause_count <=3D 0) { - error_setg(errp, "Can't resume a job that was not paused"); - return; - } - if (job_apply_verb(&job->job, JOB_VERB_RESUME, errp)) { - return; - } - block_job_iostatus_reset(job); - job->user_paused =3D false; - block_job_resume(job); -} - void block_job_cancel(BlockJob *job, bool force) { if (job->job.status =3D=3D JOB_STATUS_CONCLUDED) { @@ -844,6 +796,7 @@ void *block_job_create(const char *job_id, const BlockJ= obDriver *driver, =20 assert(is_block_job(&job->job)); assert(job->job.driver->free =3D=3D &block_job_free); + assert(job->job.driver->user_resume =3D=3D &block_job_user_resume); =20 job->driver =3D driver; job->blk =3D blk; @@ -934,10 +887,16 @@ void block_job_iostatus_reset(BlockJob *job) if (job->iostatus =3D=3D BLOCK_DEVICE_IO_STATUS_OK) { return; } - assert(job->user_paused && job->job.pause_count > 0); + assert(job->job.user_paused && job->job.pause_count > 0); job->iostatus =3D BLOCK_DEVICE_IO_STATUS_OK; } =20 +void block_job_user_resume(Job *job) +{ + BlockJob *bjob =3D container_of(job, BlockJob, job); + block_job_iostatus_reset(bjob); +} + void block_job_event_ready(BlockJob *job) { job_state_transition(&job->job, JOB_STATUS_READY); @@ -984,9 +943,9 @@ BlockErrorAction block_job_error_action(BlockJob *job, = BlockdevOnError on_err, action, &error_abort); } if (action =3D=3D BLOCK_ERROR_ACTION_STOP) { - block_job_pause(job); + job_pause(&job->job); /* make the pause user visible, which will be resumed from QMP. */ - job->user_paused =3D true; + job->job.user_paused =3D true; block_job_iostatus_set_err(job, error); } return action; diff --git a/job.c b/job.c index 932ccea105..94ad01a51a 100644 --- a/job.c +++ b/job.c @@ -341,6 +341,57 @@ void job_start(Job *job) aio_co_enter(job->aio_context, job->co); } =20 +void job_pause(Job *job) +{ + job->pause_count++; +} + +void job_resume(Job *job) +{ + assert(job->pause_count > 0); + job->pause_count--; + if (job->pause_count) { + return; + } + job_enter(job); +} + +void job_user_pause(Job *job, Error **errp) +{ + if (job_apply_verb(job, JOB_VERB_PAUSE, errp)) { + return; + } + if (job->user_paused) { + error_setg(errp, "Job is already paused"); + return; + } + job->user_paused =3D true; + job_pause(job); +} + +bool job_user_paused(Job *job) +{ + return job->user_paused; +} + +void job_user_resume(Job *job, Error **errp) +{ + assert(job); + if (!job->user_paused || job->pause_count <=3D 0) { + error_setg(errp, "Can't resume a job that was not paused"); + return; + } + if (job_apply_verb(job, JOB_VERB_RESUME, errp)) { + return; + } + if (job->driver->user_resume) { + job->driver->user_resume(job); + } + job->user_paused =3D false; + job_resume(job); +} + + typedef struct { Job *job; JobDeferToMainLoopFn *fn; diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c index 50232f5eaf..c993512f66 100644 --- a/tests/test-bdrv-drain.c +++ b/tests/test-bdrv-drain.c @@ -524,6 +524,7 @@ BlockJobDriver test_job_driver =3D { .job_driver =3D { .instance_size =3D sizeof(TestBlockJob), .free =3D block_job_free, + .user_resume =3D block_job_user_resume, .start =3D test_job_start, }, .complete =3D test_job_complete, diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c index 0e6162bc71..93d1ff0859 100644 --- a/tests/test-blockjob-txn.c +++ b/tests/test-blockjob-txn.c @@ -78,6 +78,7 @@ static const BlockJobDriver test_block_job_driver =3D { .job_driver =3D { .instance_size =3D sizeof(TestBlockJob), .free =3D block_job_free, + .user_resume =3D block_job_user_resume, .start =3D test_block_job_run, }, }; diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c index b329bd5274..ceb59600ed 100644 --- a/tests/test-blockjob.c +++ b/tests/test-blockjob.c @@ -20,6 +20,7 @@ static const BlockJobDriver test_block_job_driver =3D { .job_driver =3D { .instance_size =3D sizeof(BlockJob), .free =3D block_job_free, + .user_resume =3D block_job_user_resume, }, }; =20 @@ -199,6 +200,7 @@ static const BlockJobDriver test_cancel_driver =3D { .job_driver =3D { .instance_size =3D sizeof(CancelJob), .free =3D block_job_free, + .user_resume =3D block_job_user_resume, .start =3D cancel_job_start, }, .complete =3D cancel_job_complete, @@ -270,7 +272,7 @@ static void test_cancel_paused(void) job_start(&job->job); assert(job->job.status =3D=3D JOB_STATUS_RUNNING); =20 - block_job_user_pause(job, &error_abort); + job_user_pause(&job->job, &error_abort); block_job_enter(job); assert(job->job.status =3D=3D JOB_STATUS_PAUSED); =20 @@ -308,7 +310,7 @@ static void test_cancel_standby(void) block_job_enter(job); assert(job->job.status =3D=3D JOB_STATUS_READY); =20 - block_job_user_pause(job, &error_abort); + job_user_pause(&job->job, &error_abort); block_job_enter(job); assert(job->job.status =3D=3D JOB_STATUS_STANDBY); =20 --=20 2.13.6