mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
Block layer patches:
- qcow2 cache option default changes (Linux: 32 MB maximum, limited by whatever cache size can be made use of with the specific image; default cache-clean-interval of 10 minutes) - reopen: Allow specifying unchanged child node references, and changing a few generic options (discard, detect-zeroes) - Fix werror/rerror defaults for -device drive=<node-name> - Test case fixes -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbslavAAoJEH8JsnLIjy/Wi0kP/jU18AzfISoIhcJ2GBXYU2aV /FnUdB/L3mjMZOYkIgjDunw/fgfvelLqNdWb7xlijYeDPAiYKNEmJHX+iznE5ieP KnpHOxASSe8w5SFlnF8h30rLK05gcy/rg/QcuMX4KkU46E0C8t0rSLBJE5FdYiRU HN00jraTNfzyixuFxRVpqyadbhbCCEVwlwjDg3GMjGEML/WRk6jmhOOF5tVX72om gmVrzA1lAlzkFnx32Bloevp72iolWFLkyA86oNgPMwIFG0zj9lnK5B/fvnkVTY2v MnXGPwEVZUoZnif4nAXA2+bBqKT4Nbo21N8OylJhmNUi8K/rndiZdHH5Kph+yFod RGkBI4Pb5KxiI+YDiRKJmyQd/7IiWLarjP1nV3UjvPLnpmuTA54jRjDVmA6AW8OH BFu34+jfA4rll2dorVmQAFES4yvvj/brtTsCZfG5VNl60tigdqeLCZrQkNwR188q osKGWBEKy7+2SYj5q+s0BSO+caXmU2XLSdcE1gEHFQ51eU0mRZA0OrooNUuUk30E 42n8BZ77P8EGb7UQBmKqYwWL4hXQPWL3m3i7Mnz19+iwk/m8SHvj2nriouDoiVtf gtUwfr7TKvL9JcPLHrS3/j8boC5S4Rm+wlyyIlta8n2rS4bh1e2bGEZuNxZKyKCg Y9WO6KxbztbO9X0ZnxFW =ai81 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block layer patches: - qcow2 cache option default changes (Linux: 32 MB maximum, limited by whatever cache size can be made use of with the specific image; default cache-clean-interval of 10 minutes) - reopen: Allow specifying unchanged child node references, and changing a few generic options (discard, detect-zeroes) - Fix werror/rerror defaults for -device drive=<node-name> - Test case fixes # gpg: Signature made Mon 01 Oct 2018 18:17:35 BST # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (23 commits) tests/test-bdrv-drain: Fix too late qemu_event_reset() test-replication: Lock AioContext around blk_unref() qcow2: Fix cache-clean-interval documentation block-backend: Set werror/rerror defaults in blk_new() qcow2: Explicit number replaced by a constant qcow2: Set the default cache-clean-interval to 10 minutes qcow2: Resize the cache upon image resizing qcow2: Increase the default upper limit on the L2 cache size qcow2: Assign the L2 cache relatively to the image size qcow2: Avoid duplication in setting the refcount cache size qcow2: Make sizes more humanly readable include: Add a lookup table of sizes qcow2: Options' documentation fixes block: Allow changing 'detect-zeroes' on reopen block: Allow changing 'discard' on reopen file-posix: Forbid trying to change unsupported options during reopen block: Forbid trying to change unsupported options during reopen block: Allow child references on reopen block: Don't look for child references in append_open_options() block: Remove child references from bs->{options,explicit_options} ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e32e62f253
127
block.c
127
block.c
@ -764,6 +764,31 @@ static void bdrv_join_options(BlockDriverState *bs, QDict *options,
|
||||
}
|
||||
}
|
||||
|
||||
static BlockdevDetectZeroesOptions bdrv_parse_detect_zeroes(QemuOpts *opts,
|
||||
int open_flags,
|
||||
Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
char *value = qemu_opt_get_del(opts, "detect-zeroes");
|
||||
BlockdevDetectZeroesOptions detect_zeroes =
|
||||
qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup, value,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF, &local_err);
|
||||
g_free(value);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return detect_zeroes;
|
||||
}
|
||||
|
||||
if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
|
||||
!(open_flags & BDRV_O_UNMAP))
|
||||
{
|
||||
error_setg(errp, "setting detect-zeroes to unmap is not allowed "
|
||||
"without setting discard operation to unmap");
|
||||
}
|
||||
|
||||
return detect_zeroes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set open flags for a given discard mode
|
||||
*
|
||||
@ -1094,19 +1119,19 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
|
||||
*flags &= ~BDRV_O_CACHE_MASK;
|
||||
|
||||
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
|
||||
if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
|
||||
if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
|
||||
*flags |= BDRV_O_NO_FLUSH;
|
||||
}
|
||||
|
||||
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT));
|
||||
if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
|
||||
if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_DIRECT, false)) {
|
||||
*flags |= BDRV_O_NOCACHE;
|
||||
}
|
||||
|
||||
*flags &= ~BDRV_O_RDWR;
|
||||
|
||||
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
|
||||
if (!qemu_opt_get_bool(opts, BDRV_OPT_READ_ONLY, false)) {
|
||||
if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
|
||||
*flags |= BDRV_O_RDWR;
|
||||
}
|
||||
|
||||
@ -1328,7 +1353,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
|
||||
const char *driver_name = NULL;
|
||||
const char *node_name = NULL;
|
||||
const char *discard;
|
||||
const char *detect_zeroes;
|
||||
QemuOpts *opts;
|
||||
BlockDriver *drv;
|
||||
Error *local_err = NULL;
|
||||
@ -1417,31 +1441,14 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
|
||||
}
|
||||
}
|
||||
|
||||
detect_zeroes = qemu_opt_get(opts, "detect-zeroes");
|
||||
if (detect_zeroes) {
|
||||
BlockdevDetectZeroesOptions value =
|
||||
qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
|
||||
detect_zeroes,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||
&local_err);
|
||||
bs->detect_zeroes =
|
||||
bdrv_parse_detect_zeroes(opts, bs->open_flags, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto fail_opts;
|
||||
}
|
||||
|
||||
if (value == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
|
||||
!(bs->open_flags & BDRV_O_UNMAP))
|
||||
{
|
||||
error_setg(errp, "setting detect-zeroes to unmap is not allowed "
|
||||
"without setting discard operation to unmap");
|
||||
ret = -EINVAL;
|
||||
goto fail_opts;
|
||||
}
|
||||
|
||||
bs->detect_zeroes = value;
|
||||
}
|
||||
|
||||
if (filename != NULL) {
|
||||
pstrcpy(bs->filename, sizeof(bs->filename), filename);
|
||||
} else {
|
||||
@ -2763,12 +2770,15 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all children options from bs->options and bs->explicit_options */
|
||||
/* Remove all children options and references
|
||||
* from bs->options and bs->explicit_options */
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
char *child_key_dot;
|
||||
child_key_dot = g_strdup_printf("%s.", child->name);
|
||||
qdict_extract_subqdict(bs->explicit_options, NULL, child_key_dot);
|
||||
qdict_extract_subqdict(bs->options, NULL, child_key_dot);
|
||||
qdict_del(bs->explicit_options, child->name);
|
||||
qdict_del(bs->options, child->name);
|
||||
g_free(child_key_dot);
|
||||
}
|
||||
|
||||
@ -3153,7 +3163,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||
BlockDriver *drv;
|
||||
QemuOpts *opts;
|
||||
QDict *orig_reopen_opts;
|
||||
const char *value;
|
||||
char *discard = NULL;
|
||||
bool read_only;
|
||||
|
||||
assert(reopen_state != NULL);
|
||||
@ -3176,18 +3186,28 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||
|
||||
update_flags_from_options(&reopen_state->flags, opts);
|
||||
|
||||
/* node-name and driver must be unchanged. Put them back into the QDict, so
|
||||
* that they are checked at the end of this function. */
|
||||
value = qemu_opt_get(opts, "node-name");
|
||||
if (value) {
|
||||
qdict_put_str(reopen_state->options, "node-name", value);
|
||||
discard = qemu_opt_get_del(opts, "discard");
|
||||
if (discard != NULL) {
|
||||
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
|
||||
error_setg(errp, "Invalid discard option");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
value = qemu_opt_get(opts, "driver");
|
||||
if (value) {
|
||||
qdict_put_str(reopen_state->options, "driver", value);
|
||||
reopen_state->detect_zeroes =
|
||||
bdrv_parse_detect_zeroes(opts, reopen_state->flags, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* All other options (including node-name and driver) must be unchanged.
|
||||
* Put them back into the QDict, so that they are checked at the end
|
||||
* of this function. */
|
||||
qemu_opts_to_qdict(opts, reopen_state->options);
|
||||
|
||||
/* If we are to stay read-only, do not allow permission change
|
||||
* to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
|
||||
* not set, or if the BDS still has copy_on_read enabled */
|
||||
@ -3239,6 +3259,24 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||
QObject *new = entry->value;
|
||||
QObject *old = qdict_get(reopen_state->bs->options, entry->key);
|
||||
|
||||
/* Allow child references (child_name=node_name) as long as they
|
||||
* point to the current child (i.e. everything stays the same). */
|
||||
if (qobject_type(new) == QTYPE_QSTRING) {
|
||||
BdrvChild *child;
|
||||
QLIST_FOREACH(child, &reopen_state->bs->children, next) {
|
||||
if (!strcmp(child->name, entry->key)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (child) {
|
||||
const char *str = qobject_get_try_str(new);
|
||||
if (!strcmp(child->bs->node_name, str)) {
|
||||
continue; /* Found child with this name, skip option */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: When using -drive to specify blockdev options, all values
|
||||
* will be strings; however, when using -blockdev, blockdev-add or
|
||||
@ -3278,6 +3316,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||
error:
|
||||
qemu_opts_del(opts);
|
||||
qobject_unref(orig_reopen_opts);
|
||||
g_free(discard);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3290,6 +3329,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
|
||||
{
|
||||
BlockDriver *drv;
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
bool old_can_write, new_can_write;
|
||||
|
||||
assert(reopen_state != NULL);
|
||||
@ -3313,6 +3353,14 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
|
||||
bs->options = reopen_state->options;
|
||||
bs->open_flags = reopen_state->flags;
|
||||
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
|
||||
bs->detect_zeroes = reopen_state->detect_zeroes;
|
||||
|
||||
/* Remove child references from bs->options and bs->explicit_options.
|
||||
* Child options were already removed in bdrv_reopen_queue_child() */
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
qdict_del(bs->explicit_options, child->name);
|
||||
qdict_del(bs->options, child->name);
|
||||
}
|
||||
|
||||
bdrv_refresh_limits(bs, NULL);
|
||||
|
||||
@ -5139,23 +5187,12 @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
|
||||
{
|
||||
const QDictEntry *entry;
|
||||
QemuOptDesc *desc;
|
||||
BdrvChild *child;
|
||||
bool found_any = false;
|
||||
|
||||
for (entry = qdict_first(bs->options); entry;
|
||||
entry = qdict_next(bs->options, entry))
|
||||
{
|
||||
/* Exclude node-name references to children */
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
if (!strcmp(entry->key, child->name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (child) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* And exclude all non-driver-specific options */
|
||||
/* Exclude all non-driver-specific options */
|
||||
for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
|
||||
if (!strcmp(qdict_entry_key(entry), desc->name)) {
|
||||
break;
|
||||
|
@ -325,6 +325,9 @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
|
||||
blk->shared_perm = shared_perm;
|
||||
blk_set_enable_write_cache(blk, true);
|
||||
|
||||
blk->on_read_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||
blk->on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
|
||||
|
||||
block_acct_init(&blk->stats);
|
||||
|
||||
notifier_list_init(&blk->remove_bs_notifiers);
|
||||
|
@ -741,8 +741,6 @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
|
||||
"Failed to get \"%s\" lock",
|
||||
perm_name);
|
||||
g_free(perm_name);
|
||||
error_append_hint(errp,
|
||||
"Is another process using the image?\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -758,8 +756,6 @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
|
||||
"Failed to get shared \"%s\" lock",
|
||||
perm_name);
|
||||
g_free(perm_name);
|
||||
error_append_hint(errp,
|
||||
"Is another process using the image?\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -796,6 +792,9 @@ static int raw_handle_perm_lock(BlockDriverState *bs,
|
||||
if (!ret) {
|
||||
return 0;
|
||||
}
|
||||
error_append_hint(errp,
|
||||
"Is another process using the image [%s]?\n",
|
||||
bs->filename);
|
||||
}
|
||||
op = RAW_PL_ABORT;
|
||||
/* fall through to unlock bytes. */
|
||||
@ -850,8 +849,13 @@ static int raw_reopen_prepare(BDRVReopenState *state,
|
||||
goto out;
|
||||
}
|
||||
|
||||
rs->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped",
|
||||
s->check_cache_dropped);
|
||||
rs->check_cache_dropped =
|
||||
qemu_opt_get_bool_del(opts, "x-check-cache-dropped", false);
|
||||
|
||||
/* This driver's reopen function doesn't currently allow changing
|
||||
* other options, so let's put them back in the original QDict and
|
||||
* bdrv_reopen_prepare() will detect changes and complain. */
|
||||
qemu_opts_to_qdict(opts, state->options);
|
||||
|
||||
if (s->type == FTYPE_CD) {
|
||||
rs->open_flags |= O_NONBLOCK;
|
||||
@ -2217,6 +2221,9 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
|
||||
/* Step two: Check that nobody else has taken conflicting locks */
|
||||
result = raw_check_lock_bytes(fd, perm, shared, errp);
|
||||
if (result < 0) {
|
||||
error_append_hint(errp,
|
||||
"Is another process using the image [%s]?\n",
|
||||
file_opts->filename);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
|
@ -777,29 +777,35 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
|
||||
uint64_t *refcount_cache_size, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t combined_cache_size;
|
||||
uint64_t combined_cache_size, l2_cache_max_setting;
|
||||
bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
|
||||
int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
|
||||
uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
|
||||
|
||||
combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
|
||||
l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
|
||||
refcount_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_REFCOUNT_CACHE_SIZE);
|
||||
|
||||
combined_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_CACHE_SIZE, 0);
|
||||
*l2_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE, 0);
|
||||
l2_cache_max_setting = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE,
|
||||
DEFAULT_L2_CACHE_MAX_SIZE);
|
||||
*refcount_cache_size = qemu_opt_get_size(opts,
|
||||
QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
|
||||
|
||||
*l2_cache_entry_size = qemu_opt_get_size(
|
||||
opts, QCOW2_OPT_L2_CACHE_ENTRY_SIZE, s->cluster_size);
|
||||
|
||||
*l2_cache_size = MIN(max_l2_cache, l2_cache_max_setting);
|
||||
|
||||
if (combined_cache_size_set) {
|
||||
if (l2_cache_size_set && refcount_cache_size_set) {
|
||||
error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
|
||||
" and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
|
||||
"at the same time");
|
||||
return;
|
||||
} else if (*l2_cache_size > combined_cache_size) {
|
||||
} else if (l2_cache_size_set &&
|
||||
(l2_cache_max_setting > combined_cache_size)) {
|
||||
error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
|
||||
QCOW2_OPT_CACHE_SIZE);
|
||||
return;
|
||||
@ -814,9 +820,6 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
|
||||
} else if (refcount_cache_size_set) {
|
||||
*l2_cache_size = combined_cache_size - *refcount_cache_size;
|
||||
} else {
|
||||
uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
|
||||
|
||||
/* Assign as much memory as possible to the L2 cache, and
|
||||
* use the remainder for the refcount cache */
|
||||
if (combined_cache_size >= max_l2_cache + min_refcount_cache) {
|
||||
@ -828,16 +831,9 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
|
||||
*l2_cache_size = combined_cache_size - *refcount_cache_size;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!l2_cache_size_set) {
|
||||
*l2_cache_size = MAX(DEFAULT_L2_CACHE_BYTE_SIZE,
|
||||
(uint64_t)DEFAULT_L2_CACHE_CLUSTERS
|
||||
* s->cluster_size);
|
||||
}
|
||||
if (!refcount_cache_size_set) {
|
||||
*refcount_cache_size = min_refcount_cache;
|
||||
}
|
||||
}
|
||||
/* l2_cache_size and refcount_cache_size are ensured to have at least
|
||||
* their minimum values in qcow2_update_options_prepare() */
|
||||
|
||||
if (*l2_cache_entry_size < (1 << MIN_CLUSTER_BITS) ||
|
||||
*l2_cache_entry_size > s->cluster_size ||
|
||||
@ -948,7 +944,7 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
|
||||
/* New interval for cache cleanup timer */
|
||||
r->cache_clean_interval =
|
||||
qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL,
|
||||
s->cache_clean_interval);
|
||||
DEFAULT_CACHE_CLEAN_INTERVAL);
|
||||
#ifndef CONFIG_LINUX
|
||||
if (r->cache_clean_interval != 0) {
|
||||
error_setg(errp, QCOW2_OPT_CACHE_CLEAN_INTERVAL
|
||||
@ -1328,7 +1324,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
|
||||
/* 2^(s->refcount_order - 3) is the refcount width in bytes */
|
||||
s->refcount_block_bits = s->cluster_bits - (s->refcount_order - 3);
|
||||
s->refcount_block_size = 1 << s->refcount_block_bits;
|
||||
bs->total_sectors = header.size / 512;
|
||||
bs->total_sectors = header.size / BDRV_SECTOR_SIZE;
|
||||
s->csize_shift = (62 - (s->cluster_bits - 8));
|
||||
s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
|
||||
s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
|
||||
@ -3422,6 +3418,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
uint64_t old_length;
|
||||
int64_t new_l1_size;
|
||||
int ret;
|
||||
QDict *options;
|
||||
|
||||
if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_METADATA &&
|
||||
prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL)
|
||||
@ -3453,7 +3450,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
old_length = bs->total_sectors * 512;
|
||||
old_length = bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
new_l1_size = size_to_l1(s, offset);
|
||||
|
||||
if (offset < old_length) {
|
||||
@ -3646,6 +3643,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
}
|
||||
}
|
||||
|
||||
bs->total_sectors = offset / BDRV_SECTOR_SIZE;
|
||||
|
||||
/* write updated header.size */
|
||||
offset = cpu_to_be64(offset);
|
||||
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
|
||||
@ -3656,6 +3655,14 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
|
||||
}
|
||||
|
||||
s->l1_vm_state_index = new_l1_size;
|
||||
|
||||
/* Update cache sizes */
|
||||
options = qdict_clone_shallow(bs->options);
|
||||
ret = qcow2_update_options(bs, options, s->flags, errp);
|
||||
qobject_unref(options);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ret = 0;
|
||||
fail:
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "crypto/block.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/units.h"
|
||||
|
||||
//#define DEBUG_ALLOC
|
||||
//#define DEBUG_ALLOC2
|
||||
@ -43,11 +44,11 @@
|
||||
|
||||
/* 8 MB refcount table is enough for 2 PB images at 64k cluster size
|
||||
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
|
||||
#define QCOW_MAX_REFTABLE_SIZE 0x800000
|
||||
#define QCOW_MAX_REFTABLE_SIZE S_8MiB
|
||||
|
||||
/* 32 MB L1 table is enough for 2 PB images at 64k cluster size
|
||||
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
|
||||
#define QCOW_MAX_L1_SIZE 0x2000000
|
||||
#define QCOW_MAX_L1_SIZE S_32MiB
|
||||
|
||||
/* Allow for an average of 1k per snapshot table entry, should be plenty of
|
||||
* space for snapshot names and IDs */
|
||||
@ -73,12 +74,16 @@
|
||||
/* Must be at least 4 to cover all cases of refcount table growth */
|
||||
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
|
||||
|
||||
/* Whichever is more */
|
||||
#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
|
||||
#define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */
|
||||
|
||||
#define DEFAULT_CLUSTER_SIZE 65536
|
||||
#ifdef CONFIG_LINUX
|
||||
#define DEFAULT_L2_CACHE_MAX_SIZE S_32MiB
|
||||
#define DEFAULT_CACHE_CLEAN_INTERVAL 600 /* seconds */
|
||||
#else
|
||||
#define DEFAULT_L2_CACHE_MAX_SIZE S_8MiB
|
||||
/* Cache clean interval is currently available only on Linux, so must be 0 */
|
||||
#define DEFAULT_CACHE_CLEAN_INTERVAL 0
|
||||
#endif
|
||||
|
||||
#define DEFAULT_CLUSTER_SIZE S_64KiB
|
||||
|
||||
#define QCOW2_OPT_LAZY_REFCOUNTS "lazy-refcounts"
|
||||
#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"
|
||||
|
@ -79,14 +79,14 @@ Choosing the right cache sizes
|
||||
In order to choose the cache sizes we need to know how they relate to
|
||||
the amount of allocated space.
|
||||
|
||||
The amount of virtual disk that can be mapped by the L2 and refcount
|
||||
The part of the virtual disk that can be mapped by the L2 and refcount
|
||||
caches (in bytes) is:
|
||||
|
||||
disk_size = l2_cache_size * cluster_size / 8
|
||||
disk_size = refcount_cache_size * cluster_size * 8 / refcount_bits
|
||||
|
||||
With the default values for cluster_size (64KB) and refcount_bits
|
||||
(16), that is
|
||||
(16), this becomes:
|
||||
|
||||
disk_size = l2_cache_size * 8192
|
||||
disk_size = refcount_cache_size * 32768
|
||||
@ -97,12 +97,16 @@ need:
|
||||
l2_cache_size = disk_size_GB * 131072
|
||||
refcount_cache_size = disk_size_GB * 32768
|
||||
|
||||
QEMU has a default L2 cache of 1MB (1048576 bytes) and a refcount
|
||||
cache of 256KB (262144 bytes), so using the formulas we've just seen
|
||||
we have
|
||||
For example, 1MB of L2 cache is needed to cover every 8 GB of the virtual
|
||||
image size (given that the default cluster size is used):
|
||||
|
||||
1048576 / 131072 = 8 GB of virtual disk covered by that cache
|
||||
262144 / 32768 = 8 GB
|
||||
8 GB / 8192 = 1 MB
|
||||
|
||||
The refcount cache is 4 times the cluster size by default. With the default
|
||||
cluster size of 64 KB, it is 256 KB (262144 bytes). This is sufficient for
|
||||
8 GB of image size:
|
||||
|
||||
262144 * 32768 = 8 GB
|
||||
|
||||
|
||||
How to configure the cache sizes
|
||||
@ -121,8 +125,15 @@ There are a few things that need to be taken into account:
|
||||
- Both caches must have a size that is a multiple of the cluster size
|
||||
(or the cache entry size: see "Using smaller cache sizes" below).
|
||||
|
||||
- The default L2 cache size is 8 clusters or 1MB (whichever is more),
|
||||
and the minimum is 2 clusters (or 2 cache entries, see below).
|
||||
- The maximum L2 cache size is 32 MB by default on Linux platforms (enough
|
||||
for full coverage of 256 GB images, with the default cluster size). This
|
||||
value can be modified using the "l2-cache-size" option. QEMU will not use
|
||||
more memory than needed to hold all of the image's L2 tables, regardless
|
||||
of this max. value.
|
||||
On non-Linux platforms the maximal value is smaller by default (8 MB) and
|
||||
this difference stems from the fact that on Linux the cache can be cleared
|
||||
periodically if needed, using the "cache-clean-interval" option (see below).
|
||||
The minimal L2 cache size is 2 clusters (or 2 cache entries, see below).
|
||||
|
||||
- The default (and minimum) refcount cache size is 4 clusters.
|
||||
|
||||
@ -130,6 +141,9 @@ There are a few things that need to be taken into account:
|
||||
memory as possible to the L2 cache before increasing the refcount
|
||||
cache size.
|
||||
|
||||
- At most two of "l2-cache-size", "refcount-cache-size", and "cache-size"
|
||||
can be set simultaneously.
|
||||
|
||||
Unlike L2 tables, refcount blocks are not used during normal I/O but
|
||||
only during allocations and internal snapshots. In most cases they are
|
||||
accessed sequentially (even during random guest I/O) so increasing the
|
||||
@ -177,9 +191,10 @@ Some things to take into account:
|
||||
always uses the cluster size as the entry size.
|
||||
|
||||
- If the L2 cache is big enough to hold all of the image's L2 tables
|
||||
(as explained in the "Choosing the right cache sizes" section
|
||||
earlier in this document) then none of this is necessary and you
|
||||
can omit the "l2-cache-entry-size" parameter altogether.
|
||||
(as explained in the "Choosing the right cache sizes" and "How to
|
||||
configure the cache sizes" sections in this document) then none of
|
||||
this is necessary and you can omit the "l2-cache-entry-size"
|
||||
parameter altogether.
|
||||
|
||||
|
||||
Reducing the memory usage
|
||||
@ -187,18 +202,18 @@ Reducing the memory usage
|
||||
It is possible to clean unused cache entries in order to reduce the
|
||||
memory usage during periods of low I/O activity.
|
||||
|
||||
The parameter "cache-clean-interval" defines an interval (in seconds).
|
||||
All cache entries that haven't been accessed during that interval are
|
||||
removed from memory.
|
||||
The parameter "cache-clean-interval" defines an interval (in seconds),
|
||||
after which all the cache entries that haven't been accessed during the
|
||||
interval are removed from memory. Setting this parameter to 0 disables this
|
||||
feature.
|
||||
|
||||
This example removes all unused cache entries every 15 minutes:
|
||||
The following example removes all unused cache entries every 15 minutes:
|
||||
|
||||
-drive file=hd.qcow2,cache-clean-interval=900
|
||||
|
||||
If unset, the default value for this parameter is 0 and it disables
|
||||
this feature.
|
||||
If unset, the default value for this parameter is 600 on platforms which
|
||||
support this functionality, and is 0 (disabled) on other platforms.
|
||||
|
||||
Note that this functionality currently relies on the MADV_DONTNEED
|
||||
argument for madvise() to actually free the memory. This is a
|
||||
Linux-specific feature, so cache-clean-interval is not supported in
|
||||
other systems.
|
||||
This functionality currently relies on the MADV_DONTNEED argument for
|
||||
madvise() to actually free the memory. This is a Linux-specific feature,
|
||||
so cache-clean-interval is not supported on other systems.
|
||||
|
@ -184,6 +184,7 @@ typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
|
||||
typedef struct BDRVReopenState {
|
||||
BlockDriverState *bs;
|
||||
int flags;
|
||||
BlockdevDetectZeroesOptions detect_zeroes;
|
||||
uint64_t perm, shared_perm;
|
||||
QDict *options;
|
||||
QDict *explicit_options;
|
||||
|
@ -17,4 +17,59 @@
|
||||
#define PiB (INT64_C(1) << 50)
|
||||
#define EiB (INT64_C(1) << 60)
|
||||
|
||||
#define S_1KiB 1024
|
||||
#define S_2KiB 2048
|
||||
#define S_4KiB 4096
|
||||
#define S_8KiB 8192
|
||||
#define S_16KiB 16384
|
||||
#define S_32KiB 32768
|
||||
#define S_64KiB 65536
|
||||
#define S_128KiB 131072
|
||||
#define S_256KiB 262144
|
||||
#define S_512KiB 524288
|
||||
#define S_1MiB 1048576
|
||||
#define S_2MiB 2097152
|
||||
#define S_4MiB 4194304
|
||||
#define S_8MiB 8388608
|
||||
#define S_16MiB 16777216
|
||||
#define S_32MiB 33554432
|
||||
#define S_64MiB 67108864
|
||||
#define S_128MiB 134217728
|
||||
#define S_256MiB 268435456
|
||||
#define S_512MiB 536870912
|
||||
#define S_1GiB 1073741824
|
||||
#define S_2GiB 2147483648
|
||||
#define S_4GiB 4294967296
|
||||
#define S_8GiB 8589934592
|
||||
#define S_16GiB 17179869184
|
||||
#define S_32GiB 34359738368
|
||||
#define S_64GiB 68719476736
|
||||
#define S_128GiB 137438953472
|
||||
#define S_256GiB 274877906944
|
||||
#define S_512GiB 549755813888
|
||||
#define S_1TiB 1099511627776
|
||||
#define S_2TiB 2199023255552
|
||||
#define S_4TiB 4398046511104
|
||||
#define S_8TiB 8796093022208
|
||||
#define S_16TiB 17592186044416
|
||||
#define S_32TiB 35184372088832
|
||||
#define S_64TiB 70368744177664
|
||||
#define S_128TiB 140737488355328
|
||||
#define S_256TiB 281474976710656
|
||||
#define S_512TiB 562949953421312
|
||||
#define S_1PiB 1125899906842624
|
||||
#define S_2PiB 2251799813685248
|
||||
#define S_4PiB 4503599627370496
|
||||
#define S_8PiB 9007199254740992
|
||||
#define S_16PiB 18014398509481984
|
||||
#define S_32PiB 36028797018963968
|
||||
#define S_64PiB 72057594037927936
|
||||
#define S_128PiB 144115188075855872
|
||||
#define S_256PiB 288230376151711744
|
||||
#define S_512PiB 576460752303423488
|
||||
#define S_1EiB 1152921504606846976
|
||||
#define S_2EiB 2305843009213693952
|
||||
#define S_4EiB 4611686018427387904
|
||||
#define S_8EiB 9223372036854775808
|
||||
|
||||
#endif
|
||||
|
@ -2897,7 +2897,9 @@
|
||||
#
|
||||
# @cache-clean-interval: clean unused entries in the L2 and refcount
|
||||
# caches. The interval is in seconds. The default value
|
||||
# is 0 and it disables this feature (since 2.5)
|
||||
# is 600 on supporting platforms, and 0 on other
|
||||
# platforms. 0 disables this feature. (since 2.5)
|
||||
#
|
||||
# @encrypt: Image decryption options. Mandatory for
|
||||
# encrypted images, except when doing a metadata-only
|
||||
# probe of the image. (since 2.10)
|
||||
|
@ -2025,7 +2025,7 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (writethrough != blk_enable_write_cache(blk) &&
|
||||
if (!writethrough != blk_enable_write_cache(blk) &&
|
||||
blk_get_attached_dev(blk))
|
||||
{
|
||||
error_report("Cannot change cache.writeback: Device attached");
|
||||
|
@ -732,19 +732,23 @@ image file)
|
||||
|
||||
@item cache-size
|
||||
The maximum total size of the L2 table and refcount block caches in bytes
|
||||
(default: 1048576 bytes or 8 clusters, whichever is larger)
|
||||
(default: the sum of l2-cache-size and refcount-cache-size)
|
||||
|
||||
@item l2-cache-size
|
||||
The maximum size of the L2 table cache in bytes
|
||||
(default: 4/5 of the total cache size)
|
||||
(default: if cache-size is not specified - 32M on Linux platforms, and 8M on
|
||||
non-Linux platforms; otherwise, as large as possible within the cache-size,
|
||||
while permitting the requested or the minimal refcount cache size)
|
||||
|
||||
@item refcount-cache-size
|
||||
The maximum size of the refcount block cache in bytes
|
||||
(default: 1/5 of the total cache size)
|
||||
(default: 4 times the cluster size; or if cache-size is specified, the part of
|
||||
it which is not used for the L2 cache)
|
||||
|
||||
@item cache-clean-interval
|
||||
Clean unused entries in the L2 and refcount caches. The interval is in seconds.
|
||||
The default value is 0 and it disables this feature.
|
||||
The default value is 600 on supporting platforms, and 0 on other platforms.
|
||||
Setting it to 0 disables this feature.
|
||||
|
||||
@item pass-discard-request
|
||||
Whether discard requests to the qcow2 device should be forwarded to the data
|
||||
|
@ -385,6 +385,7 @@ Testing: -device virtio-scsi -device scsi-cd,id=cd0
|
||||
{
|
||||
"return": [
|
||||
{
|
||||
"io-status": "ok",
|
||||
"device": "",
|
||||
"locked": false,
|
||||
"removable": true,
|
||||
|
@ -109,7 +109,6 @@ $QEMU_IO \
|
||||
-c "reopen -o cache-size=1M,l2-cache-size=64k,refcount-cache-size=64k" \
|
||||
-c "reopen -o cache-size=1M,l2-cache-size=2M" \
|
||||
-c "reopen -o cache-size=1M,refcount-cache-size=2M" \
|
||||
-c "reopen -o l2-cache-size=256T" \
|
||||
-c "reopen -o l2-cache-entry-size=33k" \
|
||||
-c "reopen -o l2-cache-entry-size=128k" \
|
||||
-c "reopen -o refcount-cache-size=256T" \
|
||||
@ -119,6 +118,13 @@ $QEMU_IO \
|
||||
-c "reopen -o cache-clean-interval=-1" \
|
||||
"$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
IMGOPTS="cluster_size=256k" _make_test_img 32P
|
||||
$QEMU_IO \
|
||||
-c "reopen -o l2-cache-entry-size=512,l2-cache-size=1T" \
|
||||
"$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
_make_test_img 64M
|
||||
|
||||
echo
|
||||
echo === Test transaction semantics ===
|
||||
echo
|
||||
|
@ -19,7 +19,6 @@ Parameter 'lazy-refcounts' expects 'on' or 'off'
|
||||
cache-size, l2-cache-size and refcount-cache-size may not be set at the same time
|
||||
l2-cache-size may not exceed cache-size
|
||||
refcount-cache-size may not exceed cache-size
|
||||
L2 cache size too big
|
||||
L2 cache entry size must be a power of two between 512 and the cluster size (65536)
|
||||
L2 cache entry size must be a power of two between 512 and the cluster size (65536)
|
||||
Refcount cache size too big
|
||||
@ -27,6 +26,9 @@ Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-c
|
||||
Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
|
||||
Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
|
||||
Cache clean interval too big
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=36028797018963968
|
||||
L2 cache size too big
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
|
||||
=== Test transaction semantics ===
|
||||
|
||||
|
@ -12,11 +12,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t
|
||||
|
||||
== Launching another QEMU, opts: '' ==
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Launching another QEMU, opts: 'read-only=on' ==
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,read-only=on: Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Launching another QEMU, opts: 'read-only=on,force-share=on' ==
|
||||
|
||||
@ -24,77 +24,77 @@ Is another process using the image?
|
||||
|
||||
_qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
no file open, try 'help open'
|
||||
|
||||
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
no file open, try 'help open'
|
||||
|
||||
_qemu_img_wrapper info TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper check TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper map TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper commit TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper resize TEST_DIR/t.qcow2 32M
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper convert TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper dd if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
|
||||
qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
file format: IMGFMT
|
||||
|
||||
== Running utility commands -U ==
|
||||
@ -132,7 +132,7 @@ Try 'qemu-img --help' for more information
|
||||
|
||||
_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2
|
||||
|
||||
@ -157,7 +157,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t
|
||||
|
||||
== Launching another QEMU, opts: '' ==
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Launching another QEMU, opts: 'read-only=on' ==
|
||||
|
||||
@ -167,13 +167,13 @@ Is another process using the image?
|
||||
|
||||
_qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
|
||||
|
||||
_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
no file open, try 'help open'
|
||||
|
||||
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
|
||||
@ -188,19 +188,19 @@ _qemu_img_wrapper map TEST_DIR/t.qcow2
|
||||
|
||||
_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper commit TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper resize TEST_DIR/t.qcow2 32M
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2
|
||||
|
||||
@ -212,11 +212,11 @@ _qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
|
||||
|
||||
_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
|
||||
qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
file format: IMGFMT
|
||||
|
||||
== Running utility commands -U ==
|
||||
@ -254,7 +254,7 @@ Try 'qemu-img --help' for more information
|
||||
|
||||
_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
|
||||
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
_qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2
|
||||
|
||||
@ -372,17 +372,17 @@ Round done
|
||||
|
||||
== Two devices with the same image (read-only=off - read-only=off) ==
|
||||
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Two devices with the same image (read-only=off - read-only=on) ==
|
||||
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=on: Failed to get shared "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Two devices with the same image (read-only=off - read-only=on,force-share=on) ==
|
||||
|
||||
== Two devices with the same image (read-only=on - read-only=off) ==
|
||||
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Two devices with the same image (read-only=on - read-only=on) ==
|
||||
|
||||
@ -403,13 +403,13 @@ Formatting 'TEST_DIR/t.IMGFMT.c', fmt=IMGFMT size=33554432 backing_file=TEST_DIR
|
||||
|
||||
== Backing image also as an active device ==
|
||||
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Backing image also as an active device (ro) ==
|
||||
|
||||
== Symbolic link ==
|
||||
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
|
||||
== Active commit to intermediate layer should work when base in use ==
|
||||
{"return": {}}
|
||||
@ -420,7 +420,7 @@ Adding drive
|
||||
|
||||
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
Creating overlay with qemu-img when the guest is running should be allowed
|
||||
|
||||
_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay
|
||||
@ -433,7 +433,7 @@ _qemu_img_wrapper info TEST_DIR/t.qcow2
|
||||
|
||||
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
||||
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
Closing the other
|
||||
|
||||
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
|
||||
|
@ -4,5 +4,5 @@ Starting QEMU
|
||||
|
||||
Starting a second QEMU using the same image should fail
|
||||
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0,file.locking=on: Failed to get "write" lock
|
||||
Is another process using the image?
|
||||
Is another process using the image [TEST_DIR/t.qcow2]?
|
||||
*** done
|
||||
|
@ -694,6 +694,8 @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
|
||||
s->bh_indirection_ctx = ctx_b;
|
||||
|
||||
aio_ret = -EINPROGRESS;
|
||||
qemu_event_reset(&done_event);
|
||||
|
||||
if (drain_thread == 0) {
|
||||
acb = blk_aio_preadv(blk, 0, &qiov, 0, test_iothread_aio_cb, &aio_ret);
|
||||
} else {
|
||||
@ -723,7 +725,6 @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
|
||||
* but the drain in this thread can continue immediately after
|
||||
* bdrv_dec_in_flight() and aio_ret might be assigned only slightly
|
||||
* later. */
|
||||
qemu_event_reset(&done_event);
|
||||
do_drain_begin(drain_type, bs);
|
||||
g_assert_cmpint(bs->in_flight, ==, 0);
|
||||
|
||||
@ -743,7 +744,6 @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
qemu_event_reset(&done_event);
|
||||
aio_bh_schedule_oneshot(ctx_a, test_iothread_drain_entry, &data);
|
||||
qemu_event_wait(&done_event);
|
||||
break;
|
||||
|
@ -207,13 +207,17 @@ static BlockBackend *start_primary(void)
|
||||
static void teardown_primary(void)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
AioContext *ctx;
|
||||
|
||||
/* remove P_ID */
|
||||
blk = blk_by_name(P_ID);
|
||||
assert(blk);
|
||||
|
||||
ctx = blk_get_aio_context(blk);
|
||||
aio_context_acquire(ctx);
|
||||
monitor_remove_blk(blk);
|
||||
blk_unref(blk);
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
|
||||
static void test_primary_read(void)
|
||||
@ -365,20 +369,27 @@ static void teardown_secondary(void)
|
||||
{
|
||||
/* only need to destroy two BBs */
|
||||
BlockBackend *blk;
|
||||
AioContext *ctx;
|
||||
|
||||
/* remove S_LOCAL_DISK_ID */
|
||||
blk = blk_by_name(S_LOCAL_DISK_ID);
|
||||
assert(blk);
|
||||
|
||||
ctx = blk_get_aio_context(blk);
|
||||
aio_context_acquire(ctx);
|
||||
monitor_remove_blk(blk);
|
||||
blk_unref(blk);
|
||||
aio_context_release(ctx);
|
||||
|
||||
/* remove S_ID */
|
||||
blk = blk_by_name(S_ID);
|
||||
assert(blk);
|
||||
|
||||
ctx = blk_get_aio_context(blk);
|
||||
aio_context_acquire(ctx);
|
||||
monitor_remove_blk(blk);
|
||||
blk_unref(blk);
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
|
||||
static void test_secondary_read(void)
|
||||
|
Loading…
Reference in New Issue
Block a user