[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH 27/29] qcow2-bitmap: delete in_use bitmaps on image
From: |
Vladimir Sementsov-Ogievskiy |
Subject: |
[Qemu-block] [PATCH 27/29] qcow2-bitmap: delete in_use bitmaps on image load |
Date: |
Mon, 8 Aug 2016 18:05:18 +0300 |
Signed-off-by: Vladimir Sementsov-Ogievskiy <address@hidden>
Signed-off-by: Denis V. Lunev <address@hidden>
---
block/qcow2-bitmap.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 49066bd..e94019c 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -28,6 +28,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/cutils.h"
+#include "qemu/log.h"
#include "block/block_int.h"
#include "block/qcow2.h"
@@ -132,6 +133,17 @@ static inline QCow2BitmapHeader
*next_dir_entry(QCow2BitmapHeader *entry)
return (QCow2BitmapHeader *)((uint8_t *)entry + dir_entry_size(entry));
}
+static inline void bitmap_directory_to_cpu(uint8_t *dir, size_t size)
+{
+ QCow2BitmapHeader *h;
+
+ /* loop is safe because next entry offset is calculated after conversion to
+ * cpu format */
+ for_each_bitmap_header_in_dir(h, dir, size) {
+ bitmap_header_to_cpu(h);
+ }
+}
+
static inline void bitmap_directory_to_be(uint8_t *dir, size_t size)
{
uint8_t *end = dir + size;
@@ -241,6 +253,7 @@ static int load_autoload_bitmaps(BlockDriverState *bs,
Error **errp)
return 0;
}
+static int handle_in_use_bitmaps(BlockDriverState *bs);
int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp)
{
int ret;
@@ -262,6 +275,19 @@ int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp)
return -EINVAL;
}
+ if (can_write(bs)) {
+ ret = handle_in_use_bitmaps(bs);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Can't delete in_use bitmaps.");
+ goto fail;
+ }
+
+ if (s->nb_bitmaps == 0) {
+ /* No bitmaps - nothing to do */
+ return 0;
+ }
+ }
+
ret = load_autoload_bitmaps(bs, errp);
if (ret < 0) {
goto fail;
@@ -685,6 +711,75 @@ int qcow2_delete_bitmaps(BlockDriverState *bs)
return directory_update(bs, NULL, 0, 0);
}
+static int handle_in_use_bitmaps(BlockDriverState *bs)
+{
+ int ret;
+ BDRVQcow2State *s = bs->opaque;
+ uint64_t new_size = 0;
+ uint32_t new_nb_bitmaps = 0;
+ uint8_t *new_dir = NULL, *p;
+ QCow2BitmapHeader *h;
+
+ /* free in_use bitmaps clusters */
+ for_each_bitmap_header(h, s) {
+ if (h->flags & BME_FLAG_IN_USE) {
+ free_bitmap_clusters(bs, h);
+ h->bitmap_table_offset = 0;
+ h->bitmap_table_size = 0;
+ } else {
+ new_size += dir_entry_size(h);
+ new_nb_bitmaps++;
+ }
+ }
+
+ /* no in_use bitmaps */
+ if (new_nb_bitmaps == s->nb_bitmaps) {
+ return 0;
+ }
+
+ /* just update bitmap directory with freed out in_use bitmaps */
+ if (!(bdrv_get_flags(bs) & BDRV_O_CHECK)) {
+ bitmap_directory_to_be(s->bitmap_directory, s->bitmap_directory_size);
+ ret = bdrv_pwrite(bs->file,
+ s->bitmap_directory_offset,
+ s->bitmap_directory,
+ s->bitmap_directory_size);
+ bitmap_directory_to_cpu(s->bitmap_directory, s->bitmap_directory_size);
+
+ return ret;
+ }
+
+ if (new_nb_bitmaps == 0) {
+ goto update;
+ }
+
+ p = new_dir = g_try_malloc(new_size);
+ if (new_dir == NULL) {
+ return -ENOMEM;
+ }
+
+ for_each_bitmap_header(h, s) {
+ if (h->flags & BME_FLAG_IN_USE) {
+ char *bitmap_name = g_strndup((char *)(h + 1), h->name_size);
+ qemu_log("Delete corrupted (in_use) bitmap '%s' from device
'%s'\n",
+ bitmap_name, bdrv_get_device_or_node_name(bs));
+ g_free(bitmap_name);
+ } else {
+ memcpy(p, h, dir_entry_size(h));
+ p += dir_entry_size(h);
+ }
+ }
+
+update:
+ ret = directory_update(bs, new_dir, new_size, new_nb_bitmaps);
+ if (ret < 0) {
+ g_free(new_dir);
+ return ret;
+ }
+
+ return 0;
+}
+
/* store_bitmap_data()
* Store bitmap to image, filling bitamp table accordingly.
*/
--
1.8.3.1
- [Qemu-block] [PATCH v6 00/29] qcow2: persistent dirty bitmaps, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 28/29] qcow2-bitmap: do not try reloading bitmaps, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 07/29] qcow2-bitmap: add qcow2_bitmap_load(), Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 26/29] iotests: test qcow2 persistent dirty bitmap, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 21/29] qcow2-bitmap: add EXTRA_DATA_COMPATIBLE flag, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 13/29] qcow2: add dirty bitmaps extension, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 27/29] qcow2-bitmap: delete in_use bitmaps on image load,
Vladimir Sementsov-Ogievskiy <=
- [Qemu-block] [PATCH 22/29] qmp: add persistent flag to block-dirty-bitmap-add, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 24/29] qcow2-bitmap: maintian BlockDirtyBitmap.autoload, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 01/29] hbitmap: fix dirty iter, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 14/29] qcow2-bitmap: add qcow2_bitmap_load_check(), Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 15/29] block/dirty-bitmap: introduce persistent bitmaps, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 11/29] qcow2-bitmap: check constraints, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 12/29] qcow2: add qcow2_delete_bitmaps, Vladimir Sementsov-Ogievskiy, 2016/08/08
- [Qemu-block] [PATCH 06/29] qcow2-bitmap: add qcow2_read_bitmaps(), Vladimir Sementsov-Ogievskiy, 2016/08/08