2013-06-24 23:13:11 +08:00
|
|
|
/*
|
|
|
|
* QEMU backup
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 Proxmox Server Solutions
|
block/backup: use backup-top instead of write notifiers
Drop write notifiers and use filter node instead.
= Changes =
1. Add filter-node-name argument for backup qmp api. We have to do it
in this commit, as 257 needs to be fixed.
2. There are no more write notifiers here, so is_write_notifier
parameter is dropped from block-copy paths.
3. To sync with in-flight requests at job finish we now have drained
removing of the filter, we don't need rw-lock.
4. Block-copy is now using BdrvChildren instead of BlockBackends
5. As backup-top owns these children, we also move block-copy state
into backup-top's ownership.
= Iotest changes =
56: op-blocker doesn't shoot now, as we set it on source, but then
check on filter, when trying to start second backup.
To keep the test we instead can catch another collision: both jobs will
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
interleaving with file-posix locks (as they are dependent on config)
let's use another target for second backup.
Also, it's obvious now that we'd like to drop this op-blocker at all
and add a test-case for two backups from one node (to different
destinations) actually works. But not in these series.
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
check inside qmp_blockdev_del. But we've dropped block-copy blk
objects, so no more blk objects on source bs (job blk is on backup-top
filter bs). New message is from op-blocker, which is the next check in
qmp_blockdev_add.
257: The test wants to emulate guest write during backup. They should
go to filter node, not to original source node, of course. Therefore we
need to specify filter node name and use it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2019-10-01 21:14:09 +08:00
|
|
|
* Copyright (c) 2019 Virtuozzo International GmbH.
|
2013-06-24 23:13:11 +08:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Dietmar Maurer (dietmar@proxmox.com)
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-01-19 02:01:42 +08:00
|
|
|
#include "qemu/osdep.h"
|
2013-06-24 23:13:11 +08:00
|
|
|
|
|
|
|
#include "trace.h"
|
|
|
|
#include "block/block.h"
|
|
|
|
#include "block/block_int.h"
|
2016-10-28 00:07:00 +08:00
|
|
|
#include "block/blockjob_int.h"
|
2016-07-27 15:01:43 +08:00
|
|
|
#include "block/block_backup.h"
|
2019-09-20 22:20:48 +08:00
|
|
|
#include "block/block-copy.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 16:01:28 +08:00
|
|
|
#include "qapi/error.h"
|
2015-03-18 00:22:46 +08:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2016-03-21 01:16:19 +08:00
|
|
|
#include "qemu/cutils.h"
|
2015-10-19 23:53:22 +08:00
|
|
|
#include "sysemu/block-backend.h"
|
2016-03-08 12:44:52 +08:00
|
|
|
#include "qemu/bitmap.h"
|
2017-03-01 03:33:40 +08:00
|
|
|
#include "qemu/error-report.h"
|
2013-06-24 23:13:11 +08:00
|
|
|
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
#include "block/copy-before-write.h"
|
block/backup: use backup-top instead of write notifiers
Drop write notifiers and use filter node instead.
= Changes =
1. Add filter-node-name argument for backup qmp api. We have to do it
in this commit, as 257 needs to be fixed.
2. There are no more write notifiers here, so is_write_notifier
parameter is dropped from block-copy paths.
3. To sync with in-flight requests at job finish we now have drained
removing of the filter, we don't need rw-lock.
4. Block-copy is now using BdrvChildren instead of BlockBackends
5. As backup-top owns these children, we also move block-copy state
into backup-top's ownership.
= Iotest changes =
56: op-blocker doesn't shoot now, as we set it on source, but then
check on filter, when trying to start second backup.
To keep the test we instead can catch another collision: both jobs will
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
interleaving with file-posix locks (as they are dependent on config)
let's use another target for second backup.
Also, it's obvious now that we'd like to drop this op-blocker at all
and add a test-case for two backups from one node (to different
destinations) actually works. But not in these series.
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
check inside qmp_blockdev_del. But we've dropped block-copy blk
objects, so no more blk objects on source bs (job blk is on backup-top
filter bs). New message is from op-blocker, which is the next check in
qmp_blockdev_add.
257: The test wants to emulate guest write during backup. They should
go to filter node, not to original source node, of course. Therefore we
need to specify filter node name and use it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2019-10-01 21:14:09 +08:00
|
|
|
|
2013-06-24 23:13:11 +08:00
|
|
|
typedef struct BackupBlockJob {
|
|
|
|
BlockJob common;
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
BlockDriverState *cbw;
|
2019-09-20 22:20:46 +08:00
|
|
|
BlockDriverState *source_bs;
|
2021-02-06 00:37:19 +08:00
|
|
|
BlockDriverState *target_bs;
|
2019-07-30 04:35:53 +08:00
|
|
|
|
2015-04-18 07:49:58 +08:00
|
|
|
BdrvDirtyBitmap *sync_bitmap;
|
2019-07-30 04:35:53 +08:00
|
|
|
|
2013-07-27 02:39:04 +08:00
|
|
|
MirrorSyncMode sync_mode;
|
2019-07-30 04:35:52 +08:00
|
|
|
BitmapSyncMode bitmap_mode;
|
2013-06-24 23:13:11 +08:00
|
|
|
BlockdevOnError on_source_error;
|
|
|
|
BlockdevOnError on_target_error;
|
2018-01-19 01:08:22 +08:00
|
|
|
uint64_t len;
|
2016-02-26 04:58:29 +08:00
|
|
|
int64_t cluster_size;
|
qapi: backup: add perf.use-copy-range parameter
Experiments show, that copy_range is not always making things faster.
So, to make experimentation simpler, let's add a parameter. Some more
perf parameters will be added soon, so here is a new struct.
For now, add new backup qmp parameter with x- prefix for the following
reasons:
- We are going to add more performance parameters, some will be
related to the whole block-copy process, some only to background
copying in backup (ignored for copy-before-write operations).
- On the other hand, we are going to use block-copy interface in other
block jobs, which will need performance options as well.. And it
should be the same structure or at least somehow related.
So, there are too much unclean things about how the interface and now
we need the new options mostly for testing. Let's keep them
experimental for a while.
In do_backup_common() new x-perf parameter handled in a way to
make further options addition simpler.
We add use-copy-range with default=true, and we'll change the default
in further patch, after moving backup to use block-copy.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210116214705.822267-2-vsementsov@virtuozzo.com>
[mreitz: s/5\.2/6.0/]
Signed-off-by: Max Reitz <mreitz@redhat.com>
2021-01-17 05:46:43 +08:00
|
|
|
BackupPerf perf;
|
2017-10-12 21:53:10 +08:00
|
|
|
|
2019-09-20 22:20:46 +08:00
|
|
|
BlockCopyState *bcs;
|
2021-01-17 05:46:59 +08:00
|
|
|
|
|
|
|
bool wait;
|
|
|
|
BlockCopyCallState *bg_bcs_call;
|
2013-06-24 23:13:11 +08:00
|
|
|
} BackupBlockJob;
|
|
|
|
|
2018-01-19 22:54:40 +08:00
|
|
|
static const BlockJobDriver backup_job_driver;
|
|
|
|
|
2015-11-06 07:13:10 +08:00
|
|
|
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
|
|
|
|
{
|
|
|
|
BdrvDirtyBitmap *bm;
|
2019-07-30 04:35:53 +08:00
|
|
|
bool sync = (((ret == 0) || (job->bitmap_mode == BITMAP_SYNC_MODE_ALWAYS)) \
|
|
|
|
&& (job->bitmap_mode != BITMAP_SYNC_MODE_NEVER));
|
2015-11-06 07:13:10 +08:00
|
|
|
|
2019-07-30 04:35:53 +08:00
|
|
|
if (sync) {
|
2019-07-30 04:35:53 +08:00
|
|
|
/*
|
2019-07-30 04:35:53 +08:00
|
|
|
* We succeeded, or we always intended to sync the bitmap.
|
|
|
|
* Delete this bitmap and install the child.
|
2019-07-30 04:35:53 +08:00
|
|
|
*/
|
2019-09-16 22:19:09 +08:00
|
|
|
bm = bdrv_dirty_bitmap_abdicate(job->sync_bitmap, NULL);
|
2019-07-30 04:35:53 +08:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* We failed, or we never intended to sync the bitmap anyway.
|
|
|
|
* Merge the successor back into the parent, keeping all data.
|
|
|
|
*/
|
2019-09-16 22:19:09 +08:00
|
|
|
bm = bdrv_reclaim_dirty_bitmap(job->sync_bitmap, NULL);
|
2019-07-30 04:35:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(bm);
|
|
|
|
|
|
|
|
if (ret < 0 && job->bitmap_mode == BITMAP_SYNC_MODE_ALWAYS) {
|
|
|
|
/* If we failed and synced, merge in the bits we didn't copy: */
|
2020-03-11 18:30:04 +08:00
|
|
|
bdrv_dirty_bitmap_merge_internal(bm, block_copy_dirty_bitmap(job->bcs),
|
2019-07-30 04:35:53 +08:00
|
|
|
NULL, true);
|
2015-11-06 07:13:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-19 23:30:16 +08:00
|
|
|
static void backup_commit(Job *job)
|
2015-11-06 07:13:16 +08:00
|
|
|
{
|
2018-04-19 23:30:16 +08:00
|
|
|
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
|
2015-11-06 07:13:16 +08:00
|
|
|
if (s->sync_bitmap) {
|
|
|
|
backup_cleanup_sync_bitmap(s, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-19 23:30:16 +08:00
|
|
|
static void backup_abort(Job *job)
|
2015-11-06 07:13:16 +08:00
|
|
|
{
|
2018-04-19 23:30:16 +08:00
|
|
|
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
|
2015-11-06 07:13:16 +08:00
|
|
|
if (s->sync_bitmap) {
|
|
|
|
backup_cleanup_sync_bitmap(s, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-19 23:30:16 +08:00
|
|
|
static void backup_clean(Job *job)
|
blockjob: add .clean property
Cleaning up after we have deferred to the main thread but before the
transaction has converged can be dangerous and result in deadlocks
if the job cleanup invokes any BH polling loops.
A job may attempt to begin cleaning up, but may induce another job to
enter its cleanup routine. The second job, part of our same transaction,
will block waiting for the first job to finish, so neither job may now
make progress.
To rectify this, allow jobs to register a cleanup operation that will
always run regardless of if the job was in a transaction or not, and
if the transaction job group completed successfully or not.
Move sensitive cleanup to this callback instead which is guaranteed to
be run only after the transaction has converged, which removes sensitive
timing constraints from said cleanup.
Furthermore, in future patches these cleanup operations will be performed
regardless of whether or not we actually started the job. Therefore,
cleanup callbacks should essentially confine themselves to undoing create
operations, e.g. setup actions taken in what is now backup_start.
Reported-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1478587839-9834-3-git-send-email-jsnow@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-11-08 14:50:35 +08:00
|
|
|
{
|
2018-04-19 23:30:16 +08:00
|
|
|
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
|
2021-02-19 23:33:46 +08:00
|
|
|
block_job_remove_all_bdrv(&s->common);
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
bdrv_cbw_drop(s->cbw);
|
blockjob: add .clean property
Cleaning up after we have deferred to the main thread but before the
transaction has converged can be dangerous and result in deadlocks
if the job cleanup invokes any BH polling loops.
A job may attempt to begin cleaning up, but may induce another job to
enter its cleanup routine. The second job, part of our same transaction,
will block waiting for the first job to finish, so neither job may now
make progress.
To rectify this, allow jobs to register a cleanup operation that will
always run regardless of if the job was in a transaction or not, and
if the transaction job group completed successfully or not.
Move sensitive cleanup to this callback instead which is guaranteed to
be run only after the transaction has converged, which removes sensitive
timing constraints from said cleanup.
Furthermore, in future patches these cleanup operations will be performed
regardless of whether or not we actually started the job. Therefore,
cleanup callbacks should essentially confine themselves to undoing create
operations, e.g. setup actions taken in what is now backup_start.
Reported-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1478587839-9834-3-git-send-email-jsnow@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-11-08 14:50:35 +08:00
|
|
|
}
|
|
|
|
|
2016-07-27 15:01:43 +08:00
|
|
|
void backup_do_checkpoint(BlockJob *job, Error **errp)
|
|
|
|
{
|
|
|
|
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
|
|
|
|
|
2018-01-19 22:54:40 +08:00
|
|
|
assert(block_job_driver(job) == &backup_job_driver);
|
2016-07-27 15:01:43 +08:00
|
|
|
|
|
|
|
if (backup_job->sync_mode != MIRROR_SYNC_MODE_NONE) {
|
|
|
|
error_setg(errp, "The backup job only supports block checkpoint in"
|
|
|
|
" sync=none mode");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-11 18:30:04 +08:00
|
|
|
bdrv_set_dirty_bitmap(block_copy_dirty_bitmap(backup_job->bcs), 0,
|
|
|
|
backup_job->len);
|
2016-07-27 15:01:43 +08:00
|
|
|
}
|
|
|
|
|
2013-06-24 23:13:11 +08:00
|
|
|
static BlockErrorAction backup_error_action(BackupBlockJob *job,
|
|
|
|
bool read, int error)
|
|
|
|
{
|
|
|
|
if (read) {
|
2016-04-18 17:36:38 +08:00
|
|
|
return block_job_error_action(&job->common, job->on_source_error,
|
|
|
|
true, error);
|
2013-06-24 23:13:11 +08:00
|
|
|
} else {
|
2016-04-18 17:36:38 +08:00
|
|
|
return block_job_error_action(&job->common, job->on_target_error,
|
|
|
|
false, error);
|
2013-06-24 23:13:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 05:46:59 +08:00
|
|
|
static void coroutine_fn backup_block_copy_callback(void *opaque)
|
2015-04-18 07:49:58 +08:00
|
|
|
{
|
2021-01-17 05:46:59 +08:00
|
|
|
BackupBlockJob *s = opaque;
|
2015-04-18 07:49:58 +08:00
|
|
|
|
2021-01-17 05:46:59 +08:00
|
|
|
if (s->wait) {
|
|
|
|
s->wait = false;
|
|
|
|
aio_co_wake(s->common.job.co);
|
|
|
|
} else {
|
|
|
|
job_enter(&s->common.job);
|
2015-04-18 07:49:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-29 17:08:41 +08:00
|
|
|
static int coroutine_fn backup_loop(BackupBlockJob *job)
|
2015-04-18 07:49:58 +08:00
|
|
|
{
|
2021-01-17 05:46:59 +08:00
|
|
|
BlockCopyCallState *s = NULL;
|
2019-07-30 04:35:53 +08:00
|
|
|
int ret = 0;
|
2021-01-17 05:46:59 +08:00
|
|
|
bool error_is_read;
|
|
|
|
BlockErrorAction act;
|
|
|
|
|
|
|
|
while (true) { /* retry loop */
|
|
|
|
job->bg_bcs_call = s = block_copy_async(job->bcs, 0,
|
|
|
|
QEMU_ALIGN_UP(job->len, job->cluster_size),
|
|
|
|
job->perf.max_workers, job->perf.max_chunk,
|
|
|
|
backup_block_copy_callback, job);
|
|
|
|
|
|
|
|
while (!block_copy_call_finished(s) &&
|
|
|
|
!job_is_cancelled(&job->common.job))
|
|
|
|
{
|
|
|
|
job_yield(&job->common.job);
|
|
|
|
}
|
2015-04-18 07:49:58 +08:00
|
|
|
|
2021-01-17 05:46:59 +08:00
|
|
|
if (!block_copy_call_finished(s)) {
|
|
|
|
assert(job_is_cancelled(&job->common.job));
|
|
|
|
/*
|
|
|
|
* Note that we can't use job_yield() here, as it doesn't work for
|
|
|
|
* cancelled job.
|
|
|
|
*/
|
|
|
|
block_copy_call_cancel(s);
|
|
|
|
job->wait = true;
|
|
|
|
qemu_coroutine_yield();
|
|
|
|
assert(block_copy_call_finished(s));
|
|
|
|
ret = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (job_is_cancelled(&job->common.job) ||
|
|
|
|
block_copy_call_succeeded(s))
|
|
|
|
{
|
|
|
|
ret = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (block_copy_call_cancelled(s)) {
|
|
|
|
/*
|
|
|
|
* Job is not cancelled but only block-copy call. This is possible
|
|
|
|
* after job pause. Now the pause is finished, start new block-copy
|
|
|
|
* iteration.
|
|
|
|
*/
|
|
|
|
block_copy_call_free(s);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The only remaining case is failed block-copy call. */
|
|
|
|
assert(block_copy_call_failed(s));
|
|
|
|
|
|
|
|
ret = block_copy_call_status(s, &error_is_read);
|
|
|
|
act = backup_error_action(job, error_is_read, -ret);
|
|
|
|
switch (act) {
|
|
|
|
case BLOCK_ERROR_ACTION_REPORT:
|
|
|
|
goto out;
|
|
|
|
case BLOCK_ERROR_ACTION_STOP:
|
|
|
|
/*
|
|
|
|
* Go to pause prior to starting new block-copy call on the next
|
|
|
|
* iteration.
|
|
|
|
*/
|
|
|
|
job_pause_point(&job->common.job);
|
|
|
|
break;
|
|
|
|
case BLOCK_ERROR_ACTION_IGNORE:
|
|
|
|
/* Proceed to new block-copy call to retry. */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
block_copy_call_free(s);
|
2015-04-18 07:49:58 +08:00
|
|
|
}
|
|
|
|
|
2021-01-17 05:46:59 +08:00
|
|
|
out:
|
|
|
|
block_copy_call_free(s);
|
|
|
|
job->bg_bcs_call = NULL;
|
2019-07-30 04:35:53 +08:00
|
|
|
return ret;
|
2015-04-18 07:49:58 +08:00
|
|
|
}
|
|
|
|
|
2020-03-11 18:30:04 +08:00
|
|
|
static void backup_init_bcs_bitmap(BackupBlockJob *job)
|
2017-10-12 21:53:11 +08:00
|
|
|
{
|
2019-07-30 04:35:55 +08:00
|
|
|
uint64_t estimate;
|
2020-03-11 18:30:04 +08:00
|
|
|
BdrvDirtyBitmap *bcs_bitmap = block_copy_dirty_bitmap(job->bcs);
|
2019-07-30 04:35:55 +08:00
|
|
|
|
|
|
|
if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
2021-08-24 16:38:41 +08:00
|
|
|
bdrv_clear_dirty_bitmap(bcs_bitmap, NULL);
|
2022-05-17 19:12:06 +08:00
|
|
|
bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap, NULL,
|
|
|
|
true);
|
2021-08-24 16:38:41 +08:00
|
|
|
} else if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
|
|
|
|
/*
|
|
|
|
* We can't hog the coroutine to initialize this thoroughly.
|
|
|
|
* Set a flag and resume work when we are able to yield safely.
|
|
|
|
*/
|
|
|
|
block_copy_set_skip_unallocated(job->bcs, true);
|
2019-07-30 04:35:55 +08:00
|
|
|
}
|
2017-10-12 21:53:11 +08:00
|
|
|
|
2020-03-11 18:30:04 +08:00
|
|
|
estimate = bdrv_get_dirty_count(bcs_bitmap);
|
2019-07-30 04:35:55 +08:00
|
|
|
job_progress_set_remaining(&job->common.job, estimate);
|
2017-10-12 21:53:11 +08:00
|
|
|
}
|
|
|
|
|
2018-08-30 09:57:32 +08:00
|
|
|
static int coroutine_fn backup_run(Job *job, Error **errp)
|
2013-06-24 23:13:11 +08:00
|
|
|
{
|
2018-08-30 09:57:32 +08:00
|
|
|
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
|
2021-01-17 05:46:58 +08:00
|
|
|
int ret;
|
2013-06-24 23:13:11 +08:00
|
|
|
|
2020-03-11 18:30:04 +08:00
|
|
|
backup_init_bcs_bitmap(s);
|
2017-10-12 21:53:11 +08:00
|
|
|
|
2019-07-30 04:35:55 +08:00
|
|
|
if (s->sync_mode == MIRROR_SYNC_MODE_TOP) {
|
|
|
|
int64_t offset = 0;
|
|
|
|
int64_t count;
|
|
|
|
|
|
|
|
for (offset = 0; offset < s->len; ) {
|
2021-01-17 05:46:59 +08:00
|
|
|
if (job_is_cancelled(job)) {
|
|
|
|
return -ECANCELED;
|
|
|
|
}
|
|
|
|
|
|
|
|
job_pause_point(job);
|
|
|
|
|
|
|
|
if (job_is_cancelled(job)) {
|
2021-01-17 05:46:58 +08:00
|
|
|
return -ECANCELED;
|
2019-07-30 04:35:55 +08:00
|
|
|
}
|
|
|
|
|
2019-09-20 22:20:46 +08:00
|
|
|
ret = block_copy_reset_unallocated(s->bcs, offset, &count);
|
2019-07-30 04:35:55 +08:00
|
|
|
if (ret < 0) {
|
2021-01-17 05:46:58 +08:00
|
|
|
return ret;
|
2019-07-30 04:35:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
offset += count;
|
|
|
|
}
|
2020-03-11 18:30:04 +08:00
|
|
|
block_copy_set_skip_unallocated(s->bcs, false);
|
2019-07-30 04:35:55 +08:00
|
|
|
}
|
|
|
|
|
2018-08-30 09:57:32 +08:00
|
|
|
if (s->sync_mode == MIRROR_SYNC_MODE_NONE) {
|
2019-09-20 22:20:47 +08:00
|
|
|
/*
|
2020-03-11 18:30:04 +08:00
|
|
|
* All bits are set in bcs bitmap to allow any cluster to be copied.
|
2019-09-20 22:20:47 +08:00
|
|
|
* This does not actually require them to be copied.
|
|
|
|
*/
|
2018-08-30 09:57:32 +08:00
|
|
|
while (!job_is_cancelled(job)) {
|
2019-09-20 22:20:47 +08:00
|
|
|
/*
|
|
|
|
* Yield until the job is cancelled. We just let our before_write
|
|
|
|
* notify callback service CoW requests.
|
|
|
|
*/
|
2018-08-30 09:57:32 +08:00
|
|
|
job_yield(job);
|
2013-06-24 23:13:11 +08:00
|
|
|
}
|
2013-07-27 02:39:04 +08:00
|
|
|
} else {
|
2021-01-17 05:46:58 +08:00
|
|
|
return backup_loop(s);
|
2013-06-24 23:13:11 +08:00
|
|
|
}
|
|
|
|
|
2021-01-17 05:46:58 +08:00
|
|
|
return 0;
|
2013-06-24 23:13:11 +08:00
|
|
|
}
|
|
|
|
|
2021-01-17 05:46:59 +08:00
|
|
|
static void coroutine_fn backup_pause(Job *job)
|
|
|
|
{
|
|
|
|
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
|
|
|
|
|
|
|
|
if (s->bg_bcs_call && !block_copy_call_finished(s->bg_bcs_call)) {
|
|
|
|
block_copy_call_cancel(s->bg_bcs_call);
|
|
|
|
s->wait = true;
|
|
|
|
qemu_coroutine_yield();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-13 20:36:48 +08:00
|
|
|
static void backup_set_speed(BlockJob *job, int64_t speed)
|
2021-01-17 05:46:59 +08:00
|
|
|
{
|
|
|
|
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* block_job_set_speed() is called first from block_job_create(), when we
|
|
|
|
* don't yet have s->bcs.
|
|
|
|
*/
|
|
|
|
if (s->bcs) {
|
|
|
|
block_copy_set_speed(s->bcs, speed);
|
|
|
|
if (s->bg_bcs_call) {
|
|
|
|
block_copy_kick(s->bg_bcs_call);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
jobs: Give Job.force_cancel more meaning
We largely have two cancel modes for jobs:
First, there is actual cancelling. The job is terminated as soon as
possible, without trying to reach a consistent result.
Second, we have mirror in the READY state. Technically, the job is not
really cancelled, but it just is a different completion mode. The job
can still run for an indefinite amount of time while it tries to reach a
consistent result.
We want to be able to clearly distinguish which cancel mode a job is in
(when it has been cancelled). We can use Job.force_cancel for this, but
right now it only reflects cancel requests from the user with
force=true, but clearly, jobs that do not even distinguish between
force=false and force=true are effectively always force-cancelled.
So this patch has Job.force_cancel signify whether the job will
terminate as soon as possible (force_cancel=true) or whether it will
effectively remain running despite being "cancelled"
(force_cancel=false).
To this end, we let jobs that provide JobDriver.cancel() tell the
generic job code whether they will terminate as soon as possible or not,
and for jobs that do not provide that method we assume they will.
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20211006151940.214590-7-hreitz@redhat.com>
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2021-10-06 23:19:33 +08:00
|
|
|
static bool backup_cancel(Job *job, bool force)
|
2021-02-06 00:37:19 +08:00
|
|
|
{
|
|
|
|
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
|
|
|
|
|
|
|
|
bdrv_cancel_in_flight(s->target_bs);
|
jobs: Give Job.force_cancel more meaning
We largely have two cancel modes for jobs:
First, there is actual cancelling. The job is terminated as soon as
possible, without trying to reach a consistent result.
Second, we have mirror in the READY state. Technically, the job is not
really cancelled, but it just is a different completion mode. The job
can still run for an indefinite amount of time while it tries to reach a
consistent result.
We want to be able to clearly distinguish which cancel mode a job is in
(when it has been cancelled). We can use Job.force_cancel for this, but
right now it only reflects cancel requests from the user with
force=true, but clearly, jobs that do not even distinguish between
force=false and force=true are effectively always force-cancelled.
So this patch has Job.force_cancel signify whether the job will
terminate as soon as possible (force_cancel=true) or whether it will
effectively remain running despite being "cancelled"
(force_cancel=false).
To this end, we let jobs that provide JobDriver.cancel() tell the
generic job code whether they will terminate as soon as possible or not,
and for jobs that do not provide that method we assume they will.
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20211006151940.214590-7-hreitz@redhat.com>
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2021-10-06 23:19:33 +08:00
|
|
|
return true;
|
2021-02-06 00:37:19 +08:00
|
|
|
}
|
|
|
|
|
2016-11-08 14:50:36 +08:00
|
|
|
static const BlockJobDriver backup_job_driver = {
|
2018-04-12 23:29:59 +08:00
|
|
|
.job_driver = {
|
|
|
|
.instance_size = sizeof(BackupBlockJob),
|
2018-04-12 23:57:08 +08:00
|
|
|
.job_type = JOB_TYPE_BACKUP,
|
2018-04-14 00:50:05 +08:00
|
|
|
.free = block_job_free,
|
2018-04-18 23:10:26 +08:00
|
|
|
.user_resume = block_job_user_resume,
|
2018-08-30 09:57:26 +08:00
|
|
|
.run = backup_run,
|
2018-04-19 23:30:16 +08:00
|
|
|
.commit = backup_commit,
|
|
|
|
.abort = backup_abort,
|
|
|
|
.clean = backup_clean,
|
2021-01-17 05:46:59 +08:00
|
|
|
.pause = backup_pause,
|
2021-02-06 00:37:19 +08:00
|
|
|
.cancel = backup_cancel,
|
2021-01-17 05:46:59 +08:00
|
|
|
},
|
|
|
|
.set_speed = backup_set_speed,
|
2016-11-08 14:50:36 +08:00
|
|
|
};
|
|
|
|
|
2016-11-08 14:50:38 +08:00
|
|
|
BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
2016-07-05 22:28:58 +08:00
|
|
|
BlockDriverState *target, int64_t speed,
|
|
|
|
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
2019-07-30 04:35:52 +08:00
|
|
|
BitmapSyncMode bitmap_mode,
|
2016-07-22 16:17:52 +08:00
|
|
|
bool compress,
|
block/backup: use backup-top instead of write notifiers
Drop write notifiers and use filter node instead.
= Changes =
1. Add filter-node-name argument for backup qmp api. We have to do it
in this commit, as 257 needs to be fixed.
2. There are no more write notifiers here, so is_write_notifier
parameter is dropped from block-copy paths.
3. To sync with in-flight requests at job finish we now have drained
removing of the filter, we don't need rw-lock.
4. Block-copy is now using BdrvChildren instead of BlockBackends
5. As backup-top owns these children, we also move block-copy state
into backup-top's ownership.
= Iotest changes =
56: op-blocker doesn't shoot now, as we set it on source, but then
check on filter, when trying to start second backup.
To keep the test we instead can catch another collision: both jobs will
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
interleaving with file-posix locks (as they are dependent on config)
let's use another target for second backup.
Also, it's obvious now that we'd like to drop this op-blocker at all
and add a test-case for two backups from one node (to different
destinations) actually works. But not in these series.
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
check inside qmp_blockdev_del. But we've dropped block-copy blk
objects, so no more blk objects on source bs (job blk is on backup-top
filter bs). New message is from op-blocker, which is the next check in
qmp_blockdev_add.
257: The test wants to emulate guest write during backup. They should
go to filter node, not to original source node, of course. Therefore we
need to specify filter node name and use it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2019-10-01 21:14:09 +08:00
|
|
|
const char *filter_node_name,
|
qapi: backup: add perf.use-copy-range parameter
Experiments show, that copy_range is not always making things faster.
So, to make experimentation simpler, let's add a parameter. Some more
perf parameters will be added soon, so here is a new struct.
For now, add new backup qmp parameter with x- prefix for the following
reasons:
- We are going to add more performance parameters, some will be
related to the whole block-copy process, some only to background
copying in backup (ignored for copy-before-write operations).
- On the other hand, we are going to use block-copy interface in other
block jobs, which will need performance options as well.. And it
should be the same structure or at least somehow related.
So, there are too much unclean things about how the interface and now
we need the new options mostly for testing. Let's keep them
experimental for a while.
In do_backup_common() new x-perf parameter handled in a way to
make further options addition simpler.
We add use-copy-range with default=true, and we'll change the default
in further patch, after moving backup to use block-copy.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210116214705.822267-2-vsementsov@virtuozzo.com>
[mreitz: s/5\.2/6.0/]
Signed-off-by: Max Reitz <mreitz@redhat.com>
2021-01-17 05:46:43 +08:00
|
|
|
BackupPerf *perf,
|
2013-06-24 23:13:11 +08:00
|
|
|
BlockdevOnError on_source_error,
|
|
|
|
BlockdevOnError on_target_error,
|
2016-10-28 00:06:57 +08:00
|
|
|
int creation_flags,
|
2014-10-07 19:59:15 +08:00
|
|
|
BlockCompletionFunc *cb, void *opaque,
|
2018-04-19 22:09:52 +08:00
|
|
|
JobTxn *txn, Error **errp)
|
2013-06-24 23:13:11 +08:00
|
|
|
{
|
2020-04-30 22:27:54 +08:00
|
|
|
int64_t len, target_len;
|
2016-04-14 18:59:55 +08:00
|
|
|
BackupBlockJob *job = NULL;
|
2019-04-29 17:08:42 +08:00
|
|
|
int64_t cluster_size;
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
BlockDriverState *cbw = NULL;
|
block/backup: use backup-top instead of write notifiers
Drop write notifiers and use filter node instead.
= Changes =
1. Add filter-node-name argument for backup qmp api. We have to do it
in this commit, as 257 needs to be fixed.
2. There are no more write notifiers here, so is_write_notifier
parameter is dropped from block-copy paths.
3. To sync with in-flight requests at job finish we now have drained
removing of the filter, we don't need rw-lock.
4. Block-copy is now using BdrvChildren instead of BlockBackends
5. As backup-top owns these children, we also move block-copy state
into backup-top's ownership.
= Iotest changes =
56: op-blocker doesn't shoot now, as we set it on source, but then
check on filter, when trying to start second backup.
To keep the test we instead can catch another collision: both jobs will
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
interleaving with file-posix locks (as they are dependent on config)
let's use another target for second backup.
Also, it's obvious now that we'd like to drop this op-blocker at all
and add a test-case for two backups from one node (to different
destinations) actually works. But not in these series.
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
check inside qmp_blockdev_del. But we've dropped block-copy blk
objects, so no more blk objects on source bs (job blk is on backup-top
filter bs). New message is from op-blocker, which is the next check in
qmp_blockdev_add.
257: The test wants to emulate guest write during backup. They should
go to filter node, not to original source node, of course. Therefore we
need to specify filter node name and use it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2019-10-01 21:14:09 +08:00
|
|
|
BlockCopyState *bcs = NULL;
|
2013-06-24 23:13:11 +08:00
|
|
|
|
|
|
|
assert(bs);
|
|
|
|
assert(target);
|
2022-03-03 23:15:57 +08:00
|
|
|
GLOBAL_STATE_CODE();
|
2013-06-24 23:13:11 +08:00
|
|
|
|
2019-07-30 04:35:55 +08:00
|
|
|
/* QMP interface protects us from these cases */
|
|
|
|
assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
|
|
|
|
assert(sync_bitmap || sync_mode != MIRROR_SYNC_MODE_BITMAP);
|
|
|
|
|
2014-12-18 18:37:05 +08:00
|
|
|
if (bs == target) {
|
|
|
|
error_setg(errp, "Source and target cannot be the same");
|
2016-11-08 14:50:38 +08:00
|
|
|
return NULL;
|
2014-12-18 18:37:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!bdrv_is_inserted(bs)) {
|
|
|
|
error_setg(errp, "Device is not inserted: %s",
|
|
|
|
bdrv_get_device_name(bs));
|
2016-11-08 14:50:38 +08:00
|
|
|
return NULL;
|
2014-12-18 18:37:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!bdrv_is_inserted(target)) {
|
|
|
|
error_setg(errp, "Device is not inserted: %s",
|
|
|
|
bdrv_get_device_name(target));
|
2016-11-08 14:50:38 +08:00
|
|
|
return NULL;
|
2014-12-18 18:37:05 +08:00
|
|
|
}
|
|
|
|
|
2019-06-12 23:46:45 +08:00
|
|
|
if (compress && !bdrv_supports_compressed_writes(target)) {
|
2016-07-22 16:17:52 +08:00
|
|
|
error_setg(errp, "Compression is not supported for this drive %s",
|
|
|
|
bdrv_get_device_name(target));
|
2016-11-08 14:50:38 +08:00
|
|
|
return NULL;
|
2016-07-22 16:17:52 +08:00
|
|
|
}
|
|
|
|
|
2014-12-18 18:37:05 +08:00
|
|
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
2016-11-08 14:50:38 +08:00
|
|
|
return NULL;
|
2014-12-18 18:37:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
|
2016-11-08 14:50:38 +08:00
|
|
|
return NULL;
|
2014-12-18 18:37:05 +08:00
|
|
|
}
|
|
|
|
|
2021-10-06 00:11:56 +08:00
|
|
|
if (perf->max_workers < 1 || perf->max_workers > INT_MAX) {
|
|
|
|
error_setg(errp, "max-workers must be between 1 and %d", INT_MAX);
|
2021-01-17 05:46:52 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (perf->max_chunk < 0) {
|
|
|
|
error_setg(errp, "max-chunk must be zero (which means no limit) or "
|
|
|
|
"positive");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-07-30 04:35:55 +08:00
|
|
|
if (sync_bitmap) {
|
2019-07-30 04:35:54 +08:00
|
|
|
/* If we need to write to this bitmap, check that we can: */
|
|
|
|
if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
|
|
|
|
bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-04-18 07:49:58 +08:00
|
|
|
/* Create a new bitmap, and freeze/disable this one. */
|
2019-09-16 22:19:09 +08:00
|
|
|
if (bdrv_dirty_bitmap_create_successor(sync_bitmap, errp) < 0) {
|
2016-11-08 14:50:38 +08:00
|
|
|
return NULL;
|
2015-04-18 07:49:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-24 23:13:11 +08:00
|
|
|
len = bdrv_getlength(bs);
|
|
|
|
if (len < 0) {
|
2020-04-30 22:27:53 +08:00
|
|
|
error_setg_errno(errp, -len, "Unable to get length for '%s'",
|
|
|
|
bdrv_get_device_or_node_name(bs));
|
2015-04-18 07:49:58 +08:00
|
|
|
goto error;
|
2013-06-24 23:13:11 +08:00
|
|
|
}
|
|
|
|
|
2020-04-30 22:27:54 +08:00
|
|
|
target_len = bdrv_getlength(target);
|
|
|
|
if (target_len < 0) {
|
|
|
|
error_setg_errno(errp, -target_len, "Unable to get length for '%s'",
|
|
|
|
bdrv_get_device_or_node_name(bs));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target_len != len) {
|
|
|
|
error_setg(errp, "Source and target image have different sizes");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2021-08-24 16:38:39 +08:00
|
|
|
cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp);
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
if (!cbw) {
|
block/backup: use backup-top instead of write notifiers
Drop write notifiers and use filter node instead.
= Changes =
1. Add filter-node-name argument for backup qmp api. We have to do it
in this commit, as 257 needs to be fixed.
2. There are no more write notifiers here, so is_write_notifier
parameter is dropped from block-copy paths.
3. To sync with in-flight requests at job finish we now have drained
removing of the filter, we don't need rw-lock.
4. Block-copy is now using BdrvChildren instead of BlockBackends
5. As backup-top owns these children, we also move block-copy state
into backup-top's ownership.
= Iotest changes =
56: op-blocker doesn't shoot now, as we set it on source, but then
check on filter, when trying to start second backup.
To keep the test we instead can catch another collision: both jobs will
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
interleaving with file-posix locks (as they are dependent on config)
let's use another target for second backup.
Also, it's obvious now that we'd like to drop this op-blocker at all
and add a test-case for two backups from one node (to different
destinations) actually works. But not in these series.
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
check inside qmp_blockdev_del. But we've dropped block-copy blk
objects, so no more blk objects on source bs (job blk is on backup-top
filter bs). New message is from op-blocker, which is the next check in
qmp_blockdev_add.
257: The test wants to emulate guest write during backup. They should
go to filter node, not to original source node, of course. Therefore we
need to specify filter node name and use it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2019-10-01 21:14:09 +08:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2021-08-24 16:38:31 +08:00
|
|
|
cluster_size = block_copy_cluster_size(bcs);
|
|
|
|
|
|
|
|
if (perf->max_chunk && perf->max_chunk < cluster_size) {
|
|
|
|
error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
|
|
|
|
"cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2019-10-01 21:14:06 +08:00
|
|
|
/* job->len is fixed, so we can't allow resize */
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
job = block_job_create(job_id, &backup_job_driver, txn, cbw,
|
block/backup: use backup-top instead of write notifiers
Drop write notifiers and use filter node instead.
= Changes =
1. Add filter-node-name argument for backup qmp api. We have to do it
in this commit, as 257 needs to be fixed.
2. There are no more write notifiers here, so is_write_notifier
parameter is dropped from block-copy paths.
3. To sync with in-flight requests at job finish we now have drained
removing of the filter, we don't need rw-lock.
4. Block-copy is now using BdrvChildren instead of BlockBackends
5. As backup-top owns these children, we also move block-copy state
into backup-top's ownership.
= Iotest changes =
56: op-blocker doesn't shoot now, as we set it on source, but then
check on filter, when trying to start second backup.
To keep the test we instead can catch another collision: both jobs will
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
interleaving with file-posix locks (as they are dependent on config)
let's use another target for second backup.
Also, it's obvious now that we'd like to drop this op-blocker at all
and add a test-case for two backups from one node (to different
destinations) actually works. But not in these series.
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
check inside qmp_blockdev_del. But we've dropped block-copy blk
objects, so no more blk objects on source bs (job blk is on backup-top
filter bs). New message is from op-blocker, which is the next check in
qmp_blockdev_add.
257: The test wants to emulate guest write during backup. They should
go to filter node, not to original source node, of course. Therefore we
need to specify filter node name and use it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2019-10-01 21:14:09 +08:00
|
|
|
0, BLK_PERM_ALL,
|
2019-10-01 21:14:06 +08:00
|
|
|
speed, creation_flags, cb, opaque, errp);
|
|
|
|
if (!job) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
job->cbw = cbw;
|
2019-10-01 21:14:06 +08:00
|
|
|
job->source_bs = bs;
|
2021-02-06 00:37:19 +08:00
|
|
|
job->target_bs = target;
|
2019-10-01 21:14:06 +08:00
|
|
|
job->on_source_error = on_source_error;
|
|
|
|
job->on_target_error = on_target_error;
|
|
|
|
job->sync_mode = sync_mode;
|
|
|
|
job->sync_bitmap = sync_bitmap;
|
|
|
|
job->bitmap_mode = bitmap_mode;
|
block/backup: use backup-top instead of write notifiers
Drop write notifiers and use filter node instead.
= Changes =
1. Add filter-node-name argument for backup qmp api. We have to do it
in this commit, as 257 needs to be fixed.
2. There are no more write notifiers here, so is_write_notifier
parameter is dropped from block-copy paths.
3. To sync with in-flight requests at job finish we now have drained
removing of the filter, we don't need rw-lock.
4. Block-copy is now using BdrvChildren instead of BlockBackends
5. As backup-top owns these children, we also move block-copy state
into backup-top's ownership.
= Iotest changes =
56: op-blocker doesn't shoot now, as we set it on source, but then
check on filter, when trying to start second backup.
To keep the test we instead can catch another collision: both jobs will
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
interleaving with file-posix locks (as they are dependent on config)
let's use another target for second backup.
Also, it's obvious now that we'd like to drop this op-blocker at all
and add a test-case for two backups from one node (to different
destinations) actually works. But not in these series.
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
check inside qmp_blockdev_del. But we've dropped block-copy blk
objects, so no more blk objects on source bs (job blk is on backup-top
filter bs). New message is from op-blocker, which is the next check in
qmp_blockdev_add.
257: The test wants to emulate guest write during backup. They should
go to filter node, not to original source node, of course. Therefore we
need to specify filter node name and use it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2019-10-01 21:14:09 +08:00
|
|
|
job->bcs = bcs;
|
2019-04-29 17:08:42 +08:00
|
|
|
job->cluster_size = cluster_size;
|
2019-10-01 21:14:06 +08:00
|
|
|
job->len = len;
|
qapi: backup: add perf.use-copy-range parameter
Experiments show, that copy_range is not always making things faster.
So, to make experimentation simpler, let's add a parameter. Some more
perf parameters will be added soon, so here is a new struct.
For now, add new backup qmp parameter with x- prefix for the following
reasons:
- We are going to add more performance parameters, some will be
related to the whole block-copy process, some only to background
copying in backup (ignored for copy-before-write operations).
- On the other hand, we are going to use block-copy interface in other
block jobs, which will need performance options as well.. And it
should be the same structure or at least somehow related.
So, there are too much unclean things about how the interface and now
we need the new options mostly for testing. Let's keep them
experimental for a while.
In do_backup_common() new x-perf parameter handled in a way to
make further options addition simpler.
We add use-copy-range with default=true, and we'll change the default
in further patch, after moving backup to use block-copy.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210116214705.822267-2-vsementsov@virtuozzo.com>
[mreitz: s/5\.2/6.0/]
Signed-off-by: Max Reitz <mreitz@redhat.com>
2021-01-17 05:46:43 +08:00
|
|
|
job->perf = *perf;
|
block/backup: avoid copying less than full target clusters
During incremental backups, if the target has a cluster size that is
larger than the backup cluster size and we are backing up to a target
that cannot (for whichever reason) pull clusters up from a backing image,
we may inadvertantly create unusable incremental backup images.
For example:
If the bitmap tracks changes at a 64KB granularity and we transmit 64KB
of data at a time but the target uses a 128KB cluster size, it is
possible that only half of a target cluster will be recognized as dirty
by the backup block job. When the cluster is allocated on the target
image but only half populated with data, we lose the ability to
distinguish between zero padding and uninitialized data.
This does not happen if the target image has a backing file that points
to the last known good backup.
Even if we have a backing file, though, it's likely going to be faster
to just buffer the redundant data ourselves from the live image than
fetching it from the backing file, so let's just always round up to the
target granularity.
The same logic applies to backup modes top, none, and full. Copying
fractional clusters without the guarantee of COW is dangerous, but even
if we can rely on COW, it's likely better to just re-copy the data.
Reported-by: Fam Zheng <famz@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1456433911-24718-3-git-send-email-jsnow@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2016-02-26 04:58:30 +08:00
|
|
|
|
2021-08-24 16:38:30 +08:00
|
|
|
block_copy_set_copy_opts(bcs, perf->use_copy_range, compress);
|
block/block-copy: fix progress calculation
Assume we have two regions, A and B, and region B is in-flight now,
region A is not yet touched, but it is unallocated and should be
skipped.
Correspondingly, as progress we have
total = A + B
current = 0
If we reset unallocated region A and call progress_reset_callback,
it will calculate 0 bytes dirty in the bitmap and call
job_progress_set_remaining, which will set
total = current + 0 = 0 + 0 = 0
So, B bytes are actually removed from total accounting. When job
finishes we'll have
total = 0
current = B
, which doesn't sound good.
This is because we didn't considered in-flight bytes, actually when
calculating remaining, we should have set (in_flight + dirty_bytes)
as remaining, not only dirty_bytes.
To fix it, let's refactor progress calculation, moving it to block-copy
itself instead of fixing callback. And, of course, track in_flight
bytes count.
We still have to keep one callback, to maintain backup job bytes_read
calculation, but it will go on soon, when we turn the whole backup
process into one block_copy call.
Cc: qemu-stable@nongnu.org
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Message-Id: <20200311103004.7649-3-vsementsov@virtuozzo.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2020-03-11 18:29:57 +08:00
|
|
|
block_copy_set_progress_meter(bcs, &job->common.job.progress);
|
2021-01-17 05:46:59 +08:00
|
|
|
block_copy_set_speed(bcs, speed);
|
2019-10-01 21:14:07 +08:00
|
|
|
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
/* Required permissions are taken by copy-before-write filter target */
|
2017-01-17 18:56:42 +08:00
|
|
|
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
|
|
|
&error_abort);
|
2016-11-08 14:50:38 +08:00
|
|
|
|
|
|
|
return &job->common;
|
2015-04-18 07:49:58 +08:00
|
|
|
|
|
|
|
error:
|
|
|
|
if (sync_bitmap) {
|
2019-09-16 22:19:09 +08:00
|
|
|
bdrv_reclaim_dirty_bitmap(sync_bitmap, NULL);
|
2015-04-18 07:49:58 +08:00
|
|
|
}
|
block: rename backup-top to copy-before-write
We are going to convert backup_top to full featured public filter,
which can be used in separate of backup job. Start from renaming from
"how it used" to "what it does".
While updating comments in 283 iotest, drop and rephrase also things
about ".active", as this field is now dropped, and filter doesn't have
"inactive" mode.
Note that this change may be considered as incompatible interface
change, as backup-top filter format name was visible through
query-block and query-named-block-nodes.
Still, consider the following reasoning:
1. backup-top was never documented, so if someone depends on format
name (for driver that can't be used other than it is automatically
inserted on backup job start), it's a kind of "undocumented feature
use". So I think we are free to change it.
2. There is a hope, that there is no such users: it's a lot more native
to give a good node-name to backup-top filter if need to operate
with it somehow, and don't touch format name.
3. Another "incompatible" change in further commit would be moving
copy-before-write filter from using backing child to file child. And
this is even more reasonable than renaming: for now all public
filters are file-child based.
So, it's a risky change, but risk seems small and good interface worth
it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
2021-08-24 16:38:27 +08:00
|
|
|
if (cbw) {
|
|
|
|
bdrv_cbw_drop(cbw);
|
2016-04-14 18:59:55 +08:00
|
|
|
}
|
2016-11-08 14:50:38 +08:00
|
|
|
|
|
|
|
return NULL;
|
2013-06-24 23:13:11 +08:00
|
|
|
}
|