Re: [Qemu-devel] [PATCH V19 7/8] add-cow file format core code.

2013-06-05 Thread Stefan Hajnoczi
On Thu, May 30, 2013 at 06:00:24PM +0800, Dongxu Wang wrote:
> +static coroutine_fn int add_cow_co_writev(BlockDriverState *bs,
> +  int64_t sector_num,
> +  int remaining_sectors,
> +  QEMUIOVector *qiov)
> +{
> +BDRVAddCowState *s = bs->opaque;
> +int ret = 0, i;
> +QEMUIOVector hd_qiov;
> +uint8_t *table;
> +uint64_t offset;
> +int mask = s->cluster_sectors - 1;
> +int cluster_mask = s->cluster_size - 1;
> +AddCowMeta *meta = NULL;
> +
> +if (remaining_sectors == 0) {
> +return ret;
> +}
> +
> +qemu_co_mutex_lock(&s->lock);
> +
> +meta = g_malloc0(sizeof(*meta));
> +again:
> +*meta = (AddCowMeta) {
> +.next   = QLIST_FIRST(&s->cluster_allocs),
> +.start_sector   = sector_num,
> +.remaining_sectors  = remaining_sectors,
> +};
> +if (handle_dependencies(bs, sector_num, remaining_sectors) == -EAGAIN) {
> +goto again;
> +}
> +qemu_co_queue_init(&meta->dependent_requests);
> +QLIST_INSERT_HEAD(&s->cluster_allocs, meta, next_in_flight);
> +qemu_iovec_init(&hd_qiov, qiov->niov);

hd_qiov is unused.

> +ret = bdrv_co_writev(s->image_hd, sector_num, remaining_sectors, qiov);

s->lock is held so write requests block other requests, this is not
parallel.



[Qemu-devel] [PATCH V19 7/8] add-cow file format core code.

2013-05-30 Thread Dongxu Wang
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