From: Dong Xu Wang
add-cow file format core code. It use block-cache.c as cache code.
It lacks of snapshot_blkdev support.
v18->v19:
1) add aio parallel write support.
2) fix flush method.
v17-v18:
1) use error_report, not fprintf.
2) remove version field from header.
3) header_size is MAX(cluster_size, 4096).
4) introduce s->cluster_sectors.
5) use BLKDBG_L2_LOAD/UPDATE.
v16->v17:
1) Use stringify.
v15->v16:
1) Judge if opts is null in add_cow_create function.
Signed-off-by: Dong Xu Wang
Conflicts:
block/block-cache.c
Signed-off-by: Dongxu Wang
---
block/Makefile.objs | 1 +
block/add-cow.c | 812
block/block-cache.c | 16 +-
include/block/block-cache.h | 4 +
include/block/block_int.h | 2 +
5 files changed, 831 insertions(+), 4 deletions(-)
create mode 100644 block/add-cow.c
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 16e574a..f666a7a 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -1,6 +1,7 @@
block-obj-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o
vvfat.o
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
block-obj-y += block-cache.o
+block-obj-y += add-cow.o
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o
block-obj-y += vhdx.o
diff --git a/block/add-cow.c b/block/add-cow.c
new file mode 100644
index 000..290da3c
--- /dev/null
+++ b/block/add-cow.c
@@ -0,0 +1,812 @@
+/*
+ * QEMU ADD-COW Disk Format
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Dong Xu Wang
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "block/block_int.h"
+#include "qemu/module.h"
+#include "block/block-cache.h"
+
+#define ACOW_CLUSTER_SIZE 65536
+
+typedef struct AddCowMeta
+{
+uint64_t start_sector;
+int remaining_sectors;
+CoQueue dependent_requests;
+struct AddCowMeta *next;
+
+QLIST_ENTRY(AddCowMeta) next_in_flight;
+} AddCowMeta;
+
+enum {
+/* compat_features bit */
+ACOW_F_ALL_ALLOCATED= 0X01,
+
+/* none feature bit used now */
+ACOW_FEATURE_MASK = 0,
+
+ACOW_MAGIC = 'A' | 'C' << 8 | 'O' << 16 | 'W' << 24,
+ACOW_CACHE_SIZE = 16,
+DEFAULT_HEADER_SIZE = 4096,
+MIN_CLUSTER_BITS= 12,
+MAX_CLUSTER_BITS= 21,
+};
+
+typedef struct AddCowHeader {
+uint32_tmagic;
+
+uint32_tbacking_offset;
+uint32_tbacking_size;
+uint32_timage_offset;
+uint32_timage_size;
+
+uint32_tcluster_bits;
+uint64_tfeatures;
+uint64_tcompat_features;
+uint32_theader_size;
+
+charbacking_fmt[16];
+charimage_fmt[16];
+} QEMU_PACKED AddCowHeader;
+
+typedef struct BDRVAddCowState {
+BlockDriverState*image_hd;
+CoMutex lock;
+int cluster_size;
+int cluster_sectors;
+BlockCache *bitmap_cache;
+uint64_tbitmap_size;
+AddCowHeaderheader;
+charbacking_fmt[16];
+charimage_fmt[16];
+BlockCache *image_hd_cache;
+QLIST_HEAD(AddCowAlloc, AddCowMeta) cluster_allocs;
+} BDRVAddCowState;
+
+/* Convert sector_num to offset in bitmap */
+static inline int64_t offset_in_bitmap(int64_t sector_num,
+ int64_t cluster_sectors)
+{
+int64_t cluster_num = sector_num / cluster_sectors;
+return cluster_num / 8;
+}
+
+static inline bool is_cluster_head(int64_t sector_num,
+ int64_t cluster_sectors)
+{
+return sector_num % cluster_sectors == 0;
+}
+
+static inline bool is_cluster_tail(int64_t sector_num,
+ int64_t cluster_sectors)
+{
+return (sector_num + 1) % cluster_sectors == 0;
+}
+
+static void add_cow_header_le_to_cpu(const AddCowHeader *le, AddCowHeader *cpu)
+{
+cpu->magic = le32_to_cpu(le->magic);
+
+cpu->backing_offset = le32_to_cpu(le->backing_offset);
+cpu->backing_size = le32_to_cpu(le->backing_size);
+cpu->image_offset = le32_to_cpu(le->image_offset);
+cpu->image_size = le32_to_cpu(le->image_size);
+
+cpu->cluster_bits = le32_to_cpu(le->cluster_bits);
+cpu->features = le64_to_cpu(le->features);
+cpu->compat_features= le64_to_cpu(le->compat_features);
+cpu->header_size= le32_to_cpu(le->header_size);
+
+memcpy(cpu->backing_fmt, le->backing_fmt, sizeof(cpu->backing_fmt));
+memcpy(cpu->image_fmt, le->image_fmt, sizeof(cpu->image_fmt));
+}
+
+static void add_cow_header_cpu_to_le(const AddCowHeader *cpu, AddCowHeader *le)
+{
+le->magic = cpu_to_le32(cpu->magic);
+
+le->backing_offset = cpu_to