mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches - Make blockdev-reopen stable - Remove deprecated qemu-img backing file without format - rbd: Convert to coroutines and add write zeroes support - rbd: Updated MAINTAINERS - export/fuse: Allow other users access to the export - vhost-user: Fix backends without multiqueue support - Fix drive-backup transaction endless drained section # gpg: Signature made Fri 09 Jul 2021 13:49:22 BST # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (28 commits) block: Make blockdev-reopen stable API iotests: Test reopening multiple devices at the same time block: Support multiple reopening with x-blockdev-reopen block: Acquire AioContexts during bdrv_reopen_multiple() block: Add bdrv_reopen_queue_free() qcow2: Fix dangling pointer after reopen for 'file' qemu-img: Improve error for rebase without backing format qemu-img: Require -F with -b backing image qcow2: Prohibit backing file changes in 'qemu-img amend' blockdev: fix drive-backup transaction endless drained section vhost-user: Fix backends without multiqueue support MAINTAINERS: add block/rbd.c reviewer block/rbd: fix type of task->complete iotests/fuse-allow-other: Test allow-other iotests/308: Test +w on read-only FUSE exports export/fuse: Let permissions be adjustable export/fuse: Give SET_ATTR_SIZE its own branch export/fuse: Add allow-other option export/fuse: Pass default_permissions for mount util/uri: do not check argument of uri_free() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+2
-1
@@ -3081,7 +3081,8 @@ S: Supported
|
||||
F: block/vmdk.c
|
||||
|
||||
RBD
|
||||
M: Jason Dillaman <dillaman@redhat.com>
|
||||
M: Ilya Dryomov <idryomov@gmail.com>
|
||||
R: Peter Lieven <pl@kamp.de>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: block/rbd.c
|
||||
|
||||
@@ -4095,6 +4095,19 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||
NULL, 0, keep_old_opts);
|
||||
}
|
||||
|
||||
void bdrv_reopen_queue_free(BlockReopenQueue *bs_queue)
|
||||
{
|
||||
if (bs_queue) {
|
||||
BlockReopenQueueEntry *bs_entry, *next;
|
||||
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
||||
qobject_unref(bs_entry->state.explicit_options);
|
||||
qobject_unref(bs_entry->state.options);
|
||||
g_free(bs_entry);
|
||||
}
|
||||
g_free(bs_queue);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reopen multiple BlockDriverStates atomically & transactionally.
|
||||
*
|
||||
@@ -4111,19 +4124,26 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||
*
|
||||
* All affected nodes must be drained between bdrv_reopen_queue() and
|
||||
* bdrv_reopen_multiple().
|
||||
*
|
||||
* To be called from the main thread, with all other AioContexts unlocked.
|
||||
*/
|
||||
int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
{
|
||||
int ret = -1;
|
||||
BlockReopenQueueEntry *bs_entry, *next;
|
||||
AioContext *ctx;
|
||||
Transaction *tran = tran_new();
|
||||
g_autoptr(GHashTable) found = NULL;
|
||||
g_autoptr(GSList) refresh_list = NULL;
|
||||
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
assert(bs_queue != NULL);
|
||||
|
||||
QTAILQ_FOREACH(bs_entry, bs_queue, entry) {
|
||||
ctx = bdrv_get_aio_context(bs_entry->state.bs);
|
||||
aio_context_acquire(ctx);
|
||||
ret = bdrv_flush(bs_entry->state.bs);
|
||||
aio_context_release(ctx);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Error flushing drive");
|
||||
goto abort;
|
||||
@@ -4132,7 +4152,10 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
|
||||
QTAILQ_FOREACH(bs_entry, bs_queue, entry) {
|
||||
assert(bs_entry->state.bs->quiesce_counter > 0);
|
||||
ctx = bdrv_get_aio_context(bs_entry->state.bs);
|
||||
aio_context_acquire(ctx);
|
||||
ret = bdrv_reopen_prepare(&bs_entry->state, bs_queue, tran, errp);
|
||||
aio_context_release(ctx);
|
||||
if (ret < 0) {
|
||||
goto abort;
|
||||
}
|
||||
@@ -4175,7 +4198,10 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
* to first element.
|
||||
*/
|
||||
QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) {
|
||||
ctx = bdrv_get_aio_context(bs_entry->state.bs);
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_reopen_commit(&bs_entry->state);
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
|
||||
tran_commit(tran);
|
||||
@@ -4184,7 +4210,10 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
BlockDriverState *bs = bs_entry->state.bs;
|
||||
|
||||
if (bs->drv->bdrv_reopen_commit_post) {
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
bs->drv->bdrv_reopen_commit_post(&bs_entry->state);
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4195,17 +4224,38 @@ abort:
|
||||
tran_abort(tran);
|
||||
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
||||
if (bs_entry->prepared) {
|
||||
ctx = bdrv_get_aio_context(bs_entry->state.bs);
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_reopen_abort(&bs_entry->state);
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
qobject_unref(bs_entry->state.explicit_options);
|
||||
qobject_unref(bs_entry->state.options);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
||||
g_free(bs_entry);
|
||||
bdrv_reopen_queue_free(bs_queue);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_reopen(BlockDriverState *bs, QDict *opts, bool keep_old_opts,
|
||||
Error **errp)
|
||||
{
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
BlockReopenQueue *queue;
|
||||
int ret;
|
||||
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
if (ctx != qemu_get_aio_context()) {
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
g_free(bs_queue);
|
||||
|
||||
queue = bdrv_reopen_queue(NULL, bs, opts, keep_old_opts);
|
||||
ret = bdrv_reopen_multiple(queue, errp);
|
||||
|
||||
if (ctx != qemu_get_aio_context()) {
|
||||
aio_context_acquire(ctx);
|
||||
}
|
||||
bdrv_subtree_drained_end(bs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -4213,18 +4263,11 @@ cleanup:
|
||||
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
BlockReopenQueue *queue;
|
||||
QDict *opts = qdict_new();
|
||||
|
||||
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, read_only);
|
||||
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
queue = bdrv_reopen_queue(NULL, bs, opts, true);
|
||||
ret = bdrv_reopen_multiple(queue, errp);
|
||||
bdrv_subtree_drained_end(bs);
|
||||
|
||||
return ret;
|
||||
return bdrv_reopen(bs, opts, true, errp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4573,6 +4616,8 @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
|
||||
/* set BDS specific flags now */
|
||||
qobject_unref(bs->explicit_options);
|
||||
qobject_unref(bs->options);
|
||||
qobject_ref(reopen_state->explicit_options);
|
||||
qobject_ref(reopen_state->options);
|
||||
|
||||
bs->explicit_options = reopen_state->explicit_options;
|
||||
bs->options = reopen_state->options;
|
||||
@@ -5074,7 +5119,7 @@ int coroutine_fn bdrv_co_check(BlockDriverState *bs,
|
||||
* -ENOTSUP - format driver doesn't support changing the backing file
|
||||
*/
|
||||
int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
|
||||
const char *backing_fmt, bool warn)
|
||||
const char *backing_fmt, bool require)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret;
|
||||
@@ -5088,10 +5133,8 @@ int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (warn && backing_file && !backing_fmt) {
|
||||
warn_report("Deprecated use of backing file without explicit "
|
||||
"backing format, use of this image requires "
|
||||
"potentially unsafe format probing");
|
||||
if (require && backing_file && !backing_fmt) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (drv->bdrv_change_backing_file != NULL) {
|
||||
@@ -6601,24 +6644,11 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
goto out;
|
||||
} else {
|
||||
if (!backing_fmt) {
|
||||
warn_report("Deprecated use of backing file without explicit "
|
||||
"backing format (detected format of %s)",
|
||||
bs->drv->format_name);
|
||||
if (bs->drv != &bdrv_raw) {
|
||||
/*
|
||||
* A probe of raw deserves the most attention:
|
||||
* leaving the backing format out of the image
|
||||
* will ensure bs->probed is set (ensuring we
|
||||
* don't accidentally commit into the backing
|
||||
* file), and allow more spots to warn the users
|
||||
* to fix their toolchain when opening this image
|
||||
* later. For other images, we can safely record
|
||||
* the format that we probed.
|
||||
*/
|
||||
backing_fmt = bs->drv->format_name;
|
||||
qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, backing_fmt,
|
||||
NULL);
|
||||
}
|
||||
error_setg(&local_err,
|
||||
"Backing file specified without backing format");
|
||||
error_append_hint(&local_err, "Detected format of %s.",
|
||||
bs->drv->format_name);
|
||||
goto out;
|
||||
}
|
||||
if (size == -1) {
|
||||
/* Opened BS, have no size */
|
||||
@@ -6635,9 +6665,9 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
}
|
||||
/* (backing_file && !(flags & BDRV_O_NO_BACKING)) */
|
||||
} else if (backing_file && !backing_fmt) {
|
||||
warn_report("Deprecated use of unopened backing file without "
|
||||
"explicit backing format, use of this image requires "
|
||||
"potentially unsafe format probing");
|
||||
error_setg(&local_err,
|
||||
"Backing file specified without backing format");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size == -1) {
|
||||
|
||||
+98
-23
@@ -46,6 +46,12 @@ typedef struct FuseExport {
|
||||
char *mountpoint;
|
||||
bool writable;
|
||||
bool growable;
|
||||
/* Whether allow_other was used as a mount option or not */
|
||||
bool allow_other;
|
||||
|
||||
mode_t st_mode;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
} FuseExport;
|
||||
|
||||
static GHashTable *exports;
|
||||
@@ -57,7 +63,7 @@ static void fuse_export_delete(BlockExport *exp);
|
||||
static void init_exports_table(void);
|
||||
|
||||
static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
|
||||
Error **errp);
|
||||
bool allow_other, Error **errp);
|
||||
static void read_from_fuse_export(void *opaque);
|
||||
|
||||
static bool is_regular_file(const char *path, Error **errp);
|
||||
@@ -118,7 +124,29 @@ static int fuse_export_create(BlockExport *blk_exp,
|
||||
exp->writable = blk_exp_args->writable;
|
||||
exp->growable = args->growable;
|
||||
|
||||
ret = setup_fuse_export(exp, args->mountpoint, errp);
|
||||
/* set default */
|
||||
if (!args->has_allow_other) {
|
||||
args->allow_other = FUSE_EXPORT_ALLOW_OTHER_AUTO;
|
||||
}
|
||||
|
||||
exp->st_mode = S_IFREG | S_IRUSR;
|
||||
if (exp->writable) {
|
||||
exp->st_mode |= S_IWUSR;
|
||||
}
|
||||
exp->st_uid = getuid();
|
||||
exp->st_gid = getgid();
|
||||
|
||||
if (args->allow_other == FUSE_EXPORT_ALLOW_OTHER_AUTO) {
|
||||
/* Ignore errors on our first attempt */
|
||||
ret = setup_fuse_export(exp, args->mountpoint, true, NULL);
|
||||
exp->allow_other = ret == 0;
|
||||
if (ret < 0) {
|
||||
ret = setup_fuse_export(exp, args->mountpoint, false, errp);
|
||||
}
|
||||
} else {
|
||||
exp->allow_other = args->allow_other == FUSE_EXPORT_ALLOW_OTHER_ON;
|
||||
ret = setup_fuse_export(exp, args->mountpoint, exp->allow_other, errp);
|
||||
}
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -146,15 +174,20 @@ static void init_exports_table(void)
|
||||
* Create exp->fuse_session and mount it.
|
||||
*/
|
||||
static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
|
||||
Error **errp)
|
||||
bool allow_other, Error **errp)
|
||||
{
|
||||
const char *fuse_argv[4];
|
||||
char *mount_opts;
|
||||
struct fuse_args fuse_args;
|
||||
int ret;
|
||||
|
||||
/* Needs to match what fuse_init() sets. Only max_read must be supplied. */
|
||||
mount_opts = g_strdup_printf("max_read=%zu", FUSE_MAX_BOUNCE_BYTES);
|
||||
/*
|
||||
* max_read needs to match what fuse_init() sets.
|
||||
* max_write need not be supplied.
|
||||
*/
|
||||
mount_opts = g_strdup_printf("max_read=%zu,default_permissions%s",
|
||||
FUSE_MAX_BOUNCE_BYTES,
|
||||
allow_other ? ",allow_other" : "");
|
||||
|
||||
fuse_argv[0] = ""; /* Dummy program name */
|
||||
fuse_argv[1] = "-o";
|
||||
@@ -316,7 +349,6 @@ static void fuse_getattr(fuse_req_t req, fuse_ino_t inode,
|
||||
int64_t length, allocated_blocks;
|
||||
time_t now = time(NULL);
|
||||
FuseExport *exp = fuse_req_userdata(req);
|
||||
mode_t mode;
|
||||
|
||||
length = blk_getlength(exp->common.blk);
|
||||
if (length < 0) {
|
||||
@@ -331,17 +363,12 @@ static void fuse_getattr(fuse_req_t req, fuse_ino_t inode,
|
||||
allocated_blocks = DIV_ROUND_UP(allocated_blocks, 512);
|
||||
}
|
||||
|
||||
mode = S_IFREG | S_IRUSR;
|
||||
if (exp->writable) {
|
||||
mode |= S_IWUSR;
|
||||
}
|
||||
|
||||
statbuf = (struct stat) {
|
||||
.st_ino = inode,
|
||||
.st_mode = mode,
|
||||
.st_mode = exp->st_mode,
|
||||
.st_nlink = 1,
|
||||
.st_uid = getuid(),
|
||||
.st_gid = getgid(),
|
||||
.st_uid = exp->st_uid,
|
||||
.st_gid = exp->st_gid,
|
||||
.st_size = length,
|
||||
.st_blksize = blk_bs(exp->common.blk)->bl.request_alignment,
|
||||
.st_blocks = allocated_blocks,
|
||||
@@ -387,28 +414,76 @@ static int fuse_do_truncate(const FuseExport *exp, int64_t size,
|
||||
}
|
||||
|
||||
/**
|
||||
* Let clients set file attributes. Only resizing is supported.
|
||||
* Let clients set file attributes. Only resizing and changing
|
||||
* permissions (st_mode, st_uid, st_gid) is allowed.
|
||||
* Changing permissions is only allowed as far as it will actually
|
||||
* permit access: Read-only exports cannot be given +w, and exports
|
||||
* without allow_other cannot be given a different UID or GID, and
|
||||
* they cannot be given non-owner access.
|
||||
*/
|
||||
static void fuse_setattr(fuse_req_t req, fuse_ino_t inode, struct stat *statbuf,
|
||||
int to_set, struct fuse_file_info *fi)
|
||||
{
|
||||
FuseExport *exp = fuse_req_userdata(req);
|
||||
int supported_attrs;
|
||||
int ret;
|
||||
|
||||
if (!exp->writable) {
|
||||
fuse_reply_err(req, EACCES);
|
||||
return;
|
||||
supported_attrs = FUSE_SET_ATTR_SIZE | FUSE_SET_ATTR_MODE;
|
||||
if (exp->allow_other) {
|
||||
supported_attrs |= FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID;
|
||||
}
|
||||
|
||||
if (to_set & ~FUSE_SET_ATTR_SIZE) {
|
||||
if (to_set & ~supported_attrs) {
|
||||
fuse_reply_err(req, ENOTSUP);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = fuse_do_truncate(exp, statbuf->st_size, true, PREALLOC_MODE_OFF);
|
||||
if (ret < 0) {
|
||||
fuse_reply_err(req, -ret);
|
||||
return;
|
||||
/* Do some argument checks first before committing to anything */
|
||||
if (to_set & FUSE_SET_ATTR_MODE) {
|
||||
/*
|
||||
* Without allow_other, non-owners can never access the export, so do
|
||||
* not allow setting permissions for them
|
||||
*/
|
||||
if (!exp->allow_other &&
|
||||
(statbuf->st_mode & (S_IRWXG | S_IRWXO)) != 0)
|
||||
{
|
||||
fuse_reply_err(req, EPERM);
|
||||
return;
|
||||
}
|
||||
|
||||
/* +w for read-only exports makes no sense, disallow it */
|
||||
if (!exp->writable &&
|
||||
(statbuf->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
|
||||
{
|
||||
fuse_reply_err(req, EROFS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_SIZE) {
|
||||
if (!exp->writable) {
|
||||
fuse_reply_err(req, EACCES);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = fuse_do_truncate(exp, statbuf->st_size, true, PREALLOC_MODE_OFF);
|
||||
if (ret < 0) {
|
||||
fuse_reply_err(req, -ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_MODE) {
|
||||
/* Ignore FUSE-supplied file type, only change the mode */
|
||||
exp->st_mode = (statbuf->st_mode & 07777) | S_IFREG;
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_UID) {
|
||||
exp->st_uid = statbuf->st_uid;
|
||||
}
|
||||
|
||||
if (to_set & FUSE_SET_ATTR_GID) {
|
||||
exp->st_gid = statbuf->st_gid;
|
||||
}
|
||||
|
||||
fuse_getattr(req, inode, fi);
|
||||
|
||||
+1
-3
@@ -147,9 +147,7 @@ out:
|
||||
if (qp) {
|
||||
query_params_free(qp);
|
||||
}
|
||||
if (uri) {
|
||||
uri_free(uri);
|
||||
}
|
||||
uri_free(uri);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+33
-9
@@ -1926,6 +1926,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
static int qcow2_reopen_prepare(BDRVReopenState *state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = state->bs->opaque;
|
||||
Qcow2ReopenState *r;
|
||||
int ret;
|
||||
|
||||
@@ -1956,6 +1957,16 @@ static int qcow2_reopen_prepare(BDRVReopenState *state,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Without an external data file, s->data_file points to the same BdrvChild
|
||||
* as bs->file. It needs to be resynced after reopen because bs->file may
|
||||
* be changed. We can't use it in the meantime.
|
||||
*/
|
||||
if (!has_data_file(state->bs)) {
|
||||
assert(s->data_file == state->bs->file);
|
||||
s->data_file = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -1966,7 +1977,16 @@ fail:
|
||||
|
||||
static void qcow2_reopen_commit(BDRVReopenState *state)
|
||||
{
|
||||
BDRVQcow2State *s = state->bs->opaque;
|
||||
|
||||
qcow2_update_options_commit(state->bs, state->opaque);
|
||||
if (!s->data_file) {
|
||||
/*
|
||||
* If we don't have an external data file, s->data_file was cleared by
|
||||
* qcow2_reopen_prepare() and needs to be updated.
|
||||
*/
|
||||
s->data_file = state->bs->file;
|
||||
}
|
||||
g_free(state->opaque);
|
||||
}
|
||||
|
||||
@@ -1990,6 +2010,15 @@ static void qcow2_reopen_commit_post(BDRVReopenState *state)
|
||||
|
||||
static void qcow2_reopen_abort(BDRVReopenState *state)
|
||||
{
|
||||
BDRVQcow2State *s = state->bs->opaque;
|
||||
|
||||
if (!s->data_file) {
|
||||
/*
|
||||
* If we don't have an external data file, s->data_file was cleared by
|
||||
* qcow2_reopen_prepare() and needs to be restored.
|
||||
*/
|
||||
s->data_file = state->bs->file;
|
||||
}
|
||||
qcow2_update_options_abort(state->bs, state->opaque);
|
||||
g_free(state->opaque);
|
||||
}
|
||||
@@ -5620,15 +5649,10 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
if (backing_file || backing_format) {
|
||||
if (g_strcmp0(backing_file, s->image_backing_file) ||
|
||||
g_strcmp0(backing_format, s->image_backing_format)) {
|
||||
warn_report("Deprecated use of amend to alter the backing file; "
|
||||
"use qemu-img rebase instead");
|
||||
}
|
||||
ret = qcow2_change_backing_file(bs,
|
||||
backing_file ?: s->image_backing_file,
|
||||
backing_format ?: s->image_backing_format);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to change the backing file");
|
||||
return ret;
|
||||
error_setg(errp, "Cannot amend the backing file");
|
||||
error_append_hint(errp,
|
||||
"You can use 'qemu-img rebase' instead.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+486
-293
File diff suppressed because it is too large
Load Diff
@@ -390,7 +390,14 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
|
||||
}
|
||||
|
||||
if (reopen_queue) {
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
if (ctx != qemu_get_aio_context()) {
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
bdrv_reopen_multiple(reopen_queue, errp);
|
||||
if (ctx != qemu_get_aio_context()) {
|
||||
aio_context_acquire(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
bdrv_subtree_drained_end(s->hidden_disk->bs);
|
||||
|
||||
+1
-3
@@ -237,9 +237,7 @@ static int parse_uri(const char *filename, QDict *options, Error **errp)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (uri) {
|
||||
uri_free(uri);
|
||||
}
|
||||
uri_free(uri);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
+47
-34
@@ -1714,6 +1714,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
state->bs = bs;
|
||||
/* Paired with .clean() */
|
||||
bdrv_drained_begin(bs);
|
||||
|
||||
@@ -1813,8 +1814,6 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
state->bs = bs;
|
||||
|
||||
state->job = do_backup_common(qapi_DriveBackup_base(backup),
|
||||
bs, target_bs, aio_context,
|
||||
common->block_job_txn, errp);
|
||||
@@ -3560,46 +3559,60 @@ fail:
|
||||
visit_free(v);
|
||||
}
|
||||
|
||||
void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp)
|
||||
void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
AioContext *ctx;
|
||||
QObject *obj;
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
BlockReopenQueue *queue;
|
||||
QDict *qdict;
|
||||
BlockReopenQueue *queue = NULL;
|
||||
GSList *drained = NULL;
|
||||
|
||||
/* Check for the selected node name */
|
||||
if (!options->has_node_name) {
|
||||
error_setg(errp, "node-name not specified");
|
||||
goto fail;
|
||||
/* Add each one of the BDS that we want to reopen to the queue */
|
||||
for (; reopen_list != NULL; reopen_list = reopen_list->next) {
|
||||
BlockdevOptions *options = reopen_list->value;
|
||||
BlockDriverState *bs;
|
||||
AioContext *ctx;
|
||||
QObject *obj;
|
||||
Visitor *v;
|
||||
QDict *qdict;
|
||||
|
||||
/* Check for the selected node name */
|
||||
if (!options->has_node_name) {
|
||||
error_setg(errp, "node-name not specified");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs = bdrv_find_node(options->node_name);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Failed to find node with node-name='%s'",
|
||||
options->node_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Put all options in a QDict and flatten it */
|
||||
v = qobject_output_visitor_new(&obj);
|
||||
visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
visit_free(v);
|
||||
|
||||
qdict = qobject_to(QDict, obj);
|
||||
|
||||
qdict_flatten(qdict);
|
||||
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
queue = bdrv_reopen_queue(queue, bs, qdict, false);
|
||||
drained = g_slist_prepend(drained, bs);
|
||||
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
|
||||
bs = bdrv_find_node(options->node_name);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Failed to find node with node-name='%s'",
|
||||
options->node_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Put all options in a QDict and flatten it */
|
||||
visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
qdict = qobject_to(QDict, obj);
|
||||
|
||||
qdict_flatten(qdict);
|
||||
|
||||
/* Perform the reopen operation */
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
queue = bdrv_reopen_queue(NULL, bs, qdict, false);
|
||||
bdrv_reopen_multiple(queue, errp);
|
||||
bdrv_subtree_drained_end(bs);
|
||||
aio_context_release(ctx);
|
||||
queue = NULL;
|
||||
|
||||
fail:
|
||||
visit_free(v);
|
||||
bdrv_reopen_queue_free(queue);
|
||||
g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end);
|
||||
}
|
||||
|
||||
void qmp_blockdev_del(const char *node_name, Error **errp)
|
||||
|
||||
@@ -300,38 +300,6 @@ this CPU is also deprecated.
|
||||
Related binaries
|
||||
----------------
|
||||
|
||||
qemu-img amend to adjust backing file (since 5.1)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The use of ``qemu-img amend`` to modify the name or format of a qcow2
|
||||
backing image is deprecated; this functionality was never fully
|
||||
documented or tested, and interferes with other amend operations that
|
||||
need access to the original backing image (such as deciding whether a
|
||||
v3 zero cluster may be left unallocated when converting to a v2
|
||||
image). Rather, any changes to the backing chain should be performed
|
||||
with ``qemu-img rebase -u`` either before or after the remaining
|
||||
changes being performed by amend, as appropriate.
|
||||
|
||||
qemu-img backing file without format (since 5.1)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The use of ``qemu-img create``, ``qemu-img rebase``, or ``qemu-img
|
||||
convert`` to create or modify an image that depends on a backing file
|
||||
now recommends that an explicit backing format be provided. This is
|
||||
for safety: if QEMU probes a different format than what you thought,
|
||||
the data presented to the guest will be corrupt; similarly, presenting
|
||||
a raw image to a guest allows a potential security exploit if a future
|
||||
probe sees a non-raw image based on guest writes.
|
||||
|
||||
To avoid the warning message, or even future refusal to create an
|
||||
unsafe image, you must pass ``-o backing_fmt=`` (or the shorthand
|
||||
``-F`` during create) to specify the intended backing format. You may
|
||||
use ``qemu-img rebase -u`` to retroactively add a backing format to an
|
||||
existing image. However, be aware that there are already potential
|
||||
security risks to blindly using ``qemu-img info`` to probe the format
|
||||
of an untrusted backing image, when deciding what format to add into
|
||||
an existing image.
|
||||
|
||||
Backwards compatibility
|
||||
-----------------------
|
||||
|
||||
|
||||
@@ -491,6 +491,37 @@ topologies described with -smp include all possible cpus, i.e.
|
||||
The ``enforce-config-section`` property was replaced by the
|
||||
``-global migration.send-configuration={on|off}`` option.
|
||||
|
||||
qemu-img amend to adjust backing file (removed in 6.1)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The use of ``qemu-img amend`` to modify the name or format of a qcow2
|
||||
backing image was never fully documented or tested, and interferes
|
||||
with other amend operations that need access to the original backing
|
||||
image (such as deciding whether a v3 zero cluster may be left
|
||||
unallocated when converting to a v2 image). Any changes to the
|
||||
backing chain should be performed with ``qemu-img rebase -u`` either
|
||||
before or after the remaining changes being performed by amend, as
|
||||
appropriate.
|
||||
|
||||
qemu-img backing file without format (removed in 6.1)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The use of ``qemu-img create``, ``qemu-img rebase``, or ``qemu-img
|
||||
convert`` to create or modify an image that depends on a backing file
|
||||
now requires that an explicit backing format be provided. This is
|
||||
for safety: if QEMU probes a different format than what you thought,
|
||||
the data presented to the guest will be corrupt; similarly, presenting
|
||||
a raw image to a guest allows a potential security exploit if a future
|
||||
probe sees a non-raw image based on guest writes.
|
||||
|
||||
To avoid creating unsafe backing chains, you must pass ``-o
|
||||
backing_fmt=`` (or the shorthand ``-F`` during create) to specify the
|
||||
intended backing format. You may use ``qemu-img rebase -u`` to
|
||||
retroactively add a backing format to an existing image. However, be
|
||||
aware that there are already potential security risks to blindly using
|
||||
``qemu-img info`` to probe the format of an untrusted backing image,
|
||||
when deciding what format to add into an existing image.
|
||||
|
||||
Block devices
|
||||
-------------
|
||||
|
||||
|
||||
@@ -1913,7 +1913,10 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
|
||||
if (err < 0) {
|
||||
return -EPROTO;
|
||||
}
|
||||
} else {
|
||||
dev->max_queues = 1;
|
||||
}
|
||||
|
||||
if (dev->num_queues && dev->max_queues < dev->num_queues) {
|
||||
error_setg(errp, "The maximum number of queues supported by the "
|
||||
"backend is %" PRIu64, dev->max_queues);
|
||||
|
||||
@@ -386,7 +386,10 @@ BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
|
||||
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||
BlockDriverState *bs, QDict *options,
|
||||
bool keep_old_opts);
|
||||
void bdrv_reopen_queue_free(BlockReopenQueue *bs_queue);
|
||||
int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
|
||||
int bdrv_reopen(BlockDriverState *bs, QDict *opts, bool keep_old_opts,
|
||||
Error **errp);
|
||||
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
|
||||
Error **errp);
|
||||
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||
|
||||
+5
-2
@@ -710,13 +710,16 @@ if not get_option('rbd').auto() or have_block
|
||||
int main(void) {
|
||||
rados_t cluster;
|
||||
rados_create(&cluster, NULL);
|
||||
#if LIBRBD_VERSION_CODE < LIBRBD_VERSION(1, 12, 0)
|
||||
#error
|
||||
#endif
|
||||
return 0;
|
||||
}''', dependencies: [librbd, librados])
|
||||
rbd = declare_dependency(dependencies: [librbd, librados])
|
||||
elif get_option('rbd').enabled()
|
||||
error('could not link librados')
|
||||
error('librbd >= 1.12.0 required')
|
||||
else
|
||||
warning('could not link librados, disabling')
|
||||
warning('librbd >= 1.12.0 not found, disabling')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
+121
-13
@@ -127,6 +127,18 @@
|
||||
'extents': ['ImageInfo']
|
||||
} }
|
||||
|
||||
##
|
||||
# @ImageInfoSpecificRbd:
|
||||
#
|
||||
# @encryption-format: Image encryption format
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'struct': 'ImageInfoSpecificRbd',
|
||||
'data': {
|
||||
'*encryption-format': 'RbdImageEncryptionFormat'
|
||||
} }
|
||||
|
||||
##
|
||||
# @ImageInfoSpecific:
|
||||
#
|
||||
@@ -141,7 +153,8 @@
|
||||
# If we need to add block driver specific parameters for
|
||||
# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
|
||||
# to define a ImageInfoSpecificLUKS
|
||||
'luks': 'QCryptoBlockInfoLUKS'
|
||||
'luks': 'QCryptoBlockInfoLUKS',
|
||||
'rbd': 'ImageInfoSpecificRbd'
|
||||
} }
|
||||
|
||||
##
|
||||
@@ -3613,6 +3626,94 @@
|
||||
{ 'enum': 'RbdAuthMode',
|
||||
'data': [ 'cephx', 'none' ] }
|
||||
|
||||
##
|
||||
# @RbdImageEncryptionFormat:
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'enum': 'RbdImageEncryptionFormat',
|
||||
'data': [ 'luks', 'luks2' ] }
|
||||
|
||||
##
|
||||
# @RbdEncryptionOptionsLUKSBase:
|
||||
#
|
||||
# @key-secret: ID of a QCryptoSecret object providing a passphrase
|
||||
# for unlocking the encryption
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'struct': 'RbdEncryptionOptionsLUKSBase',
|
||||
'data': { 'key-secret': 'str' } }
|
||||
|
||||
##
|
||||
# @RbdEncryptionCreateOptionsLUKSBase:
|
||||
#
|
||||
# @cipher-alg: The encryption algorithm
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'struct': 'RbdEncryptionCreateOptionsLUKSBase',
|
||||
'base': 'RbdEncryptionOptionsLUKSBase',
|
||||
'data': { '*cipher-alg': 'QCryptoCipherAlgorithm' } }
|
||||
|
||||
##
|
||||
# @RbdEncryptionOptionsLUKS:
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'struct': 'RbdEncryptionOptionsLUKS',
|
||||
'base': 'RbdEncryptionOptionsLUKSBase',
|
||||
'data': { } }
|
||||
|
||||
##
|
||||
# @RbdEncryptionOptionsLUKS2:
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'struct': 'RbdEncryptionOptionsLUKS2',
|
||||
'base': 'RbdEncryptionOptionsLUKSBase',
|
||||
'data': { } }
|
||||
|
||||
##
|
||||
# @RbdEncryptionCreateOptionsLUKS:
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'struct': 'RbdEncryptionCreateOptionsLUKS',
|
||||
'base': 'RbdEncryptionCreateOptionsLUKSBase',
|
||||
'data': { } }
|
||||
|
||||
##
|
||||
# @RbdEncryptionCreateOptionsLUKS2:
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'struct': 'RbdEncryptionCreateOptionsLUKS2',
|
||||
'base': 'RbdEncryptionCreateOptionsLUKSBase',
|
||||
'data': { } }
|
||||
|
||||
##
|
||||
# @RbdEncryptionOptions:
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'union': 'RbdEncryptionOptions',
|
||||
'base': { 'format': 'RbdImageEncryptionFormat' },
|
||||
'discriminator': 'format',
|
||||
'data': { 'luks': 'RbdEncryptionOptionsLUKS',
|
||||
'luks2': 'RbdEncryptionOptionsLUKS2' } }
|
||||
|
||||
##
|
||||
# @RbdEncryptionCreateOptions:
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'union': 'RbdEncryptionCreateOptions',
|
||||
'base': { 'format': 'RbdImageEncryptionFormat' },
|
||||
'discriminator': 'format',
|
||||
'data': { 'luks': 'RbdEncryptionCreateOptionsLUKS',
|
||||
'luks2': 'RbdEncryptionCreateOptionsLUKS2' } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsRbd:
|
||||
#
|
||||
@@ -3628,6 +3729,8 @@
|
||||
#
|
||||
# @snapshot: Ceph snapshot name.
|
||||
#
|
||||
# @encrypt: Image encryption options. (Since 6.1)
|
||||
#
|
||||
# @user: Ceph id name.
|
||||
#
|
||||
# @auth-client-required: Acceptable authentication modes.
|
||||
@@ -3650,6 +3753,7 @@
|
||||
'image': 'str',
|
||||
'*conf': 'str',
|
||||
'*snapshot': 'str',
|
||||
'*encrypt': 'RbdEncryptionOptions',
|
||||
'*user': 'str',
|
||||
'*auth-client-required': ['RbdAuthMode'],
|
||||
'*key-secret': 'str',
|
||||
@@ -4115,15 +4219,17 @@
|
||||
{ 'command': 'blockdev-add', 'data': 'BlockdevOptions', 'boxed': true }
|
||||
|
||||
##
|
||||
# @x-blockdev-reopen:
|
||||
# @blockdev-reopen:
|
||||
#
|
||||
# Reopens a block device using the given set of options. Any option
|
||||
# not specified will be reset to its default value regardless of its
|
||||
# previous status. If an option cannot be changed or a particular
|
||||
# Reopens one or more block devices using the given set of options.
|
||||
# Any option not specified will be reset to its default value regardless
|
||||
# of its previous status. If an option cannot be changed or a particular
|
||||
# driver does not support reopening then the command will return an
|
||||
# error.
|
||||
# error. All devices in the list are reopened in one transaction, so
|
||||
# if one of them fails then the whole transaction is cancelled.
|
||||
#
|
||||
# The top-level @node-name option (from BlockdevOptions) must be
|
||||
# The command receives a list of block devices to reopen. For each one
|
||||
# of them, the top-level @node-name option (from BlockdevOptions) must be
|
||||
# specified and is used to select the block device to be reopened.
|
||||
# Other @node-name options must be either omitted or set to the
|
||||
# current name of the appropriate node. This command won't change any
|
||||
@@ -4143,18 +4249,18 @@
|
||||
#
|
||||
# 4) NULL: the current child (if any) is detached.
|
||||
#
|
||||
# Options (1) and (2) are supported in all cases, but at the moment
|
||||
# only @backing allows replacing or detaching an existing child.
|
||||
# Options (1) and (2) are supported in all cases. Option (3) is
|
||||
# supported for @file and @backing, and option (4) for @backing only.
|
||||
#
|
||||
# Unlike with blockdev-add, the @backing option must always be present
|
||||
# unless the node being reopened does not have a backing file and its
|
||||
# image does not have a default backing file name as part of its
|
||||
# metadata.
|
||||
#
|
||||
# Since: 4.0
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'command': 'x-blockdev-reopen',
|
||||
'data': 'BlockdevOptions', 'boxed': true }
|
||||
{ 'command': 'blockdev-reopen',
|
||||
'data': { 'options': ['BlockdevOptions'] } }
|
||||
|
||||
##
|
||||
# @blockdev-del:
|
||||
@@ -4403,13 +4509,15 @@
|
||||
# point to a snapshot.
|
||||
# @size: Size of the virtual disk in bytes
|
||||
# @cluster-size: RBD object size
|
||||
# @encrypt: Image encryption options. (Since 6.1)
|
||||
#
|
||||
# Since: 2.12
|
||||
##
|
||||
{ 'struct': 'BlockdevCreateOptionsRbd',
|
||||
'data': { 'location': 'BlockdevOptionsRbd',
|
||||
'size': 'size',
|
||||
'*cluster-size' : 'size' } }
|
||||
'*cluster-size' : 'size',
|
||||
'*encrypt' : 'RbdEncryptionCreateOptions' } }
|
||||
|
||||
##
|
||||
# @BlockdevVmdkSubformat:
|
||||
|
||||
+32
-1
@@ -120,6 +120,23 @@
|
||||
'*logical-block-size': 'size',
|
||||
'*num-queues': 'uint16'} }
|
||||
|
||||
##
|
||||
# @FuseExportAllowOther:
|
||||
#
|
||||
# Possible allow_other modes for FUSE exports.
|
||||
#
|
||||
# @off: Do not pass allow_other as a mount option.
|
||||
#
|
||||
# @on: Pass allow_other as a mount option.
|
||||
#
|
||||
# @auto: Try mounting with allow_other first, and if that fails, retry
|
||||
# without allow_other.
|
||||
#
|
||||
# Since: 6.1
|
||||
##
|
||||
{ 'enum': 'FuseExportAllowOther',
|
||||
'data': ['off', 'on', 'auto'] }
|
||||
|
||||
##
|
||||
# @BlockExportOptionsFuse:
|
||||
#
|
||||
@@ -132,11 +149,25 @@
|
||||
# @growable: Whether writes beyond the EOF should grow the block node
|
||||
# accordingly. (default: false)
|
||||
#
|
||||
# @allow-other: If this is off, only qemu's user is allowed access to
|
||||
# this export. That cannot be changed even with chmod or
|
||||
# chown.
|
||||
# Enabling this option will allow other users access to
|
||||
# the export with the FUSE mount option "allow_other".
|
||||
# Note that using allow_other as a non-root user requires
|
||||
# user_allow_other to be enabled in the global fuse.conf
|
||||
# configuration file.
|
||||
# In auto mode (the default), the FUSE export driver will
|
||||
# first attempt to mount the export with allow_other, and
|
||||
# if that fails, try again without.
|
||||
# (since 6.1; default: auto)
|
||||
#
|
||||
# Since: 6.0
|
||||
##
|
||||
{ 'struct': 'BlockExportOptionsFuse',
|
||||
'data': { 'mountpoint': 'str',
|
||||
'*growable': 'bool' },
|
||||
'*growable': 'bool',
|
||||
'*allow-other': 'FuseExportAllowOther' },
|
||||
'if': 'defined(CONFIG_FUSE)' }
|
||||
|
||||
##
|
||||
|
||||
+7
-2
@@ -2508,8 +2508,10 @@ static int img_convert(int argc, char **argv)
|
||||
|
||||
if (out_baseimg_param) {
|
||||
if (!qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT)) {
|
||||
warn_report("Deprecated use of backing file without explicit "
|
||||
"backing format");
|
||||
error_report("Use of backing file requires explicit "
|
||||
"backing format");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3765,6 +3767,9 @@ static int img_rebase(int argc, char **argv)
|
||||
if (ret == -ENOSPC) {
|
||||
error_report("Could not change the backing file to '%s': No "
|
||||
"space left in the file header", out_baseimg);
|
||||
} else if (ret == -EINVAL && out_baseimg && !out_basefmt) {
|
||||
error_report("Could not change the backing file to '%s': backing "
|
||||
"format must be specified", out_baseimg);
|
||||
} else if (ret < 0) {
|
||||
error_report("Could not change the backing file to '%s': %s",
|
||||
out_baseimg, strerror(-ret));
|
||||
|
||||
+1
-6
@@ -2116,8 +2116,6 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
|
||||
bool writethrough = !blk_enable_write_cache(blk);
|
||||
bool has_rw_option = false;
|
||||
bool has_cache_option = false;
|
||||
|
||||
BlockReopenQueue *brq;
|
||||
Error *local_err = NULL;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
|
||||
@@ -2210,10 +2208,7 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
|
||||
qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
|
||||
}
|
||||
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
brq = bdrv_reopen_queue(NULL, bs, opts, true);
|
||||
bdrv_reopen_multiple(brq, &local_err);
|
||||
bdrv_subtree_drained_end(bs);
|
||||
bdrv_reopen(bs, opts, true, &local_err);
|
||||
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
|
||||
@@ -920,8 +920,8 @@ class TestCommitWithOverriddenBacking(iotests.QMPTestCase):
|
||||
def setUp(self):
|
||||
qemu_img('create', '-f', iotests.imgfmt, self.img_base_a, '1M')
|
||||
qemu_img('create', '-f', iotests.imgfmt, self.img_base_b, '1M')
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-b', self.img_base_a, \
|
||||
self.img_top)
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-b', self.img_base_a,
|
||||
'-F', iotests.imgfmt, self.img_top)
|
||||
|
||||
self.vm = iotests.VM()
|
||||
self.vm.launch()
|
||||
|
||||
@@ -1295,8 +1295,10 @@ class TestReplaces(iotests.QMPTestCase):
|
||||
class TestFilters(iotests.QMPTestCase):
|
||||
def setUp(self):
|
||||
qemu_img('create', '-f', iotests.imgfmt, backing_img, '1M')
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, test_img)
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, target_img)
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img,
|
||||
'-F', iotests.imgfmt, test_img)
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img,
|
||||
'-F', iotests.imgfmt, target_img)
|
||||
|
||||
qemu_io('-c', 'write -P 1 0 512k', backing_img)
|
||||
qemu_io('-c', 'write -P 2 512k 512k', test_img)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user