aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'block.c')
-rw-r--r--block.c183
1 files changed, 96 insertions, 87 deletions
diff --git a/block.c b/block.c
index 6943962..d24ae85 100644
--- a/block.c
+++ b/block.c
@@ -2185,6 +2185,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
ret = -EINVAL;
goto free_exit;
}
+ bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
/* Hook up the backing file link; drop our reference, bs owns the
* backing_hd reference now */
@@ -2573,15 +2574,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
goto close_and_fail;
}
- if (!bdrv_key_required(bs)) {
- bdrv_parent_cb_change_media(bs, true);
- } else if (!runstate_check(RUN_STATE_PRELAUNCH)
- && !runstate_check(RUN_STATE_INMIGRATE)
- && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
- error_setg(errp,
- "Guest must be stopped for opening of encrypted image");
- goto close_and_fail;
- }
+ bdrv_parent_cb_change_media(bs, true);
QDECREF(options);
@@ -2989,24 +2982,45 @@ error:
void bdrv_reopen_commit(BDRVReopenState *reopen_state)
{
BlockDriver *drv;
+ BlockDriverState *bs;
+ bool old_can_write, new_can_write;
assert(reopen_state != NULL);
- drv = reopen_state->bs->drv;
+ bs = reopen_state->bs;
+ drv = bs->drv;
assert(drv != NULL);
+ old_can_write =
+ !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
+
/* If there are any driver level actions to take */
if (drv->bdrv_reopen_commit) {
drv->bdrv_reopen_commit(reopen_state);
}
/* set BDS specific flags now */
- QDECREF(reopen_state->bs->explicit_options);
+ QDECREF(bs->explicit_options);
- reopen_state->bs->explicit_options = reopen_state->explicit_options;
- reopen_state->bs->open_flags = reopen_state->flags;
- reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
+ bs->explicit_options = reopen_state->explicit_options;
+ bs->open_flags = reopen_state->flags;
+ bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
+
+ bdrv_refresh_limits(bs, NULL);
- bdrv_refresh_limits(reopen_state->bs, NULL);
+ new_can_write =
+ !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
+ if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) {
+ Error *local_err = NULL;
+ if (drv->bdrv_reopen_bitmaps_rw(bs, &local_err) < 0) {
+ /* This is not fatal, bitmaps just left read-only, so all following
+ * writes will fail. User can remove read-only bitmaps to unblock
+ * writes.
+ */
+ error_reportf_err(local_err,
+ "%s: Failed to make dirty bitmaps writable: ",
+ bdrv_get_node_name(bs));
+ }
+ }
}
/*
@@ -3040,9 +3054,6 @@ static void bdrv_close(BlockDriverState *bs)
bdrv_flush(bs);
bdrv_drain(bs); /* in case flush left pending I/O */
- bdrv_release_named_dirty_bitmaps(bs);
- assert(QLIST_EMPTY(&bs->dirty_bitmaps));
-
if (bs->drv) {
BdrvChild *child, *next;
@@ -3072,7 +3083,6 @@ static void bdrv_close(BlockDriverState *bs)
bs->backing_format[0] = '\0';
bs->total_sectors = 0;
bs->encrypted = false;
- bs->valid_key = false;
bs->sg = false;
QDECREF(bs->options);
QDECREF(bs->explicit_options);
@@ -3081,6 +3091,9 @@ static void bdrv_close(BlockDriverState *bs)
bs->full_open_options = NULL;
}
+ bdrv_release_named_dirty_bitmaps(bs);
+ assert(QLIST_EMPTY(&bs->dirty_bitmaps));
+
QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
g_free(ban);
}
@@ -3398,7 +3411,8 @@ exit:
/**
* Truncate file to 'offset' bytes (needed only for file protocols)
*/
-int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp)
+int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
+ Error **errp)
{
BlockDriverState *bs = child->bs;
BlockDriver *drv = bs->drv;
@@ -3421,7 +3435,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp)
assert(!(bs->open_flags & BDRV_O_INACTIVE));
- ret = drv->bdrv_truncate(bs, offset, errp);
+ ret = drv->bdrv_truncate(bs, offset, prealloc, errp);
if (ret == 0) {
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
bdrv_dirty_bitmap_truncate(bs);
@@ -3450,6 +3464,41 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
return -ENOTSUP;
}
+/*
+ * bdrv_measure:
+ * @drv: Format driver
+ * @opts: Creation options for new image
+ * @in_bs: Existing image containing data for new image (may be NULL)
+ * @errp: Error object
+ * Returns: A #BlockMeasureInfo (free using qapi_free_BlockMeasureInfo())
+ * or NULL on error
+ *
+ * Calculate file size required to create a new image.
+ *
+ * If @in_bs is given then space for allocated clusters and zero clusters
+ * from that image are included in the calculation. If @opts contains a
+ * backing file that is shared by @in_bs then backing clusters may be omitted
+ * from the calculation.
+ *
+ * If @in_bs is NULL then the calculation includes no allocated clusters
+ * unless a preallocation option is given in @opts.
+ *
+ * Note that @in_bs may use a different BlockDriver from @drv.
+ *
+ * If an error occurs the @errp pointer is set.
+ */
+BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
+ BlockDriverState *in_bs, Error **errp)
+{
+ if (!drv->bdrv_measure) {
+ error_setg(errp, "Block driver '%s' does not support size measurement",
+ drv->format_name);
+ return NULL;
+ }
+
+ return drv->bdrv_measure(opts, in_bs, errp);
+}
+
/**
* Return number of sectors on success, -errno on error.
*/
@@ -3502,72 +3551,6 @@ bool bdrv_is_encrypted(BlockDriverState *bs)
return bs->encrypted;
}
-bool bdrv_key_required(BlockDriverState *bs)
-{
- BdrvChild *backing = bs->backing;
-
- if (backing && backing->bs->encrypted && !backing->bs->valid_key) {
- return true;
- }
- return (bs->encrypted && !bs->valid_key);
-}
-
-int bdrv_set_key(BlockDriverState *bs, const char *key)
-{
- int ret;
- if (bs->backing && bs->backing->bs->encrypted) {
- ret = bdrv_set_key(bs->backing->bs, key);
- if (ret < 0)
- return ret;
- if (!bs->encrypted)
- return 0;
- }
- if (!bs->encrypted) {
- return -EINVAL;
- } else if (!bs->drv || !bs->drv->bdrv_set_key) {
- return -ENOMEDIUM;
- }
- ret = bs->drv->bdrv_set_key(bs, key);
- if (ret < 0) {
- bs->valid_key = false;
- } else if (!bs->valid_key) {
- /* call the change callback now, we skipped it on open */
- bs->valid_key = true;
- bdrv_parent_cb_change_media(bs, true);
- }
- return ret;
-}
-
-/*
- * Provide an encryption key for @bs.
- * If @key is non-null:
- * If @bs is not encrypted, fail.
- * Else if the key is invalid, fail.
- * Else set @bs's key to @key, replacing the existing key, if any.
- * If @key is null:
- * If @bs is encrypted and still lacks a key, fail.
- * Else do nothing.
- * On failure, store an error object through @errp if non-null.
- */
-void bdrv_add_key(BlockDriverState *bs, const char *key, Error **errp)
-{
- if (key) {
- if (!bdrv_is_encrypted(bs)) {
- error_setg(errp, "Node '%s' is not encrypted",
- bdrv_get_device_or_node_name(bs));
- } else if (bdrv_set_key(bs, key) < 0) {
- error_setg(errp, QERR_INVALID_PASSWORD);
- }
- } else {
- if (bdrv_key_required(bs)) {
- error_set(errp, ERROR_CLASS_DEVICE_ENCRYPTED,
- "'%s' (%s) is encrypted",
- bdrv_get_device_or_node_name(bs),
- bdrv_get_encrypted_filename(bs));
- }
- }
-}
-
const char *bdrv_get_format_name(BlockDriverState *bs)
{
return bs->drv ? bs->drv->format_name : NULL;
@@ -4135,6 +4118,10 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
}
}
+ /* At this point persistent bitmaps should be already stored by the format
+ * driver */
+ bdrv_release_persistent_dirty_bitmaps(bs);
+
return 0;
}
@@ -4933,3 +4920,25 @@ void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)
parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
}
+
+bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
+ uint32_t granularity, Error **errp)
+{
+ BlockDriver *drv = bs->drv;
+
+ if (!drv) {
+ error_setg_errno(errp, ENOMEDIUM,
+ "Can't store persistent bitmaps to %s",
+ bdrv_get_device_or_node_name(bs));
+ return false;
+ }
+
+ if (!drv->bdrv_can_store_new_dirty_bitmap) {
+ error_setg_errno(errp, ENOTSUP,
+ "Can't store persistent bitmaps to %s",
+ bdrv_get_device_or_node_name(bs));
+ return false;
+ }
+
+ return drv->bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp);
+}