[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 08/30] block: add support functions for live commit,
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PATCH 08/30] block: add support functions for live commit, to find and delete images. |
Date: |
Fri, 28 Sep 2012 19:56:51 +0200 |
From: Jeff Cody <address@hidden>
Add bdrv_find_overlay(), and bdrv_drop_intermediate().
bdrv_find_overlay(): given 'bs' and the active (topmost) BDS of an image chain,
find the image that is the immediate top of 'bs'
bdrv_drop_intermediate():
Given 3 BDS (active, top, base), drop images above
base up to and including top, and set base to be the
backing file of top's overlay node.
E.g., this converts:
bottom <- base <- intermediate <- top <- active
to
bottom <- base <- active
Signed-off-by: Jeff Cody <address@hidden>
Reviewed-by: Eric Blake <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
---
block.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
block.h | 4 ++
2 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/block.c b/block.c
index 751ebdc..54209a5 100644
--- a/block.c
+++ b/block.c
@@ -1724,6 +1724,149 @@ int bdrv_change_backing_file(BlockDriverState *bs,
return ret;
}
+/*
+ * Finds the image layer in the chain that has 'bs' as its backing file.
+ *
+ * active is the current topmost image.
+ *
+ * Returns NULL if bs is not found in active's image chain,
+ * or if active == bs.
+ */
+BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
+ BlockDriverState *bs)
+{
+ BlockDriverState *overlay = NULL;
+ BlockDriverState *intermediate;
+
+ assert(active != NULL);
+ assert(bs != NULL);
+
+ /* if bs is the same as active, then by definition it has no overlay
+ */
+ if (active == bs) {
+ return NULL;
+ }
+
+ intermediate = active;
+ while (intermediate->backing_hd) {
+ if (intermediate->backing_hd == bs) {
+ overlay = intermediate;
+ break;
+ }
+ intermediate = intermediate->backing_hd;
+ }
+
+ return overlay;
+}
+
+typedef struct BlkIntermediateStates {
+ BlockDriverState *bs;
+ QSIMPLEQ_ENTRY(BlkIntermediateStates) entry;
+} BlkIntermediateStates;
+
+
+/*
+ * Drops images above 'base' up to and including 'top', and sets the image
+ * above 'top' to have base as its backing file.
+ *
+ * Requires that the overlay to 'top' is opened r/w, so that the backing file
+ * information in 'bs' can be properly updated.
+ *
+ * E.g., this will convert the following chain:
+ * bottom <- base <- intermediate <- top <- active
+ *
+ * to
+ *
+ * bottom <- base <- active
+ *
+ * It is allowed for bottom==base, in which case it converts:
+ *
+ * base <- intermediate <- top <- active
+ *
+ * to
+ *
+ * base <- active
+ *
+ * Error conditions:
+ * if active == top, that is considered an error
+ *
+ */
+int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
+ BlockDriverState *base)
+{
+ BlockDriverState *intermediate;
+ BlockDriverState *base_bs = NULL;
+ BlockDriverState *new_top_bs = NULL;
+ BlkIntermediateStates *intermediate_state, *next;
+ int ret = -EIO;
+
+ QSIMPLEQ_HEAD(states_to_delete, BlkIntermediateStates) states_to_delete;
+ QSIMPLEQ_INIT(&states_to_delete);
+
+ if (!top->drv || !base->drv) {
+ goto exit;
+ }
+
+ new_top_bs = bdrv_find_overlay(active, top);
+
+ if (new_top_bs == NULL) {
+ /* we could not find the image above 'top', this is an error */
+ goto exit;
+ }
+
+ /* special case of new_top_bs->backing_hd already pointing to base -
nothing
+ * to do, no intermediate images */
+ if (new_top_bs->backing_hd == base) {
+ ret = 0;
+ goto exit;
+ }
+
+ intermediate = top;
+
+ /* now we will go down through the list, and add each BDS we find
+ * into our deletion queue, until we hit the 'base'
+ */
+ while (intermediate) {
+ intermediate_state = g_malloc0(sizeof(BlkIntermediateStates));
+ intermediate_state->bs = intermediate;
+ QSIMPLEQ_INSERT_TAIL(&states_to_delete, intermediate_state, entry);
+
+ if (intermediate->backing_hd == base) {
+ base_bs = intermediate->backing_hd;
+ break;
+ }
+ intermediate = intermediate->backing_hd;
+ }
+ if (base_bs == NULL) {
+ /* something went wrong, we did not end at the base. safely
+ * unravel everything, and exit with error */
+ goto exit;
+ }
+
+ /* success - we can delete the intermediate states, and link top->base */
+ ret = bdrv_change_backing_file(new_top_bs, base_bs->filename,
+ base_bs->drv ? base_bs->drv->format_name :
"");
+ if (ret) {
+ goto exit;
+ }
+ new_top_bs->backing_hd = base_bs;
+
+
+ QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) {
+ /* so that bdrv_close() does not recursively close the chain */
+ intermediate_state->bs->backing_hd = NULL;
+ bdrv_delete(intermediate_state->bs);
+ }
+ ret = 0;
+
+exit:
+ QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) {
+ g_free(intermediate_state);
+ }
+ return ret;
+}
+
+
static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
size_t size)
{
diff --git a/block.h b/block.h
index b1095d8..8c9b424 100644
--- a/block.h
+++ b/block.h
@@ -203,6 +203,10 @@ int bdrv_commit_all(void);
int bdrv_change_backing_file(BlockDriverState *bs,
const char *backing_file, const char *backing_fmt);
void bdrv_register(BlockDriver *bdrv);
+int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
+ BlockDriverState *base);
+BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
+ BlockDriverState *bs);
typedef struct BdrvCheckResult {
--
1.7.6.5
- [Qemu-devel] [PULL 00/30] Block patches, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 02/30] block: after creating a live snapshot, make old image read-only, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 01/30] block-migration: Flush requests in blk_mig_cleanup, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 03/30] aio: Fix qemu_aio_wait() to maintain correct walking_handlers count, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 06/30] configure: Add a config option for GlusterFS as block backend, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 07/30] block: Support GlusterFS as a QEMU block backend., Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 05/30] aio: Another fix to the walking_handlers logic, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 10/30] blockdev: rename block_stream_cb to a generic block_job_cb, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 09/30] block: add live block commit functionality, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 11/30] block: helper function, to find the base image of a chain, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 08/30] block: add support functions for live commit, to find and delete images.,
Kevin Wolf <=
- [Qemu-devel] [PATCH 04/30] qemu: URI parsing library, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 12/30] QAPI: add command for live block commit, 'block-commit', Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 13/30] qemu-iotests: add initial tests for live block commit, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 14/30] qerror/block: introduce QERR_BLOCK_JOB_NOT_ACTIVE, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 15/30] block: fix documentation of block_job_cancel_sync, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 17/30] block: add block_job_query, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 18/30] qmp: add 'busy' member to BlockJobInfo, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 16/30] block: move job APIs to separate files, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 19/30] block: add support for job pause/resume, Kevin Wolf, 2012/09/28
- [Qemu-devel] [PATCH 20/30] qmp: add block-job-pause and block-job-resume, Kevin Wolf, 2012/09/28