Patchwork [4/6] libqblock internal used functions

login
register
mail settings
Submitter Wayne Xia
Date Sept. 3, 2012, 9:18 a.m.
Message ID <1346663926-20188-5-git-send-email-xiawenc@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/181342/
State New
Headers show

Comments

Wayne Xia - Sept. 3, 2012, 9:18 a.m.
This patch contains internal helper codes.

Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
 block.c                      |    2 +-
 block.h                      |    1 +
 libqblock/libqblock-helper.c |   92 ++++++++++++++++++++++++++++++++++++++++++
 libqblock/libqblock-helper.h |   57 ++++++++++++++++++++++++++
 4 files changed, 151 insertions(+), 1 deletions(-)
 create mode 100644 libqblock/libqblock-helper.c
 create mode 100644 libqblock/libqblock-helper.h
Paolo Bonzini - Sept. 3, 2012, 1:18 p.m.
Il 03/09/2012 11:18, Wenchao Xia ha scritto:
>   This patch contains internal helper codes.
> 
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
>  block.c                      |    2 +-
>  block.h                      |    1 +
>  libqblock/libqblock-helper.c |   92 ++++++++++++++++++++++++++++++++++++++++++
>  libqblock/libqblock-helper.h |   57 ++++++++++++++++++++++++++
>  4 files changed, 151 insertions(+), 1 deletions(-)
>  create mode 100644 libqblock/libqblock-helper.c
>  create mode 100644 libqblock/libqblock-helper.h
> 
> diff --git a/block.c b/block.c
> index 470bdcc..8b312f8 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 2e2be11..e7da711 100644
> --- a/block.h
> +++ b/block.h
> @@ -405,4 +405,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-helper.c b/libqblock/libqblock-helper.c
> new file mode 100644
> index 0000000..f9e8ce9
> --- /dev/null
> +++ b/libqblock/libqblock-helper.c
> @@ -0,0 +1,92 @@
> +#include "libqblock-helper.h"
> +#include "libqblock-types.h"
> +#include "libqblock-error.h"
> +
> +const char *fmt2str(enum QBlockFormat fmt)
> +{
> +    const char *ret = NULL;
> +    switch (fmt) {
> +    case QB_FMT_COW:
> +        ret = "cow";
> +        break;
> +    case QB_FMT_QED:
> +        ret = "qed";
> +        break;
> +    case QB_FMT_QCOW:
> +        ret = "qcow";
> +        break;
> +    case QB_FMT_QCOW2:
> +        ret = "qcow2";
> +        break;
> +    case QB_FMT_RAW:
> +        ret = "raw";
> +        break;
> +    case QB_FMT_RBD:
> +        ret = "rbd";
> +        break;
> +    case QB_FMT_SHEEPDOG:
> +        ret = "sheepdog";
> +        break;
> +    case QB_FMT_VDI:
> +        ret = "vdi";
> +        break;
> +    case QB_FMT_VMDK:
> +        ret = "vmdk";
> +        break;
> +    case QB_FMT_VPC:
> +        ret = "vpc";
> +        break;
> +    default:
> +        break;
> +    }
> +    return ret;
> +}
> +
> +enum QBlockFormat str2fmt(const char *fmt)
> +{
> +    enum QBlockFormat ret = QB_FMT_NONE;
> +    if (0 == strcmp(fmt, "cow")) {
> +        ret = QB_FMT_COW;
> +    } else if (0 == strcmp(fmt, "qed")) {
> +        ret = QB_FMT_QED;
> +    } else if (0 == strcmp(fmt, "qcow")) {
> +        ret = QB_FMT_QCOW;
> +    } else if (0 == strcmp(fmt, "qcow2")) {
> +        ret = QB_FMT_QCOW2;
> +    } else if (0 == strcmp(fmt, "raw")) {
> +        ret = QB_FMT_RAW;
> +    } else if (0 == strcmp(fmt, "rbd")) {
> +        ret = QB_FMT_RBD;
> +    } else if (0 == strcmp(fmt, "sheepdog")) {
> +        ret = QB_FMT_SHEEPDOG;
> +    } else if (0 == strcmp(fmt, "vdi")) {
> +        ret = QB_FMT_VDI;
> +    } else if (0 == strcmp(fmt, "vmdk")) {
> +        ret = QB_FMT_VMDK;
> +    } else if (0 == strcmp(fmt, "vpc")) {
> +        ret = QB_FMT_VPC;
> +    }
> +    return ret;
> +}
> +
> +void set_broker_err(struct QBroker *broker, int err_ret,
> +                           const char *fmt, ...)
> +{
> +    va_list ap;
> +
> +    broker->err_ret = err_ret;
> +    if (err_ret == QB_ERR_INTERNAL_ERR) {
> +        broker->err_no = -errno;
> +    } else {
> +        broker->err_no = 0;
> +    }
> +
> +    va_start(ap, fmt);
> +    vsnprintf(broker->err_msg, sizeof(broker->err_msg), fmt, ap);
> +    va_end(ap);
> +}
> +
> +void set_broker_err_nomem(struct QBroker *broker)
> +{
> +    set_broker_err(broker, QB_ERR_MEM_ERR, "No Memory.");
> +}
> diff --git a/libqblock/libqblock-helper.h b/libqblock/libqblock-helper.h
> new file mode 100644
> index 0000000..4330472
> --- /dev/null
> +++ b/libqblock/libqblock-helper.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_HELPER
> +#define LIBQBLOCK_HELPER
> +
> +#include "block.h"
> +#include "block_int.h"
> +
> +#include "libqblock-types.h"
> +
> +/* this file contains helper function used internally. */
> +#define SECTOR_SIZE (512)
> +#define SECTOR_SIZE_MASK (0x01ff)
> +#define SECTOR_SIZE_BITS_NUM (9)
> +#define FUNC_FREE free
> +#define FUNC_MALLOC malloc
> +#define FUNC_CALLOC calloc
> +
> +#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;
> +};
> +
> +#define QB_ERR_STRING_SIZE (1024)
> +struct QBroker {
> +    /* last error */
> +    char err_msg[QB_ERR_STRING_SIZE];
> +    int err_ret; /* last error return of libqblock. */
> +    int err_no; /* 2nd level of error, errno what below reports */
> +};
> +
> +const char *fmt2str(enum QBlockFormat fmt);
> +enum QBlockFormat str2fmt(const char *fmt);
> +void set_broker_err(struct QBroker *broker, int err_ret,
> +                           const char *fmt, ...);
> +void set_broker_err_nomem(struct QBroker *broker);
> +#endif
> 

Please squash this into patch 1, there is no need to keep separate files.

Paolo
Eric Blake - Sept. 3, 2012, 2:28 p.m.
On 09/03/2012 03:18 AM, Wenchao Xia wrote:
>   This patch contains internal helper codes.
> 
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
>  block.c                      |    2 +-
>  block.h                      |    1 +
>  libqblock/libqblock-helper.c |   92 ++++++++++++++++++++++++++++++++++++++++++
>  libqblock/libqblock-helper.h |   57 ++++++++++++++++++++++++++
>  4 files changed, 151 insertions(+), 1 deletions(-)
>  create mode 100644 libqblock/libqblock-helper.c
>  create mode 100644 libqblock/libqblock-helper.h
> 

> +++ b/libqblock/libqblock-helper.c
> @@ -0,0 +1,92 @@
> +#include "libqblock-helper.h"

No copyright.  Shame.  I'll quit pointing it out for the rest of the series.

> +++ b/libqblock/libqblock-helper.h

> +
> +/* this file contains helper function used internally. */
> +#define SECTOR_SIZE (512)

Hard-coding this feels wrong, in this day and age of disks with 4096
sectors.  Why isn't this a per-image property?

> +#define SECTOR_SIZE_MASK (0x01ff)
> +#define SECTOR_SIZE_BITS_NUM (9)

and these computed from a dynamic per-image sector size?

> +#define FUNC_FREE free
> +#define FUNC_MALLOC malloc
> +#define FUNC_CALLOC calloc

Is libqblock-helper.h intended to be installed and included in client
applications, or is it internal only?  If clients can ever use this
header, then you need to avoid namespace violations, by using naming
such as QB_SECTOR_SIZE, QB_FUNC_FREE, and so forth.

> +
> +const char *fmt2str(enum QBlockFormat fmt);
> +enum QBlockFormat str2fmt(const char *fmt);

Even if this header is not intended for clients, you STILL need to avoid
namespace pollution, by either ensuring that your library marks
visibility annotations to avoid exporting symbols outside of the public
namespace, or by renaming even your internal functions to comply with
the namespace.  In other words, stomping on the name 'fmt2str' and
'str2fmt' as an external function name is just too likely to clash with
an arbitrary client linking against your library.
Paolo Bonzini - Sept. 3, 2012, 3:18 p.m.
Il 03/09/2012 16:28, Eric Blake ha scritto:
>> > +/* this file contains helper function used internally. */
>> > +#define SECTOR_SIZE (512)
> Hard-coding this feels wrong, in this day and age of disks with 4096
> sectors.  Why isn't this a per-image property?

In this day and age of disks with 4096 sectors, Linux does not provide a
way to query the required alignment for O_DIRECT...

Paolo
Wayne Xia - Sept. 4, 2012, 3:19 a.m.
于 2012-9-3 21:18, Paolo Bonzini 写道:
> Il 03/09/2012 11:18, Wenchao Xia ha scritto:
>>    This patch contains internal helper codes.
>>
>> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> ---
>>   block.c                      |    2 +-
>>   block.h                      |    1 +
>>   libqblock/libqblock-helper.c |   92 ++++++++++++++++++++++++++++++++++++++++++
>>   libqblock/libqblock-helper.h |   57 ++++++++++++++++++++++++++
>>   4 files changed, 151 insertions(+), 1 deletions(-)
>>   create mode 100644 libqblock/libqblock-helper.c
>>   create mode 100644 libqblock/libqblock-helper.h
>>
>> diff --git a/block.c b/block.c
>> index 470bdcc..8b312f8 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 2e2be11..e7da711 100644
>> --- a/block.h
>> +++ b/block.h
>> @@ -405,4 +405,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-helper.c b/libqblock/libqblock-helper.c
>> new file mode 100644
>> index 0000000..f9e8ce9
>> --- /dev/null
>> +++ b/libqblock/libqblock-helper.c
>> @@ -0,0 +1,92 @@
>> +#include "libqblock-helper.h"
>> +#include "libqblock-types.h"
>> +#include "libqblock-error.h"
>> +
>> +const char *fmt2str(enum QBlockFormat fmt)
>> +{
>> +    const char *ret = NULL;
>> +    switch (fmt) {
>> +    case QB_FMT_COW:
>> +        ret = "cow";
>> +        break;
>> +    case QB_FMT_QED:
>> +        ret = "qed";
>> +        break;
>> +    case QB_FMT_QCOW:
>> +        ret = "qcow";
>> +        break;
>> +    case QB_FMT_QCOW2:
>> +        ret = "qcow2";
>> +        break;
>> +    case QB_FMT_RAW:
>> +        ret = "raw";
>> +        break;
>> +    case QB_FMT_RBD:
>> +        ret = "rbd";
>> +        break;
>> +    case QB_FMT_SHEEPDOG:
>> +        ret = "sheepdog";
>> +        break;
>> +    case QB_FMT_VDI:
>> +        ret = "vdi";
>> +        break;
>> +    case QB_FMT_VMDK:
>> +        ret = "vmdk";
>> +        break;
>> +    case QB_FMT_VPC:
>> +        ret = "vpc";
>> +        break;
>> +    default:
>> +        break;
>> +    }
>> +    return ret;
>> +}
>> +
>> +enum QBlockFormat str2fmt(const char *fmt)
>> +{
>> +    enum QBlockFormat ret = QB_FMT_NONE;
>> +    if (0 == strcmp(fmt, "cow")) {
>> +        ret = QB_FMT_COW;
>> +    } else if (0 == strcmp(fmt, "qed")) {
>> +        ret = QB_FMT_QED;
>> +    } else if (0 == strcmp(fmt, "qcow")) {
>> +        ret = QB_FMT_QCOW;
>> +    } else if (0 == strcmp(fmt, "qcow2")) {
>> +        ret = QB_FMT_QCOW2;
>> +    } else if (0 == strcmp(fmt, "raw")) {
>> +        ret = QB_FMT_RAW;
>> +    } else if (0 == strcmp(fmt, "rbd")) {
>> +        ret = QB_FMT_RBD;
>> +    } else if (0 == strcmp(fmt, "sheepdog")) {
>> +        ret = QB_FMT_SHEEPDOG;
>> +    } else if (0 == strcmp(fmt, "vdi")) {
>> +        ret = QB_FMT_VDI;
>> +    } else if (0 == strcmp(fmt, "vmdk")) {
>> +        ret = QB_FMT_VMDK;
>> +    } else if (0 == strcmp(fmt, "vpc")) {
>> +        ret = QB_FMT_VPC;
>> +    }
>> +    return ret;
>> +}
>> +
>> +void set_broker_err(struct QBroker *broker, int err_ret,
>> +                           const char *fmt, ...)
>> +{
>> +    va_list ap;
>> +
>> +    broker->err_ret = err_ret;
>> +    if (err_ret == QB_ERR_INTERNAL_ERR) {
>> +        broker->err_no = -errno;
>> +    } else {
>> +        broker->err_no = 0;
>> +    }
>> +
>> +    va_start(ap, fmt);
>> +    vsnprintf(broker->err_msg, sizeof(broker->err_msg), fmt, ap);
>> +    va_end(ap);
>> +}
>> +
>> +void set_broker_err_nomem(struct QBroker *broker)
>> +{
>> +    set_broker_err(broker, QB_ERR_MEM_ERR, "No Memory.");
>> +}
>> diff --git a/libqblock/libqblock-helper.h b/libqblock/libqblock-helper.h
>> new file mode 100644
>> index 0000000..4330472
>> --- /dev/null
>> +++ b/libqblock/libqblock-helper.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_HELPER
>> +#define LIBQBLOCK_HELPER
>> +
>> +#include "block.h"
>> +#include "block_int.h"
>> +
>> +#include "libqblock-types.h"
>> +
>> +/* this file contains helper function used internally. */
>> +#define SECTOR_SIZE (512)
>> +#define SECTOR_SIZE_MASK (0x01ff)
>> +#define SECTOR_SIZE_BITS_NUM (9)
>> +#define FUNC_FREE free
>> +#define FUNC_MALLOC malloc
>> +#define FUNC_CALLOC calloc
>> +
>> +#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;
>> +};
>> +
>> +#define QB_ERR_STRING_SIZE (1024)
>> +struct QBroker {
>> +    /* last error */
>> +    char err_msg[QB_ERR_STRING_SIZE];
>> +    int err_ret; /* last error return of libqblock. */
>> +    int err_no; /* 2nd level of error, errno what below reports */
>> +};
>> +
>> +const char *fmt2str(enum QBlockFormat fmt);
>> +enum QBlockFormat str2fmt(const char *fmt);
>> +void set_broker_err(struct QBroker *broker, int err_ret,
>> +                           const char *fmt, ...);
>> +void set_broker_err_nomem(struct QBroker *broker);
>> +#endif
>>
>
> Please squash this into patch 1, there is no need to keep separate files.
>
> Paolo
>
   OK. It was done for make a patch smaller to easy reviewing.
Wayne Xia - Sept. 4, 2012, 7:15 a.m.
于 2012-9-3 23:18, Paolo Bonzini 写道:
> Il 03/09/2012 16:28, Eric Blake ha scritto:
>>>> +/* this file contains helper function used internally. */
>>>> +#define SECTOR_SIZE (512)
>> Hard-coding this feels wrong, in this day and age of disks with 4096
>> sectors.  Why isn't this a per-image property?
>
> In this day and age of disks with 4096 sectors, Linux does not provide a
> way to query the required alignment for O_DIRECT...
>
> Paolo
>
in block.h:
#define BDRV_SECTOR_BITS   9
#define BDRV_SECTOR_SIZE   (1ULL << BDRV_SECTOR_BITS)
#define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1)
   it seems block size is always 512 in qemu block layer, so I can
ignore the 4096 case, do you think so?
Paolo Bonzini - Sept. 4, 2012, 7:38 a.m.
Il 04/09/2012 09:15, Wenchao Xia ha scritto:
>>>>> +/* this file contains helper function used internally. */
>>>>> +#define SECTOR_SIZE (512)
>>> Hard-coding this feels wrong, in this day and age of disks with 4096
>>> sectors.  Why isn't this a per-image property?
>>
>> In this day and age of disks with 4096 sectors, Linux does not provide a
>> way to query the required alignment for O_DIRECT...
>>
>> Paolo
>>
> in block.h:
> #define BDRV_SECTOR_BITS   9
> #define BDRV_SECTOR_SIZE   (1ULL << BDRV_SECTOR_BITS)
> #define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1)
>   it seems block size is always 512 in qemu block layer, so I can
> ignore the 4096 case, do you think so?

Yes.  It is not well supported yet by QEMU, either.

Paolo
Eric Blake - Sept. 4, 2012, 11:38 a.m.
On 09/04/2012 01:15 AM, Wenchao Xia wrote:
> 于 2012-9-3 23:18, Paolo Bonzini 写道:
>> Il 03/09/2012 16:28, Eric Blake ha scritto:
>>>>> +/* this file contains helper function used internally. */
>>>>> +#define SECTOR_SIZE (512)
>>> Hard-coding this feels wrong, in this day and age of disks with 4096
>>> sectors.  Why isn't this a per-image property?
>>
>> In this day and age of disks with 4096 sectors, Linux does not provide a
>> way to query the required alignment for O_DIRECT...
>>
>> Paolo
>>
> in block.h:
> #define BDRV_SECTOR_BITS   9
> #define BDRV_SECTOR_SIZE   (1ULL << BDRV_SECTOR_BITS)
> #define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1)
>   it seems block size is always 512 in qemu block layer, so I can
> ignore the 4096 case, do you think so?

Since qemu does not support it now, yes, you can ignore it for now.  But
please make sure that you aren't hard-coding it into the API - that is,
make sure that the API can someday grow to support larger sector sizes
with minimal impact to library clients (that is, that new clients aware
of the new API can target larger sector size once qemu has been patched
to support larger sector size).
Paolo Bonzini - Sept. 4, 2012, 1:49 p.m.
Il 04/09/2012 13:38, Eric Blake ha scritto:
> Since qemu does not support it now, yes, you can ignore it for now.  But
> please make sure that you aren't hard-coding it into the API - that is,
> make sure that the API can someday grow to support larger sector sizes
> with minimal impact to library clients (that is, that new clients aware
> of the new API can target larger sector size once qemu has been patched
> to support larger sector size).

We can support 4k sector disks even if the addressing unit remains 512
bytes, just like in the Linux kernel.

Wenchao, you can add a logical_block_size item to the image info and
make it always return 512.

Paolo
Kevin Wolf - Sept. 4, 2012, 1:51 p.m.
Am 04.09.2012 15:49, schrieb Paolo Bonzini:
> Il 04/09/2012 13:38, Eric Blake ha scritto:
>> Since qemu does not support it now, yes, you can ignore it for now.  But
>> please make sure that you aren't hard-coding it into the API - that is,
>> make sure that the API can someday grow to support larger sector sizes
>> with minimal impact to library clients (that is, that new clients aware
>> of the new API can target larger sector size once qemu has been patched
>> to support larger sector size).
> 
> We can support 4k sector disks even if the addressing unit remains 512
> bytes, just like in the Linux kernel.

Why should we even use an arbitrary unit like 512 bytes for addressing?
To me using byte granularity everywhere makes more sense and is clearer.

Kevin
Wayne Xia - Sept. 10, 2012, 8:23 a.m.
Using unit byte now, thanks.

> Am 04.09.2012 15:49, schrieb Paolo Bonzini:
>> Il 04/09/2012 13:38, Eric Blake ha scritto:
>>> Since qemu does not support it now, yes, you can ignore it for now.  But
>>> please make sure that you aren't hard-coding it into the API - that is,
>>> make sure that the API can someday grow to support larger sector sizes
>>> with minimal impact to library clients (that is, that new clients aware
>>> of the new API can target larger sector size once qemu has been patched
>>> to support larger sector size).
>>
>> We can support 4k sector disks even if the addressing unit remains 512
>> bytes, just like in the Linux kernel.
>
> Why should we even use an arbitrary unit like 512 bytes for addressing?
> To me using byte granularity everywhere makes more sense and is clearer.
>
> Kevin
>

Patch

diff --git a/block.c b/block.c
index 470bdcc..8b312f8 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 2e2be11..e7da711 100644
--- a/block.h
+++ b/block.h
@@ -405,4 +405,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-helper.c b/libqblock/libqblock-helper.c
new file mode 100644
index 0000000..f9e8ce9
--- /dev/null
+++ b/libqblock/libqblock-helper.c
@@ -0,0 +1,92 @@ 
+#include "libqblock-helper.h"
+#include "libqblock-types.h"
+#include "libqblock-error.h"
+
+const char *fmt2str(enum QBlockFormat fmt)
+{
+    const char *ret = NULL;
+    switch (fmt) {
+    case QB_FMT_COW:
+        ret = "cow";
+        break;
+    case QB_FMT_QED:
+        ret = "qed";
+        break;
+    case QB_FMT_QCOW:
+        ret = "qcow";
+        break;
+    case QB_FMT_QCOW2:
+        ret = "qcow2";
+        break;
+    case QB_FMT_RAW:
+        ret = "raw";
+        break;
+    case QB_FMT_RBD:
+        ret = "rbd";
+        break;
+    case QB_FMT_SHEEPDOG:
+        ret = "sheepdog";
+        break;
+    case QB_FMT_VDI:
+        ret = "vdi";
+        break;
+    case QB_FMT_VMDK:
+        ret = "vmdk";
+        break;
+    case QB_FMT_VPC:
+        ret = "vpc";
+        break;
+    default:
+        break;
+    }
+    return ret;
+}
+
+enum QBlockFormat str2fmt(const char *fmt)
+{
+    enum QBlockFormat ret = QB_FMT_NONE;
+    if (0 == strcmp(fmt, "cow")) {
+        ret = QB_FMT_COW;
+    } else if (0 == strcmp(fmt, "qed")) {
+        ret = QB_FMT_QED;
+    } else if (0 == strcmp(fmt, "qcow")) {
+        ret = QB_FMT_QCOW;
+    } else if (0 == strcmp(fmt, "qcow2")) {
+        ret = QB_FMT_QCOW2;
+    } else if (0 == strcmp(fmt, "raw")) {
+        ret = QB_FMT_RAW;
+    } else if (0 == strcmp(fmt, "rbd")) {
+        ret = QB_FMT_RBD;
+    } else if (0 == strcmp(fmt, "sheepdog")) {
+        ret = QB_FMT_SHEEPDOG;
+    } else if (0 == strcmp(fmt, "vdi")) {
+        ret = QB_FMT_VDI;
+    } else if (0 == strcmp(fmt, "vmdk")) {
+        ret = QB_FMT_VMDK;
+    } else if (0 == strcmp(fmt, "vpc")) {
+        ret = QB_FMT_VPC;
+    }
+    return ret;
+}
+
+void set_broker_err(struct QBroker *broker, int err_ret,
+                           const char *fmt, ...)
+{
+    va_list ap;
+
+    broker->err_ret = err_ret;
+    if (err_ret == QB_ERR_INTERNAL_ERR) {
+        broker->err_no = -errno;
+    } else {
+        broker->err_no = 0;
+    }
+
+    va_start(ap, fmt);
+    vsnprintf(broker->err_msg, sizeof(broker->err_msg), fmt, ap);
+    va_end(ap);
+}
+
+void set_broker_err_nomem(struct QBroker *broker)
+{
+    set_broker_err(broker, QB_ERR_MEM_ERR, "No Memory.");
+}
diff --git a/libqblock/libqblock-helper.h b/libqblock/libqblock-helper.h
new file mode 100644
index 0000000..4330472
--- /dev/null
+++ b/libqblock/libqblock-helper.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_HELPER
+#define LIBQBLOCK_HELPER
+
+#include "block.h"
+#include "block_int.h"
+
+#include "libqblock-types.h"
+
+/* this file contains helper function used internally. */
+#define SECTOR_SIZE (512)
+#define SECTOR_SIZE_MASK (0x01ff)
+#define SECTOR_SIZE_BITS_NUM (9)
+#define FUNC_FREE free
+#define FUNC_MALLOC malloc
+#define FUNC_CALLOC calloc
+
+#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;
+};
+
+#define QB_ERR_STRING_SIZE (1024)
+struct QBroker {
+    /* last error */
+    char err_msg[QB_ERR_STRING_SIZE];
+    int err_ret; /* last error return of libqblock. */
+    int err_no; /* 2nd level of error, errno what below reports */
+};
+
+const char *fmt2str(enum QBlockFormat fmt);
+enum QBlockFormat str2fmt(const char *fmt);
+void set_broker_err(struct QBroker *broker, int err_ret,
+                           const char *fmt, ...);
+void set_broker_err_nomem(struct QBroker *broker);
+#endif