All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
To: Blue Swirl <blauwirbel@gmail.com>
Cc: kwolf@redhat.com, aliguori@us.ibm.com, stefanha@gmail.com,
	qemu-devel@nongnu.org, pbonzini@redhat.com, eblake@redhat.com
Subject: Re: [Qemu-devel] [PATCH V2 1/6] libqblock API design
Date: Wed, 12 Sep 2012 10:54:44 +0800	[thread overview]
Message-ID: <504FF974.7080408@linux.vnet.ibm.com> (raw)
In-Reply-To: <CAAu8pHufF57R6GZv+KDewKOgueEx40b+uuS1k3S2wdrJUFA09A@mail.gmail.com>

   All changed, thanks.

> On Mon, Sep 10, 2012 at 8:26 AM, Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
>>    This patch contains the major APIs in the library.
>> Important APIs:
>>    1 QBroker. These structure was used to retrieve errors, every thread must
>> create one first, later maybe thread related staff could be added into it.
>>    2 QBlockState. It stands for an block image object.
>>    3 QBlockStaticInfo. It contains static information such as location, backing
>> file, size.
>>    4 ABI was kept with reserved members.
>>    5 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>
>> ---
>>   libqblock/libqblock.c | 1077 +++++++++++++++++++++++++++++++++++++++++++++++++
>>   libqblock/libqblock.h |  292 +++++++++++++
>>   2 files changed, 1369 insertions(+), 0 deletions(-)
>>   create mode 100644 libqblock/libqblock.c
>>   create mode 100644 libqblock/libqblock.h
>>
>> diff --git a/libqblock/libqblock.c b/libqblock/libqblock.c
>> new file mode 100644
>> index 0000000..133ac0f
>> --- /dev/null
>> +++ b/libqblock/libqblock.c
>> @@ -0,0 +1,1077 @@
>> +/*
>> + * 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"
>> +
>> +struct LibqblockGlobalData {
>> +    int init_flag;
>> +};
>> +
>> +struct LibqblockGlobalData g_libqblock_data;
>> +
>> +__attribute__((constructor))
>> +static void libqblock_init(void)
>> +{
>> +    if (g_libqblock_data.init_flag == 0) {
>> +        bdrv_init();
>> +        qemu_init_main_loop();
>> +    }
>> +    g_libqblock_data.init_flag = 1;
>> +}
>> +
>> +const char *qb_fmttype2str(enum QBlockFmtType fmt_type)
>> +{
>> +    const char *ret = NULL;
>> +    switch (fmt_type) {
>> +    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 QBlockFmtType qb_str2fmttype(const char *fmt_str)
>> +{
>> +    enum QBlockFmtType ret = QB_FMT_NONE;
>> +    if (0 == strcmp(fmt_str, "cow")) {
>
> This order is not common in QEMU.
>
>> +        ret = QB_FMT_COW;
>> +    } else if (0 == strcmp(fmt_str, "qed")) {
>> +        ret = QB_FMT_QED;
>> +    } else if (0 == strcmp(fmt_str, "qcow")) {
>> +        ret = QB_FMT_QCOW;
>> +    } else if (0 == strcmp(fmt_str, "qcow2")) {
>> +        ret = QB_FMT_QCOW2;
>> +    } else if (0 == strcmp(fmt_str, "raw")) {
>> +        ret = QB_FMT_RAW;
>> +    } else if (0 == strcmp(fmt_str, "rbd")) {
>> +        ret = QB_FMT_RBD;
>> +    } else if (0 == strcmp(fmt_str, "sheepdog")) {
>> +        ret = QB_FMT_SHEEPDOG;
>> +    } else if (0 == strcmp(fmt_str, "vdi")) {
>> +        ret = QB_FMT_VDI;
>> +    } else if (0 == strcmp(fmt_str, "vmdk")) {
>> +        ret = QB_FMT_VMDK;
>> +    } else if (0 == strcmp(fmt_str, "vpc")) {
>> +        ret = QB_FMT_VPC;
>> +    }
>> +    return ret;
>> +}
>> +
>> +static 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);
>> +}
>> +
>> +static void set_broker_err_nomem(struct QBroker *broker)
>> +{
>> +    set_broker_err(broker, QB_ERR_MEM_ERR, "No Memory.");
>> +}
>> +
>> +int qb_broker_new(struct QBroker **broker)
>> +{
>> +    *broker = FUNC_CALLOC(1, sizeof(struct QBroker));
>> +    if (*broker == NULL) {
>> +        return QB_ERR_MEM_ERR;
>> +    }
>> +    return 0;
>> +}
>> +
>> +void qb_broker_delete(struct QBroker **broker)
>> +{
>> +    CLEAN_FREE(*broker);
>> +    return;
>> +}
>> +
>> +int qb_state_new(struct QBroker *broker,
>> +                 struct QBlockState **qbs)
>> +{
>> +    *qbs = FUNC_CALLOC(1, sizeof(struct QBlockState));
>> +    if (*qbs == NULL) {
>> +        set_broker_err_nomem(broker);
>> +        return broker->err_ret;
>> +    }
>> +    (*qbs)->bdrvs = bdrv_new("hda");
>> +    if ((*qbs)->bdrvs == NULL) {
>> +        CLEAN_FREE(*qbs);
>> +        set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                       "failed to create the driver.");
>> +        return broker->err_ret;
>> +    }
>> +    return 0;
>> +}
>> +
>> +void qb_state_delete(struct QBroker *broker,
>> +                     struct QBlockState **qbs)
>> +{
>> +    CLEAN_FREE((*qbs)->filename);
>> +    if ((*qbs)->bdrvs != NULL) {
>> +        bdrv_delete((*qbs)->bdrvs);
>> +        (*qbs)->bdrvs = NULL;
>> +    }
>> +    CLEAN_FREE(*qbs);
>> +    return;
>> +}
>> +
>> +int qb_prot_info_new(struct QBroker *broker,
>> +                     struct QBlockProtInfo **op)
>> +{
>> +    *op = FUNC_CALLOC(1, sizeof(struct QBlockProtInfo));
>> +    if (*op == NULL) {
>> +        set_broker_err_nomem(broker);
>> +        return broker->err_ret;
>> +    }
>> +    return 0;
>> +}
>> +
>> +void qb_prot_info_delete(struct QBroker *broker,
>> +                         struct QBlockProtInfo **op)
>> +{
>> +    CLEAN_FREE(*op);
>> +}
>> +
>> +int qb_fmt_info_new(struct QBroker *broker,
>> +                    struct QBlockFmtInfo **op)
>> +{
>> +    *op = FUNC_CALLOC(1, sizeof(struct QBlockFmtInfo));
>> +    if (*op == NULL) {
>> +        set_broker_err_nomem(broker);
>> +        return broker->err_ret;
>> +    }
>> +    return 0;
>> +}
>> +
>> +void qb_fmt_info_delete(struct QBroker *broker,
>> +                        struct QBlockFmtInfo **op)
>> +{
>> +    CLEAN_FREE(*op);
>> +}
>> +
>> +/* return 0 if every thing is fine */
>> +static int loc_check_params(struct QBroker *broker,
>> +                            struct QBlockProtInfo *loc)
>> +{
>> +    broker->err_ret = 0;
>> +
>> +    switch (loc->prot_type) {
>> +    case QB_PROT_FILE:
>> +        if (loc->prot_op.o_file.filename == NULL) {
>> +            set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                           "Filename was not set.");
>> +            goto out;
>> +        }
>> +        if (path_has_protocol(loc->prot_op.o_file.filename) > 0) {
>> +            set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                           "filename [%s] had protocol.",
>> +                           loc->prot_op.o_file.filename);
>> +            goto out;
>> +        }
>> +        break;
>> +    default:
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                       "Protocol type [%d] was not valid.",
>> +                       loc->prot_type);
>> +        break;
>> +    }
>> +
>> + out:
>> +    return broker->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(struct QBroker *broker,
>> +                        struct QBlockProtInfo *loc,
>> +                        char **filename)
>> +{
>> +    broker->err_ret = 0;
>> +
>> +    if (*filename != NULL) {
>> +        CLEAN_FREE(*filename);
>> +    }
>> +    switch (loc->prot_type) {
>> +    case QB_PROT_FILE:
>> +        *filename = strdup(loc->prot_op.o_file.filename);
>> +        if (*filename == NULL) {
>> +            set_broker_err_nomem(broker);
>> +        }
>> +        break;
>> +    default:
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                 "protocol type [%d] is not supported.",
>> +                  loc->prot_type);
>> +        break;
>> +    }
>> +
>> +    return broker->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(struct QBroker *broker,
>> +                        struct QBlockProtInfo *loc,
>> +                        const char *filename)
>> +{
>> +    broker->err_ret = 0;
>> +
>> +    if (path_has_protocol(filename) > 0) {
>> +        set_broker_err(broker, 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 = strdup(filename);
>> +        if (loc->prot_op.o_file.filename == NULL) {
>> +            set_broker_err_nomem(broker);
>> +            goto out;
>> +        }
>> +        break;
>> +    default:
>> +        break;
>> +    }
>> +
>> + out:
>> +    return broker->err_ret;
>> +}
>> +
>> +/* return 0 if OK, or qblock error number */
>> +static int set_backing_file_options(struct QBroker *broker,
>> +                                    QEMUOptionParameter *param,
>> +                                    struct QBlockProtInfo *loc,
>> +                                    enum QBlockFmtType *fmt)
>> +{
>> +    char *backing_filename = NULL;
>> +    const char *fmtstr_backing = NULL;
>> +    int ret = 0;
>> +
>> +    if (loc == NULL) {
>> +        goto out;
>> +    }
>> +
>> +    ret = loc2filename(broker, loc, &backing_filename);
>> +    /* ret can < 0 if loc have not been set, mean user did not specify backing
>> +       file */
>> +    if (ret == QB_ERR_MEM_ERR) {
>> +        goto out;
>> +    }
>> +    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(struct QBroker *broker,
>> +              struct QBlockState *qbs,
>> +              struct QBlockProtInfo *loc,
>> +              struct 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;
>> +    struct QBlockFmtOptionCow *o_cow = NULL;
>> +    struct QBlockFmtOptionQed *o_qed = NULL;
>> +    struct QBlockFmtOptionQcow *o_qcow = NULL;
>> +    struct QBlockFmtOptionQcow2 *o_qcow2 = NULL;
>> +    struct QBlockFmtOptionRaw *o_raw = NULL;
>> +    struct QBlockFmtOptionRbd *o_rbd = NULL;
>> +    struct QBlockFmtOptionSheepdog *o_sd = NULL;
>> +    struct QBlockFmtOptionVdi *o_vdi = NULL;
>> +    struct QBlockFmtOptionVmdk *o_vmdk = NULL;
>> +    struct QBlockFmtOptionVpc *o_vpc = NULL;
>> +
>> +
>> +    /* check parameters */
>> +    if (flag & (~LIBQBLOCK_O_VALID_MASK)) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                           "invalid flag was set.");
>> +        ret = broker->err_ret;
>> +        goto out;
>> +    }
>> +
>> +    if ((loc == NULL) || (qbs == NULL) || (fmt == NULL)) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                          "Got unexpected NULL pointer in parameters.");
>> +        ret = broker->err_ret;
>> +        goto out;
>> +    }
>> +
>> +    ret = loc_check_params(broker, loc);
>> +    if (ret != 0) {
>> +        goto out;
>> +    }
>> +
>> +    /* internal translate */
>> +    ret = loc2filename(broker, loc, &filename);
>> +    if (ret != 0) {
>> +        goto out;
>> +    }
>> +
>> +    fmtstr = qb_fmttype2str(fmt->fmt_type);
>> +    if (fmtstr == NULL) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                 "Got unexpected NULL pointer in parameters.");
>> +        ret = broker->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(broker, 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(broker, 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(broker, 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(broker, 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(broker, 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(broker, 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:
>> +        assert(false);
>
> 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_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                          "Backing file is the same with new file.");
>> +            ret = broker->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_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                               "Failed to open the backing file.");
>> +                ret = broker->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_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "Neither size or backing file was not set.");
>> +            ret = broker->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_broker_err(broker, QB_ERR_INTERNAL_ERR, errstr);
>> +        ret = broker->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(struct QBroker *broker,
>> +            struct QBlockState *qbs,
>> +            struct QBlockProtInfo *loc,
>> +            struct 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_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                      "Invalid flag was set.");
>> +        ret = broker->err_ret;
>> +        goto out;
>> +    }
>> +
>> +    if ((loc == NULL) || (qbs == NULL)) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                      "Got unexpected NULL pointer in parameters.");
>> +        ret = broker->err_ret;
>> +        goto out;
>> +    }
>> +
>> +    ret = loc_check_params(broker, loc);
>> +    if (ret != 0) {
>> +        goto out;
>> +    }
>> +
>> +    /* internal translate */
>> +    ret = loc2filename(broker, 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 openning */
>
> opening
>
>> +    bs = qbs->bdrvs;
>> +    bd_ret = bdrv_open(bs, filename, flag, bd);
>> +    if (bd_ret < 0) {
>> +        set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                      "Failed in opening with driver, bd_ret is %d.", bd_ret);
>> +        ret = broker->err_ret;
>> +        goto out;
>> +    }
>> +
>> +    if (qbs->filename != NULL) {
>> +        FUNC_FREE(qbs->filename);
>> +    }
>> +    qbs->filename = strdup(filename);
>> +    if (qbs->filename == NULL) {
>> +        set_broker_err_nomem(broker);
>> +        ret = broker->err_ret;
>> +        bdrv_close(bs);
>> +        goto out;
>> +    }
>> +
>> + out:
>> +    FUNC_FREE(filename);
>> +    return ret;
>> +}
>> +
>> +void qb_close(struct QBroker *broker,
>> +              struct QBlockState *qbs)
>> +{
>> +    BlockDriverState *bs;
>> +
>> +    bs = qbs->bdrvs;
>> +
>> +    if (qbs->filename != NULL) {
>> +        CLEAN_FREE(qbs->filename);
>> +        bdrv_close(bs);
>> +    }
>> +    return;
>> +}
>> +
>> +int64_t qb_read(struct QBroker *broker,
>> +                struct 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;
>> +    int remains;
>> +
>> +    broker->err_ret = 0;
>> +    bs = qbs->bdrvs;
>> +
>> +    if (len <= 0) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                      "Param len is less or equal to zero.");
>> +        return broker->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 aligned, need to read/write this sector. */
>> +        bd_ret = bdrv_read(bs, sector_start, temp_buf, 1);
>> +        if (bd_ret < 0) {
>> +            set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->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 aligned. */
>> +    if (remains >= BDRV_SECTOR_SIZE) {
>> +        sector_num = len >> BDRV_SECTOR_BITS;
>> +        bd_ret = bdrv_read(bs, sector_start, p, sector_num);
>> +        if (bd_ret < 0) {
>> +            set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->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_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->err_ret;
>> +        }
>> +        memcpy(p, temp_buf, remains);
>> +        remains -= remains;
>> +    }
>> +
>> +    return len-remains;
>> +}
>> +
>> +int64_t qb_write(struct QBroker *broker,
>> +                 struct 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;
>> +    int remains;
>> +
>> +    broker->err_ret = 0;
>> +    bs = qbs->bdrvs;
>> +
>> +    if (len <= 0) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                      "Param len is less or equal to zero.");
>> +        return broker->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 aligned, need to read/write this sector. */
>> +        bd_ret = bdrv_read(bs, sector_start, temp_buf, 1);
>> +        if (bd_ret < 0) {
>> +            set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->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_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->err_ret;
>> +        }
>> +        remains -= cp_len;
>> +        p += cp_len;
>> +        sector_start++;
>> +    }
>> +
>> +    /* now start position is aligned. */
>> +    if (remains >= BDRV_SECTOR_SIZE) {
>> +        sector_num = len >> BDRV_SECTOR_BITS;
>> +        bd_ret = bdrv_write(bs, sector_start, p, sector_num);
>> +        if (bd_ret < 0) {
>> +            set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->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_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->err_ret;
>> +        }
>> +        memcpy(temp_buf, p, remains);
>> +        bd_ret = bdrv_write(bs, sector_start, temp_buf, 1);
>> +        if (bd_ret < 0) {
>> +            set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                           "QEMU internal block error.");
>> +            return broker->err_ret;
>> +        }
>> +        remains -= remains;
>> +    }
>> +
>> +    return len-remains;
>> +}
>> +
>> +int qb_flush(struct QBroker *broker,
>> +             struct QBlockState *qbs)
>> +{
>> +    int bd_ret;
>> +    BlockDriverState *bs;
>> +
>> +    broker->err_ret = 0;
>> +    bs = qbs->bdrvs;
>> +    bd_ret = bdrv_flush(bs);
>> +    if (bd_ret < 0) {
>> +        set_broker_err(broker, QB_ERR_INTERNAL_ERR,
>> +                       "Internal error.");
>> +    }
>> +    return broker->err_ret;
>> +}
>> +
>> +int qb_check_allocation(struct QBroker *broker,
>> +                        struct QBlockState *qbs,
>> +                        uint64_t start,
>> +                        int length,
>> +                        int *pstatus,
>> +                        int *plength)
>> +{
>> +    int ret;
>> +    int sector_start, sector_num, num;
>> +    BlockDriverState *bs;
>> +    unsigned int real_len, ret_len;
>> +
>> +    broker->err_ret = 0;
>> +    bs = qbs->bdrvs;
>> +
>> +    if (qbs->filename == NULL) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                       "Image was not opened first.");
>> +        goto out;
>> +    }
>> +
>> +    if (length <= 0) {
>> +        set_broker_err(broker, 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_broker_err(broker, 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 broker->err_ret;
>> +}
>> +
>> +int qb_info_image_static_get(struct QBroker *broker,
>> +                             struct QBlockState *qbs,
>> +                             struct QBlockStaticInfo **info)
>> +{
>> +    int ret = 0;
>> +    BlockDriverState *bs;
>> +    struct QBlockStaticInfo *info_tmp;
>> +    const char *fmt_str;
>> +    size_t total_sectors;
>> +    char backing_filename[1024];
>> +
>> +    if (qbs->filename == NULL) {
>> +        set_broker_err(broker, QB_ERR_INVALID_PARAM,
>> +                       "Block Image was not openned.");
>> +        ret = broker->err_ret;
>> +        goto out;
>> +    }
>> +
>> +    info_tmp = FUNC_CALLOC(1, sizeof(struct QBlockStaticInfo));
>> +    if (info_tmp == NULL) {
>> +        set_broker_err_nomem(broker);
>> +        ret = broker->err_ret;
>> +        goto out;
>> +    }
>> +
>> +    bs = qbs->bdrvs;
>> +
>> +    ret = filename2loc(broker,
>> +                       &(info_tmp->loc),
>> +                       qbs->filename);
>> +    if (ret < 0) {
>> +        goto free;
>> +    }
>> +
>> +    fmt_str = bdrv_get_format_name(bs);
>> +    info_tmp->fmt_type = qb_str2fmttype(fmt_str);
>> +
>> +    bdrv_get_geometry(bs, &total_sectors);
>> +    info_tmp->virt_size = total_sectors * BDRV_SECTOR_SIZE;
>> +
>> +    info_tmp->encrypt = bdrv_is_encrypted(bs);
>> +
>> +    bdrv_get_full_backing_filename(bs, backing_filename,
>> +                                   sizeof(backing_filename));
>> +    if (backing_filename[0] != '\0') {
>> +        ret = filename2loc(broker,
>> +                           &(info_tmp->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(broker, &info_tmp);
>> +    return ret;
>> +}
>> +
>> +/* free locations if it has string allocated on heap. */
>> +static void loc_free(struct 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;
>> +    }
>> +}
>> +
>> +void qb_info_image_static_delete(struct QBroker *broker,
>> +                                 struct QBlockStaticInfo **info)
>> +{
>> +    loc_free(&(*info)->loc);
>> +    loc_free(&(*info)->backing_loc);
>> +
>> +    CLEAN_FREE(*info);
>> +}
>> diff --git a/libqblock/libqblock.h b/libqblock/libqblock.h
>> new file mode 100644
>> index 0000000..97e6c7c
>> --- /dev/null
>> +++ b/libqblock/libqblock.h
>> @@ -0,0 +1,292 @@
>> +/*
>> + * 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_broker_new: allocate a new broker
>> + *
>> + * Broker is used to pass operation to libqblock, and get feed back from it.
>> + *
>> + * Returns 0 on success, libqblock negative error value on fail.
>> + *
>> + * @broker: used to receive the created struct.
>> + */
>> +DLL_PUBLIC
>> +int qb_broker_new(struct QBroker **broker);
>> +
>> +/**
>> + * qb_broker_delete: delete broker
>> + *
>> + * Broker will be freed and set to NULL.
>> + *
>> + * @broker: operation broker to be deleted.
>> + */
>> +DLL_PUBLIC
>> +void qb_broker_delete(struct QBroker **broker);
>> +
>> +/**
>> + * 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.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: used to receive the created struct.
>> + */
>> +DLL_PUBLIC
>> +int qb_state_new(struct QBroker *broker,
>> +                 struct QBlockState **qbs);
>> +
>> +/**
>> + * qb_state_delete: free a QBlockState struct
>> + *
>> + * if image was opened, qb_close must be called before delete.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to the struct's pointer.
>> + */
>> +DLL_PUBLIC
>> +void qb_state_delete(struct QBroker *broker,
>> +                     struct QBlockState **qbs);
>> +
>> +/**
>> + * qb_prot_info_new: create a new struct QBlockProtInfo.
>> + *
>> + * return 0 on success, libqblock negative error value on fail.
>> + *
>> + * @broker: operation broker.
>> + * @op: pointer to receive the new created one.
>> + */
>> +DLL_PUBLIC
>> +int qb_prot_info_new(struct QBroker *broker,
>> +                     struct QBlockProtInfo **op);
>> +
>> +/**
>> + * qb_prot_info_delete: free a struct QBlockProtInfo.
>> + *
>> + * @broker: operation broker.
>> + * @op: pointer to the object, *op would be set to NULL.
>> + */
>> +DLL_PUBLIC
>> +void qb_prot_info_delete(struct QBroker *broker,
>> +                         struct QBlockProtInfo **op);
>> +
>> +/**
>> + * qb_fmt_info_new: create a new QBlockFmtInfo structure.
>> + *
>> + * return 0 on success, libqblock negative error value on fail.
>> + *
>> + * @broker: operation broker.
>> + * @op: pointer that will receive created struct.
>> + */
>> +DLL_PUBLIC
>> +int qb_fmt_info_new(struct QBroker *broker,
>> +                    struct QBlockFmtInfo **op);
>> +
>> +/**
>> + * qb_fmt_info_delete: free QBlockFmtInfo structure.
>> + *
>> + * @broker: operation broker.
>> + * @op: pointer to the struct, *op would be set to NULL.
>> + */
>> +DLL_PUBLIC
>> +void qb_fmt_info_delete(struct QBroker *broker,
>> +                        struct QBlockFmtInfo **op);
>> +
>> +
>> +/**
>> + * qb_open: open a block object.
>> + *
>> + * return 0 on success, libqblock negative error value on fail.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct 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(struct QBroker *broker,
>> +            struct QBlockState *qbs,
>> +            struct QBlockProtInfo *loc,
>> +            struct QBlockFmtInfo *fmt,
>> +            int flag);
>> +
>> +/**
>> + * qb_close: close a block object.
>> + *
>> + * qb_flush is automatically done inside.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct QBlockState.
>> + */
>> +DLL_PUBLIC
>> +void qb_close(struct QBroker *broker,
>> +              struct 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.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct 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(struct QBroker *broker,
>> +              struct QBlockState *qbs,
>> +              struct QBlockProtInfo *loc,
>> +              struct QBlockFmtInfo *fmt,
>> +              int flag);
>> +
>> +
>> +/* sync access */
>> +/**
>> + * qb_read: block sync read.
>> + *
>> + * return number of bytes read, libqblock negative error value on fail.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct QBlockState.
>> + * @buf: buffer that receive the content.
>> + * @len: length to read.
>> + * @offset: offset in the block data.
>> + */
>> +DLL_PUBLIC
>> +int64_t qb_read(struct QBroker *broker,
>> +                struct 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.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct QBlockState.
>> + * @buf: buffer that receive the content.
>> + * @len: length to write.
>> + * @offset: offset in the block data.
>> + */
>> +DLL_PUBLIC
>> +int64_t qb_write(struct QBroker *broker,
>> +                 struct 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.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct QBlockState.
>> + */
>> +DLL_PUBLIC
>> +int qb_flush(struct QBroker *broker,
>> +             struct 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.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct QBlockState.
>> + * @start: start position, unit is byte.
>> + * @length: length to check, unit is byte.
>> + * @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(struct QBroker *broker,
>> +                        struct QBlockState *qbs,
>> +                        uint64_t start,
>> +                        int length,
>> +                        int *pstatus,
>> +                        int *plength);
>> +
>> +/* image information */
>> +/**
>> + * qb_get_image_info: get image info.
>> + *
>> + * return 0 on success, libqblock negative error value on fail.
>> + *
>> + * @broker: operation broker.
>> + * @qbs: pointer to struct QBlockState.
>> + * @info: pointer that would receive the information.
>> + */
>> +DLL_PUBLIC
>> +int qb_info_image_static_get(struct QBroker *broker,
>> +                             struct QBlockState *qbs,
>> +                             struct QBlockStaticInfo **info);
>> +
>> +/**
>> + * qb_delete_image_info: free image info.
>> + *
>> + * @broker: operation broker.
>> + * @info: pointer to the information struct.
>> + */
>> +DLL_PUBLIC
>> +void qb_info_image_static_delete(struct QBroker *broker,
>> +                                 struct 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
>> +enum QBlockFmtType qb_str2fmttype(const char *fmt_str);
>> +
>> +/**
>> + * qb_fmttype2str: libqblock format enum type to a string.
>> + *
>> + * return a pointer to the string, or NULL if type is not supported, and
>> + *  returned pointer do NOT need to free.
>> + *
>> + * @fmt: the format enum type.
>> + */
>> +DLL_PUBLIC
>> +const char *qb_fmttype2str(enum QBlockFmtType fmt_type);
>> +#endif
>> --
>> 1.7.1
>>
>>
>
>


-- 
Best Regards

Wenchao Xia

  reply	other threads:[~2012-09-12  2:56 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-10  8:26 [Qemu-devel] [PATCH V2 0/6] libqblock, qemu block layer library Wenchao Xia
2012-09-10  8:26 ` [Qemu-devel] [PATCH V2 1/6] libqblock API design Wenchao Xia
2012-09-10 21:07   ` Eric Blake
2012-09-11  3:16     ` Wenchao Xia
2012-09-14  2:03       ` Wenchao Xia
2012-09-11 20:28   ` Blue Swirl
2012-09-12  2:54     ` Wenchao Xia [this message]
2012-09-12  8:19     ` Kevin Wolf
2012-09-12  9:21       ` Wenchao Xia
2012-09-14 19:08       ` Blue Swirl
2012-09-10  8:26 ` [Qemu-devel] [PATCH V2 2/6] libqblock type and structure defines Wenchao Xia
2012-09-10 21:27   ` Eric Blake
2012-09-11  3:26     ` Wenchao Xia
2012-09-11  4:12       ` Eric Blake
2012-09-11 20:31   ` Blue Swirl
2012-09-11 22:52     ` Eric Blake
2012-09-12  3:05       ` Wenchao Xia
2012-09-12 12:59         ` Eric Blake
2012-09-13  3:24           ` Wenchao Xia
2012-09-13  3:33             ` Eric Blake
2012-09-13  3:49               ` Eric Blake
2012-09-14 18:11                 ` Blue Swirl
2012-09-17  2:23                   ` Wenchao Xia
2012-09-17 19:08                     ` Blue Swirl
2012-09-14 18:02       ` Blue Swirl
2012-09-10  8:26 ` [Qemu-devel] [PATCH V2 3/6] libqblock error handling Wenchao Xia
2012-09-10 21:33   ` Eric Blake
2012-09-11  4:36     ` Wenchao Xia
2012-09-11 20:32   ` Blue Swirl
2012-09-12  2:58     ` Wenchao Xia
2012-09-14 17:09       ` Blue Swirl
2012-09-10  8:26 ` [Qemu-devel] [PATCH V2 4/6] libqblock export some qemu block function Wenchao Xia
2012-09-10  8:26 ` [Qemu-devel] [PATCH V2 5/6] libqblock building system Wenchao Xia
2012-09-10  8:26 ` [Qemu-devel] [PATCH V2 6/6] libqblock test example Wenchao Xia

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=504FF974.7080408@linux.vnet.ibm.com \
    --to=xiawenc@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=blauwirbel@gmail.com \
    --cc=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.