From: Max Reitz <mreitz@redhat.com>
To: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
qemu-block@nongnu.org
Cc: kwolf@redhat.com, wencongyang2@huawei.com,
xiechanglong.d@gmail.com, armbru@redhat.com,
qemu-devel@nongnu.org, den@openvz.org, jsnow@redhat.com
Subject: Re: [PATCH v2 17/20] backup: move to block-copy
Date: Thu, 23 Jul 2020 11:47:41 +0200 [thread overview]
Message-ID: <6376705f-d24d-1b40-f4dd-480c53c7ae55@redhat.com> (raw)
In-Reply-To: <20200601181118.579-18-vsementsov@virtuozzo.com>
[-- Attachment #1.1: Type: text/plain, Size: 6501 bytes --]
On 01.06.20 20:11, Vladimir Sementsov-Ogievskiy wrote:
> This brings async request handling and block-status driven chunk sizes
> to backup out of the box, which improves backup performance.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> ---
> include/block/block-copy.h | 9 +--
> block/backup.c | 145 +++++++++++++++++++------------------
> block/block-copy.c | 21 ++----
> 3 files changed, 83 insertions(+), 92 deletions(-)
This patch feels like it should be multiple ones. I don’t see why a
patch that lets backup use block-copy (more) should have to modify the
block-copy code.
More specifically: I think that block_copy_set_progress_callback()
should be removed in a separate patch. Also, moving
@cb_opaque/@progress_opaque from BlockCopyState into BlockCopyCallState
seems like a separate patch to me, too.
(I presume if the cb had had its own opaque object from patch 5 on,
there wouldn’t be this problem now. We’d just stop using the progress
callback in backup, and remove it in one separate patch.)
[...]
> diff --git a/block/backup.c b/block/backup.c
> index ec2676abc2..59c00f5293 100644
> --- a/block/backup.c
> +++ b/block/backup.c
> @@ -44,42 +44,19 @@ typedef struct BackupBlockJob {
> BlockdevOnError on_source_error;
> BlockdevOnError on_target_error;
> uint64_t len;
> - uint64_t bytes_read;
> int64_t cluster_size;
> int max_workers;
> int64_t max_chunk;
>
> BlockCopyState *bcs;
> +
> + BlockCopyCallState *bcs_call;
Can this be more descriptive? E.g. background_bcs? bg_bcs_call? bg_bcsc?
> + int ret;
> + bool error_is_read;
> } BackupBlockJob;
>
> static const BlockJobDriver backup_job_driver;
>
[...]
> static int coroutine_fn backup_loop(BackupBlockJob *job)
> {
> - bool error_is_read;
> - int64_t offset;
> - BdrvDirtyBitmapIter *bdbi;
> - int ret = 0;
> + while (true) { /* retry loop */
> + assert(!job->bcs_call);
> + job->bcs_call = block_copy_async(job->bcs, 0,
> + QEMU_ALIGN_UP(job->len,
> + job->cluster_size),
> + true, job->max_workers, job->max_chunk,
> + backup_block_copy_callback, job);
>
> - bdbi = bdrv_dirty_iter_new(block_copy_dirty_bitmap(job->bcs));
> - while ((offset = bdrv_dirty_iter_next(bdbi)) != -1) {
> - do {
> - if (yield_and_check(job)) {
> - goto out;
> + while (job->bcs_call && !job->common.job.cancelled) {
> + /* wait and handle pauses */
Doesn’t someone need to reset BlockCopyCallState.cancelled when the job
is unpaused? I can’t see anyone doing that.
Well, or even just reentering the block-copy operation after
backup_pause() has cancelled it. Is there some magic I’m missing?
Does pausing (which leads to cancelling the block-copy operation) just
yield to the CB being invoked, so the copy operation is considered done,
and then we just enter the next iteration of the loop and try again?
But cancelling the block-copy operation leads to it returning 0, AFAIR,
so...
> +
> + job_pause_point(&job->common.job);
> +
> + if (job->bcs_call && !job->common.job.cancelled) {
> + job_yield(&job->common.job);
> }
> - ret = backup_do_cow(job, offset, job->cluster_size, &error_is_read);
> - if (ret < 0 && backup_error_action(job, error_is_read, -ret) ==
> - BLOCK_ERROR_ACTION_REPORT)
> - {
> - goto out;
> + }
> +
> + if (!job->bcs_call && job->ret == 0) {
> + /* Success */
> + return 0;
...I would assume we return here when the job is paused.
> + }
> +
> + if (job->common.job.cancelled) {
> + if (job->bcs_call) {
> + block_copy_cancel(job->bcs_call);
> }
> - } while (ret < 0);
> + return 0;
> + }
> +
> + if (!job->bcs_call && job->ret < 0 &&
Is it even possible for bcs_call to be non-NULL here?
> + (backup_error_action(job, job->error_is_read, -job->ret) ==
> + BLOCK_ERROR_ACTION_REPORT))
> + {
> + return job->ret;
> + }
So if we get an error, and the error action isn’t REPORT, we just try
the whole operation again? That doesn’t sound very IGNORE-y to me.
> }
>
> - out:
> - bdrv_dirty_iter_free(bdbi);
> - return ret;
> + g_assert_not_reached();
> }
>
> static void backup_init_bcs_bitmap(BackupBlockJob *job)
> @@ -246,9 +227,14 @@ static int coroutine_fn backup_run(Job *job, Error **errp)
> int64_t count;
>
> for (offset = 0; offset < s->len; ) {
> - if (yield_and_check(s)) {
> - ret = -ECANCELED;
> - goto out;
> + if (job_is_cancelled(job)) {
> + return -ECANCELED;
I’d either drop the out label altogether, or use it here. It’s a bit
weird to use it sometimes, but not all the time.
> + }
> +
> + job_pause_point(job);
> +
> + if (job_is_cancelled(job)) {
> + return -ECANCELED;
> }
>
> ret = block_copy_reset_unallocated(s->bcs, offset, &count);
> @@ -281,6 +267,25 @@ static int coroutine_fn backup_run(Job *job, Error **errp)
> return ret;
> }
>
> +static void coroutine_fn backup_pause(Job *job)
> +{
> + BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
> +
> + if (s->bcs_call) {
> + block_copy_cancel(s->bcs_call);
> + }
> +}
> +
> +static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
> +{
> + BackupBlockJob *s = container_of(job, BackupBlockJob, common);
> +
> + if (s->bcs) {
> + /* In block_job_create we yet don't have bcs */
Shouldn’t hurt to make it conditional, but how can we get here in
block_job_create()?
> + block_copy_set_speed(s->bcs, s->bcs_call, speed);
> + }
> +}
> +
> static const BlockJobDriver backup_job_driver = {
> .job_driver = {
> .instance_size = sizeof(BackupBlockJob),
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
next prev parent reply other threads:[~2020-07-23 9:48 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-01 18:10 [PATCH v2 00/20] backup performance: block_status + async Vladimir Sementsov-Ogievskiy
2020-06-01 18:10 ` [PATCH v2 01/20] block/block-copy: block_copy_dirty_clusters: fix failure check Vladimir Sementsov-Ogievskiy
2020-06-01 18:11 ` [PATCH v2 02/20] iotests: 129 don't check backup "busy" Vladimir Sementsov-Ogievskiy
2020-07-17 12:57 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 03/20] qapi: backup: add x-use-copy-range parameter Vladimir Sementsov-Ogievskiy
2020-07-17 13:15 ` Max Reitz
2020-07-17 15:18 ` Vladimir Sementsov-Ogievskiy
2020-06-01 18:11 ` [PATCH v2 04/20] block/block-copy: More explicit call_state Vladimir Sementsov-Ogievskiy
2020-07-17 13:45 ` Max Reitz
2020-09-18 20:11 ` Vladimir Sementsov-Ogievskiy
2020-09-21 8:54 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 05/20] block/block-copy: implement block_copy_async Vladimir Sementsov-Ogievskiy
2020-07-17 14:00 ` Max Reitz
2020-07-17 15:24 ` Vladimir Sementsov-Ogievskiy
2020-07-21 8:43 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 06/20] block/block-copy: add max_chunk and max_workers parameters Vladimir Sementsov-Ogievskiy
2020-07-22 9:39 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 07/20] block/block-copy: add ratelimit to block-copy Vladimir Sementsov-Ogievskiy
2020-07-22 11:05 ` Max Reitz
2020-09-25 18:19 ` Vladimir Sementsov-Ogievskiy
2020-06-01 18:11 ` [PATCH v2 08/20] block/block-copy: add block_copy_cancel Vladimir Sementsov-Ogievskiy
2020-07-22 11:28 ` Max Reitz
2020-10-22 20:50 ` Vladimir Sementsov-Ogievskiy
2020-10-23 9:49 ` Vladimir Sementsov-Ogievskiy
2020-11-04 17:26 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 09/20] blockjob: add set_speed to BlockJobDriver Vladimir Sementsov-Ogievskiy
2020-07-22 11:34 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 10/20] job: call job_enter from job_user_pause Vladimir Sementsov-Ogievskiy
2020-07-22 11:49 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 11/20] qapi: backup: add x-max-chunk and x-max-workers parameters Vladimir Sementsov-Ogievskiy
2020-06-02 8:19 ` Vladimir Sementsov-Ogievskiy
2020-07-22 12:22 ` Max Reitz
2020-07-23 7:43 ` Max Reitz
2020-10-22 20:35 ` Vladimir Sementsov-Ogievskiy
2020-11-04 17:19 ` Max Reitz
2020-11-09 11:11 ` Vladimir Sementsov-Ogievskiy
2020-06-01 18:11 ` [PATCH v2 12/20] iotests: 56: prepare for backup over block-copy Vladimir Sementsov-Ogievskiy
2020-07-23 7:57 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 13/20] iotests: 129: " Vladimir Sementsov-Ogievskiy
2020-07-23 8:03 ` Max Reitz
2020-10-22 21:10 ` Vladimir Sementsov-Ogievskiy
2020-11-04 17:30 ` Max Reitz
2020-11-09 12:16 ` Vladimir Sementsov-Ogievskiy
2020-06-01 18:11 ` [PATCH v2 14/20] iotests: 185: " Vladimir Sementsov-Ogievskiy
2020-07-23 8:19 ` Max Reitz
2020-10-22 21:16 ` Vladimir Sementsov-Ogievskiy
2020-06-01 18:11 ` [PATCH v2 15/20] iotests: 219: " Vladimir Sementsov-Ogievskiy
2020-07-23 8:35 ` Max Reitz
2020-10-22 21:20 ` Vladimir Sementsov-Ogievskiy
2020-06-01 18:11 ` [PATCH v2 16/20] iotests: 257: " Vladimir Sementsov-Ogievskiy
2020-07-23 8:49 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 17/20] backup: move to block-copy Vladimir Sementsov-Ogievskiy
2020-07-23 9:47 ` Max Reitz [this message]
2020-09-21 13:58 ` Vladimir Sementsov-Ogievskiy
2020-10-26 15:18 ` Vladimir Sementsov-Ogievskiy
2020-11-04 17:45 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 18/20] block/block-copy: drop unused argument of block_copy() Vladimir Sementsov-Ogievskiy
2020-07-23 13:24 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 19/20] simplebench: bench_block_job: add cmd_options argument Vladimir Sementsov-Ogievskiy
2020-07-23 13:30 ` Max Reitz
2020-06-01 18:11 ` [PATCH v2 20/20] simplebench: add bench-backup.py Vladimir Sementsov-Ogievskiy
2020-07-23 13:47 ` Max Reitz
2020-06-01 18:15 ` [PATCH v2 00/20] backup performance: block_status + async Vladimir Sementsov-Ogievskiy
2020-06-01 18:59 ` no-reply
2020-06-02 8:20 ` Vladimir Sementsov-Ogievskiy
2020-06-01 19:43 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6376705f-d24d-1b40-f4dd-480c53c7ae55@redhat.com \
--to=mreitz@redhat.com \
--cc=armbru@redhat.com \
--cc=den@openvz.org \
--cc=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@virtuozzo.com \
--cc=wencongyang2@huawei.com \
--cc=xiechanglong.d@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).