qdict_set_default_str(child_options, BDRV_OPT_CACHE_DIRECT, "off");
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
- /* Copy the read-only option from the parent */
+ /* Copy the read-only and discard options from the parent */
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_DISCARD);
/* aio=native doesn't work for cache.direct=off, so disable it for the
* temporary snapshot */
/*
* Return true if at least one of the backing links between @bs and
* @base is frozen. @errp is set if that's the case.
+ * @base must be reachable from @bs, or NULL.
*/
bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base,
Error **errp)
{
BlockDriverState *i;
- for (i = bs; i != base && i->backing; i = backing_bs(i)) {
- if (i->backing->frozen) {
+ for (i = bs; i != base; i = backing_bs(i)) {
+ if (i->backing && i->backing->frozen) {
error_setg(errp, "Cannot change '%s' link from '%s' to '%s'",
i->backing->name, i->node_name,
backing_bs(i)->node_name);
* Freeze all backing links between @bs and @base.
* If any of the links is already frozen the operation is aborted and
* none of the links are modified.
+ * @base must be reachable from @bs, or NULL.
* Returns 0 on success. On failure returns < 0 and sets @errp.
*/
int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
return -EPERM;
}
- for (i = bs; i != base && i->backing; i = backing_bs(i)) {
- i->backing->frozen = true;
+ for (i = bs; i != base; i = backing_bs(i)) {
+ if (i->backing) {
+ i->backing->frozen = true;
+ }
}
return 0;
/*
* Unfreeze all backing links between @bs and @base. The caller must
* ensure that all links are frozen before using this function.
+ * @base must be reachable from @bs, or NULL.
*/
void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base)
{
BlockDriverState *i;
- for (i = bs; i != base && i->backing; i = backing_bs(i)) {
- assert(i->backing->frozen);
- i->backing->frozen = false;
+ for (i = bs; i != base; i = backing_bs(i)) {
+ if (i->backing) {
+ assert(i->backing->frozen);
+ i->backing->frozen = false;
+ }
}
}
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
/* Check whether we are allowed to switch c from top to base */
GSList *ignore_children = g_slist_prepend(NULL, c);
- bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm,
- ignore_children, &local_err);
+ ret = bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm,
+ ignore_children, &local_err);
g_slist_free(ignore_children);
- if (local_err) {
- ret = -EPERM;
+ if (ret < 0) {
error_report_err(local_err);
goto exit;
}
BdrvAioNotifier *baf, *baf_tmp;
BdrvChild *child;
- if (!bs->drv) {
- return;
- }
-
assert(!bs->walking_aio_notifiers);
bs->walking_aio_notifiers = true;
QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
*/
bs->walking_aio_notifiers = false;
- if (bs->drv->bdrv_detach_aio_context) {
+ if (bs->drv && bs->drv->bdrv_detach_aio_context) {
bs->drv->bdrv_detach_aio_context(bs);
}
QLIST_FOREACH(child, &bs->children, next) {
BdrvAioNotifier *ban, *ban_tmp;
BdrvChild *child;
- if (!bs->drv) {
- return;
- }
-
if (bs->quiesce_counter) {
aio_disable_external(new_context);
}
QLIST_FOREACH(child, &bs->children, next) {
bdrv_attach_aio_context(child->bs, new_context);
}
- if (bs->drv->bdrv_attach_aio_context) {
+ if (bs->drv && bs->drv->bdrv_attach_aio_context) {
bs->drv->bdrv_attach_aio_context(bs, new_context);
}