Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into s…
Browse files Browse the repository at this point in the history
…taging

Block layer patches:

- Relax restrictions for blockdev-snapshot (allows libvirt to do live
  storage migration with blockdev-mirror)
- luks: Delete created files when block_crypto_co_create_opts_luks fails
- Fix memleaks in qmp_object_add

# gpg: Signature made Wed 11 Mar 2020 15:38:59 GMT
# gpg:                using RSA key 7F09B272C88F2FD6
# 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:
  qemu-iotests: adding LUKS cleanup for non-UTF8 secret error
  crypto.c: cleanup created file when block_crypto_co_create_opts_luks fails
  block.c: adding bdrv_co_delete_file
  block: introducing 'bdrv_co_delete_file' interface
  tests/qemu-iotests: Fix socket_scm_helper build path
  qapi: Add '@allow-write-only-overlay' feature for 'blockdev-snapshot'
  iotests: Add iothread cases to 155
  block: Fix cross-AioContext blockdev-snapshot
  iotests: Test mirror with temporarily disabled target backing file
  iotests: Fix run_job() with use_log=False
  block: Relax restrictions for blockdev-snapshot
  block: Make bdrv_get_cumulative_perm() public
  qom-qmp-cmds: fix two memleaks in qmp_object_add

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Mar 12, 2020
2 parents 10b1140 + 8bb3b02 commit 49780a5
Show file tree
Hide file tree
Showing 17 changed files with 262 additions and 57 deletions.
33 changes: 29 additions & 4 deletions block.c
Expand Up @@ -668,6 +668,32 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
}
}

int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp)
{
Error *local_err = NULL;
int ret;

assert(bs != NULL);

if (!bs->drv) {
error_setg(errp, "Block node '%s' is not opened", bs->filename);
return -ENOMEDIUM;
}

if (!bs->drv->bdrv_co_delete_file) {
error_setg(errp, "Driver '%s' does not support image deletion",
bs->drv->format_name);
return -ENOTSUP;
}

ret = bs->drv->bdrv_co_delete_file(bs, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
}

return ret;
}

/**
* Try to get @bs's logical and physical block size.
* On success, store them in @bsz struct and return 0.
Expand Down Expand Up @@ -1872,8 +1898,6 @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
bool *tighten_restrictions, Error **errp);
static void bdrv_child_abort_perm_update(BdrvChild *c);
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
static void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
uint64_t *shared_perm);

typedef struct BlockReopenQueueEntry {
bool prepared;
Expand Down Expand Up @@ -2097,8 +2121,8 @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
}
}

static void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
uint64_t *shared_perm)
void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
uint64_t *shared_perm)
{
BdrvChild *c;
uint64_t cumulative_perms = 0;
Expand Down Expand Up @@ -4367,6 +4391,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
bdrv_ref(from);

assert(qemu_get_current_aio_context() == qemu_get_aio_context());
assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to));
bdrv_drained_begin(from);

/* Put all parents into @list and calculate their cumulative permissions */
Expand Down
18 changes: 18 additions & 0 deletions block/crypto.c
Expand Up @@ -30,6 +30,7 @@
#include "qapi/error.h"
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/cutils.h"
#include "crypto.h"

typedef struct BlockCrypto BlockCrypto;
Expand Down Expand Up @@ -657,6 +658,23 @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,

ret = 0;
fail:
/*
* If an error occurred, delete 'filename'. Even if the file existed
* beforehand, it has been truncated and corrupted in the process.
*/
if (ret && bs) {
Error *local_delete_err = NULL;
int r_del = bdrv_co_delete_file(bs, &local_delete_err);
/*
* ENOTSUP will happen if the block driver doesn't support
* the 'bdrv_co_delete_file' interface. This is a predictable
* scenario and shouldn't be reported back to the user.
*/
if ((r_del < 0) && (r_del != -ENOTSUP)) {
error_report_err(local_delete_err);
}
}

bdrv_unref(bs);
qapi_free_QCryptoBlockCreateOptions(create_opts);
qobject_unref(cryptoopts);
Expand Down
23 changes: 23 additions & 0 deletions block/file-posix.c
Expand Up @@ -2445,6 +2445,28 @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
return raw_co_create(&options, errp);
}

static int coroutine_fn raw_co_delete_file(BlockDriverState *bs,
Error **errp)
{
struct stat st;
int ret;

if (!(stat(bs->filename, &st) == 0) || !S_ISREG(st.st_mode)) {
error_setg_errno(errp, ENOENT, "%s is not a regular file",
bs->filename);
return -ENOENT;
}

ret = unlink(bs->filename);
if (ret < 0) {
ret = -errno;
error_setg_errno(errp, -ret, "Error when deleting file %s",
bs->filename);
}

return ret;
}

/*
* Find allocation range in @bs around offset @start.
* May change underlying file descriptor's file offset.
Expand Down Expand Up @@ -3075,6 +3097,7 @@ BlockDriver bdrv_file = {
.bdrv_co_block_status = raw_co_block_status,
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
.bdrv_co_delete_file = raw_co_delete_file,

.bdrv_co_preadv = raw_co_preadv,
.bdrv_co_pwritev = raw_co_pwritev,
Expand Down
30 changes: 8 additions & 22 deletions blockdev.c
Expand Up @@ -1470,8 +1470,7 @@ static void external_snapshot_prepare(BlkActionState *common,
DO_UPCAST(ExternalSnapshotState, common, common);
TransactionAction *action = common->action;
AioContext *aio_context;
AioContext *old_context;
int ret;
uint64_t perm, shared;

/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
* purpose but a different set of parameters */
Expand Down Expand Up @@ -1586,16 +1585,17 @@ static void external_snapshot_prepare(BlkActionState *common,
goto out;
}

if (bdrv_has_blk(state->new_bs)) {
/*
* Allow attaching a backing file to an overlay that's already in use only
* if the parents don't assume that they are already seeing a valid image.
* (Specifically, allow it as a mirror target, which is write-only access.)
*/
bdrv_get_cumulative_perm(state->new_bs, &perm, &shared);
if (perm & BLK_PERM_CONSISTENT_READ) {
error_setg(errp, "The overlay is already in use");
goto out;
}

if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
errp)) {
goto out;
}

if (state->new_bs->backing != NULL) {
error_setg(errp, "The overlay already has a backing image");
goto out;
Expand All @@ -1606,20 +1606,6 @@ static void external_snapshot_prepare(BlkActionState *common,
goto out;
}

/* Honor bdrv_try_set_aio_context() context acquisition requirements. */
old_context = bdrv_get_aio_context(state->new_bs);
aio_context_release(aio_context);
aio_context_acquire(old_context);

ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);

aio_context_release(old_context);
aio_context_acquire(aio_context);

if (ret < 0) {
goto out;
}

/* This removes our old bs and adds the new bs. This is an operation that
* can fail, so we need to do it in .prepare; undoing it for abort is
* always possible. */
Expand Down
1 change: 1 addition & 0 deletions include/block/block.h
Expand Up @@ -363,6 +363,7 @@ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
Error **errp);
void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base);
int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp);


typedef struct BdrvCheckResult {
Expand Down
7 changes: 7 additions & 0 deletions include/block/block_int.h
Expand Up @@ -314,6 +314,10 @@ struct BlockDriver {
*/
int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);

/* Delete a created file. */
int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs,
Error **errp);

/*
* Flushes all data that was already written to the OS all the way down to
* the disk (for example file-posix.c calls fsync()).
Expand Down Expand Up @@ -1224,6 +1228,9 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
void *opaque, Error **errp);
void bdrv_root_unref_child(BdrvChild *child);

void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
uint64_t *shared_perm);

/**
* Sets a BdrvChild's permissions. Avoid if the parent is a BDS; use
* bdrv_child_refresh_perms() instead and make the parent's
Expand Down
9 changes: 8 additions & 1 deletion qapi/block-core.json
Expand Up @@ -1472,6 +1472,12 @@
#
# For the arguments, see the documentation of BlockdevSnapshot.
#
# Features:
# @allow-write-only-overlay: If present, the check whether this operation is safe
# was relaxed so that it can be used to change
# backing file of a destination of a blockdev-mirror.
# (since 5.0)
#
# Since: 2.5
#
# Example:
Expand All @@ -1492,7 +1498,8 @@
#
##
{ 'command': 'blockdev-snapshot',
'data': 'BlockdevSnapshot' }
'data': 'BlockdevSnapshot',
'features': [ 'allow-write-only-overlay' ] }

##
# @change-backing-file:
Expand Down
16 changes: 6 additions & 10 deletions qom/qom-qmp-cmds.c
Expand Up @@ -247,26 +247,22 @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
QDict *pdict;
Visitor *v;
Object *obj;
const char *type;
const char *id;
g_autofree char *type = NULL;
g_autofree char *id = NULL;

type = qdict_get_try_str(qdict, "qom-type");
type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
if (!type) {
error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
return;
} else {
type = g_strdup(type);
qdict_del(qdict, "qom-type");
}
qdict_del(qdict, "qom-type");

id = qdict_get_try_str(qdict, "id");
id = g_strdup(qdict_get_try_str(qdict, "id"));
if (!id) {
error_setg(errp, QERR_MISSING_PARAMETER, "id");
return;
} else {
id = g_strdup(id);
qdict_del(qdict, "id");
}
qdict_del(qdict, "id");

props = qdict_get(qdict, "props");
if (props) {
Expand Down
1 change: 1 addition & 0 deletions tests/Makefile.include
Expand Up @@ -589,6 +589,7 @@ include $(SRC_PATH)/tests/qtest/Makefile.include
tests/test-qga$(EXESUF): qemu-ga$(EXESUF)
tests/test-qga$(EXESUF): tests/test-qga.o $(qtest-obj-y)
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o

SPEED = quick

Expand Down
4 changes: 2 additions & 2 deletions tests/qemu-iotests/085.out
Expand Up @@ -82,7 +82,7 @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f
=== Invalid command - cannot create a snapshot using a file BDS ===

{ 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'file_12' } }
{"error": {"class": "GenericError", "desc": "The overlay does not support backing images"}}
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}

=== Invalid command - snapshot node used as active layer ===

Expand All @@ -96,7 +96,7 @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f
=== Invalid command - snapshot node used as backing hd ===

{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node is used as backing hd of 'snap_12'"}}
{"error": {"class": "GenericError", "desc": "The overlay is already in use"}}

=== Invalid command - snapshot node has a backing image ===

Expand Down

0 comments on commit 49780a5

Please sign in to comment.