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:
Peter Maydell 2018-10-01 18:22:55 +01:00
commit e32e62f253
18 changed files with 307 additions and 151 deletions

135
block.c
View File

@ -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 * 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; *flags &= ~BDRV_O_CACHE_MASK;
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH)); 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; *flags |= BDRV_O_NO_FLUSH;
} }
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT)); 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_NOCACHE;
} }
*flags &= ~BDRV_O_RDWR; *flags &= ~BDRV_O_RDWR;
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY)); 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; *flags |= BDRV_O_RDWR;
} }
@ -1328,7 +1353,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
const char *driver_name = NULL; const char *driver_name = NULL;
const char *node_name = NULL; const char *node_name = NULL;
const char *discard; const char *discard;
const char *detect_zeroes;
QemuOpts *opts; QemuOpts *opts;
BlockDriver *drv; BlockDriver *drv;
Error *local_err = NULL; Error *local_err = NULL;
@ -1417,29 +1441,12 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
} }
} }
detect_zeroes = qemu_opt_get(opts, "detect-zeroes"); bs->detect_zeroes =
if (detect_zeroes) { bdrv_parse_detect_zeroes(opts, bs->open_flags, &local_err);
BlockdevDetectZeroesOptions value = if (local_err) {
qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup, error_propagate(errp, local_err);
detect_zeroes, ret = -EINVAL;
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF, goto fail_opts;
&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) { if (filename != NULL) {
@ -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) { QLIST_FOREACH(child, &bs->children, next) {
char *child_key_dot; char *child_key_dot;
child_key_dot = g_strdup_printf("%s.", child->name); child_key_dot = g_strdup_printf("%s.", child->name);
qdict_extract_subqdict(bs->explicit_options, NULL, child_key_dot); qdict_extract_subqdict(bs->explicit_options, NULL, child_key_dot);
qdict_extract_subqdict(bs->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); g_free(child_key_dot);
} }
@ -3153,7 +3163,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
BlockDriver *drv; BlockDriver *drv;
QemuOpts *opts; QemuOpts *opts;
QDict *orig_reopen_opts; QDict *orig_reopen_opts;
const char *value; char *discard = NULL;
bool read_only; bool read_only;
assert(reopen_state != NULL); 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); update_flags_from_options(&reopen_state->flags, opts);
/* node-name and driver must be unchanged. Put them back into the QDict, so discard = qemu_opt_get_del(opts, "discard");
* that they are checked at the end of this function. */ if (discard != NULL) {
value = qemu_opt_get(opts, "node-name"); if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
if (value) { error_setg(errp, "Invalid discard option");
qdict_put_str(reopen_state->options, "node-name", value); ret = -EINVAL;
goto error;
}
} }
value = qemu_opt_get(opts, "driver"); reopen_state->detect_zeroes =
if (value) { bdrv_parse_detect_zeroes(opts, reopen_state->flags, &local_err);
qdict_put_str(reopen_state->options, "driver", value); 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 /* 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 * 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 */ * 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 *new = entry->value;
QObject *old = qdict_get(reopen_state->bs->options, entry->key); 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 * TODO: When using -drive to specify blockdev options, all values
* will be strings; however, when using -blockdev, blockdev-add or * will be strings; however, when using -blockdev, blockdev-add or
@ -3278,6 +3316,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
error: error:
qemu_opts_del(opts); qemu_opts_del(opts);
qobject_unref(orig_reopen_opts); qobject_unref(orig_reopen_opts);
g_free(discard);
return ret; return ret;
} }
@ -3290,6 +3329,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
{ {
BlockDriver *drv; BlockDriver *drv;
BlockDriverState *bs; BlockDriverState *bs;
BdrvChild *child;
bool old_can_write, new_can_write; bool old_can_write, new_can_write;
assert(reopen_state != NULL); assert(reopen_state != NULL);
@ -3313,6 +3353,14 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
bs->options = reopen_state->options; bs->options = reopen_state->options;
bs->open_flags = reopen_state->flags; bs->open_flags = reopen_state->flags;
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR); 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); bdrv_refresh_limits(bs, NULL);
@ -5139,23 +5187,12 @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
{ {
const QDictEntry *entry; const QDictEntry *entry;
QemuOptDesc *desc; QemuOptDesc *desc;
BdrvChild *child;
bool found_any = false; bool found_any = false;
for (entry = qdict_first(bs->options); entry; for (entry = qdict_first(bs->options); entry;
entry = qdict_next(bs->options, entry)) entry = qdict_next(bs->options, entry))
{ {
/* Exclude node-name references to children */ /* Exclude all non-driver-specific options */
QLIST_FOREACH(child, &bs->children, next) {
if (!strcmp(entry->key, child->name)) {
break;
}
}
if (child) {
continue;
}
/* And exclude all non-driver-specific options */
for (desc = bdrv_runtime_opts.desc; desc->name; desc++) { for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
if (!strcmp(qdict_entry_key(entry), desc->name)) { if (!strcmp(qdict_entry_key(entry), desc->name)) {
break; break;

View File

@ -325,6 +325,9 @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
blk->shared_perm = shared_perm; blk->shared_perm = shared_perm;
blk_set_enable_write_cache(blk, true); 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); block_acct_init(&blk->stats);
notifier_list_init(&blk->remove_bs_notifiers); notifier_list_init(&blk->remove_bs_notifiers);

View File

@ -741,8 +741,6 @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
"Failed to get \"%s\" lock", "Failed to get \"%s\" lock",
perm_name); perm_name);
g_free(perm_name); g_free(perm_name);
error_append_hint(errp,
"Is another process using the image?\n");
return ret; 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", "Failed to get shared \"%s\" lock",
perm_name); perm_name);
g_free(perm_name); g_free(perm_name);
error_append_hint(errp,
"Is another process using the image?\n");
return ret; return ret;
} }
} }
@ -796,6 +792,9 @@ static int raw_handle_perm_lock(BlockDriverState *bs,
if (!ret) { if (!ret) {
return 0; return 0;
} }
error_append_hint(errp,
"Is another process using the image [%s]?\n",
bs->filename);
} }
op = RAW_PL_ABORT; op = RAW_PL_ABORT;
/* fall through to unlock bytes. */ /* fall through to unlock bytes. */
@ -850,8 +849,13 @@ static int raw_reopen_prepare(BDRVReopenState *state,
goto out; goto out;
} }
rs->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped", rs->check_cache_dropped =
s->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) { if (s->type == FTYPE_CD) {
rs->open_flags |= O_NONBLOCK; 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 */ /* Step two: Check that nobody else has taken conflicting locks */
result = raw_check_lock_bytes(fd, perm, shared, errp); result = raw_check_lock_bytes(fd, perm, shared, errp);
if (result < 0) { if (result < 0) {
error_append_hint(errp,
"Is another process using the image [%s]?\n",
file_opts->filename);
goto out_unlock; goto out_unlock;
} }

View File

@ -777,29 +777,35 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
uint64_t *refcount_cache_size, Error **errp) uint64_t *refcount_cache_size, Error **errp)
{ {
BDRVQcow2State *s = bs->opaque; 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; bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size; 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); 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); 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); 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); 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, *refcount_cache_size = qemu_opt_get_size(opts,
QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0); QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
*l2_cache_entry_size = qemu_opt_get_size( *l2_cache_entry_size = qemu_opt_get_size(
opts, QCOW2_OPT_L2_CACHE_ENTRY_SIZE, s->cluster_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 (combined_cache_size_set) {
if (l2_cache_size_set && refcount_cache_size_set) { if (l2_cache_size_set && refcount_cache_size_set) {
error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
" and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set " " and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
"at the same time"); "at the same time");
return; 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 " error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
QCOW2_OPT_CACHE_SIZE); QCOW2_OPT_CACHE_SIZE);
return; return;
@ -814,9 +820,6 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
} else if (refcount_cache_size_set) { } else if (refcount_cache_size_set) {
*l2_cache_size = combined_cache_size - *refcount_cache_size; *l2_cache_size = combined_cache_size - *refcount_cache_size;
} else { } 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 /* Assign as much memory as possible to the L2 cache, and
* use the remainder for the refcount cache */ * use the remainder for the refcount cache */
if (combined_cache_size >= max_l2_cache + min_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; *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) || if (*l2_cache_entry_size < (1 << MIN_CLUSTER_BITS) ||
*l2_cache_entry_size > s->cluster_size || *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 */ /* New interval for cache cleanup timer */
r->cache_clean_interval = r->cache_clean_interval =
qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL, qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL,
s->cache_clean_interval); DEFAULT_CACHE_CLEAN_INTERVAL);
#ifndef CONFIG_LINUX #ifndef CONFIG_LINUX
if (r->cache_clean_interval != 0) { if (r->cache_clean_interval != 0) {
error_setg(errp, QCOW2_OPT_CACHE_CLEAN_INTERVAL 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 */ /* 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_bits = s->cluster_bits - (s->refcount_order - 3);
s->refcount_block_size = 1 << s->refcount_block_bits; 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_shift = (62 - (s->cluster_bits - 8));
s->csize_mask = (1 << (s->cluster_bits - 8)) - 1; s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
s->cluster_offset_mask = (1LL << s->csize_shift) - 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; uint64_t old_length;
int64_t new_l1_size; int64_t new_l1_size;
int ret; int ret;
QDict *options;
if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_METADATA && if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_METADATA &&
prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL) 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; goto fail;
} }
old_length = bs->total_sectors * 512; old_length = bs->total_sectors * BDRV_SECTOR_SIZE;
new_l1_size = size_to_l1(s, offset); new_l1_size = size_to_l1(s, offset);
if (offset < old_length) { 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 */ /* write updated header.size */
offset = cpu_to_be64(offset); offset = cpu_to_be64(offset);
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), 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; 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; ret = 0;
fail: fail:
qemu_co_mutex_unlock(&s->lock); qemu_co_mutex_unlock(&s->lock);

View File

@ -27,6 +27,7 @@
#include "crypto/block.h" #include "crypto/block.h"
#include "qemu/coroutine.h" #include "qemu/coroutine.h"
#include "qemu/units.h"
//#define DEBUG_ALLOC //#define DEBUG_ALLOC
//#define DEBUG_ALLOC2 //#define DEBUG_ALLOC2
@ -43,11 +44,11 @@
/* 8 MB refcount table is enough for 2 PB images at 64k cluster size /* 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) */ * (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 /* 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) */ * (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 /* Allow for an average of 1k per snapshot table entry, should be plenty of
* space for snapshot names and IDs */ * space for snapshot names and IDs */
@ -73,12 +74,16 @@
/* Must be at least 4 to cover all cases of refcount table growth */ /* Must be at least 4 to cover all cases of refcount table growth */
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */ #define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
/* Whichever is more */ #ifdef CONFIG_LINUX
#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */ #define DEFAULT_L2_CACHE_MAX_SIZE S_32MiB
#define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */ #define DEFAULT_CACHE_CLEAN_INTERVAL 600 /* seconds */
#else
#define DEFAULT_CLUSTER_SIZE 65536 #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_LAZY_REFCOUNTS "lazy-refcounts"
#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request" #define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"

View File

@ -79,14 +79,14 @@ Choosing the right cache sizes
In order to choose the cache sizes we need to know how they relate to In order to choose the cache sizes we need to know how they relate to
the amount of allocated space. 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: caches (in bytes) is:
disk_size = l2_cache_size * cluster_size / 8 disk_size = l2_cache_size * cluster_size / 8
disk_size = refcount_cache_size * cluster_size * 8 / refcount_bits disk_size = refcount_cache_size * cluster_size * 8 / refcount_bits
With the default values for cluster_size (64KB) and 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 = l2_cache_size * 8192
disk_size = refcount_cache_size * 32768 disk_size = refcount_cache_size * 32768
@ -97,12 +97,16 @@ need:
l2_cache_size = disk_size_GB * 131072 l2_cache_size = disk_size_GB * 131072
refcount_cache_size = disk_size_GB * 32768 refcount_cache_size = disk_size_GB * 32768
QEMU has a default L2 cache of 1MB (1048576 bytes) and a refcount For example, 1MB of L2 cache is needed to cover every 8 GB of the virtual
cache of 256KB (262144 bytes), so using the formulas we've just seen image size (given that the default cluster size is used):
we have
1048576 / 131072 = 8 GB of virtual disk covered by that cache 8 GB / 8192 = 1 MB
262144 / 32768 = 8 GB
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 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 - 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). (or the cache entry size: see "Using smaller cache sizes" below).
- The default L2 cache size is 8 clusters or 1MB (whichever is more), - The maximum L2 cache size is 32 MB by default on Linux platforms (enough
and the minimum is 2 clusters (or 2 cache entries, see below). 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. - 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 memory as possible to the L2 cache before increasing the refcount
cache size. 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 Unlike L2 tables, refcount blocks are not used during normal I/O but
only during allocations and internal snapshots. In most cases they are only during allocations and internal snapshots. In most cases they are
accessed sequentially (even during random guest I/O) so increasing the 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. 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 - 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 (as explained in the "Choosing the right cache sizes" and "How to
earlier in this document) then none of this is necessary and you configure the cache sizes" sections in this document) then none of
can omit the "l2-cache-entry-size" parameter altogether. this is necessary and you can omit the "l2-cache-entry-size"
parameter altogether.
Reducing the memory usage 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 It is possible to clean unused cache entries in order to reduce the
memory usage during periods of low I/O activity. memory usage during periods of low I/O activity.
The parameter "cache-clean-interval" defines an interval (in seconds). The parameter "cache-clean-interval" defines an interval (in seconds),
All cache entries that haven't been accessed during that interval are after which all the cache entries that haven't been accessed during the
removed from memory. 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 -drive file=hd.qcow2,cache-clean-interval=900
If unset, the default value for this parameter is 0 and it disables If unset, the default value for this parameter is 600 on platforms which
this feature. support this functionality, and is 0 (disabled) on other platforms.
Note that this functionality currently relies on the MADV_DONTNEED This functionality currently relies on the MADV_DONTNEED argument for
argument for madvise() to actually free the memory. This is a madvise() to actually free the memory. This is a Linux-specific feature,
Linux-specific feature, so cache-clean-interval is not supported in so cache-clean-interval is not supported on other systems.
other systems.

View File

@ -184,6 +184,7 @@ typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
typedef struct BDRVReopenState { typedef struct BDRVReopenState {
BlockDriverState *bs; BlockDriverState *bs;
int flags; int flags;
BlockdevDetectZeroesOptions detect_zeroes;
uint64_t perm, shared_perm; uint64_t perm, shared_perm;
QDict *options; QDict *options;
QDict *explicit_options; QDict *explicit_options;

View File

@ -17,4 +17,59 @@
#define PiB (INT64_C(1) << 50) #define PiB (INT64_C(1) << 50)
#define EiB (INT64_C(1) << 60) #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 #endif

View File

@ -2897,7 +2897,9 @@
# #
# @cache-clean-interval: clean unused entries in the L2 and refcount # @cache-clean-interval: clean unused entries in the L2 and refcount
# caches. The interval is in seconds. The default value # 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 # @encrypt: Image decryption options. Mandatory for
# encrypted images, except when doing a metadata-only # encrypted images, except when doing a metadata-only
# probe of the image. (since 2.10) # probe of the image. (since 2.10)

View File

@ -2025,7 +2025,7 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
return -EINVAL; return -EINVAL;
} }
if (writethrough != blk_enable_write_cache(blk) && if (!writethrough != blk_enable_write_cache(blk) &&
blk_get_attached_dev(blk)) blk_get_attached_dev(blk))
{ {
error_report("Cannot change cache.writeback: Device attached"); error_report("Cannot change cache.writeback: Device attached");

View File

@ -732,19 +732,23 @@ image file)
@item cache-size @item cache-size
The maximum total size of the L2 table and refcount block caches in bytes 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 @item l2-cache-size
The maximum size of the L2 table cache in bytes 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 @item refcount-cache-size
The maximum size of the refcount block cache in bytes 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 @item cache-clean-interval
Clean unused entries in the L2 and refcount caches. The interval is in seconds. 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 @item pass-discard-request
Whether discard requests to the qcow2 device should be forwarded to the data Whether discard requests to the qcow2 device should be forwarded to the data

View File

@ -385,6 +385,7 @@ Testing: -device virtio-scsi -device scsi-cd,id=cd0
{ {
"return": [ "return": [
{ {
"io-status": "ok",
"device": "", "device": "",
"locked": false, "locked": false,
"removable": true, "removable": true,

View File

@ -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=64k,refcount-cache-size=64k" \
-c "reopen -o cache-size=1M,l2-cache-size=2M" \ -c "reopen -o cache-size=1M,l2-cache-size=2M" \
-c "reopen -o cache-size=1M,refcount-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=33k" \
-c "reopen -o l2-cache-entry-size=128k" \ -c "reopen -o l2-cache-entry-size=128k" \
-c "reopen -o refcount-cache-size=256T" \ -c "reopen -o refcount-cache-size=256T" \
@ -119,6 +118,13 @@ $QEMU_IO \
-c "reopen -o cache-clean-interval=-1" \ -c "reopen -o cache-clean-interval=-1" \
"$TEST_IMG" | _filter_qemu_io "$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
echo === Test transaction semantics === echo === Test transaction semantics ===
echo echo

View File

@ -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 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 l2-cache-size may not exceed cache-size
refcount-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)
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 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
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 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 === === Test transaction semantics ===

View File

@ -12,11 +12,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t
== Launching another QEMU, opts: '' == == Launching another QEMU, opts: '' ==
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock 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' == == 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 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' == == 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 _qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock 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 -r -c read 0 512 TEST_DIR/t.qcow2
can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock 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 _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 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' no file open, try 'help open'
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512 _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 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' no file open, try 'help open'
_qemu_img_wrapper info TEST_DIR/t.qcow2 _qemu_img_wrapper info TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock 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_wrapper check TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock 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_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 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_wrapper map TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock 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_wrapper amend -o TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_wrapper commit TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_wrapper resize TEST_DIR/t.qcow2 32M
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_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 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_wrapper snapshot -l TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock 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_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 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_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 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_wrapper bench -c 1 TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock 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_wrapper bench -w -c 1 TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_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 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 file format: IMGFMT
== Running utility commands -U == == 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_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 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 _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: '' == == Launching another QEMU, opts: '' ==
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock 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' == == 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 _qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock 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 -r -c read 0 512 TEST_DIR/t.qcow2
_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512 _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 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' no file open, try 'help open'
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512 _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_wrapper amend -o TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_wrapper commit TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_wrapper resize TEST_DIR/t.qcow2 32M
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_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 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_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_wrapper bench -w -c 1 TEST_DIR/t.qcow2
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock 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_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 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 file format: IMGFMT
== Running utility commands -U == == 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_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 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 _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) == == 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 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) == == 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 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=off - read-only=on,force-share=on) ==
== Two devices with the same image (read-only=on - read-only=off) == == 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 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) == == 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 == == Backing image also as an active device ==
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock 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) == == Backing image also as an active device (ro) ==
== Symbolic link == == Symbolic link ==
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock 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 == == Active commit to intermediate layer should work when base in use ==
{"return": {}} {"return": {}}
@ -420,7 +420,7 @@ Adding drive
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock 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 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 _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 _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock 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 Closing the other
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512

View File

@ -4,5 +4,5 @@ Starting QEMU
Starting a second QEMU using the same image should fail 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 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 *** done

View File

@ -694,6 +694,8 @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
s->bh_indirection_ctx = ctx_b; s->bh_indirection_ctx = ctx_b;
aio_ret = -EINPROGRESS; aio_ret = -EINPROGRESS;
qemu_event_reset(&done_event);
if (drain_thread == 0) { if (drain_thread == 0) {
acb = blk_aio_preadv(blk, 0, &qiov, 0, test_iothread_aio_cb, &aio_ret); acb = blk_aio_preadv(blk, 0, &qiov, 0, test_iothread_aio_cb, &aio_ret);
} else { } 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 * but the drain in this thread can continue immediately after
* bdrv_dec_in_flight() and aio_ret might be assigned only slightly * bdrv_dec_in_flight() and aio_ret might be assigned only slightly
* later. */ * later. */
qemu_event_reset(&done_event);
do_drain_begin(drain_type, bs); do_drain_begin(drain_type, bs);
g_assert_cmpint(bs->in_flight, ==, 0); 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; break;
case 1: case 1:
qemu_event_reset(&done_event);
aio_bh_schedule_oneshot(ctx_a, test_iothread_drain_entry, &data); aio_bh_schedule_oneshot(ctx_a, test_iothread_drain_entry, &data);
qemu_event_wait(&done_event); qemu_event_wait(&done_event);
break; break;

View File

@ -207,13 +207,17 @@ static BlockBackend *start_primary(void)
static void teardown_primary(void) static void teardown_primary(void)
{ {
BlockBackend *blk; BlockBackend *blk;
AioContext *ctx;
/* remove P_ID */ /* remove P_ID */
blk = blk_by_name(P_ID); blk = blk_by_name(P_ID);
assert(blk); assert(blk);
ctx = blk_get_aio_context(blk);
aio_context_acquire(ctx);
monitor_remove_blk(blk); monitor_remove_blk(blk);
blk_unref(blk); blk_unref(blk);
aio_context_release(ctx);
} }
static void test_primary_read(void) static void test_primary_read(void)
@ -365,20 +369,27 @@ static void teardown_secondary(void)
{ {
/* only need to destroy two BBs */ /* only need to destroy two BBs */
BlockBackend *blk; BlockBackend *blk;
AioContext *ctx;
/* remove S_LOCAL_DISK_ID */ /* remove S_LOCAL_DISK_ID */
blk = blk_by_name(S_LOCAL_DISK_ID); blk = blk_by_name(S_LOCAL_DISK_ID);
assert(blk); assert(blk);
ctx = blk_get_aio_context(blk);
aio_context_acquire(ctx);
monitor_remove_blk(blk); monitor_remove_blk(blk);
blk_unref(blk); blk_unref(blk);
aio_context_release(ctx);
/* remove S_ID */ /* remove S_ID */
blk = blk_by_name(S_ID); blk = blk_by_name(S_ID);
assert(blk); assert(blk);
ctx = blk_get_aio_context(blk);
aio_context_acquire(ctx);
monitor_remove_blk(blk); monitor_remove_blk(blk);
blk_unref(blk); blk_unref(blk);
aio_context_release(ctx);
} }
static void test_secondary_read(void) static void test_secondary_read(void)