qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library
@ 2012-09-27  2:23 Wenchao Xia
  2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 1/5] libqblock build system Wenchao Xia
                   ` (4 more replies)
  0 siblings, 5 replies; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  2:23 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, aliguori, stefanha, blauwirbel, pbonzini, eblake,
	Wenchao Xia

  This patch introduce libqblock API, make libqblock.la and make check-libqblock
could build this library.
Functionalities:
 1 create a new image.
 2 sync access of an image.
 3 basic image information retrieving such as backing file.
 4 detect if a sector is allocated in an image.
Supported Formats:
 ALL using file protocols.

v2:
  Insert reserved bytes into union.
  Use uint64_t instead of size_t, offset.
  Use const char * in filename pointer.
  Initialization function removed and it was automatically executed when
library is loaded.
  Added compile flag visibility=hidden, to avoid name space pollution.
  Structure naming style changed.
  Using byte unit instead of sector for every API.
  Added a member in image static information structure, to report logical
sector size, which is always 512 now.
  Read and write API can take request not aligned to 512 now. It returns the
byte number that have succeed in operation, but now either negative value
or the number requested would be returned, because qemu block sync I/O API
would not return such number.
  Typo fix due to comments and improved documents.

v3:
  Removed the code about OOM error, introduced GError.
  Used a table to map from string to enum types about format.
  Use typedef for every structure.
  Improved the gcc compiler macro to warn if gcc was not used.
  Global variable name changed with prefix libqb_.
  The struct QBlockStaticInfo was changed to folder full format related
information inside, and a new member with pointers pointing to the mostly used
members, such as backing file, virt size, was added. This would allow the user
to get full information about how it is created in the future.
  Each patch in the serial can work with qemu now.
  Typo fixes.

v4:
  Renamed QBroker to QBlockContext.
  Removed tool objs out of libqblock.
  Added a check in initialization about structure size for ABI.
  Added a new helper API to duplicate protocol information, helps to open files
in a backing file chain.
  Check-libqblock will not rebuild libqblock every time now.
  Test case file renamed to "libqblock-[FMT].c".
  Test use gtest framework now.
  Test do random creation of test file now, added check for information API in
it.
  Test do random sync io instead of fixed offset io now.
  Test accept one parameter about where to place the test image, now it is
./tests/libqblock/test_images.

Wenchao Xia (5):
  libqblock build system
  libqblock type defines
  libqblock API
  libqblock test build system
  libqblock test example

 .gitignore                        |    2 +
 Makefile                          |   15 +-
 Makefile.objs                     |    6 +
 block.c                           |    2 +-
 block.h                           |    1 +
 libqblock/Makefile                |   56 ++
 libqblock/libqblock-error.c       |   57 ++
 libqblock/libqblock-error.h       |   49 ++
 libqblock/libqblock-internal.h    |   57 ++
 libqblock/libqblock-types.h       |  268 +++++++++
 libqblock/libqblock.c             | 1165 +++++++++++++++++++++++++++++++++++++
 libqblock/libqblock.h             |  308 ++++++++++
 tests/Makefile                    |   45 ++
 tests/libqblock/libqblock-qcow2.c |  368 ++++++++++++
 14 files changed, 2396 insertions(+), 3 deletions(-)
 create mode 100644 libqblock/Makefile
 create mode 100644 libqblock/libqblock-error.c
 create mode 100644 libqblock/libqblock-error.h
 create mode 100644 libqblock/libqblock-internal.h
 create mode 100644 libqblock/libqblock-types.h
 create mode 100644 libqblock/libqblock.c
 create mode 100644 libqblock/libqblock.h
 create mode 100644 tests/libqblock/libqblock-qcow2.c

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH V4 1/5] libqblock build system
  2012-09-27  2:23 [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library Wenchao Xia
@ 2012-09-27  2:23 ` Wenchao Xia
  2012-09-27  8:06   ` Paolo Bonzini
  2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 2/5] libqblock type defines Wenchao Xia
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  2:23 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, aliguori, stefanha, blauwirbel, pbonzini, eblake,
	Wenchao Xia

  Libqblock was placed in new directory ./libqblock, libtool will build
dynamic library there, source files of block layer remains in ./block.
So block related source code will generate 3 sets of binary, first is old
ones used in qemu, second and third are non PIC and PIC ones in ./libqblock.
  GCC compiler flag visibility=hidden was used with special macro, to export
only symbols that was marked as PUBLIC.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 Makefile                    |   14 +++++++++-
 Makefile.objs               |    6 ++++
 libqblock/Makefile          |   56 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 libqblock/Makefile
 create mode 100644 libqblock/libqblock-error.c
 create mode 100644 libqblock/libqblock.c

diff --git a/Makefile b/Makefile
index def2ae2..128bc6a 100644
--- a/Makefile
+++ b/Makefile
@@ -164,6 +164,17 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
 
+######################################################################
+# Support building shared library libqblock
+ifeq ($(LIBTOOL),)
+$(libqblock-lib-la):
+	@echo "libtool is missing, please install and rerun configure"; exit 1
+else
+$(libqblock-lib-la):
+	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libqblock V="$(V)" TARGET_DIR="$*/" $(libqblock-lib-la),)
+endif
+###########################################################################
+
 vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) $(tools-obj-y) qemu-timer-common.o libcacard/vscclient.o
 	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
 
@@ -226,8 +237,7 @@ clean:
 	rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
 	rm -rf qapi-generated
 	rm -rf qga/qapi-generated
-	$(MAKE) -C tests/tcg clean
-	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
+	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard libqblock; do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
 	rm -f $$d/qemu-options.def; \
         done
diff --git a/Makefile.objs b/Makefile.objs
index 4412757..8a4c9fc 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -248,3 +248,9 @@ nested-vars += \
 	common-obj-y \
 	extra-obj-y
 dummy := $(call unnest-vars)
+
+#############################################################################
+# libqblock
+
+libqblock-lib-la = libqblock.la
+libqblock-lib-path = libqblock
diff --git a/libqblock/Makefile b/libqblock/Makefile
new file mode 100644
index 0000000..5f65613
--- /dev/null
+++ b/libqblock/Makefile
@@ -0,0 +1,56 @@
+###########################################################################
+# libqblock Makefile
+# Todo:
+#    1 trace related files is generated in this directory, move
+#  them to the root directory.
+##########################################################################
+-include ../config-host.mak
+-include $(SRC_PATH)/Makefile.objs
+-include $(SRC_PATH)/rules.mak
+
+#############################################################################
+# Library settings
+#############################################################################
+$(call set-vpath, $(SRC_PATH))
+
+#expand the foldered vars,especially ./block
+dummy := $(call unnest-vars-1)
+
+#library objects
+libqblock-y=libqblock.o libqblock-error.o
+
+QEMU_OBJS= $(libqblock-y) $(block-obj-y)
+#filter out ./block
+QEMU_OBJS_FILTERED=$(filter %.o, $(QEMU_OBJS))
+QEMU_OBJS_LIB=$(patsubst %.o, %.lo, $(QEMU_OBJS_FILTERED))
+
+QEMU_CFLAGS+= -I../ -I../include
+#adding magic macro define for symbol hiding and exposing
+QEMU_CFLAGS+= -fvisibility=hidden -D LIBQB_BUILD
+
+#dependency libraries
+LIBS+=-lz $(LIBS_TOOLS)
+
+#################################################################
+# Runtime rules
+#################################################################
+clean:
+	rm -f *.lo *.o *.d *.la libqblock-test trace.c trace.c-timestamp
+	rm -rf .libs block trace
+
+help:
+	@echo type make libqblock-test at root dirtory, libtool is required
+
+#make directory ./block at runtime which would hold the output of block/*.c
+block:
+	@mkdir block
+
+ifeq ($(LIBTOOL),)
+$(libqblock-lib-la):
+	@echo "libtool is missing, please install and rerun configure"; exit 1
+else
+$(libqblock-lib-la): $(QEMU_OBJS_LIB)
+	$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(LIBS),"  lt LINK $@")
+endif
+
+.PHONY: libqblock.la
diff --git a/libqblock/libqblock-error.c b/libqblock/libqblock-error.c
new file mode 100644
index 0000000..e69de29
diff --git a/libqblock/libqblock.c b/libqblock/libqblock.c
new file mode 100644
index 0000000..e69de29
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-27  2:23 [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library Wenchao Xia
  2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 1/5] libqblock build system Wenchao Xia
@ 2012-09-27  2:23 ` Wenchao Xia
  2012-09-27  8:25   ` Paolo Bonzini
  2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 3/5] libqblock API Wenchao Xia
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  2:23 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, aliguori, stefanha, blauwirbel, pbonzini, eblake,
	Wenchao Xia

  This patch contains type and macro defines used in APIs, one file for public
usage by user, one for libqblock internal usage.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 libqblock/libqblock-internal.h |   57 +++++++++
 libqblock/libqblock-types.h    |  268 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 325 insertions(+), 0 deletions(-)
 create mode 100644 libqblock/libqblock-internal.h
 create mode 100644 libqblock/libqblock-types.h

diff --git a/libqblock/libqblock-internal.h b/libqblock/libqblock-internal.h
new file mode 100644
index 0000000..d3e983c
--- /dev/null
+++ b/libqblock/libqblock-internal.h
@@ -0,0 +1,57 @@
+/*
+ * QEMU block layer library
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef LIBQBLOCK_INTERNAL
+#define LIBQBLOCK_INTERNAL
+
+#include "glib.h"
+
+#include "block.h"
+#include "block_int.h"
+#include "libqblock-types.h"
+
+/* this file contains defines and types used inside the library. */
+
+#define FUNC_FREE(p) g_free((p))
+#define FUNC_MALLOC(size) g_malloc((size))
+#define FUNC_CALLOC(nmemb, size) g_malloc0((nmemb)*(size))
+#define FUNC_STRDUP(p) g_strdup((p))
+
+#define CLEAN_FREE(p) { \
+        FUNC_FREE(p); \
+        (p) = NULL; \
+}
+
+/* details should be hidden to user */
+struct QBlockState {
+    BlockDriverState *bdrvs;
+    /* internal used file name now, if it is not NULL, it means
+       image was opened.
+    */
+    char *filename;
+};
+
+struct QBlockContext {
+    /* last error */
+    GError *g_error;
+    int err_ret; /* 1st level of error, the libqblock error number */
+    int err_no; /* 2nd level of error, errno what below reports */
+};
+
+#define G_LIBQBLOCK_ERROR g_libqbock_error_quark()
+
+static inline GQuark g_libqbock_error_quark(void)
+{
+    return g_quark_from_static_string("g-libqblock-error-quark");
+}
+#endif
diff --git a/libqblock/libqblock-types.h b/libqblock/libqblock-types.h
new file mode 100644
index 0000000..948ab8a
--- /dev/null
+++ b/libqblock/libqblock-types.h
@@ -0,0 +1,268 @@
+/*
+ * QEMU block layer library
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef LIBQBLOCK_TYPES_H
+#define LIBQBLOCK_TYPES_H
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+    #ifdef LIBQB_BUILD
+        #define DLL_PUBLIC __attribute__((visibility("default")))
+    #else
+        #define DLL_PUBLIC
+    #endif
+#else
+    #warning : gcc compiler version < 4, symbols can not be hidden.
+#endif
+
+/* this library is designed around this core struct. */
+typedef struct QBlockState QBlockState;
+
+/* every thread should have a context. */
+typedef struct QBlockContext QBlockContext;
+
+/* flag used in open and create */
+#define LIBQBLOCK_O_RDWR        0x0002
+/* do not use the host page cache */
+#define LIBQBLOCK_O_NOCACHE     0x0020
+/* use write-back caching */
+#define LIBQBLOCK_O_CACHE_WB    0x0040
+/* don't open the backing file */
+#define LIBQBLOCK_O_NO_BACKING  0x0100
+/* disable flushing on this disk */
+#define LIBQBLOCK_O_NO_FLUSH    0x0200
+
+#define LIBQBLOCK_O_CACHE_MASK \
+   (LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | LIBQBLOCK_O_NO_FLUSH)
+
+#define LIBQBLOCK_O_VALID_MASK \
+   (LIBQBLOCK_O_RDWR | LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | \
+    LIBQBLOCK_O_NO_BACKING | LIBQBLOCK_O_NO_FLUSH)
+
+typedef enum QBlockProtType {
+    QB_PROT_NONE = 0,
+    QB_PROT_FILE,
+    QB_PROT_MAX
+} QBlockProtType;
+
+typedef struct QBlockProtOptionFile {
+    const char *filename;
+} QBlockProtOptionFile;
+
+#define QBLOCK_PROT_OPTIONS_UNION_SIZE (512)
+typedef union QBlockProtOptionsUnion {
+    QBlockProtOptionFile o_file;
+    uint8_t reserved[QBLOCK_PROT_OPTIONS_UNION_SIZE];
+} QBlockProtOptionsUnion;
+
+/**
+ * struct QBlockProtInfo: contains information about how to find the image
+ *
+ * @prot_type: protocol type, now only support FILE.
+ * @prot_op: protocol related options.
+ */
+typedef struct QBlockProtInfo {
+    QBlockProtType prot_type;
+    QBlockProtOptionsUnion prot_op;
+} QBlockProtInfo;
+
+
+/* format related options */
+typedef enum QBlockFmtType {
+    QB_FMT_NONE = 0,
+    QB_FMT_COW,
+    QB_FMT_QED,
+    QB_FMT_QCOW,
+    QB_FMT_QCOW2,
+    QB_FMT_RAW,
+    QB_FMT_RBD,
+    QB_FMT_SHEEPDOG,
+    QB_FMT_VDI,
+    QB_FMT_VMDK,
+    QB_FMT_VPC,
+    QB_FMT_MAX
+} QBlockFmtType;
+
+typedef struct QBlockFmtOptionCow {
+    uint64_t virt_size;
+    QBlockProtInfo backing_loc;
+} QBlockFmtOptionCow;
+
+typedef struct QBlockFmtOptionQed {
+    uint64_t virt_size;
+    QBlockProtInfo backing_loc;
+    QBlockFmtType backing_fmt;
+    uint64_t cluster_size; /* unit is bytes */
+    uint64_t table_size; /* unit is clusters */
+} QBlockFmtOptionQed;
+
+typedef struct QBlockFmtOptionQcow {
+    uint64_t virt_size;
+    QBlockProtInfo backing_loc;
+    bool encrypt;
+} QBlockFmtOptionQcow;
+
+/* "Compatibility level (0.10 or 1.1)" */
+typedef enum QBlockFmtOptionQcow2CptLv {
+    QBO_FMT_QCOW2_CPT_NONE = 0,
+    QBO_FMT_QCOW2_CPT_V010,
+    QBO_FMT_QCOW2_CPT_V110,
+} QBlockFmtOptionQcow2CptLv;
+
+/* off or metadata */
+typedef enum QBlockFmtOptionQcow2PreAllocType {
+    QBO_FMT_QCOW2_PREALLOC_NONE = 0,
+    QBO_FMT_QCOW2_PREALLOC_OFF,
+    QBO_FMT_QCOW2_PREALLOC_METADATA,
+} QBlockFmtOptionQcow2PreAllocType;
+
+typedef struct QBlockFmtOptionQcow2 {
+    uint64_t virt_size;
+    QBlockProtInfo backing_loc;
+    QBlockFmtType backing_fmt;
+    bool encrypt;
+    uint64_t cluster_size; /* unit is bytes */
+    QBlockFmtOptionQcow2CptLv cpt_lv;
+    QBlockFmtOptionQcow2PreAllocType pre_mode;
+} QBlockFmtOptionQcow2;
+
+typedef struct QBlockFmtOptionRaw {
+    uint64_t virt_size;
+} QBlockFmtOptionRaw;
+
+typedef struct QBlockFmtOptionRbd {
+    uint64_t virt_size;
+    uint64_t cluster_size;
+} QBlockFmtOptionRbd;
+
+/* off or full */
+typedef enum QBlockFmtOptionSheepdogPreAllocType {
+    QBO_FMT_SD_PREALLOC_NONE = 0,
+    QBO_FMT_SD_PREALLOC_OFF,
+    QBO_FMT_SD_PREALLOC_FULL,
+} QBlockFmtOptionSheepdogPreAllocType;
+
+typedef struct QBlockFmtOptionSheepdog {
+    uint64_t virt_size;
+    QBlockProtInfo backing_loc;
+    QBlockFmtOptionSheepdogPreAllocType pre_mode;
+} QBlockFmtOptionSheepdog;
+
+typedef enum QBlockFmtOptionVdiPreAllocType {
+    QBO_FMT_VDI_PREALLOC_NONE = 0,
+    QBO_FMT_VDI_PREALLOC_FALSE,
+    QBO_FMT_VDI_PREALLOC_TRUE,
+} QBlockFmtOptionVdiPreAllocType;
+
+typedef struct QBlockFmtOptionVdi {
+    uint64_t virt_size;
+    uint64_t cluster_size;
+    QBlockFmtOptionVdiPreAllocType pre_mode;
+} QBlockFmtOptionVdi;
+
+/* whether compact to vmdk verion 6 */
+typedef enum QBlockFmtOptionVmdkCptLv {
+    QBO_FMT_VMDK_CPT_NONE = 0,
+    QBO_FMT_VMDK_CPT_VMDKV6_FALSE,
+    QBO_FMT_VMDK_CPT_VMDKV6_TRUE,
+} QBlockFmtOptionVmdkCptLv;
+
+/* vmdk flat extent format, values:
+"{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse |
+twoGbMaxExtentFlat | streamOptimized} */
+typedef enum QBlockFmtOptionVmdkSubfmtType {
+    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE = 0,
+    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_SPARSE,
+    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_FLAT,
+    QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_SPARSE,
+    QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_FLAT,
+    QBO_FMT_VMDK_SUBFMT_STREAM_OPTIMIZED,
+} QBlockFmtOptionVmdkSubfmtType;
+
+typedef struct QBlockFmtOptionVmdk {
+    uint64_t virt_size;
+    QBlockProtInfo backing_loc;
+    QBlockFmtOptionVmdkCptLv cpt_lv;
+    QBlockFmtOptionVmdkSubfmtType subfmt;
+} QBlockFmtOptionVmdk;
+
+/* "{dynamic (default) | fixed} " */
+typedef enum QBlockFmtOptionVpcSubfmtType {
+    QBO_FMT_VPC_SUBFMT_NONE = 0,
+    QBO_FMT_VPC_SUBFMT_DYNAMIC,
+    QBO_FMT_VPC_SUBFMT_FIXED,
+} QBlockFmtOptionVpcSubfmtType;
+
+typedef struct QBlockFmtOptionVpc {
+    uint64_t virt_size;
+    QBlockFmtOptionVpcSubfmtType subfmt;
+} QBlockFmtOptionVpc;
+
+#define QBLOCK_FMT_OPTIONS_UNION_SIZE (QBLOCK_PROT_OPTIONS_UNION_SIZE*2)
+typedef union QBlockFmtOptionsUnion {
+    QBlockFmtOptionCow       o_cow;
+    QBlockFmtOptionQed       o_qed;
+    QBlockFmtOptionQcow      o_qcow;
+    QBlockFmtOptionQcow2     o_qcow2;
+    QBlockFmtOptionRaw       o_raw;
+    QBlockFmtOptionRbd       o_rbd;
+    QBlockFmtOptionSheepdog  o_sheepdog;
+    QBlockFmtOptionVdi       o_vdi;
+    QBlockFmtOptionVmdk      o_vmdk;
+    QBlockFmtOptionVpc       o_vpc;
+    uint8_t reserved[QBLOCK_FMT_OPTIONS_UNION_SIZE];
+} QBlockFmtOptionsUnion;
+
+typedef struct QBlockFmtInfo {
+    QBlockFmtType fmt_type;
+    QBlockFmtOptionsUnion fmt_op;
+} QBlockFmtInfo;
+
+/**
+ * QBlockStaticInfoAddr: a structure contains a set of pointer.
+ *
+ *    this struct contains a set of pointer pointing to some
+ *  property related to format or protocol. If a property is not available,
+ *  it will be set as NULL. User could use this to get properties directly.
+ *
+ *  @virt_size: virtual size, it is always not NULL.
+ *  @backing_loc: backing file location.
+ *  @encrypt: encryption flag.
+*/
+
+typedef struct QBlockStaticInfoAddr {
+    uint64_t *virt_size;
+    QBlockProtInfo *backing_loc;
+    bool *encrypt;
+} QBlockStaticInfoAddr;
+
+/**
+ * QBlockStaticInfo: information about the block image.
+ *
+ * @member_addr: contains pointer which can be used to access the structure.
+ * @loc: location information.
+ * @fmt: format information.
+ * @sector_size: how many bytes in a sector, it is 512 usually.
+ */
+typedef struct QBlockStaticInfo {
+    QBlockStaticInfoAddr *member_addr;
+    QBlockProtInfo loc;
+    QBlockFmtInfo fmt;
+    int sector_size;
+} QBlockStaticInfo;
+
+
+#endif
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH V4 3/5] libqblock API
  2012-09-27  2:23 [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library Wenchao Xia
  2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 1/5] libqblock build system Wenchao Xia
  2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 2/5] libqblock type defines Wenchao Xia
@ 2012-09-27  2:24 ` Wenchao Xia
  2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 4/5] libqblock test build system Wenchao Xia
  2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 5/5] libqblock test example Wenchao Xia
  4 siblings, 0 replies; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  2:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, aliguori, stefanha, blauwirbel, pbonzini, eblake,
	Wenchao Xia

  This patch contains the major APIs in the library. For ABI some reserved
members were used.
Important APIs:
  1 QBlockContext. This structure was used to retrieve errors, every thread
must create one first.
  2 QBlockState. It stands for an block image object.
  3 QBlockStaticInfo. It contains static information such as location, backing
file, size.
  4 Sync I/O. It is similar to C file open, read, write and close operations.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 block.c                     |    2 +-
 block.h                     |    1 +
 libqblock/libqblock-error.c |   57 +++
 libqblock/libqblock-error.h |   49 ++
 libqblock/libqblock.c       | 1165 +++++++++++++++++++++++++++++++++++++++++++
 libqblock/libqblock.h       |  308 ++++++++++++
 6 files changed, 1581 insertions(+), 1 deletions(-)
 create mode 100644 libqblock/libqblock-error.h
 create mode 100644 libqblock/libqblock.h

diff --git a/block.c b/block.c
index 751ebdc..24ae396 100644
--- a/block.c
+++ b/block.c
@@ -196,7 +196,7 @@ static void bdrv_io_limits_intercept(BlockDriverState *bs,
 }
 
 /* check if the path starts with "<protocol>:" */
-static int path_has_protocol(const char *path)
+int path_has_protocol(const char *path)
 {
     const char *p;
 
diff --git a/block.h b/block.h
index b1095d8..de6818f 100644
--- a/block.h
+++ b/block.h
@@ -423,4 +423,5 @@ typedef enum {
 #define BLKDBG_EVENT(bs, evt) bdrv_debug_event(bs, evt)
 void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
 
+int path_has_protocol(const char *path);
 #endif
diff --git a/libqblock/libqblock-error.c b/libqblock/libqblock-error.c
index e69de29..2a59970 100644
--- a/libqblock/libqblock-error.c
+++ b/libqblock/libqblock-error.c
@@ -0,0 +1,57 @@
+/*
+ * QEMU block layer library
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
+ *
+ * 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 "libqblock-error.h"
+#include "libqblock-internal.h"
+
+void qb_error_get_human_str(QBlockContext *context,
+                            char *buf, size_t buf_size)
+{
+    const char *err_ret_str;
+    switch (context->err_ret) {
+    case QB_ERR_INTERNAL_ERR:
+        err_ret_str = "Internal error.";
+        break;
+    case QB_ERR_INVALID_PARAM:
+        err_ret_str = "Invalid param.";
+        break;
+    case QB_ERR_BLOCK_OUT_OF_RANGE:
+        err_ret_str = "request is out of image's range.";
+        break;
+    default:
+        err_ret_str = "Unknown error.";
+        break;
+    }
+    if (context == NULL) {
+        snprintf(buf, buf_size, "%s", err_ret_str);
+        return;
+    }
+
+    if (context->err_ret == QB_ERR_INTERNAL_ERR) {
+        snprintf(buf, buf_size, "%s %s errno [%d]. strerror [%s].",
+                     err_ret_str, context->g_error->message,
+                     context->err_no, strerror(-context->err_no));
+    } else {
+        snprintf(buf, buf_size, "%s %s",
+                     err_ret_str, context->g_error->message);
+    }
+    return;
+}
+
+int qb_error_get_errno(QBlockContext *context)
+{
+    if (context->err_ret == QB_ERR_INTERNAL_ERR) {
+        return context->err_no;
+    }
+    return 0;
+}
diff --git a/libqblock/libqblock-error.h b/libqblock/libqblock-error.h
new file mode 100644
index 0000000..4ffd1f1
--- /dev/null
+++ b/libqblock/libqblock-error.h
@@ -0,0 +1,49 @@
+/*
+ * QEMU block layer library
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef LIBQBLOCK_ERROR
+#define LIBQBLOCK_ERROR
+
+#include "libqblock-types.h"
+
+#define QB_ERR_INTERNAL_ERR (-1)
+#define QB_ERR_INVALID_PARAM (-100)
+#define QB_ERR_BLOCK_OUT_OF_RANGE (-101)
+
+/* error handling */
+/**
+ * qb_error_get_human_str: get human readable error string.
+ *
+ * return a human readable string, it would be truncated if buf is not big
+ *  enough.
+ *
+ * @context: operation context, must be valid.
+ * @buf: buf to receive the string.
+ * @buf_size: the size of the string buf.
+ */
+DLL_PUBLIC
+void qb_error_get_human_str(QBlockContext *context,
+                            char *buf, size_t buf_size);
+
+/**
+ * qb_error_get_errno: get error number, only valid when err_ret is
+ *   QB_ERR_INTERNAL_ERR.
+ *
+ * return negative errno if last error is QB_ERR_INTERNAL_ERR, otherwise 0.
+ *
+ * @context: operation context.
+ */
+DLL_PUBLIC
+int qb_error_get_errno(QBlockContext *context);
+
+#endif
diff --git a/libqblock/libqblock.c b/libqblock/libqblock.c
index e69de29..ebb1dff 100644
--- a/libqblock/libqblock.c
+++ b/libqblock/libqblock.c
@@ -0,0 +1,1165 @@
+/*
+ * QEMU block layer library
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
+ *
+ * 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 <unistd.h>
+#include <stdarg.h>
+
+#include "libqblock.h"
+#include "libqblock-internal.h"
+
+#include "qemu-aio.h"
+
+#define LIBQB_FILENAME_MAX 4096
+
+typedef struct LibqblockGlobalData {
+    int init_flag;
+} LibqblockGlobalData;
+
+LibqblockGlobalData libqb_global_data;
+
+typedef struct LibqbFmtStrMapping {
+    const char *fmt_str;
+    QBlockFmtType fmt_type;
+} LibqbFmtStrMapping;
+
+LibqbFmtStrMapping libqb_fmtstr_table[] = {
+    {"cow", QB_FMT_COW},
+    {"qed", QB_FMT_QED},
+    {"qcow", QB_FMT_QCOW},
+    {"qcow2", QB_FMT_QCOW2},
+    {"raw", QB_FMT_RAW},
+    {"rbd", QB_FMT_RBD},
+    {"sheepdog", QB_FMT_SHEEPDOG},
+    {"vdi", QB_FMT_VDI},
+    {"vmdk", QB_FMT_VMDK},
+    {"vpc", QB_FMT_VPC},
+    {NULL, 0},
+};
+
+__attribute__((constructor))
+static void libqblock_init(void)
+{
+    if (libqb_global_data.init_flag == 0) {
+        bdrv_init();
+        qemu_init_main_loop();
+    }
+    libqb_global_data.init_flag = 1;
+    g_assert(sizeof(QBlockFmtOptionsUnion) == QBLOCK_FMT_OPTIONS_UNION_SIZE);
+    g_assert(sizeof(QBlockProtOptionsUnion) == QBLOCK_PROT_OPTIONS_UNION_SIZE);
+}
+
+const char *qb_fmttype2str(QBlockFmtType fmt_type)
+{
+    int i = 0;
+    LibqbFmtStrMapping *tb = libqb_fmtstr_table;
+
+    while (tb[i].fmt_str != NULL) {
+        if (tb[i].fmt_type == fmt_type) {
+            return tb[i].fmt_str;
+        }
+        i++;
+    }
+    return NULL;
+}
+
+QBlockFmtType qb_str2fmttype(const char *fmt_str)
+{
+    int i = 0;
+    LibqbFmtStrMapping *tb = libqb_fmtstr_table;
+
+    while (tb[i].fmt_str != NULL) {
+        if ((strcmp(fmt_str, tb[i].fmt_str) == 0)) {
+            return tb[i].fmt_type;
+        }
+        i++;
+    }
+    return QB_FMT_NONE;
+}
+
+static void set_context_err(QBlockContext *context, int err_ret,
+                           const char *fmt, ...)
+{
+    va_list ap;
+
+    if (context->g_error != NULL) {
+        g_error_free(context->g_error);
+    }
+
+    va_start(ap, fmt);
+    context->g_error = g_error_new_valist(G_LIBQBLOCK_ERROR, err_ret, fmt, ap);
+    va_end(ap);
+
+    context->err_ret = err_ret;
+    if (err_ret == QB_ERR_INTERNAL_ERR) {
+        context->err_no = -errno;
+    } else {
+        context->err_no = 0;
+    }
+}
+
+int qb_context_new(QBlockContext **context)
+{
+    *context = FUNC_CALLOC(1, sizeof(QBlockContext));
+    return 0;
+}
+
+void qb_context_delete(QBlockContext **context)
+{
+    if ((*context)->g_error != NULL) {
+        g_error_free((*context)->g_error);
+    }
+    CLEAN_FREE(*context);
+    return;
+}
+
+int qb_state_new(QBlockContext *context,
+                 QBlockState **qbs)
+{
+    *qbs = FUNC_CALLOC(1, sizeof(QBlockState));
+    (*qbs)->bdrvs = bdrv_new("hda");
+    if ((*qbs)->bdrvs == NULL) {
+        CLEAN_FREE(*qbs);
+        set_context_err(context, QB_ERR_INTERNAL_ERR,
+                       "failed to create the driver.");
+        return context->err_ret;
+    }
+    return 0;
+}
+
+void qb_state_delete(QBlockContext *context,
+                     QBlockState **qbs)
+{
+    if ((*qbs)->filename != NULL) {
+        qb_close(context, *qbs);
+    }
+    if ((*qbs)->bdrvs != NULL) {
+        bdrv_delete((*qbs)->bdrvs);
+        (*qbs)->bdrvs = NULL;
+    }
+    CLEAN_FREE(*qbs);
+    return;
+}
+
+int qb_prot_info_new(QBlockContext *context,
+                     QBlockProtInfo **op)
+{
+    *op = FUNC_CALLOC(1, sizeof(QBlockProtInfo));
+    return 0;
+}
+
+void qb_prot_info_delete(QBlockContext *context,
+                         QBlockProtInfo **op)
+{
+    CLEAN_FREE(*op);
+}
+
+int qb_fmt_info_new(QBlockContext *context,
+                    QBlockFmtInfo **op)
+{
+    *op = FUNC_CALLOC(1, sizeof(QBlockFmtInfo));
+    return 0;
+}
+
+void qb_fmt_info_delete(QBlockContext *context,
+                        QBlockFmtInfo **op)
+{
+    CLEAN_FREE(*op);
+}
+
+/* return 0 if every thing is fine */
+static int loc_check_params(QBlockContext *context,
+                            QBlockProtInfo *loc)
+{
+    context->err_ret = 0;
+
+    switch (loc->prot_type) {
+    case QB_PROT_FILE:
+        if (loc->prot_op.o_file.filename == NULL) {
+            set_context_err(context, QB_ERR_INVALID_PARAM,
+                           "Filename was not set.");
+            goto out;
+        }
+        if (path_has_protocol(loc->prot_op.o_file.filename) > 0) {
+            set_context_err(context, QB_ERR_INVALID_PARAM,
+                           "filename [%s] had protocol.",
+                           loc->prot_op.o_file.filename);
+            goto out;
+        }
+        break;
+    default:
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                       "Protocol type [%d] was not valid.",
+                       loc->prot_type);
+        break;
+    }
+
+ out:
+    return context->err_ret;
+}
+
+/* translate loc structure to internal filename, returned char* need free,
+ * assuming filename is not NULL. *filename would be set to NULL if no valid
+ * filename found. *filename must be freed later.
+ * return 0 if no error with *filename set.
+ */
+static int loc2filename(QBlockContext *context,
+                        QBlockProtInfo *loc,
+                        char **filename)
+{
+    context->err_ret = 0;
+
+    if (*filename != NULL) {
+        CLEAN_FREE(*filename);
+    }
+    switch (loc->prot_type) {
+    case QB_PROT_FILE:
+        *filename = FUNC_STRDUP(loc->prot_op.o_file.filename);
+        break;
+    default:
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                 "protocol type [%d] is not supported.",
+                  loc->prot_type);
+        break;
+    }
+
+    return context->err_ret;
+}
+
+/* translate filename to location, loc->prot_type = NONE if fail, filename
+   must be valid. loc internal char pointer must be freed later.
+ * return 0 if no error.
+ */
+static int filename2loc(QBlockContext *context,
+                        QBlockProtInfo *loc,
+                        const char *filename)
+{
+    context->err_ret = 0;
+
+    if (path_has_protocol(filename) > 0) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                     "Filename [%s] had protocol, not supported now.",
+                     filename);
+        goto out;
+    }
+
+    loc->prot_type = QB_PROT_FILE;
+    switch (loc->prot_type) {
+    case QB_PROT_FILE:
+        loc->prot_op.o_file.filename = FUNC_STRDUP(filename);
+        break;
+    default:
+        break;
+    }
+
+ out:
+    return context->err_ret;
+}
+
+/* return 0 if OK, or qblock error number */
+static int set_backing_file_options(QBlockContext *context,
+                                    QEMUOptionParameter *param,
+                                    QBlockProtInfo *loc,
+                                    QBlockFmtType *fmt)
+{
+    char *backing_filename = NULL;
+    const char *fmtstr_backing = NULL;
+    int ret = 0;
+
+    if (loc == NULL) {
+        goto out;
+    }
+
+    ret = loc2filename(context, loc, &backing_filename);
+    /* ret can < 0 if loc have not been set, mean user did not specify backing
+       file, so need to check return value */
+
+    ret = 0;
+
+    if (backing_filename) {
+        ret = set_option_parameter(param,
+                            BLOCK_OPT_BACKING_FILE, backing_filename);
+        assert(ret == 0);
+        if (fmt == NULL) {
+            goto out;
+        }
+        fmtstr_backing = qb_fmttype2str(*fmt);
+        if (fmtstr_backing) {
+            ret = set_option_parameter(param,
+                                BLOCK_OPT_BACKING_FMT, fmtstr_backing);
+            assert(ret == 0);
+        }
+    }
+
+ out:
+    FUNC_FREE(backing_filename);
+    return ret;
+}
+
+int qb_create(QBlockContext *context,
+              QBlockState *qbs,
+              QBlockProtInfo *loc,
+              QBlockFmtInfo *fmt,
+              int flag)
+{
+    int ret = 0, bd_ret;
+    char *filename = NULL;
+    BlockDriverState *bs = NULL;
+    BlockDriver *drv = NULL, *backing_drv = NULL;
+    bool tmp_bool;
+
+    const char *fmtstr = NULL, *tmp = NULL;
+    QEMUOptionParameter *param = NULL, *create_options = NULL;
+    QEMUOptionParameter *backing_fmt, *backing_file, *size;
+    QBlockFmtOptionCow *o_cow = NULL;
+    QBlockFmtOptionQed *o_qed = NULL;
+    QBlockFmtOptionQcow *o_qcow = NULL;
+    QBlockFmtOptionQcow2 *o_qcow2 = NULL;
+    QBlockFmtOptionRaw *o_raw = NULL;
+    QBlockFmtOptionRbd *o_rbd = NULL;
+    QBlockFmtOptionSheepdog *o_sd = NULL;
+    QBlockFmtOptionVdi *o_vdi = NULL;
+    QBlockFmtOptionVmdk *o_vmdk = NULL;
+    QBlockFmtOptionVpc *o_vpc = NULL;
+
+
+    /* check parameters */
+    if (flag & (~LIBQBLOCK_O_VALID_MASK)) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                           "invalid flag was set.");
+        ret = context->err_ret;
+        goto out;
+    }
+
+    if ((loc == NULL) || (qbs == NULL) || (fmt == NULL)) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                          "Got unexpected NULL pointer in parameters.");
+        ret = context->err_ret;
+        goto out;
+    }
+
+    ret = loc_check_params(context, loc);
+    if (ret != 0) {
+        goto out;
+    }
+
+    /* internal translate */
+    ret = loc2filename(context, loc, &filename);
+    if (ret != 0) {
+        goto out;
+    }
+
+    fmtstr = qb_fmttype2str(fmt->fmt_type);
+    if (fmtstr == NULL) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                 "Got unexpected NULL pointer in parameters.");
+        ret = context->err_ret;
+        goto out;
+    }
+
+    drv = bdrv_find_format(fmtstr);
+    assert(drv != NULL);
+
+    create_options = append_option_parameters(create_options,
+                                              drv->create_options);
+    param = parse_option_parameters("", create_options, param);
+
+    switch (fmt->fmt_type) {
+    case QB_FMT_COW:
+        o_cow = &(fmt->fmt_op.o_cow);
+        bd_ret = set_option_parameter_int(param,
+                                BLOCK_OPT_SIZE, o_cow->virt_size);
+        assert(bd_ret == 0);
+        /* do not need to check loc, it may be not set */
+        ret = set_backing_file_options(context, param,
+                                       &o_cow->backing_loc, NULL);
+        if (ret != 0) {
+            goto out;
+        }
+        break;
+    case QB_FMT_QED:
+        o_qed = &(fmt->fmt_op.o_qed);
+        bd_ret = set_option_parameter_int(param,
+                                BLOCK_OPT_SIZE, o_qed->virt_size);
+        assert(bd_ret == 0);
+        ret = set_backing_file_options(context, param,
+                                 &o_qed->backing_loc, &o_qed->backing_fmt);
+        if (ret != 0) {
+            goto out;
+        }
+        bd_ret = set_option_parameter_int(param,
+                                BLOCK_OPT_CLUSTER_SIZE, o_qed->cluster_size);
+        assert(bd_ret == 0);
+        bd_ret = set_option_parameter_int(param,
+                                BLOCK_OPT_TABLE_SIZE, o_qed->table_size);
+        assert(bd_ret == 0);
+        break;
+    case QB_FMT_QCOW:
+        o_qcow = &(fmt->fmt_op.o_qcow);
+        bd_ret = set_option_parameter_int(param,
+                                BLOCK_OPT_SIZE, o_qcow->virt_size);
+        assert(bd_ret == 0);
+        ret = set_backing_file_options(context, param,
+                                       &o_qcow->backing_loc, NULL);
+        if (ret != 0) {
+            goto out;
+        }
+        tmp = o_qcow->encrypt ? "on" : "off";
+        bd_ret = set_option_parameter(param, BLOCK_OPT_ENCRYPT, tmp);
+        assert(bd_ret == 0);
+        break;
+    case QB_FMT_QCOW2:
+        o_qcow2 = &(fmt->fmt_op.o_qcow2);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_SIZE, o_qcow2->virt_size);
+        assert(bd_ret == 0);
+        ret = set_backing_file_options(context, param,
+                              &o_qcow2->backing_loc, &o_qcow2->backing_fmt);
+        if (ret != 0) {
+            goto out;
+        }
+        tmp = o_qcow2->encrypt ? "on" : "off";
+        bd_ret = set_option_parameter(param, BLOCK_OPT_ENCRYPT, tmp);
+        assert(bd_ret == 0);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_CLUSTER_SIZE, o_qcow2->cluster_size);
+        assert(bd_ret == 0);
+
+        if (o_qcow2->cpt_lv != QBO_FMT_QCOW2_CPT_NONE) {
+            tmp = o_qcow2->cpt_lv == QBO_FMT_QCOW2_CPT_V010 ? "0.10" : "1.1";
+            bd_ret = set_option_parameter(param,
+                              BLOCK_OPT_COMPAT_LEVEL, tmp);
+            assert(bd_ret == 0);
+        }
+
+        if (o_qcow2->pre_mode != QBO_FMT_QCOW2_PREALLOC_NONE) {
+            tmp = o_qcow2->pre_mode == QBO_FMT_QCOW2_PREALLOC_OFF ?
+                                         "off" : "metadata";
+            bd_ret = set_option_parameter(param,
+                              BLOCK_OPT_PREALLOC, tmp);
+            assert(bd_ret == 0);
+        }
+        break;
+
+    case QB_FMT_RAW:
+        o_raw = &(fmt->fmt_op.o_raw);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_SIZE, o_raw->virt_size);
+        assert(bd_ret == 0);
+        break;
+    case QB_FMT_RBD:
+        o_rbd = &(fmt->fmt_op.o_rbd);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_SIZE, o_rbd->virt_size);
+        assert(bd_ret == 0);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_CLUSTER_SIZE, o_rbd->cluster_size);
+        assert(bd_ret == 0);
+        break;
+    case QB_FMT_SHEEPDOG:
+        o_sd = &(fmt->fmt_op.o_sheepdog);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_SIZE, o_sd->virt_size);
+        assert(bd_ret == 0);
+        ret = set_backing_file_options(context, param,
+                                       &o_sd->backing_loc, NULL);
+        if (ret != 0) {
+            goto out;
+        }
+        if (o_sd->pre_mode != QBO_FMT_SD_PREALLOC_NONE) {
+            tmp = o_sd->pre_mode == QBO_FMT_SD_PREALLOC_OFF ? "off" : "full";
+            bd_ret = set_option_parameter(param,
+                              BLOCK_OPT_PREALLOC, tmp);
+            assert(bd_ret == 0);
+        }
+        break;
+    case QB_FMT_VDI:
+        o_vdi = &(fmt->fmt_op.o_vdi);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_SIZE, o_vdi->virt_size);
+        assert(bd_ret == 0);
+        /* following option is not always valid depends on configuration */
+        set_option_parameter_int(param,
+                              BLOCK_OPT_CLUSTER_SIZE, o_vdi->cluster_size);
+        if (o_vdi->pre_mode != QBO_FMT_VDI_PREALLOC_NONE) {
+            tmp_bool = o_sd->pre_mode == QBO_FMT_VDI_PREALLOC_TRUE ?
+                                                     true : false;
+            set_option_parameter_int(param, "static", tmp_bool);
+        }
+        break;
+    case QB_FMT_VMDK:
+        o_vmdk = &(fmt->fmt_op.o_vmdk);
+        bd_ret = set_option_parameter_int(param,
+                              BLOCK_OPT_SIZE, o_vmdk->virt_size);
+        assert(bd_ret == 0);
+        ret = set_backing_file_options(context, param,
+                                       &o_vmdk->backing_loc, NULL);
+        if (ret != 0) {
+            goto out;
+        }
+
+        if (o_vmdk->cpt_lv != QBO_FMT_VMDK_CPT_NONE) {
+            tmp_bool = o_vmdk->cpt_lv == QBO_FMT_VMDK_CPT_VMDKV6_TRUE ?
+                                                     true : false;
+            bd_ret = set_option_parameter_int(param, BLOCK_OPT_COMPAT6,
+                                                     tmp_bool);
+            assert(bd_ret == 0);
+        }
+        if (o_vmdk->subfmt != QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE) {
+            switch (o_vmdk->subfmt) {
+            case QBO_FMT_VMDK_SUBFMT_MONOLITHIC_SPARSE:
+                tmp = "monolithicSparse";
+                break;
+            case QBO_FMT_VMDK_SUBFMT_MONOLITHIC_FLAT:
+                tmp = "monolithicFlat";
+                break;
+            case QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_SPARSE:
+                tmp = "twoGbMaxExtentSparse";
+                break;
+            case QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_FLAT:
+                tmp = "twoGbMaxExtentFlat";
+                break;
+            case QBO_FMT_VMDK_SUBFMT_STREAM_OPTIMIZED:
+                tmp = "streamOptimized";
+                break;
+            default:
+                assert(false);
+                break;
+            }
+            bd_ret = set_option_parameter(param,
+                              BLOCK_OPT_SUBFMT, tmp);
+            assert(bd_ret == 0);
+        }
+        break;
+    case QB_FMT_VPC:
+        o_vpc = &(fmt->fmt_op.o_vpc);
+        bd_ret = set_option_parameter_int(param,
+                               BLOCK_OPT_SIZE, o_vpc->virt_size);
+        assert(bd_ret == 0);
+        if (o_vpc->subfmt != QBO_FMT_VPC_SUBFMT_NONE) {
+            tmp = o_vpc->subfmt == QBO_FMT_VPC_SUBFMT_DYNAMIC ?
+                                               "dynamic" : "fixed";
+            bd_ret = set_option_parameter(param,
+                               BLOCK_OPT_SUBFMT, tmp);
+            assert(bd_ret == 0);
+        }
+        break;
+    default:
+        abort();
+        break;
+    }
+
+    backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
+    if (backing_file && backing_file->value.s) {
+        if (!strcmp(filename, backing_file->value.s)) {
+            set_context_err(context, QB_ERR_INVALID_PARAM,
+                          "Backing file is the same with new file.");
+            ret = context->err_ret;
+            goto out;
+        }
+    }
+
+    backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
+    if (backing_fmt && backing_fmt->value.s) {
+        backing_drv = bdrv_find_format(backing_fmt->value.s);
+        assert(backing_drv != NULL);
+    }
+
+    size = get_option_parameter(param, BLOCK_OPT_SIZE);
+    if (size && size->value.n <= 0) {
+        if (backing_file && backing_file->value.s) {
+            uint64_t size;
+            char buf[32];
+            int back_flags;
+
+            /* backing files always opened read-only */
+            back_flags =
+                flag &
+                ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+
+            bs = bdrv_new("");
+
+            ret = bdrv_open(bs, backing_file->value.s,
+                                back_flags, backing_drv);
+            if (ret < 0) {
+                set_context_err(context, QB_ERR_INVALID_PARAM,
+                               "Failed to open the backing file.");
+                ret = context->err_ret;
+                goto out;
+            }
+            bdrv_get_geometry(bs, &size);
+            size *= BDRV_SECTOR_SIZE;
+
+            snprintf(buf, sizeof(buf), "%" PRId64, size);
+            set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+        } else {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "Neither size or backing file was not set.");
+            ret = context->err_ret;
+            goto out;
+        }
+    }
+
+    bd_ret = bdrv_create(drv, filename, param);
+
+
+    if (bd_ret < 0) {
+        const char *errstr;
+        if (bd_ret == -ENOTSUP) {
+            errstr = "formatting option not supported.";
+        } else if (bd_ret == -EFBIG) {
+            errstr = "The image size is too large.";
+        } else {
+            errstr = "Error in creating the image.";
+        }
+        set_context_err(context, QB_ERR_INTERNAL_ERR, errstr);
+        ret = context->err_ret;
+    }
+
+out:
+    free_option_parameters(create_options);
+    free_option_parameters(param);
+    FUNC_FREE(filename);
+    if (bs) {
+        bdrv_delete(bs);
+    }
+
+    return ret;
+}
+
+int qb_open(QBlockContext *context,
+            QBlockState *qbs,
+            QBlockProtInfo *loc,
+            QBlockFmtInfo *fmt,
+            int flag)
+{
+    int ret = 0, bd_ret;
+    BlockDriverState *bs;
+    BlockDriver *bd;
+    const char *fmtstr;
+    char *filename = NULL;
+
+    /* take care of user settings */
+    /* do nothing now */
+
+    /* check parameters */
+    if (flag & (~LIBQBLOCK_O_VALID_MASK)) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                      "Invalid flag was set.");
+        ret = context->err_ret;
+        goto out;
+    }
+
+    if ((loc == NULL) || (qbs == NULL)) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                      "Got unexpected NULL pointer in parameters.");
+        ret = context->err_ret;
+        goto out;
+    }
+
+    ret = loc_check_params(context, loc);
+    if (ret != 0) {
+        goto out;
+    }
+
+    /* internal translate */
+    ret = loc2filename(context, loc, &filename);
+    if (ret != 0) {
+        goto out;
+    }
+
+    fmtstr = NULL;
+    bd = NULL;
+    if (fmt != NULL) {
+        fmtstr = qb_fmttype2str(fmt->fmt_type);
+    }
+
+    if (fmtstr != NULL) {
+        bd = bdrv_find_format(fmtstr);
+        assert(bd != NULL);
+    }
+
+    /* do real opening */
+    bs = qbs->bdrvs;
+    bd_ret = bdrv_open(bs, filename, flag, bd);
+    if (bd_ret < 0) {
+        set_context_err(context, QB_ERR_INTERNAL_ERR,
+                      "Failed in opening with driver, bd_ret is %d.", bd_ret);
+        ret = context->err_ret;
+        goto out;
+    }
+
+    if (qbs->filename != NULL) {
+        FUNC_FREE(qbs->filename);
+    }
+    qbs->filename = FUNC_STRDUP(filename);
+
+ out:
+    FUNC_FREE(filename);
+    return ret;
+}
+
+void qb_close(QBlockContext *context,
+              QBlockState *qbs)
+{
+    BlockDriverState *bs;
+
+    bs = qbs->bdrvs;
+
+    if (qbs->filename != NULL) {
+        CLEAN_FREE(qbs->filename);
+        bdrv_close(bs);
+    }
+    return;
+}
+
+int32_t qb_read(QBlockContext *context,
+                QBlockState *qbs,
+                uint8_t *buf,
+                uint32_t len,
+                uint64_t offset)
+{
+    int bd_ret;
+    BlockDriverState *bs;
+    uint8_t temp_buf[BDRV_SECTOR_SIZE], *p;
+    uint64_t sector_start;
+    int sector_num, byte_offset, cp_len;
+    uint32_t remains;
+
+    context->err_ret = 0;
+    bs = qbs->bdrvs;
+
+    if (len <= 0) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                      "Param len is less or equal to zero.");
+        return context->err_ret;
+    }
+
+    p = buf;
+    remains = len;
+
+    sector_start = offset >> BDRV_SECTOR_BITS;
+
+    byte_offset = offset & (~BDRV_SECTOR_MASK);
+    if (byte_offset != 0) {
+        /* the start sector is not alligned, need to read/write this sector. */
+        bd_ret = bdrv_read(bs, sector_start, temp_buf, 1);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        cp_len = BDRV_SECTOR_SIZE - byte_offset;
+        memcpy(p, temp_buf + byte_offset, cp_len);
+
+        remains -= cp_len;
+        p += cp_len;
+        sector_start++;
+    }
+
+    /* now start position is alligned. */
+    if (remains >= BDRV_SECTOR_SIZE) {
+        sector_num = remains >> BDRV_SECTOR_BITS;
+        bd_ret = bdrv_read(bs, sector_start, p, sector_num);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        remains -= sector_num << BDRV_SECTOR_BITS;
+        p += sector_num << BDRV_SECTOR_BITS;
+        sector_start += sector_num;
+    }
+
+    if (remains > 0) {
+        /* there is some request remains, less than 1 sector */
+        bd_ret = bdrv_read(bs, sector_start, temp_buf, 1);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        memcpy(p, temp_buf, remains);
+        remains -= remains;
+    }
+
+    return len-remains;
+}
+
+int32_t qb_write(QBlockContext *context,
+                 QBlockState *qbs,
+                 const uint8_t *buf,
+                 uint32_t len,
+                 uint64_t offset)
+{
+    int bd_ret;
+    BlockDriverState *bs;
+    uint8_t temp_buf[BDRV_SECTOR_SIZE];
+    const uint8_t *p;
+    uint64_t sector_start;
+    int sector_num, byte_offset, cp_len;
+    uint32_t remains;
+
+    context->err_ret = 0;
+    bs = qbs->bdrvs;
+
+    if (len <= 0) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                      "Param len is less or equal to zero.");
+        return context->err_ret;
+    }
+
+    p = buf;
+    remains = len;
+
+    sector_start = offset >> BDRV_SECTOR_BITS;
+
+    byte_offset = offset & (~BDRV_SECTOR_MASK);
+    if (byte_offset != 0) {
+        /* the start sector is not alligned, need to read/write this sector. */
+        bd_ret = bdrv_read(bs, sector_start, temp_buf, 1);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        cp_len = BDRV_SECTOR_SIZE - byte_offset;
+        memcpy(temp_buf + byte_offset, p, cp_len);
+        bd_ret = bdrv_write(bs, sector_start, temp_buf, 1);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        remains -= cp_len;
+        p += cp_len;
+        sector_start++;
+    }
+
+    /* now start position is alligned. */
+    if (remains >= BDRV_SECTOR_SIZE) {
+        sector_num = remains >> BDRV_SECTOR_BITS;
+        bd_ret = bdrv_write(bs, sector_start, p, sector_num);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        remains -= sector_num << BDRV_SECTOR_BITS;
+        p += sector_num << BDRV_SECTOR_BITS;
+        sector_start += sector_num;
+    }
+
+    if (remains > 0) {
+        /* there is some request remains, less than 1 sector */
+        bd_ret = bdrv_read(bs, sector_start, temp_buf, 1);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        memcpy(temp_buf, p, remains);
+        bd_ret = bdrv_write(bs, sector_start, temp_buf, 1);
+        if (bd_ret < 0) {
+            set_context_err(context, QB_ERR_INTERNAL_ERR,
+                           "QEMU internal block error.");
+            context->err_no = bd_ret;
+            return context->err_ret;
+        }
+        remains -= remains;
+    }
+
+    return len-remains;
+}
+
+int qb_flush(QBlockContext *context,
+             QBlockState *qbs)
+{
+    int bd_ret;
+    BlockDriverState *bs;
+
+    context->err_ret = 0;
+    bs = qbs->bdrvs;
+    bd_ret = bdrv_flush(bs);
+    if (bd_ret < 0) {
+        set_context_err(context, QB_ERR_INTERNAL_ERR,
+                       "Internal error.");
+    }
+    return context->err_ret;
+}
+
+int qb_check_allocation(QBlockContext *context,
+                        QBlockState *qbs,
+                        uint64_t start,
+                        int64_t length,
+                        int *pstatus,
+                        int64_t *plength)
+{
+    int ret;
+    int sector_start, sector_num, num;
+    BlockDriverState *bs;
+    unsigned int real_len, ret_len;
+
+    context->err_ret = 0;
+    bs = qbs->bdrvs;
+
+    if (length > 0x1000000000000) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                       "length is too big.");
+        goto out;
+    }
+
+    if (qbs->filename == NULL) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                       "Image was not opened first.");
+        goto out;
+    }
+
+    if (length <= 0) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                       "length is not valid.");
+        goto out;
+    }
+
+    /* translate to sector */
+    sector_start = start >> BDRV_SECTOR_BITS;
+    real_len = (start & (~BDRV_SECTOR_MASK)) + length;
+    sector_num = real_len >> BDRV_SECTOR_BITS;
+    if ((real_len & (~BDRV_SECTOR_MASK)) != 0) {
+        sector_num++;
+    }
+
+    ret = bdrv_is_allocated(bs, sector_start, sector_num, &num);
+    if ((ret == 0) && (num == 0)) {
+        set_context_err(context, QB_ERR_BLOCK_OUT_OF_RANGE,
+                       "Start position was bigger than the image's size.");
+        goto out;
+    }
+
+    *pstatus = ret;
+    ret_len = (num << BDRV_SECTOR_BITS) - (start & (~BDRV_SECTOR_MASK));
+    if (ret_len > length) {
+        ret_len = length;
+    }
+    *plength = ret_len;
+
+ out:
+    return context->err_ret;
+}
+
+static void qb_setup_info_addr(QBlockStaticInfo *info,
+                               QBlockStaticInfoAddr *info_addr)
+{
+    uint64_t *virt_size = NULL;
+    QBlockProtInfo *backing_loc = NULL;
+    bool *encrypt = NULL;
+    QBlockFmtInfo *fmt = &(info->fmt);
+
+    switch (fmt->fmt_type) {
+    case QB_FMT_COW:
+        virt_size = &(fmt->fmt_op.o_cow.virt_size);
+        backing_loc = &(fmt->fmt_op.o_cow.backing_loc);
+        break;
+    case QB_FMT_QED:
+        virt_size = &(fmt->fmt_op.o_qed.virt_size);
+        backing_loc = &(fmt->fmt_op.o_qed.backing_loc);
+        break;
+    case QB_FMT_QCOW:
+        virt_size = &(fmt->fmt_op.o_qcow.virt_size);
+        backing_loc = &(fmt->fmt_op.o_qcow.backing_loc);
+        encrypt = &(fmt->fmt_op.o_qcow.encrypt);
+        break;
+    case QB_FMT_QCOW2:
+        virt_size = &(fmt->fmt_op.o_qcow2.virt_size);
+        backing_loc = &(fmt->fmt_op.o_qcow2.backing_loc);
+        encrypt = &(fmt->fmt_op.o_qcow2.encrypt);
+        break;
+    case QB_FMT_RAW:
+        virt_size = &(fmt->fmt_op.o_raw.virt_size);
+        break;
+    case QB_FMT_RBD:
+        virt_size = &(fmt->fmt_op.o_rbd.virt_size);
+        break;
+    case QB_FMT_SHEEPDOG:
+        virt_size = &(fmt->fmt_op.o_sheepdog.virt_size);
+        backing_loc = &(fmt->fmt_op.o_sheepdog.backing_loc);
+        break;
+    case QB_FMT_VDI:
+        virt_size = &(fmt->fmt_op.o_vdi.virt_size);
+        break;
+    case QB_FMT_VMDK:
+        virt_size = &(fmt->fmt_op.o_vmdk.virt_size);
+        backing_loc = &(fmt->fmt_op.o_vmdk.backing_loc);
+        break;
+    case QB_FMT_VPC:
+        virt_size = &(fmt->fmt_op.o_vpc.virt_size);
+        break;
+    default:
+        break;
+    }
+
+    info_addr->virt_size = virt_size;
+    info_addr->backing_loc = backing_loc;
+    info_addr->encrypt = encrypt;
+    return;
+}
+
+int qb_info_image_static_get(QBlockContext *context,
+                             QBlockState *qbs,
+                             QBlockStaticInfo **info)
+{
+    int ret = 0;
+    BlockDriverState *bs;
+    QBlockStaticInfo *info_tmp;
+    QBlockStaticInfoAddr *member_addr;
+    const char *fmt_str;
+    uint64_t total_sectors;
+    char backing_filename[LIBQB_FILENAME_MAX];
+
+    if (qbs->filename == NULL) {
+        set_context_err(context, QB_ERR_INVALID_PARAM,
+                       "Block Image was not openned.");
+        ret = context->err_ret;
+        goto out;
+    }
+
+    info_tmp = FUNC_CALLOC(1, sizeof(QBlockStaticInfo));
+
+    bs = qbs->bdrvs;
+
+    ret = filename2loc(context,
+                       &(info_tmp->loc),
+                       qbs->filename);
+    if (ret < 0) {
+        goto free;
+    }
+
+    fmt_str = bdrv_get_format_name(bs);
+    info_tmp->fmt.fmt_type = qb_str2fmttype(fmt_str);
+    /* we got the format type and basic location info now, setup the struct
+    pointer to the internal members */
+    member_addr = FUNC_CALLOC(1, sizeof(QBlockStaticInfoAddr));
+    qb_setup_info_addr(info_tmp, member_addr);
+    info_tmp->member_addr = member_addr;
+
+    assert(member_addr->virt_size != NULL);
+    bdrv_get_geometry(bs, &total_sectors);
+    *(member_addr->virt_size) = total_sectors * BDRV_SECTOR_SIZE;
+
+    if (member_addr->encrypt != NULL) {
+        *(member_addr->encrypt) = bdrv_is_encrypted(bs);
+    }
+
+    bdrv_get_full_backing_filename(bs, backing_filename,
+                                   sizeof(backing_filename));
+    if (backing_filename[0] != '\0') {
+        assert(member_addr->backing_loc != NULL);
+        ret = filename2loc(context,
+                           member_addr->backing_loc,
+                           backing_filename);
+        if (ret < 0) {
+            goto free;
+        }
+    }
+
+    info_tmp->sector_size = BDRV_SECTOR_SIZE;
+    *info = info_tmp;
+
+ out:
+    return ret;
+ free:
+    qb_info_image_static_delete(context, &info_tmp);
+    return ret;
+}
+
+/* free locations if it has string allocated on heap. */
+static void loc_free(QBlockProtInfo *loc)
+{
+    switch (loc->prot_type) {
+    case QB_PROT_FILE:
+        FUNC_FREE((void *)(loc->prot_op.o_file.filename));
+        loc->prot_op.o_file.filename = NULL;
+        break;
+    default:
+        break;
+    }
+}
+
+/* free fmt related resoure. */
+static void fmt_free(QBlockFmtInfo *fmt)
+{
+    switch (fmt->fmt_type) {
+    case QB_FMT_COW:
+        loc_free(&(fmt->fmt_op.o_cow.backing_loc));
+        break;
+    case QB_FMT_QED:
+        loc_free(&(fmt->fmt_op.o_qed.backing_loc));
+        break;
+    case QB_FMT_QCOW:
+        loc_free(&(fmt->fmt_op.o_qcow.backing_loc));
+        break;
+    case QB_FMT_QCOW2:
+        loc_free(&(fmt->fmt_op.o_qcow2.backing_loc));
+        break;
+    case QB_FMT_RAW:
+        break;
+    case QB_FMT_RBD:
+        break;
+    case QB_FMT_SHEEPDOG:
+        loc_free(&(fmt->fmt_op.o_sheepdog.backing_loc));
+        break;
+    case QB_FMT_VDI:
+        break;
+    case QB_FMT_VMDK:
+        loc_free(&(fmt->fmt_op.o_vmdk.backing_loc));
+        break;
+    case QB_FMT_VPC:
+        break;
+    default:
+        break;
+    }
+    return;
+}
+
+
+void qb_info_image_static_delete(QBlockContext *context,
+                                 QBlockStaticInfo **info)
+{
+    if ((*info)->member_addr != NULL) {
+        FUNC_FREE((*info)->member_addr);
+    }
+    loc_free(&(*info)->loc);
+    fmt_free(&(*info)->fmt);
+    CLEAN_FREE(*info);
+}
+
+QBlockProtInfo *qb_prot_info_dup(const QBlockProtInfo *prot)
+{
+    QBlockProtInfo *p = FUNC_CALLOC(1, sizeof(QBlockProtInfo));
+    p->prot_type = prot->prot_type;
+    switch (p->prot_type) {
+    case QB_PROT_FILE:
+        p->prot_op.o_file.filename =
+                          FUNC_STRDUP(prot->prot_op.o_file.filename);
+        break;
+    default:
+        break;
+    }
+    return p;
+}
diff --git a/libqblock/libqblock.h b/libqblock/libqblock.h
new file mode 100644
index 0000000..9a6ed75
--- /dev/null
+++ b/libqblock/libqblock.h
@@ -0,0 +1,308 @@
+/*
+ * QEMU block layer library
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef LIBQBLOCK_H
+#define LIBQBLOCK_H
+
+#include "libqblock-types.h"
+#include "libqblock-error.h"
+
+/**
+ * qb_context_new: allocate a new context.
+ *
+ * Broker is used to pass operation to libqblock, and get feedback from it.
+ *
+ * Returns 0 on success, libqblock negative error value on fail.
+ *
+ * @context: used to receive the created struct.
+ */
+DLL_PUBLIC
+int qb_context_new(QBlockContext **context);
+
+/**
+ * qb_context_delete: delete context.
+ *
+ * Broker will be freed and set to NULL.
+ *
+ * @context: operation context to be deleted.
+ */
+DLL_PUBLIC
+void qb_context_delete(QBlockContext **context);
+
+/**
+ * qb_state_new: allocate a new QBlockState struct
+ *
+ * Subsequent qblock actions will use this struct
+ *
+ * Returns 0 if succeed, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: used to receive the created struct.
+ */
+DLL_PUBLIC
+int qb_state_new(QBlockContext *context,
+                 QBlockState **qbs);
+
+/**
+ * qb_state_delete: free a QBlockState struct
+ *
+ * if image was opened, qb_close should be called before delete, otherwise
+ *  it would be automatically closed.
+ *
+ * @context: operation context.
+ * @qbs: pointer to the struct's pointer.
+ */
+DLL_PUBLIC
+void qb_state_delete(QBlockContext *context,
+                     QBlockState **qbs);
+
+/**
+ * qb_prot_info_new: create a new QBlockProtInfo object.
+ *
+ * return 0 on success, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @op: pointer to receive the new created one.
+ */
+DLL_PUBLIC
+int qb_prot_info_new(QBlockContext *context,
+                     QBlockProtInfo **op);
+
+/**
+ * qb_prot_info_delete: free a QBlockProtInfo.
+ *
+ * @context: operation context.
+ * @op: pointer to the object, *op would be set to NULL.
+ */
+DLL_PUBLIC
+void qb_prot_info_delete(QBlockContext *context,
+                         QBlockProtInfo **op);
+
+/**
+ * qb_fmt_info_new: create a new QBlockFmtInfo structure.
+ *
+ * return 0 on success, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @op: pointer that will receive created struct.
+ */
+DLL_PUBLIC
+int qb_fmt_info_new(QBlockContext *context,
+                    QBlockFmtInfo **op);
+
+/**
+ * qb_fmt_info_delete: free QBlockFmtInfo structure.
+ *
+ * @context: operation context.
+ * @op: pointer to the struct, *op would be set to NULL.
+ */
+DLL_PUBLIC
+void qb_fmt_info_delete(QBlockContext *context,
+                        QBlockFmtInfo **op);
+
+
+/**
+ * qb_open: open a block object.
+ *
+ * return 0 on success, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ * @loc: location options for open, how to find the image.
+ * @fmt: format options, how to extract the data, only valid member now is
+ *    fmt->fmt_type, set to NULL if you want to auto discovery the format.
+ * @flag: behavior control flags, it is LIBQBLOCK_O_XXX's combination.
+ *
+ * Note: For raw image, there is a risk that it's content is changed to some
+ *  magic value resulting a wrong probing done by libqblock, so don't do
+ * probing on raw images.
+ */
+DLL_PUBLIC
+int qb_open(QBlockContext *context,
+            QBlockState *qbs,
+            QBlockProtInfo *loc,
+            QBlockFmtInfo *fmt,
+            int flag);
+
+/**
+ * qb_close: close a block object.
+ *
+ * qb_flush is automatically done inside.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ */
+DLL_PUBLIC
+void qb_close(QBlockContext *context,
+              QBlockState *qbs);
+
+/**
+ * qb_create: create a block image or object.
+ *
+ * Note: Create operation would not open the image automatically.
+ *
+ * return 0 on success, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ * @loc: location options for open, how to find the image.
+ * @fmt: format options, how to extract the data.
+ * @flag: behavior control flags, LIBQBLOCK_O_XXX's combination.
+ */
+DLL_PUBLIC
+int qb_create(QBlockContext *context,
+              QBlockState *qbs,
+              QBlockProtInfo *loc,
+              QBlockFmtInfo *fmt,
+              int flag);
+
+
+/* sync access */
+/**
+ * qb_read: block sync read.
+ *
+ * return number of bytes read, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ * @buf: buffer that receive the content.
+ * @len: length to read.
+ * @offset: offset in the block data.
+ */
+DLL_PUBLIC
+int32_t qb_read(QBlockContext *context,
+                QBlockState *qbs,
+                uint8_t *buf,
+                uint32_t len,
+                uint64_t offset);
+
+/**
+ * qb_write: block sync write.
+ *
+ * return number of bytes written, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ * @buf: buffer that receive the content.
+ * @len: length to write.
+ * @offset: offset in the block data.
+ */
+DLL_PUBLIC
+int32_t qb_write(QBlockContext *context,
+                 QBlockState *qbs,
+                 const uint8_t *buf,
+                 uint32_t len,
+                 uint64_t offset);
+
+/**
+ * qb_flush: block sync flush.
+ *
+ * return 0 on success, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ */
+DLL_PUBLIC
+int qb_flush(QBlockContext *context,
+             QBlockState *qbs);
+
+
+/* advance image APIs */
+/**
+ * qb_check_allocation: check if [start, start+lenth-1] was allocated on the
+ *  image.
+ *
+ * return 0 on success, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ * @start: start position, unit is byte.
+ * @length: length to check, unit is byte, max is 1TB, otherwise will return
+ *   QB_ERR_INVALID_PARAM.
+ * @pstatus: pointer to receive the status, 1 means allocated,
+ *  0 means unallocated.
+ * @plength: pointer to receive the length that all have the same status as
+ *  *pstatus.
+ *
+ * Note: after return, start+*plength may have the same status as
+ *  start+*plength-1.
+ */
+DLL_PUBLIC
+int qb_check_allocation(QBlockContext *context,
+                        QBlockState *qbs,
+                        uint64_t start,
+                        int64_t length,
+                        int *pstatus,
+                        int64_t *plength);
+
+/* image information */
+/**
+ * qb_get_image_info: get image info.
+ *
+ * return 0 on success, libqblock negative error value on fail.
+ *
+ * @context: operation context.
+ * @qbs: pointer to QBlockState.
+ * @info: pointer that would receive the information.
+ *
+ * *info must be not modified after return, qb_info_image_static_delete will
+ *   use the information in it.
+ */
+DLL_PUBLIC
+int qb_info_image_static_get(QBlockContext *context,
+                             QBlockState *qbs,
+                             QBlockStaticInfo **info);
+
+/**
+ * qb_delete_image_info: free image info.
+ *
+ * @context: operation context.
+ * @info: pointer to the information struct.
+ */
+DLL_PUBLIC
+void qb_info_image_static_delete(QBlockContext *context,
+                                 QBlockStaticInfo **info);
+
+/* helper functions */
+/**
+ * qb_str2fmttype: translate format string to libqblock format enum type.
+ *
+ * return the type, or QB_FMT_NONE if string matches none of supported types.
+ *
+ * @fmt: the format string.
+ */
+DLL_PUBLIC
+QBlockFmtType qb_str2fmttype(const char *fmt_str);
+
+/**
+ * qb_fmttype2str: translate libqblock format enum type to a string.
+ *
+ * return a pointer to the string, or NULL if type is not supported, and
+ *  returned pointer must NOT be freed.
+ *
+ * @fmt: the format enum type.
+ */
+DLL_PUBLIC
+const char *qb_fmttype2str(QBlockFmtType fmt_type);
+
+/**
+ * qb_prot_info_dup: duplicate a QBlockProtInfo instance.
+ *
+ * return a pointer to new allocated one having the same values with input,
+ *  it need to be freed by qb_prot_info_delete later. Never fail except OOM.
+ *
+ * @prot: pointer to the source instance.
+ */
+DLL_PUBLIC
+QBlockProtInfo *qb_prot_info_dup(const QBlockProtInfo *prot);
+#endif
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH V4 4/5] libqblock test build system
  2012-09-27  2:23 [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library Wenchao Xia
                   ` (2 preceding siblings ...)
  2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 3/5] libqblock API Wenchao Xia
@ 2012-09-27  2:24 ` Wenchao Xia
  2012-09-27  8:30   ` Paolo Bonzini
  2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 5/5] libqblock test example Wenchao Xia
  4 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  2:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, aliguori, stefanha, blauwirbel, pbonzini, eblake,
	Wenchao Xia

  This patch will create a new directory in ./tests, make check-libqblock will
build an executable binary, make clean or make check-clean will delete generated
binaries.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 .gitignore                        |    2 +
 Makefile                          |    1 +
 tests/Makefile                    |   45 +++++++++++++++++++++++++++++++++++++
 tests/libqblock/libqblock-qcow2.c |    4 +++
 4 files changed, 52 insertions(+), 0 deletions(-)
 create mode 100644 tests/libqblock/libqblock-qcow2.c

diff --git a/.gitignore b/.gitignore
index 824c0d2..080a88b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,3 +95,5 @@ cscope.*
 tags
 TAGS
 *~
+tests/libqblock/check-*
+tests/libqblock/test_images
diff --git a/Makefile b/Makefile
index 128bc6a..7cfb555 100644
--- a/Makefile
+++ b/Makefile
@@ -237,6 +237,7 @@ clean:
 	rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
 	rm -rf qapi-generated
 	rm -rf qga/qapi-generated
+	$(MAKE) check-clean
 	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard libqblock; do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
 	rm -f $$d/qemu-options.def; \
diff --git a/tests/Makefile b/tests/Makefile
index 26a67ce..668c825 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -84,6 +84,17 @@ check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)
 qtest-obj-y = tests/libqtest.o $(oslib-obj-y) $(tools-obj-y)
 $(check-qtest-y): $(qtest-obj-y)
 
+#libqblock
+LIBQBLOCK_TEST_DIR=$(SRC_PATH)/tests/libqblock/test_images
+qtest-lib-y=$(patsubst %.o, %.lo,$(qtest-obj-y))
+libqblock-la-path = $(libqblock-lib-path)/$(libqblock-lib-la)
+
+tests/libqblock/%.lo: QEMU_INCLUDES += -I$(libqblock-lib-path) -Itests
+
+check-libqblock-y = tests/libqblock/check-libqblock-qcow2$(EXESUF)
+tests/libqblock/check-libqblock-qcow2$(EXESUF): tests/libqblock/libqblock-qcow2.lo $(libqblock-la-path) $(qtest-lib-y)
+	$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -shared -rpath $(libdir) -o $@ $^,"  lt LINK $@")
+
 .PHONY: check-help
 check-help:
 	@echo "Regression testing targets:"
@@ -93,7 +104,9 @@ check-help:
 	@echo " make check-qtest          Run qtest tests"
 	@echo " make check-unit           Run qobject tests"
 	@echo " make check-block          Run block tests"
+	@echo " make check-libqblock      Run libqblock tests"
 	@echo " make check-report.html    Generates an HTML test report"
+	@echo " make check-clean          Clean the test"
 	@echo
 	@echo "Please note that HTML reports do not regenerate if the unit tests"
 	@echo "has not changed."
@@ -116,6 +129,11 @@ $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
 $(patsubst %, check-%, $(check-unit-y)): check-%: %
 	$(call quiet-command,gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
 
+#libqblock tests
+.PHONY: $(patsubst %, check-%, $(check-libqblock-y))
+$(patsubst %, check-%, $(check-libqblock-y)): check-%: %
+	$(call quiet-command, LIBQBLOCK_TEST_DIR=$(LIBQBLOCK_TEST_DIR) gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
+
 # gtester tests with XML output
 
 $(patsubst %, check-report-qtest-%.xml, $(QTEST_TARGETS)): check-report-qtest-%.xml: $(check-qtest-y)
@@ -148,4 +166,31 @@ check-unit: $(patsubst %,check-%, $(check-unit-y))
 check-block: $(patsubst %,check-%, $(check-block-y))
 check: check-unit check-qtest
 
+ifeq ($(LIBTOOL),)
+check-libqblock:
+	@echo "libtool is missing, skip libqblock test."
+else
+$(libqblock-la-path):
+	@echo "Building libqblock.la..."
+	$(call quiet-command,$(MAKE) -C $(SRC_PATH) $(libqblock-lib-la),)
+$(LIBQBLOCK_TEST_DIR):
+	@echo "Make libqblock test directory"
+	mkdir $(LIBQBLOCK_TEST_DIR)
+
+check-libqblock: $(libqblock-la-path) $(LIBQBLOCK_TEST_DIR) $(patsubst %,check-%, $(check-libqblock-y))
+endif
+
+check-clean:
+	$(MAKE) -C tests/tcg clean
+	rm -f tests/*.lo tests/*.o
+	rm -rf tests/.libs
+	rm -f tests/libqblock/*.lo tests/libqblock/*.o
+	rm -rf tests/libqblock/.libs
+	rm -f trace/*.lo trace/*.o
+	rm -rf trace/.libs
+	rm -f $(check-libqblock-y)
+	rm -rf $(LIBQBLOCK_TEST_DIR)
+	rm -f $(check-unit-y)
+	rm -f $(check-qtest-i386-y) $(check-qtest-x86_64-y) $(check-qtest-sparc64-y) $(check-qtest-sparc-y)
+
 -include $(wildcard tests/*.d)
diff --git a/tests/libqblock/libqblock-qcow2.c b/tests/libqblock/libqblock-qcow2.c
new file mode 100644
index 0000000..c05c0c4
--- /dev/null
+++ b/tests/libqblock/libqblock-qcow2.c
@@ -0,0 +1,4 @@
+int main(int argc, char **argv)
+{
+    return 0;
+}
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [PATCH V4 5/5] libqblock test example
  2012-09-27  2:23 [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library Wenchao Xia
                   ` (3 preceding siblings ...)
  2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 4/5] libqblock test build system Wenchao Xia
@ 2012-09-27  2:24 ` Wenchao Xia
  4 siblings, 0 replies; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  2:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, aliguori, stefanha, blauwirbel, pbonzini, eblake,
	Wenchao Xia

  In this example, at first it will create some qcow2 images, then get
information including backing file relationship. Then it will do sync IO on
the image.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 tests/libqblock/libqblock-qcow2.c |  366 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 365 insertions(+), 1 deletions(-)

diff --git a/tests/libqblock/libqblock-qcow2.c b/tests/libqblock/libqblock-qcow2.c
index c05c0c4..7985cb6 100644
--- a/tests/libqblock/libqblock-qcow2.c
+++ b/tests/libqblock/libqblock-qcow2.c
@@ -1,4 +1,368 @@
+/*
+ * QEMU block layer library test
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
+ *
+ * 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.
+ *
+ * Limitation:
+ *    1 filename do not support relative path, to save trouble in creating
+ * backing files.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "libqblock.h"
+#include "libqtest.h"
+
+#define LIBQB_TEST_ENV_DIR "LIBQBLOCK_TEST_DIR"
+#define LIBQB_TEST_DEFAULT_DIR "/tmp"
+#define LIBQB_TEST_DEFAULT_FILENAME "libqblock_qcow2_test_img"
+
+typedef struct LibqbTestSettings {
+    const char *image_filename;
+    uint64_t image_size;
+    unsigned int num_backings;
+    unsigned int io_buf_size;
+    uint64_t io_offset;
+    int print_flag;
+} LibqbTestSettings;
+
+LibqbTestSettings libqb_test_settings;
+
+static void print_loc(QBlockProtInfo *loc)
+{
+    if (loc == NULL) {
+        printf("backing file is NULL.");
+        return;
+    }
+    switch (loc->prot_type) {
+    case QB_PROT_NONE:
+        printf("protocol type [none].");
+        break;
+    case QB_PROT_FILE:
+        printf("protocol type [file], filename [%s].",
+               loc->prot_op.o_file.filename);
+        break;
+    default:
+        printf("protocol type not supported.");
+        break;
+    }
+}
+
+static void print_info_image_static(QBlockStaticInfo *info)
+{
+    printf("=======image location:\n");
+    print_loc(&info->loc);
+    printf("\nvirtual_size %" PRId64 ", format type %d [%s]",
+           *(info->member_addr->virt_size),
+           info->fmt.fmt_type, qb_fmttype2str(info->fmt.fmt_type));
+    printf("\nbacking image location:\n");
+    print_loc(info->member_addr->backing_loc);
+    printf("\n");
+}
+
+static char *generate_backing_filename(const char *filename, int index)
+{
+    char *backing_filename = NULL;
+
+    backing_filename = g_strdup_printf("%s_backing_%d", filename, index);
+    return backing_filename;
+}
+
+/* get filename in a full path */
+static const char *get_filename(const char *path)
+{
+    const char *filename;
+    filename = strrchr(path, '/');
+    if (filename == NULL) {
+        filename = path;
+    } else {
+        filename++;
+    }
+    return filename;
+}
+
+/* create a chain of files, num_backings must >= 0. */
+static void files_create_qcow2(const char *filename,
+                               int num_backings,
+                               uint64_t virt_size)
+{
+    QBlockContext *context = NULL;
+    QBlockState *qbs = NULL;
+    QBlockProtInfo *prot_info = NULL;
+    QBlockFmtInfo *fmt_info = NULL;
+    int ret;
+    int index;
+    int flag;
+    char *backing_filename = NULL, *new_filename = NULL;
+    const char *relative_filename = NULL;
+
+    ret = qb_context_new(&context);
+    g_assert(ret == 0);
+
+    ret = qb_state_new(context, &qbs);
+    g_assert(ret == 0);
+
+    ret = qb_prot_info_new(context, &prot_info);
+    g_assert(ret == 0);
+
+    ret = qb_fmt_info_new(context, &fmt_info);
+    g_assert(ret == 0);
+
+    prot_info->prot_type = QB_PROT_FILE;
+    fmt_info->fmt_type = QB_FMT_QCOW2;
+    fmt_info->fmt_op.o_qcow2.virt_size = virt_size;
+    flag = 0;
+
+    index = 0;
+    while (index < num_backings) {
+        new_filename = generate_backing_filename(filename, index);
+        prot_info->prot_op.o_file.filename = new_filename;
+        if (backing_filename != NULL) {
+            fmt_info->fmt_op.o_qcow2.backing_loc.prot_type = QB_PROT_FILE;
+            relative_filename = get_filename(backing_filename);
+            fmt_info->fmt_op.o_qcow2.backing_loc.prot_op.o_file.filename =
+                                                             relative_filename;
+        }
+        ret = qb_create(context, qbs, prot_info, fmt_info, flag);
+        g_assert(ret == 0);
+        free(backing_filename);
+        backing_filename = new_filename;
+        new_filename = NULL;
+        index++;
+    }
+
+    prot_info->prot_op.o_file.filename = filename;
+    if (backing_filename != NULL) {
+        fmt_info->fmt_op.o_qcow2.backing_loc.prot_type = QB_PROT_FILE;
+        relative_filename = get_filename(backing_filename);
+        fmt_info->fmt_op.o_qcow2.backing_loc.prot_op.o_file.filename =
+                                                         relative_filename;
+    }
+    ret = qb_create(context, qbs, prot_info, fmt_info, flag);
+    g_assert(ret == 0);
+    free(backing_filename);
+
+    qb_fmt_info_delete(context, &fmt_info);
+    qb_prot_info_delete(context, &prot_info);
+    qb_state_delete(context, &qbs);
+    qb_context_delete(&context);
+    return;
+}
+
+static void files_delete(const char *filename,
+                         int num_backings,
+                         uint64_t virt_size)
+{
+    char *new_filename = NULL;
+    int index = 0;
+    while (index < num_backings) {
+        new_filename = generate_backing_filename(filename, index);
+        unlink(new_filename);
+        free(new_filename);
+        index++;
+    }
+    unlink(filename);
+}
+
+static void testcase_info_image_static(void)
+{
+    const char *filename = libqb_test_settings.image_filename;
+    uint64_t image_size = libqb_test_settings.image_size;
+    int num_backings = libqb_test_settings.num_backings;
+    QBlockContext *context = NULL;
+    QBlockState *qbs = NULL;
+    QBlockProtInfo *prot_info = NULL;
+    int ret, flag;
+    QBlockStaticInfo *info_st = NULL;
+    int i;
+    char *backing_filename = NULL;
+
+    ret = qb_context_new(&context);
+    g_assert(ret == 0);
+
+    ret = qb_state_new(context, &qbs);
+    g_assert(ret == 0);
+
+    ret = qb_prot_info_new(context, &prot_info);
+    g_assert(ret == 0);
+
+    prot_info->prot_type = QB_PROT_FILE;
+    prot_info->prot_op.o_file.filename = filename;
+    flag = LIBQBLOCK_O_NO_BACKING;
+    ret = qb_open(context, qbs, prot_info, NULL, flag);
+    g_assert(ret == 0);
+
+    i = num_backings - 1;
+    while (1) {
+        ret = qb_info_image_static_get(context, qbs, &info_st);
+        g_assert(ret == 0);
+        if (libqb_test_settings.print_flag > 0) {
+            print_info_image_static(info_st);
+        }
+        qb_close(context, qbs);
+
+        /* checking the information */
+        g_assert(info_st->loc.prot_type == prot_info->prot_type);
+        ret = strcmp(info_st->loc.prot_op.o_file.filename,
+                     prot_info->prot_op.o_file.filename);
+
+        g_assert(ret == 0);
+        g_assert(info_st->fmt.fmt_type == QB_FMT_QCOW2);
+        g_assert(*(info_st->member_addr->virt_size) == image_size);
+        if (i >= 0) {
+            /* it should have backing file */
+            g_assert(info_st->member_addr->backing_loc->prot_type ==
+                                       QB_PROT_FILE);
+            backing_filename = generate_backing_filename(filename, i);
+            ret = strcmp(backing_filename,
+                   info_st->member_addr->backing_loc->prot_op.o_file.filename);
+            g_assert(ret == 0);
+            g_free(backing_filename);
+        } else {
+            g_assert(info_st->member_addr->backing_loc->prot_type ==
+                                       QB_FMT_NONE);
+        }
+        i--;
+        /* see if there is backing file need to check. */
+        if ((info_st->member_addr->backing_loc == NULL) ||
+            (info_st->member_addr->backing_loc->prot_type == QB_FMT_NONE)) {
+            break;
+        }
+        qb_prot_info_delete(context, &prot_info);
+        prot_info = qb_prot_info_dup(info_st->member_addr->backing_loc);
+        ret = qb_open(context, qbs, prot_info, NULL, flag);
+        g_assert(ret == 0);
+        qb_info_image_static_delete(context, &info_st);
+    }
+    qb_info_image_static_delete(context, &info_st);
+
+    qb_prot_info_delete(context, &prot_info);
+    qb_state_delete(context, &qbs);
+    qb_context_delete(&context);
+    return;
+}
+
+/* assuming the image is new created */
+static void testcase_sync_io(void)
+{
+    const char *filename = libqb_test_settings.image_filename;
+    uint64_t io_buf_size = libqb_test_settings.io_buf_size;
+    uint64_t io_offset = libqb_test_settings.io_offset;;
+    unsigned char *buf_r, *buf_w;
+    uint64_t i;
+    unsigned int rand_value;
+
+    buf_r = g_malloc0(io_buf_size);
+    buf_w = g_malloc0(io_buf_size);
+    for (i = 0; i < io_buf_size; i++) {
+        rand_value = g_test_rand_int_range(0, 255);
+        buf_w[i] = (unsigned char)rand_value;
+    }
+
+    QBlockContext *context = NULL;
+    QBlockState *qbs = NULL;
+    QBlockProtInfo *prot_info = NULL;
+    int ret, flag;
+
+    ret = qb_context_new(&context);
+    g_assert(ret == 0);
+
+    ret = qb_state_new(context, &qbs);
+    g_assert(ret == 0);
+
+    ret = qb_prot_info_new(context, &prot_info);
+    g_assert(ret == 0);
+
+
+    prot_info->prot_type = QB_PROT_FILE;
+    prot_info->prot_op.o_file.filename = filename;
+    flag = LIBQBLOCK_O_RDWR;
+    ret = qb_open(context, qbs, prot_info, NULL, flag);
+    g_assert(ret == 0);
+
+    int status;
+    int64_t len;
+    ret = qb_check_allocation(context, qbs, io_offset, io_buf_size,
+                                       &status, &len);
+    g_assert(ret == 0);
+    g_assert(status == 0);
+    g_assert(len == io_buf_size);
+
+    ret = qb_write(context, qbs, buf_w, io_buf_size, io_offset);
+    g_assert(ret == io_buf_size);
+
+    ret = qb_read(context, qbs, buf_r, io_buf_size, io_offset);
+    g_assert(ret == io_buf_size);
+
+    int cmp = memcmp(buf_r, buf_w, io_buf_size);
+    g_assert(cmp == 0);
+
+    ret = qb_check_allocation(context, qbs, io_offset, io_buf_size,
+                                       &status, &len);
+    g_assert(ret == 0);
+    g_assert(status == 1);
+    g_assert(len == io_buf_size);
+
+    qb_close(context, qbs);
+
+    qb_prot_info_delete(context, &prot_info);
+    qb_state_delete(context, &qbs);
+    qb_context_delete(&context);
+    g_free(buf_r);
+    g_free(buf_w);
+    return;
+}
+
 int main(int argc, char **argv)
 {
-    return 0;
+    const char *root_dir;
+    const char *name = LIBQB_TEST_DEFAULT_FILENAME;
+    int ret;
+    char *filename;
+
+    root_dir = getenv(LIBQB_TEST_ENV_DIR);
+    if (root_dir == NULL) {
+        root_dir = LIBQB_TEST_DEFAULT_DIR;
+    }
+
+    filename = g_strdup_printf("%s/%s", root_dir, name);
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_rand_int();
+
+    libqb_test_settings.image_filename = filename;
+    libqb_test_settings.image_size =
+                            1024 * 1024 * g_test_rand_int_range(1, 1024);
+    libqb_test_settings.num_backings = g_test_rand_int_range(0, 10);
+    libqb_test_settings.io_buf_size = g_test_rand_int_range(1, 1024 * 1024);
+    libqb_test_settings.io_offset = g_test_rand_int_range(0,
+            libqb_test_settings.image_size - libqb_test_settings.io_buf_size);
+
+    files_create_qcow2(libqb_test_settings.image_filename,
+                       libqb_test_settings.num_backings,
+                       libqb_test_settings.image_size);
+
+    g_test_add_func("/libqblock/sync_info_image_static",
+                      testcase_info_image_static);
+    g_test_add_func("/libqblock/sync_io", testcase_sync_io);
+
+    ret = g_test_run();
+    files_delete(libqb_test_settings.image_filename,
+                 libqb_test_settings.num_backings,
+                 libqb_test_settings.image_size);
+
+    g_free(filename);
+    return ret;
 }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 1/5] libqblock build system
  2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 1/5] libqblock build system Wenchao Xia
@ 2012-09-27  8:06   ` Paolo Bonzini
  2012-09-27  9:39     ` Wenchao Xia
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-27  8:06 UTC (permalink / raw)
  To: qemu-devel, Kevin Wolf, Stefan Hajnoczi, Eric Blake, Wayne Xia,
	Anthony Liguori

Il 27/09/2012 04:23, Wenchao Xia ha scritto:
>   Libqblock was placed in new directory ./libqblock, libtool will build
> dynamic library there, source files of block layer remains in ./block.
> So block related source code will generate 3 sets of binary, first is old
> ones used in qemu, second and third are non PIC and PIC ones in ./libqblock.
>   GCC compiler flag visibility=hidden was used with special macro, to export
> only symbols that was marked as PUBLIC.
> 
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
>  Makefile                    |   14 +++++++++-
>  Makefile.objs               |    6 ++++
>  libqblock/Makefile          |   56 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 74 insertions(+), 2 deletions(-)
>  create mode 100644 libqblock/Makefile
>  create mode 100644 libqblock/libqblock-error.c
>  create mode 100644 libqblock/libqblock.c
> 
> diff --git a/Makefile b/Makefile
> index def2ae2..128bc6a 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -164,6 +164,17 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
>  
>  qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
>  
> +######################################################################
> +# Support building shared library libqblock
> +ifeq ($(LIBTOOL),)
> +$(libqblock-lib-la):
> +	@echo "libtool is missing, please install and rerun configure"; exit 1
> +else
> +$(libqblock-lib-la):
> +	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libqblock V="$(V)" TARGET_DIR="$*/" $(libqblock-lib-la),)
> +endif

Please remove the useless indirection via $(libqblock-lib-la).  In general,
this patch should be redone more similar to how libcacard is build:

subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
...
libcacard.la: $(oslib-obj-y) qemu-timer-common.o $(trace-obj-y)
        $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" libcacard.la,)

install-libcacard: libcacard.la
        $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" install-libcacard,)


(The ifeq is not necessary, I'm going to remove it from libcacard too.  The
same error message is already raised in libcacard/Makefile).

> +###########################################################################
> +
>  vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) $(tools-obj-y) qemu-timer-common.o libcacard/vscclient.o
>  	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
>  
> @@ -226,8 +237,7 @@ clean:
>  	rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
>  	rm -rf qapi-generated
>  	rm -rf qga/qapi-generated
> -	$(MAKE) -C tests/tcg clean
> -	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
> +	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard libqblock; do \
>  	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
>  	rm -f $$d/qemu-options.def; \
>          done
> diff --git a/Makefile.objs b/Makefile.objs
> index 4412757..8a4c9fc 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -248,3 +248,9 @@ nested-vars += \
>  	common-obj-y \
>  	extra-obj-y
>  dummy := $(call unnest-vars)
> +
> +#############################################################################
> +# libqblock
> +
> +libqblock-lib-la = libqblock.la
> +libqblock-lib-path = libqblock

Remove these two please.

> diff --git a/libqblock/Makefile b/libqblock/Makefile
> new file mode 100644
> index 0000000..5f65613
> --- /dev/null
> +++ b/libqblock/Makefile
> @@ -0,0 +1,56 @@
> +###########################################################################
> +# libqblock Makefile
> +# Todo:
> +#    1 trace related files is generated in this directory, move
> +#  them to the root directory.
> +##########################################################################
> +-include ../config-host.mak
> +-include $(SRC_PATH)/Makefile.objs
> +-include $(SRC_PATH)/rules.mak
> +
> +#############################################################################
> +# Library settings
> +#############################################################################
> +$(call set-vpath, $(SRC_PATH))
> +
> +#expand the foldered vars,especially ./block
> +dummy := $(call unnest-vars-1)

Please use unnest-vars.

> +#library objects
> +libqblock-y=libqblock.o libqblock-error.o
> +
> +QEMU_OBJS= $(libqblock-y) $(block-obj-y)
> +#filter out ./block
> +QEMU_OBJS_FILTERED=$(filter %.o, $(QEMU_OBJS))
> +QEMU_OBJS_LIB=$(patsubst %.o, %.lo, $(QEMU_OBJS_FILTERED))
> +
> +QEMU_CFLAGS+= -I../ -I../include
> +#adding magic macro define for symbol hiding and exposing
> +QEMU_CFLAGS+= -fvisibility=hidden -D LIBQB_BUILD
> +
> +#dependency libraries
> +LIBS+=-lz $(LIBS_TOOLS)
> +
> +#################################################################
> +# Runtime rules
> +#################################################################
> +clean:
> +	rm -f *.lo *.o *.d *.la libqblock-test trace.c trace.c-timestamp
> +	rm -rf .libs block trace
> +
> +help:
> +	@echo type make libqblock-test at root dirtory, libtool is required

Please remove this rule.

> +#make directory ./block at runtime which would hold the output of block/*.c
> +block:
> +	@mkdir block
> +
> +ifeq ($(LIBTOOL),)
> +$(libqblock-lib-la):
> +	@echo "libtool is missing, please install and rerun configure"; exit 1
> +else
> +$(libqblock-lib-la): $(QEMU_OBJS_LIB)
> +	$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(LIBS),"  lt LINK $@")
> +endif
> +
> +.PHONY: libqblock.la

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 2/5] libqblock type defines Wenchao Xia
@ 2012-09-27  8:25   ` Paolo Bonzini
  2012-09-27  9:52     ` Wenchao Xia
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-27  8:25 UTC (permalink / raw)
  To: Wenchao Xia; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

Il 27/09/2012 04:23, Wenchao Xia ha scritto:
>   This patch contains type and macro defines used in APIs, one file for public
> usage by user, one for libqblock internal usage.
> 
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
>  libqblock/libqblock-internal.h |   57 +++++++++
>  libqblock/libqblock-types.h    |  268 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 325 insertions(+), 0 deletions(-)
>  create mode 100644 libqblock/libqblock-internal.h
>  create mode 100644 libqblock/libqblock-types.h
> 
> diff --git a/libqblock/libqblock-internal.h b/libqblock/libqblock-internal.h
> new file mode 100644
> index 0000000..d3e983c
> --- /dev/null
> +++ b/libqblock/libqblock-internal.h
> @@ -0,0 +1,57 @@
> +/*
> + * QEMU block layer library
> + *
> + * Copyright IBM, Corp. 2012
> + *
> + * Authors:
> + *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef LIBQBLOCK_INTERNAL
> +#define LIBQBLOCK_INTERNAL
> +
> +#include "glib.h"
> +
> +#include "block.h"
> +#include "block_int.h"
> +#include "libqblock-types.h"
> +
> +/* this file contains defines and types used inside the library. */
> +
> +#define FUNC_FREE(p) g_free((p))
> +#define FUNC_MALLOC(size) g_malloc((size))
> +#define FUNC_CALLOC(nmemb, size) g_malloc0((nmemb)*(size))
> +#define FUNC_STRDUP(p) g_strdup((p))
> +
> +#define CLEAN_FREE(p) { \
> +        FUNC_FREE(p); \
> +        (p) = NULL; \
> +}
> +
> +/* details should be hidden to user */
> +struct QBlockState {
> +    BlockDriverState *bdrvs;
> +    /* internal used file name now, if it is not NULL, it means
> +       image was opened.
> +    */
> +    char *filename;
> +};
> +
> +struct QBlockContext {
> +    /* last error */
> +    GError *g_error;
> +    int err_ret; /* 1st level of error, the libqblock error number */
> +    int err_no; /* 2nd level of error, errno what below reports */
> +};
> +
> +#define G_LIBQBLOCK_ERROR g_libqbock_error_quark()
> +
> +static inline GQuark g_libqbock_error_quark(void)
> +{
> +    return g_quark_from_static_string("g-libqblock-error-quark");
> +}
> +#endif
> diff --git a/libqblock/libqblock-types.h b/libqblock/libqblock-types.h
> new file mode 100644
> index 0000000..948ab8a
> --- /dev/null
> +++ b/libqblock/libqblock-types.h
> @@ -0,0 +1,268 @@
> +/*
> + * QEMU block layer library
> + *
> + * Copyright IBM, Corp. 2012
> + *
> + * Authors:
> + *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef LIBQBLOCK_TYPES_H
> +#define LIBQBLOCK_TYPES_H
> +
> +#include <sys/types.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +#if defined(__GNUC__) && __GNUC__ >= 4
> +    #ifdef LIBQB_BUILD
> +        #define DLL_PUBLIC __attribute__((visibility("default")))
> +    #else
> +        #define DLL_PUBLIC
> +    #endif
> +#else
> +    #warning : gcc compiler version < 4, symbols can not be hidden.

You don't need to warn.  If LIBQB_BUILD is not defined, DLL_PUBLIC would
be empty anyway.  If LIBQB_BUILD is defined, you know GCC >= 4.0 because
you pass -fvisibility=hidden from the Makefile.

> +#endif
> +
> +/* this library is designed around this core struct. */
> +typedef struct QBlockState QBlockState;
> +
> +/* every thread should have a context. */
> +typedef struct QBlockContext QBlockContext;
> +
> +/* flag used in open and create */
> +#define LIBQBLOCK_O_RDWR        0x0002
> +/* do not use the host page cache */
> +#define LIBQBLOCK_O_NOCACHE     0x0020
> +/* use write-back caching */
> +#define LIBQBLOCK_O_CACHE_WB    0x0040
> +/* don't open the backing file */
> +#define LIBQBLOCK_O_NO_BACKING  0x0100
> +/* disable flushing on this disk */
> +#define LIBQBLOCK_O_NO_FLUSH    0x0200
> +
> +#define LIBQBLOCK_O_CACHE_MASK \
> +   (LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | LIBQBLOCK_O_NO_FLUSH)
> +
> +#define LIBQBLOCK_O_VALID_MASK \
> +   (LIBQBLOCK_O_RDWR | LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | \
> +    LIBQBLOCK_O_NO_BACKING | LIBQBLOCK_O_NO_FLUSH)
> +
> +typedef enum QBlockProtType {
> +    QB_PROT_NONE = 0,
> +    QB_PROT_FILE,
> +    QB_PROT_MAX
> +} QBlockProtType;

Use QBlockProtocol, QB_PROTO_*.

> +typedef struct QBlockProtOptionFile {
> +    const char *filename;
> +} QBlockProtOptionFile;

Use QBlockProtocolOptionsFile

> +#define QBLOCK_PROT_OPTIONS_UNION_SIZE (512)
> +typedef union QBlockProtOptionsUnion {
> +    QBlockProtOptionFile o_file;
> +    uint8_t reserved[QBLOCK_PROT_OPTIONS_UNION_SIZE];
> +} QBlockProtOptionsUnion;

Not really options, because they are required.  I would just not name
the union, and embed it in the struct.  Also please change it to

     uint64_t reserved[QBLOCK_PROT_OPTIONS_UNION_SIZE / 8];

(Sorry for not thinking about this before).  This will fix the alignment
and ensure that future changes to the union do not change the ABI.

> +/**
> + * struct QBlockProtInfo: contains information about how to find the image
> + *
> + * @prot_type: protocol type, now only support FILE.
> + * @prot_op: protocol related options.
> + */
> +typedef struct QBlockProtInfo {
> +    QBlockProtType prot_type;
> +    QBlockProtOptionsUnion prot_op;
> +} QBlockProtInfo;

What about QBlockLocation instead?  Or QBlockLocationInfo.

> +
> +/* format related options */
> +typedef enum QBlockFmtType {
> +    QB_FMT_NONE = 0,
> +    QB_FMT_COW,
> +    QB_FMT_QED,
> +    QB_FMT_QCOW,
> +    QB_FMT_QCOW2,
> +    QB_FMT_RAW,
> +    QB_FMT_RBD,
> +    QB_FMT_SHEEPDOG,
> +    QB_FMT_VDI,
> +    QB_FMT_VMDK,
> +    QB_FMT_VPC,
> +    QB_FMT_MAX
> +} QBlockFmtType;

QBlockFormat; similarly remove "Type" from all enums.

> +typedef struct QBlockFmtOptionCow {
> +    uint64_t virt_size;
> +    QBlockProtInfo backing_loc;
> +} QBlockFmtOptionCow;

QBlockFormatOptionsCOW.  Similarly use the plural for all other formats.

> +typedef struct QBlockFmtOptionQed {
> +    uint64_t virt_size;
> +    QBlockProtInfo backing_loc;
> +    QBlockFmtType backing_fmt;
> +    uint64_t cluster_size; /* unit is bytes */
> +    uint64_t table_size; /* unit is clusters */
> +} QBlockFmtOptionQed;

Similarly use uppercase for QED, QCOW, etc.

> +typedef struct QBlockFmtOptionQcow {
> +    uint64_t virt_size;
> +    QBlockProtInfo backing_loc;
> +    bool encrypt;
> +} QBlockFmtOptionQcow;
> +
> +/* "Compatibility level (0.10 or 1.1)" */
> +typedef enum QBlockFmtOptionQcow2CptLv {
> +    QBO_FMT_QCOW2_CPT_NONE = 0,
> +    QBO_FMT_QCOW2_CPT_V010,
> +    QBO_FMT_QCOW2_CPT_V110,
> +} QBlockFmtOptionQcow2CptLv;

Please use QBO_ instead of QB_ throughout.  Also write COMPAT instead of
CPT, and remove CPT_NONE since 0.10 is the default:

typedef enum QBlockFmtOptionQCOW2Compat {
    QB_FMT_QCOW2_COMPAT_V0_10,
    QB_FMT_QCOW2_COMPAT_V1_1,
} QBlockFmtOptionQCOW2Compat

> +/* off or metadata */
> +typedef enum QBlockFmtOptionQcow2PreAllocType {
> +    QBO_FMT_QCOW2_PREALLOC_NONE = 0,
> +    QBO_FMT_QCOW2_PREALLOC_OFF,
> +    QBO_FMT_QCOW2_PREALLOC_METADATA,
> +} QBlockFmtOptionQcow2PreAllocType;

Please remove NONE since OFF is the default.  However, I would use the enum.

> +typedef struct QBlockFmtOptionQcow2 {
> +    uint64_t virt_size;
> +    QBlockProtInfo backing_loc;
> +    QBlockFmtType backing_fmt;
> +    bool encrypt;
> +    uint64_t cluster_size; /* unit is bytes */
> +    QBlockFmtOptionQcow2CptLv cpt_lv;
> +    QBlockFmtOptionQcow2PreAllocType pre_mode;
> +} QBlockFmtOptionQcow2;
> +
> +typedef struct QBlockFmtOptionRaw {
> +    uint64_t virt_size;
> +} QBlockFmtOptionRaw;
> +
> +typedef struct QBlockFmtOptionRbd {
> +    uint64_t virt_size;
> +    uint64_t cluster_size;
> +} QBlockFmtOptionRbd;
> +
> +/* off or full */
> +typedef enum QBlockFmtOptionSheepdogPreAllocType {
> +    QBO_FMT_SD_PREALLOC_NONE = 0,
> +    QBO_FMT_SD_PREALLOC_OFF,
> +    QBO_FMT_SD_PREALLOC_FULL,
> +} QBlockFmtOptionSheepdogPreAllocType;

The default is false, so just make it a bool.

> +typedef struct QBlockFmtOptionSheepdog {
> +    uint64_t virt_size;
> +    QBlockProtInfo backing_loc;
> +    QBlockFmtOptionSheepdogPreAllocType pre_mode;
> +} QBlockFmtOptionSheepdog;
> +
> +typedef enum QBlockFmtOptionVdiPreAllocType {
> +    QBO_FMT_VDI_PREALLOC_NONE = 0,
> +    QBO_FMT_VDI_PREALLOC_FALSE,
> +    QBO_FMT_VDI_PREALLOC_TRUE,
> +} QBlockFmtOptionVdiPreAllocType;

Please remove NONE, and replace FALSE/TRUE with OFF/METADATA (same as
qcow2).

> +typedef struct QBlockFmtOptionVdi {
> +    uint64_t virt_size;
> +    uint64_t cluster_size;
> +    QBlockFmtOptionVdiPreAllocType pre_mode;
> +} QBlockFmtOptionVdi;
> +
> +/* whether compact to vmdk verion 6 */
> +typedef enum QBlockFmtOptionVmdkCptLv {
> +    QBO_FMT_VMDK_CPT_NONE = 0,
> +    QBO_FMT_VMDK_CPT_VMDKV6_FALSE,
> +    QBO_FMT_VMDK_CPT_VMDKV6_TRUE,
> +} QBlockFmtOptionVmdkCptLv;

Here the default is false, so just make it a bool.

> +/* vmdk flat extent format, values:
> +"{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse |
> +twoGbMaxExtentFlat | streamOptimized} */
> +typedef enum QBlockFmtOptionVmdkSubfmtType {
> +    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE = 0,
> +    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_SPARSE,

You can remove QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE (whose more
appropriate name would be just ...SUBFMT_NONE) since the default is
QBO_FMT_VMDK_SUBFMT_MONOLITHIC_SPARSE.

> +    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_FLAT,
> +    QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_SPARSE,
> +    QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_FLAT,
> +    QBO_FMT_VMDK_SUBFMT_STREAM_OPTIMIZED,
> +} QBlockFmtOptionVmdkSubfmtType;
> +
> +typedef struct QBlockFmtOptionVmdk {
> +    uint64_t virt_size;
> +    QBlockProtInfo backing_loc;
> +    QBlockFmtOptionVmdkCptLv cpt_lv;
> +    QBlockFmtOptionVmdkSubfmtType subfmt;
> +} QBlockFmtOptionVmdk;
> +
> +/* "{dynamic (default) | fixed} " */
> +typedef enum QBlockFmtOptionVpcSubfmtType {
> +    QBO_FMT_VPC_SUBFMT_NONE = 0,
> +    QBO_FMT_VPC_SUBFMT_DYNAMIC,
> +    QBO_FMT_VPC_SUBFMT_FIXED,
> +} QBlockFmtOptionVpcSubfmtType;

Again, please remove NONE.

> +typedef struct QBlockFmtOptionVpc {
> +    uint64_t virt_size;
> +    QBlockFmtOptionVpcSubfmtType subfmt;
> +} QBlockFmtOptionVpc;
> +
> +#define QBLOCK_FMT_OPTIONS_UNION_SIZE (QBLOCK_PROT_OPTIONS_UNION_SIZE*2)
> +typedef union QBlockFmtOptionsUnion {
> +    QBlockFmtOptionCow       o_cow;
> +    QBlockFmtOptionQed       o_qed;
> +    QBlockFmtOptionQcow      o_qcow;
> +    QBlockFmtOptionQcow2     o_qcow2;
> +    QBlockFmtOptionRaw       o_raw;
> +    QBlockFmtOptionRbd       o_rbd;
> +    QBlockFmtOptionSheepdog  o_sheepdog;
> +    QBlockFmtOptionVdi       o_vdi;
> +    QBlockFmtOptionVmdk      o_vmdk;
> +    QBlockFmtOptionVpc       o_vpc;
> +    uint8_t reserved[QBLOCK_FMT_OPTIONS_UNION_SIZE];

Similarly use uint64_t here, and just embed the union in the struct.

> +} QBlockFmtOptionsUnion;
> +typedef struct QBlockFmtInfo {
> +    QBlockFmtType fmt_type;
> +    QBlockFmtOptionsUnion fmt_op;
> +} QBlockFmtInfo;

QBlockFormatInfo.

> +/**
> + * QBlockStaticInfoAddr: a structure contains a set of pointer.
> + *
> + *    this struct contains a set of pointer pointing to some
> + *  property related to format or protocol. If a property is not available,
> + *  it will be set as NULL. User could use this to get properties directly.
> + *
> + *  @virt_size: virtual size, it is always not NULL.
> + *  @backing_loc: backing file location.
> + *  @encrypt: encryption flag.
> +*/
> +
> +typedef struct QBlockStaticInfoAddr {
> +    uint64_t *virt_size;
> +    QBlockProtInfo *backing_loc;
> +    bool *encrypt;
> +} QBlockStaticInfoAddr;

Why the indirection?

> +/**
> + * QBlockStaticInfo: information about the block image.
> + *
> + * @member_addr: contains pointer which can be used to access the structure.
> + * @loc: location information.
> + * @fmt: format information.
> + * @sector_size: how many bytes in a sector, it is 512 usually.
> + */
> +typedef struct QBlockStaticInfo {
> +    QBlockStaticInfoAddr *member_addr;
> +    QBlockProtInfo loc;
> +    QBlockFmtInfo fmt;
> +    int sector_size;
> +} QBlockStaticInfo;
> +
> +
> +#endif
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system
  2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 4/5] libqblock test build system Wenchao Xia
@ 2012-09-27  8:30   ` Paolo Bonzini
  2012-09-27  9:56     ` Wenchao Xia
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-27  8:30 UTC (permalink / raw)
  To: Wenchao Xia; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

Il 27/09/2012 04:24, Wenchao Xia ha scritto:
> +#libqblock
> +LIBQBLOCK_TEST_DIR=$(SRC_PATH)/tests/libqblock/test_images
> +qtest-lib-y=$(patsubst %.o, %.lo,$(qtest-obj-y))

I don't think you need qtest-obj-y for anything.

> +libqblock-la-path = $(libqblock-lib-path)/$(libqblock-lib-la)
> +
> +tests/libqblock/%.lo: QEMU_INCLUDES += -I$(libqblock-lib-path) -Itests
> +
> +check-libqblock-y = tests/libqblock/check-libqblock-qcow2$(EXESUF)
> +tests/libqblock/check-libqblock-qcow2$(EXESUF): tests/libqblock/libqblock-qcow2.lo $(libqblock-la-path) $(qtest-lib-y)

No need to use .lo here.

> +	$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -shared -rpath $(libdir) -o $@ $^,"  lt LINK $@")
> +

> +$(libqblock-la-path):
> +	@echo "Building libqblock.la..."
> +	$(call quiet-command,$(MAKE) -C $(SRC_PATH) $(libqblock-lib-la),)

No need for this.

> +$(LIBQBLOCK_TEST_DIR):
> +	@echo "Make libqblock test directory"
> +	mkdir $(LIBQBLOCK_TEST_DIR)

You can leave the files in tests/ directly, and avoid this as well.

> +check-libqblock: $(libqblock-la-path) $(LIBQBLOCK_TEST_DIR) $(patsubst %,check-%, $(check-libqblock-y))

Please add

check: check-libqblock

here, so that if libtool is present the check is run automatically.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 1/5] libqblock build system
  2012-09-27  8:06   ` Paolo Bonzini
@ 2012-09-27  9:39     ` Wenchao Xia
  0 siblings, 0 replies; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  9:39 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Kevin Wolf, Anthony Liguori, Eric Blake, qemu-devel,
	Stefan Hajnoczi

Ok, I'll correct them.

> Il 27/09/2012 04:23, Wenchao Xia ha scritto:
>>    Libqblock was placed in new directory ./libqblock, libtool will build
>> dynamic library there, source files of block layer remains in ./block.
>> So block related source code will generate 3 sets of binary, first is old
>> ones used in qemu, second and third are non PIC and PIC ones in ./libqblock.
>>    GCC compiler flag visibility=hidden was used with special macro, to export
>> only symbols that was marked as PUBLIC.
>>
>> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> ---
>>   Makefile                    |   14 +++++++++-
>>   Makefile.objs               |    6 ++++
>>   libqblock/Makefile          |   56 +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 74 insertions(+), 2 deletions(-)
>>   create mode 100644 libqblock/Makefile
>>   create mode 100644 libqblock/libqblock-error.c
>>   create mode 100644 libqblock/libqblock.c
>>
>> diff --git a/Makefile b/Makefile
>> index def2ae2..128bc6a 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -164,6 +164,17 @@ qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
>>
>>   qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
>>
>> +######################################################################
>> +# Support building shared library libqblock
>> +ifeq ($(LIBTOOL),)
>> +$(libqblock-lib-la):
>> +	@echo "libtool is missing, please install and rerun configure"; exit 1
>> +else
>> +$(libqblock-lib-la):
>> +	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libqblock V="$(V)" TARGET_DIR="$*/" $(libqblock-lib-la),)
>> +endif
>
> Please remove the useless indirection via $(libqblock-lib-la).  In general,
> this patch should be redone more similar to how libcacard is build:
>
> subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-timer-common.o
> ...
> libcacard.la: $(oslib-obj-y) qemu-timer-common.o $(trace-obj-y)
>          $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" libcacard.la,)
>
> install-libcacard: libcacard.la
>          $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" install-libcacard,)
>
>
> (The ifeq is not necessary, I'm going to remove it from libcacard too.  The
> same error message is already raised in libcacard/Makefile).
>
>> +###########################################################################
>> +
>>   vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) $(trace-obj-y) $(tools-obj-y) qemu-timer-common.o libcacard/vscclient.o
>>   	$(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) $(LIBS),"  LINK  $@")
>>
>> @@ -226,8 +237,7 @@ clean:
>>   	rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
>>   	rm -rf qapi-generated
>>   	rm -rf qga/qapi-generated
>> -	$(MAKE) -C tests/tcg clean
>> -	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
>> +	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard libqblock; do \
>>   	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
>>   	rm -f $$d/qemu-options.def; \
>>           done
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 4412757..8a4c9fc 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -248,3 +248,9 @@ nested-vars += \
>>   	common-obj-y \
>>   	extra-obj-y
>>   dummy := $(call unnest-vars)
>> +
>> +#############################################################################
>> +# libqblock
>> +
>> +libqblock-lib-la = libqblock.la
>> +libqblock-lib-path = libqblock
>
> Remove these two please.
>
>> diff --git a/libqblock/Makefile b/libqblock/Makefile
>> new file mode 100644
>> index 0000000..5f65613
>> --- /dev/null
>> +++ b/libqblock/Makefile
>> @@ -0,0 +1,56 @@
>> +###########################################################################
>> +# libqblock Makefile
>> +# Todo:
>> +#    1 trace related files is generated in this directory, move
>> +#  them to the root directory.
>> +##########################################################################
>> +-include ../config-host.mak
>> +-include $(SRC_PATH)/Makefile.objs
>> +-include $(SRC_PATH)/rules.mak
>> +
>> +#############################################################################
>> +# Library settings
>> +#############################################################################
>> +$(call set-vpath, $(SRC_PATH))
>> +
>> +#expand the foldered vars,especially ./block
>> +dummy := $(call unnest-vars-1)
>
> Please use unnest-vars.
>
>> +#library objects
>> +libqblock-y=libqblock.o libqblock-error.o
>> +
>> +QEMU_OBJS= $(libqblock-y) $(block-obj-y)
>> +#filter out ./block
>> +QEMU_OBJS_FILTERED=$(filter %.o, $(QEMU_OBJS))
>> +QEMU_OBJS_LIB=$(patsubst %.o, %.lo, $(QEMU_OBJS_FILTERED))
>> +
>> +QEMU_CFLAGS+= -I../ -I../include
>> +#adding magic macro define for symbol hiding and exposing
>> +QEMU_CFLAGS+= -fvisibility=hidden -D LIBQB_BUILD
>> +
>> +#dependency libraries
>> +LIBS+=-lz $(LIBS_TOOLS)
>> +
>> +#################################################################
>> +# Runtime rules
>> +#################################################################
>> +clean:
>> +	rm -f *.lo *.o *.d *.la libqblock-test trace.c trace.c-timestamp
>> +	rm -rf .libs block trace
>> +
>> +help:
>> +	@echo type make libqblock-test at root dirtory, libtool is required
>
> Please remove this rule.
>
>> +#make directory ./block at runtime which would hold the output of block/*.c
>> +block:
>> +	@mkdir block
>> +
>> +ifeq ($(LIBTOOL),)
>> +$(libqblock-lib-la):
>> +	@echo "libtool is missing, please install and rerun configure"; exit 1
>> +else
>> +$(libqblock-lib-la): $(QEMU_OBJS_LIB)
>> +	$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -rpath $(libdir) -o $@ $^ $(LIBS),"  lt LINK $@")
>> +endif
>> +
>> +.PHONY: libqblock.la
>


-- 
Best Regards

Wenchao Xia

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-27  8:25   ` Paolo Bonzini
@ 2012-09-27  9:52     ` Wenchao Xia
  2012-09-27 10:16       ` Paolo Bonzini
  0 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  9:52 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

   I will change the code for most of comments, but have some response
below.
> Il 27/09/2012 04:23, Wenchao Xia ha scritto:
>>    This patch contains type and macro defines used in APIs, one file for public
>> usage by user, one for libqblock internal usage.
>>
>> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> ---
>>   libqblock/libqblock-internal.h |   57 +++++++++
>>   libqblock/libqblock-types.h    |  268 ++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 325 insertions(+), 0 deletions(-)
>>   create mode 100644 libqblock/libqblock-internal.h
>>   create mode 100644 libqblock/libqblock-types.h
>>
>> diff --git a/libqblock/libqblock-internal.h b/libqblock/libqblock-internal.h
>> new file mode 100644
>> index 0000000..d3e983c
>> --- /dev/null
>> +++ b/libqblock/libqblock-internal.h
>> @@ -0,0 +1,57 @@
>> +/*
>> + * QEMU block layer library
>> + *
>> + * Copyright IBM, Corp. 2012
>> + *
>> + * Authors:
>> + *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef LIBQBLOCK_INTERNAL
>> +#define LIBQBLOCK_INTERNAL
>> +
>> +#include "glib.h"
>> +
>> +#include "block.h"
>> +#include "block_int.h"
>> +#include "libqblock-types.h"
>> +
>> +/* this file contains defines and types used inside the library. */
>> +
>> +#define FUNC_FREE(p) g_free((p))
>> +#define FUNC_MALLOC(size) g_malloc((size))
>> +#define FUNC_CALLOC(nmemb, size) g_malloc0((nmemb)*(size))
>> +#define FUNC_STRDUP(p) g_strdup((p))
>> +
>> +#define CLEAN_FREE(p) { \
>> +        FUNC_FREE(p); \
>> +        (p) = NULL; \
>> +}
>> +
>> +/* details should be hidden to user */
>> +struct QBlockState {
>> +    BlockDriverState *bdrvs;
>> +    /* internal used file name now, if it is not NULL, it means
>> +       image was opened.
>> +    */
>> +    char *filename;
>> +};
>> +
>> +struct QBlockContext {
>> +    /* last error */
>> +    GError *g_error;
>> +    int err_ret; /* 1st level of error, the libqblock error number */
>> +    int err_no; /* 2nd level of error, errno what below reports */
>> +};
>> +
>> +#define G_LIBQBLOCK_ERROR g_libqbock_error_quark()
>> +
>> +static inline GQuark g_libqbock_error_quark(void)
>> +{
>> +    return g_quark_from_static_string("g-libqblock-error-quark");
>> +}
>> +#endif
>> diff --git a/libqblock/libqblock-types.h b/libqblock/libqblock-types.h
>> new file mode 100644
>> index 0000000..948ab8a
>> --- /dev/null
>> +++ b/libqblock/libqblock-types.h
>> @@ -0,0 +1,268 @@
>> +/*
>> + * QEMU block layer library
>> + *
>> + * Copyright IBM, Corp. 2012
>> + *
>> + * Authors:
>> + *  Wenchao Xia   <xiawenc@linux.vnet.ibm.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef LIBQBLOCK_TYPES_H
>> +#define LIBQBLOCK_TYPES_H
>> +
>> +#include <sys/types.h>
>> +#include <stdint.h>
>> +#include <stdbool.h>
>> +
>> +#if defined(__GNUC__) && __GNUC__ >= 4
>> +    #ifdef LIBQB_BUILD
>> +        #define DLL_PUBLIC __attribute__((visibility("default")))
>> +    #else
>> +        #define DLL_PUBLIC
>> +    #endif
>> +#else
>> +    #warning : gcc compiler version < 4, symbols can not be hidden.
>
> You don't need to warn.  If LIBQB_BUILD is not defined, DLL_PUBLIC would
> be empty anyway.  If LIBQB_BUILD is defined, you know GCC >= 4.0 because
> you pass -fvisibility=hidden from the Makefile.
>
>> +#endif
>> +
>> +/* this library is designed around this core struct. */
>> +typedef struct QBlockState QBlockState;
>> +
>> +/* every thread should have a context. */
>> +typedef struct QBlockContext QBlockContext;
>> +
>> +/* flag used in open and create */
>> +#define LIBQBLOCK_O_RDWR        0x0002
>> +/* do not use the host page cache */
>> +#define LIBQBLOCK_O_NOCACHE     0x0020
>> +/* use write-back caching */
>> +#define LIBQBLOCK_O_CACHE_WB    0x0040
>> +/* don't open the backing file */
>> +#define LIBQBLOCK_O_NO_BACKING  0x0100
>> +/* disable flushing on this disk */
>> +#define LIBQBLOCK_O_NO_FLUSH    0x0200
>> +
>> +#define LIBQBLOCK_O_CACHE_MASK \
>> +   (LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | LIBQBLOCK_O_NO_FLUSH)
>> +
>> +#define LIBQBLOCK_O_VALID_MASK \
>> +   (LIBQBLOCK_O_RDWR | LIBQBLOCK_O_NOCACHE | LIBQBLOCK_O_CACHE_WB | \
>> +    LIBQBLOCK_O_NO_BACKING | LIBQBLOCK_O_NO_FLUSH)
>> +
>> +typedef enum QBlockProtType {
>> +    QB_PROT_NONE = 0,
>> +    QB_PROT_FILE,
>> +    QB_PROT_MAX
>> +} QBlockProtType;
>
> Use QBlockProtocol, QB_PROTO_*.
>
>> +typedef struct QBlockProtOptionFile {
>> +    const char *filename;
>> +} QBlockProtOptionFile;
>
> Use QBlockProtocolOptionsFile
>
>> +#define QBLOCK_PROT_OPTIONS_UNION_SIZE (512)
>> +typedef union QBlockProtOptionsUnion {
>> +    QBlockProtOptionFile o_file;
>> +    uint8_t reserved[QBLOCK_PROT_OPTIONS_UNION_SIZE];
>> +} QBlockProtOptionsUnion;
>
> Not really options, because they are required.  I would just not name
> the union, and embed it in the struct.  Also please change it to
>
>       uint64_t reserved[QBLOCK_PROT_OPTIONS_UNION_SIZE / 8];
>
> (Sorry for not thinking about this before).  This will fix the alignment
> and ensure that future changes to the union do not change the ABI.
>
   You are right, I forgot alignment issue before.

>> +/**
>> + * struct QBlockProtInfo: contains information about how to find the image
>> + *
>> + * @prot_type: protocol type, now only support FILE.
>> + * @prot_op: protocol related options.
>> + */
>> +typedef struct QBlockProtInfo {
>> +    QBlockProtType prot_type;
>> +    QBlockProtOptionsUnion prot_op;
>> +} QBlockProtInfo;
>
> What about QBlockLocation instead?  Or QBlockLocationInfo.
>
>> +
>> +/* format related options */
>> +typedef enum QBlockFmtType {
>> +    QB_FMT_NONE = 0,
>> +    QB_FMT_COW,
>> +    QB_FMT_QED,
>> +    QB_FMT_QCOW,
>> +    QB_FMT_QCOW2,
>> +    QB_FMT_RAW,
>> +    QB_FMT_RBD,
>> +    QB_FMT_SHEEPDOG,
>> +    QB_FMT_VDI,
>> +    QB_FMT_VMDK,
>> +    QB_FMT_VPC,
>> +    QB_FMT_MAX
>> +} QBlockFmtType;
>
> QBlockFormat; similarly remove "Type" from all enums.
>
>> +typedef struct QBlockFmtOptionCow {
>> +    uint64_t virt_size;
>> +    QBlockProtInfo backing_loc;
>> +} QBlockFmtOptionCow;
>
> QBlockFormatOptionsCOW.  Similarly use the plural for all other formats.
>
>> +typedef struct QBlockFmtOptionQed {
>> +    uint64_t virt_size;
>> +    QBlockProtInfo backing_loc;
>> +    QBlockFmtType backing_fmt;
>> +    uint64_t cluster_size; /* unit is bytes */
>> +    uint64_t table_size; /* unit is clusters */
>> +} QBlockFmtOptionQed;
>
> Similarly use uppercase for QED, QCOW, etc.
>
>> +typedef struct QBlockFmtOptionQcow {
>> +    uint64_t virt_size;
>> +    QBlockProtInfo backing_loc;
>> +    bool encrypt;
>> +} QBlockFmtOptionQcow;
>> +
>> +/* "Compatibility level (0.10 or 1.1)" */
>> +typedef enum QBlockFmtOptionQcow2CptLv {
>> +    QBO_FMT_QCOW2_CPT_NONE = 0,
>> +    QBO_FMT_QCOW2_CPT_V010,
>> +    QBO_FMT_QCOW2_CPT_V110,
>> +} QBlockFmtOptionQcow2CptLv;
>
> Please use QBO_ instead of QB_ throughout.  Also write COMPAT instead of
> CPT, and remove CPT_NONE since 0.10 is the default:
>
   __NONE is used to indicate whether this property is set or get, so
it is actually have 3 status than just 2: Not set, V010, V110. It
is the same reason that I use __NONE in bool values, especially __NONE 
could represent it is not got in information retrieving. Maybe I should
rename them to __NOTSET.

> typedef enum QBlockFmtOptionQCOW2Compat {
>      QB_FMT_QCOW2_COMPAT_V0_10,
>      QB_FMT_QCOW2_COMPAT_V1_1,
> } QBlockFmtOptionQCOW2Compat
>
>> +/* off or metadata */
>> +typedef enum QBlockFmtOptionQcow2PreAllocType {
>> +    QBO_FMT_QCOW2_PREALLOC_NONE = 0,
>> +    QBO_FMT_QCOW2_PREALLOC_OFF,
>> +    QBO_FMT_QCOW2_PREALLOC_METADATA,
>> +} QBlockFmtOptionQcow2PreAllocType;
>
> Please remove NONE since OFF is the default.  However, I would use the enum.
>
>> +typedef struct QBlockFmtOptionQcow2 {
>> +    uint64_t virt_size;
>> +    QBlockProtInfo backing_loc;
>> +    QBlockFmtType backing_fmt;
>> +    bool encrypt;
>> +    uint64_t cluster_size; /* unit is bytes */
>> +    QBlockFmtOptionQcow2CptLv cpt_lv;
>> +    QBlockFmtOptionQcow2PreAllocType pre_mode;
>> +} QBlockFmtOptionQcow2;
>> +
>> +typedef struct QBlockFmtOptionRaw {
>> +    uint64_t virt_size;
>> +} QBlockFmtOptionRaw;
>> +
>> +typedef struct QBlockFmtOptionRbd {
>> +    uint64_t virt_size;
>> +    uint64_t cluster_size;
>> +} QBlockFmtOptionRbd;
>> +
>> +/* off or full */
>> +typedef enum QBlockFmtOptionSheepdogPreAllocType {
>> +    QBO_FMT_SD_PREALLOC_NONE = 0,
>> +    QBO_FMT_SD_PREALLOC_OFF,
>> +    QBO_FMT_SD_PREALLOC_FULL,
>> +} QBlockFmtOptionSheepdogPreAllocType;
>
> The default is false, so just make it a bool.
>
>> +typedef struct QBlockFmtOptionSheepdog {
>> +    uint64_t virt_size;
>> +    QBlockProtInfo backing_loc;
>> +    QBlockFmtOptionSheepdogPreAllocType pre_mode;
>> +} QBlockFmtOptionSheepdog;
>> +
>> +typedef enum QBlockFmtOptionVdiPreAllocType {
>> +    QBO_FMT_VDI_PREALLOC_NONE = 0,
>> +    QBO_FMT_VDI_PREALLOC_FALSE,
>> +    QBO_FMT_VDI_PREALLOC_TRUE,
>> +} QBlockFmtOptionVdiPreAllocType;
>
> Please remove NONE, and replace FALSE/TRUE with OFF/METADATA (same as
> qcow2).
>
>> +typedef struct QBlockFmtOptionVdi {
>> +    uint64_t virt_size;
>> +    uint64_t cluster_size;
>> +    QBlockFmtOptionVdiPreAllocType pre_mode;
>> +} QBlockFmtOptionVdi;
>> +
>> +/* whether compact to vmdk verion 6 */
>> +typedef enum QBlockFmtOptionVmdkCptLv {
>> +    QBO_FMT_VMDK_CPT_NONE = 0,
>> +    QBO_FMT_VMDK_CPT_VMDKV6_FALSE,
>> +    QBO_FMT_VMDK_CPT_VMDKV6_TRUE,
>> +} QBlockFmtOptionVmdkCptLv;
>
> Here the default is false, so just make it a bool.
>
>> +/* vmdk flat extent format, values:
>> +"{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse |
>> +twoGbMaxExtentFlat | streamOptimized} */
>> +typedef enum QBlockFmtOptionVmdkSubfmtType {
>> +    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE = 0,
>> +    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_SPARSE,
>
> You can remove QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE (whose more
> appropriate name would be just ...SUBFMT_NONE) since the default is
> QBO_FMT_VMDK_SUBFMT_MONOLITHIC_SPARSE.
>
>> +    QBO_FMT_VMDK_SUBFMT_MONOLITHIC_FLAT,
>> +    QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_SPARSE,
>> +    QBO_FMT_VMDK_SUBFMT_TWOGBMAX_EXTENT_FLAT,
>> +    QBO_FMT_VMDK_SUBFMT_STREAM_OPTIMIZED,
>> +} QBlockFmtOptionVmdkSubfmtType;
>> +
>> +typedef struct QBlockFmtOptionVmdk {
>> +    uint64_t virt_size;
>> +    QBlockProtInfo backing_loc;
>> +    QBlockFmtOptionVmdkCptLv cpt_lv;
>> +    QBlockFmtOptionVmdkSubfmtType subfmt;
>> +} QBlockFmtOptionVmdk;
>> +
>> +/* "{dynamic (default) | fixed} " */
>> +typedef enum QBlockFmtOptionVpcSubfmtType {
>> +    QBO_FMT_VPC_SUBFMT_NONE = 0,
>> +    QBO_FMT_VPC_SUBFMT_DYNAMIC,
>> +    QBO_FMT_VPC_SUBFMT_FIXED,
>> +} QBlockFmtOptionVpcSubfmtType;
>
> Again, please remove NONE.
>
>> +typedef struct QBlockFmtOptionVpc {
>> +    uint64_t virt_size;
>> +    QBlockFmtOptionVpcSubfmtType subfmt;
>> +} QBlockFmtOptionVpc;
>> +
>> +#define QBLOCK_FMT_OPTIONS_UNION_SIZE (QBLOCK_PROT_OPTIONS_UNION_SIZE*2)
>> +typedef union QBlockFmtOptionsUnion {
>> +    QBlockFmtOptionCow       o_cow;
>> +    QBlockFmtOptionQed       o_qed;
>> +    QBlockFmtOptionQcow      o_qcow;
>> +    QBlockFmtOptionQcow2     o_qcow2;
>> +    QBlockFmtOptionRaw       o_raw;
>> +    QBlockFmtOptionRbd       o_rbd;
>> +    QBlockFmtOptionSheepdog  o_sheepdog;
>> +    QBlockFmtOptionVdi       o_vdi;
>> +    QBlockFmtOptionVmdk      o_vmdk;
>> +    QBlockFmtOptionVpc       o_vpc;
>> +    uint8_t reserved[QBLOCK_FMT_OPTIONS_UNION_SIZE];
>
> Similarly use uint64_t here, and just embed the union in the struct.
>
>> +} QBlockFmtOptionsUnion;
>> +typedef struct QBlockFmtInfo {
>> +    QBlockFmtType fmt_type;
>> +    QBlockFmtOptionsUnion fmt_op;
>> +} QBlockFmtInfo;
>
> QBlockFormatInfo.
>
>> +/**
>> + * QBlockStaticInfoAddr: a structure contains a set of pointer.
>> + *
>> + *    this struct contains a set of pointer pointing to some
>> + *  property related to format or protocol. If a property is not available,
>> + *  it will be set as NULL. User could use this to get properties directly.
>> + *
>> + *  @virt_size: virtual size, it is always not NULL.
>> + *  @backing_loc: backing file location.
>> + *  @encrypt: encryption flag.
>> +*/
>> +
>> +typedef struct QBlockStaticInfoAddr {
>> +    uint64_t *virt_size;
>> +    QBlockProtInfo *backing_loc;
>> +    bool *encrypt;
>> +} QBlockStaticInfoAddr;
>
> Why the indirection?
>
   It helps user to get these important members, otherwise
user will need
Switch (fmt) {
   case RAW:
     ....
   case QCOW2:
     ...
}
for every attribute. The indirection address will let user directly
access the members.

>> +/**
>> + * QBlockStaticInfo: information about the block image.
>> + *
>> + * @member_addr: contains pointer which can be used to access the structure.
>> + * @loc: location information.
>> + * @fmt: format information.
>> + * @sector_size: how many bytes in a sector, it is 512 usually.
>> + */
>> +typedef struct QBlockStaticInfo {
>> +    QBlockStaticInfoAddr *member_addr;
>> +    QBlockProtInfo loc;
>> +    QBlockFmtInfo fmt;
>> +    int sector_size;
>> +} QBlockStaticInfo;
>> +
>> +
>> +#endif
>>
>


-- 
Best Regards

Wenchao Xia

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system
  2012-09-27  8:30   ` Paolo Bonzini
@ 2012-09-27  9:56     ` Wenchao Xia
  2012-09-27 10:17       ` Paolo Bonzini
  0 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-27  9:56 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini

于 2012-9-27 16:30, Paolo Bonzini 写道:
> Il 27/09/2012 04:24, Wenchao Xia ha scritto:
>> +#libqblock
>> +LIBQBLOCK_TEST_DIR=$(SRC_PATH)/tests/libqblock/test_images
>> +qtest-lib-y=$(patsubst %.o, %.lo,$(qtest-obj-y))
>
> I don't think you need qtest-obj-y for anything.
>
  OK, I will remove it.

>> +libqblock-la-path = $(libqblock-lib-path)/$(libqblock-lib-la)
>> +
>> +tests/libqblock/%.lo: QEMU_INCLUDES += -I$(libqblock-lib-path) -Itests
>> +
>> +check-libqblock-y = tests/libqblock/check-libqblock-qcow2$(EXESUF)
>> +tests/libqblock/check-libqblock-qcow2$(EXESUF): tests/libqblock/libqblock-qcow2.lo $(libqblock-la-path) $(qtest-lib-y)
>
> No need to use .lo here.
>
OK.

>> +	$(call quiet-command,$(LIBTOOL) --mode=link --quiet --tag=CC $(CC) -shared -rpath $(libdir) -o $@ $^,"  lt LINK $@")
>> +
>
>> +$(libqblock-la-path):
>> +	@echo "Building libqblock.la..."
>> +	$(call quiet-command,$(MAKE) -C $(SRC_PATH) $(libqblock-lib-la),)
>
> No need for this.
OK.

>
>> +$(LIBQBLOCK_TEST_DIR):
>> +	@echo "Make libqblock test directory"
>> +	mkdir $(LIBQBLOCK_TEST_DIR)
>
> You can leave the files in tests/ directly, and avoid this as well.
   Having a new directory will make clean easier, otherwise the script
will need to know each image file names created, whose filename are
generated in test C code at runtime.

>
>> +check-libqblock: $(libqblock-la-path) $(LIBQBLOCK_TEST_DIR) $(patsubst %,check-%, $(check-libqblock-y))
>
> Please add
>
> check: check-libqblock
>
> here, so that if libtool is present the check is run automatically.
OK.

>
> Paolo
>


-- 
Best Regards

Wenchao Xia

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-27  9:52     ` Wenchao Xia
@ 2012-09-27 10:16       ` Paolo Bonzini
  2012-09-28  3:00         ` Wenchao Xia
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-27 10:16 UTC (permalink / raw)
  To: Wenchao Xia; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

Il 27/09/2012 11:52, Wenchao Xia ha scritto:
>>
>> Please use QBO_ instead of QB_ throughout.  Also write COMPAT instead of
>> CPT, and remove CPT_NONE since 0.10 is the default:
>>
>   __NONE is used to indicate whether this property is set or get, so
> it is actually have 3 status than just 2: Not set, V010, V110. It
> is the same reason that I use __NONE in bool values, especially __NONE
> could represent it is not got in information retrieving.

Yes, that I guessed.  I thought in many cases we can anticipate that the
default is not going to change, but perhaps it's better to be safe
(which is what you did).

Please do change FALSE/TRUE to OFF/METADATA for preallocation enums, and
please remove MONOLITHIC from QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE.

> Maybe I should rename them to __NOTSET.

Perhaps "_DEFAULT" is even bette?

Paolo

>>>
>>> +typedef struct QBlockStaticInfoAddr {
>>> +    uint64_t *virt_size;
>>> +    QBlockProtInfo *backing_loc;
>>> +    bool *encrypt;
>>> +} QBlockStaticInfoAddr;
>>
>> Why the indirection?
>>
>   It helps user to get these important members, otherwise
> user will need
> Switch (fmt) {
>   case RAW:
>     ....
>   case QCOW2:
>     ...
> }
> for every attribute. The indirection address will let user directly
> access the members.

Ah, ok, now I understand.  Interesting.  An alternative could be to add
generic accessors like these:

uint64_t qblock_get_virt_size(QBlockFmtInfo *fmt);
QBlockProtInfo *qblock_get_backing_loc(QBlockFmtInfo *fmt);
bool qblock_get_encrypt(QBlockFmtInfo *fmt);

etc. that include the switch statement.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system
  2012-09-27  9:56     ` Wenchao Xia
@ 2012-09-27 10:17       ` Paolo Bonzini
  2012-09-28  3:04         ` Wenchao Xia
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-27 10:17 UTC (permalink / raw)
  To: Wenchao Xia; +Cc: qemu-devel

Il 27/09/2012 11:56, Wenchao Xia ha scritto:
>>
>>> +$(LIBQBLOCK_TEST_DIR):
>>> +    @echo "Make libqblock test directory"
>>> +    mkdir $(LIBQBLOCK_TEST_DIR)
>>
>> You can leave the files in tests/ directly, and avoid this as well.
>   Having a new directory will make clean easier, otherwise the script
> will need to know each image file names created, whose filename are
> generated in test C code at runtime.

If you want a subdirectory for images, you can create it in the test code.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-27 10:16       ` Paolo Bonzini
@ 2012-09-28  3:00         ` Wenchao Xia
  2012-09-28  7:51           ` Paolo Bonzini
  0 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-28  3:00 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

于 2012-9-27 18:16, Paolo Bonzini 写道:
> Il 27/09/2012 11:52, Wenchao Xia ha scritto:
>>>
>>> Please use QBO_ instead of QB_ throughout.  Also write COMPAT instead of
>>> CPT, and remove CPT_NONE since 0.10 is the default:
>>>
>>    __NONE is used to indicate whether this property is set or get, so
>> it is actually have 3 status than just 2: Not set, V010, V110. It
>> is the same reason that I use __NONE in bool values, especially __NONE
>> could represent it is not got in information retrieving.
>
> Yes, that I guessed.  I thought in many cases we can anticipate that the
> default is not going to change, but perhaps it's better to be safe
> (which is what you did).
>
> Please do change FALSE/TRUE to OFF/METADATA for preallocation enums, and
> please remove MONOLITHIC from QBO_FMT_VMDK_SUBFMT_MONOLITHIC_NONE.
>
   OK, these should be changed.

>> Maybe I should rename them to __NOTSET.
>
> Perhaps "_DEFAULT" is even bette?
>
> Paolo
>
   Yep, _DEFAULT seems good to me.

>>>>
>>>> +typedef struct QBlockStaticInfoAddr {
>>>> +    uint64_t *virt_size;
>>>> +    QBlockProtInfo *backing_loc;
>>>> +    bool *encrypt;
>>>> +} QBlockStaticInfoAddr;
>>>
>>> Why the indirection?
>>>
>>    It helps user to get these important members, otherwise
>> user will need
>> Switch (fmt) {
>>    case RAW:
>>      ....
>>    case QCOW2:
>>      ...
>> }
>> for every attribute. The indirection address will let user directly
>> access the members.
>
> Ah, ok, now I understand.  Interesting.  An alternative could be to add
> generic accessors like these:
>
> uint64_t qblock_get_virt_size(QBlockFmtInfo *fmt);
> QBlockProtInfo *qblock_get_backing_loc(QBlockFmtInfo *fmt);
> bool qblock_get_encrypt(QBlockFmtInfo *fmt);
>
> etc. that include the switch statement.
>
   I think it is reasonable use generic accessors instead of embbed
structure, maybe an additional helper function should be added as:

QBlockStaticInfoAddr *qblock_get_static_info_addr(QBlockStaticInfo
  *info)

   In this way only one switch statement is needed in source code,
and only one new API is added.

> Paolo
>


-- 
Best Regards

Wenchao Xia

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system
  2012-09-27 10:17       ` Paolo Bonzini
@ 2012-09-28  3:04         ` Wenchao Xia
  2012-09-28  7:52           ` Paolo Bonzini
  0 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-28  3:04 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

于 2012-9-27 18:17, Paolo Bonzini 写道:
> Il 27/09/2012 11:56, Wenchao Xia ha scritto:
>>>
>>>> +$(LIBQBLOCK_TEST_DIR):
>>>> +    @echo "Make libqblock test directory"
>>>> +    mkdir $(LIBQBLOCK_TEST_DIR)
>>>
>>> You can leave the files in tests/ directly, and avoid this as well.
>>    Having a new directory will make clean easier, otherwise the script
>> will need to know each image file names created, whose filename are
>> generated in test C code at runtime.
>
> If you want a subdirectory for images, you can create it in the test code.
>
   My original idea is creating and deleting them in C test code, but I
found that there is many "assert" in the code, which may cause the clean
step missing. So I think it is simpler to clean them in Makefile, make
sure the temporal files are deleted.

> Paolo
>


-- 
Best Regards

Wenchao Xia

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-28  3:00         ` Wenchao Xia
@ 2012-09-28  7:51           ` Paolo Bonzini
  2012-09-28 10:52             ` Wenchao Xia
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-28  7:51 UTC (permalink / raw)
  To: Wenchao Xia; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

Il 28/09/2012 05:00, Wenchao Xia ha scritto:
>>
>>
>> uint64_t qblock_get_virt_size(QBlockFmtInfo *fmt);
>> QBlockProtInfo *qblock_get_backing_loc(QBlockFmtInfo *fmt);
>> bool qblock_get_encrypt(QBlockFmtInfo *fmt);
>>
>> etc. that include the switch statement.
>>
>   I think it is reasonable use generic accessors instead of embbed
> structure, maybe an additional helper function should be added as:
> 
> QBlockStaticInfoAddr *qblock_get_static_info_addr(QBlockStaticInfo
>  *info)
> 
>   In this way only one switch statement is needed in source code,
> and only one new API is added.

No problem for the implementation, but please make this function static.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system
  2012-09-28  3:04         ` Wenchao Xia
@ 2012-09-28  7:52           ` Paolo Bonzini
  2012-09-28  9:46             ` Wenchao Xia
  0 siblings, 1 reply; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-28  7:52 UTC (permalink / raw)
  To: Wenchao Xia; +Cc: qemu-devel

Il 28/09/2012 05:04, Wenchao Xia ha scritto:
>>>>> +$(LIBQBLOCK_TEST_DIR):
>>>>> +    @echo "Make libqblock test directory"
>>>>> +    mkdir $(LIBQBLOCK_TEST_DIR)
>>>>
>>>> You can leave the files in tests/ directly, and avoid this as well.
>>>    Having a new directory will make clean easier, otherwise the script
>>> will need to know each image file names created, whose filename are
>>> generated in test C code at runtime.
>>
>> If you want a subdirectory for images, you can create it in the test
>> code.
>>
>   My original idea is creating and deleting them in C test code, but I
> found that there is many "assert" in the code, which may cause the clean
> step missing. So I think it is simpler to clean them in Makefile, make
> sure the temporal files are deleted.

Yes, you can mkdir() in the test code, and delete the whole directory
from the Makefile.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system
  2012-09-28  7:52           ` Paolo Bonzini
@ 2012-09-28  9:46             ` Wenchao Xia
  0 siblings, 0 replies; 21+ messages in thread
From: Wenchao Xia @ 2012-09-28  9:46 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

于 2012-9-28 15:52, Paolo Bonzini 写道:
> Il 28/09/2012 05:04, Wenchao Xia ha scritto:
>>>>>> +$(LIBQBLOCK_TEST_DIR):
>>>>>> +    @echo "Make libqblock test directory"
>>>>>> +    mkdir $(LIBQBLOCK_TEST_DIR)
>>>>>
>>>>> You can leave the files in tests/ directly, and avoid this as well.
>>>>     Having a new directory will make clean easier, otherwise the script
>>>> will need to know each image file names created, whose filename are
>>>> generated in test C code at runtime.
>>>
>>> If you want a subdirectory for images, you can create it in the test
>>> code.
>>>
>>    My original idea is creating and deleting them in C test code, but I
>> found that there is many "assert" in the code, which may cause the clean
>> step missing. So I think it is simpler to clean them in Makefile, make
>> sure the temporal files are deleted.
>
> Yes, you can mkdir() in the test code, and delete the whole directory
> from the Makefile.
>
   Ok, I got your idea.

> Paolo
>


-- 
Best Regards

Wenchao Xia

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-28  7:51           ` Paolo Bonzini
@ 2012-09-28 10:52             ` Wenchao Xia
  2012-09-28 10:58               ` Paolo Bonzini
  0 siblings, 1 reply; 21+ messages in thread
From: Wenchao Xia @ 2012-09-28 10:52 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

于 2012-9-28 15:51, Paolo Bonzini 写道:
> Il 28/09/2012 05:00, Wenchao Xia ha scritto:
>>>
>>>
>>> uint64_t qblock_get_virt_size(QBlockFmtInfo *fmt);
>>> QBlockProtInfo *qblock_get_backing_loc(QBlockFmtInfo *fmt);
>>> bool qblock_get_encrypt(QBlockFmtInfo *fmt);
>>>
>>> etc. that include the switch statement.
>>>
>>    I think it is reasonable use generic accessors instead of embbed
>> structure, maybe an additional helper function should be added as:
>>
>> QBlockStaticInfoAddr *qblock_get_static_info_addr(QBlockStaticInfo
>>   *info)
>>
>>    In this way only one switch statement is needed in source code,
>> and only one new API is added.
>
> No problem for the implementation, but please make this function static.
>
> Paolo
>
   Do you mean declaring it as static function? I think user may need
call it to get information so it need to be public.



-- 
Best Regards

Wenchao Xia

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines
  2012-09-28 10:52             ` Wenchao Xia
@ 2012-09-28 10:58               ` Paolo Bonzini
  0 siblings, 0 replies; 21+ messages in thread
From: Paolo Bonzini @ 2012-09-28 10:58 UTC (permalink / raw)
  To: Wenchao Xia; +Cc: kwolf, aliguori, stefanha, qemu-devel, blauwirbel, eblake

Il 28/09/2012 12:52, Wenchao Xia ha scritto:
>> No problem for the implementation, but please make this function static.
>
>   Do you mean declaring it as static function? I think user may need
> call it to get information so it need to be public.

The user can use the accessors.  Let's not add a function to the public
interface until we're 101% sure it is a good idea.

Paolo

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2012-09-28 10:58 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-27  2:23 [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library Wenchao Xia
2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 1/5] libqblock build system Wenchao Xia
2012-09-27  8:06   ` Paolo Bonzini
2012-09-27  9:39     ` Wenchao Xia
2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 2/5] libqblock type defines Wenchao Xia
2012-09-27  8:25   ` Paolo Bonzini
2012-09-27  9:52     ` Wenchao Xia
2012-09-27 10:16       ` Paolo Bonzini
2012-09-28  3:00         ` Wenchao Xia
2012-09-28  7:51           ` Paolo Bonzini
2012-09-28 10:52             ` Wenchao Xia
2012-09-28 10:58               ` Paolo Bonzini
2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 3/5] libqblock API Wenchao Xia
2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 4/5] libqblock test build system Wenchao Xia
2012-09-27  8:30   ` Paolo Bonzini
2012-09-27  9:56     ` Wenchao Xia
2012-09-27 10:17       ` Paolo Bonzini
2012-09-28  3:04         ` Wenchao Xia
2012-09-28  7:52           ` Paolo Bonzini
2012-09-28  9:46             ` Wenchao Xia
2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 5/5] libqblock test example Wenchao Xia

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).