qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] [RFC] libqblock draft code v1


From: Blue Swirl
Subject: Re: [Qemu-devel] [PATCH] [RFC] libqblock draft code v1
Date: Wed, 1 Aug 2012 18:04:36 +0000

On Wed, Aug 1, 2012 at 9:09 AM, Wenchao Xia <address@hidden> wrote:
>   This patch encapsulate qemu general block layer to provide block
> services. API are declared in libqblock.h. libqblock-test.c
> simulate library consumer's behaviors. Make libqblock-test could
> build the code.
>   For easy this patch does not form a dynamic libarary yet.
>
> Signed-off-by: Wenchao Xia <address@hidden>
> ---
>  Makefile         |    4 +-
>  libqblock-test.c |   56 +++++++++++++++
>  libqblock.c      |  199 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  libqblock.h      |   72 ++++++++++++++++++++
>  4 files changed, 330 insertions(+), 1 deletions(-)
>  create mode 100644 libqblock-test.c
>  create mode 100644 libqblock.c
>  create mode 100644 libqblock.h
>
> diff --git a/Makefile b/Makefile
> index 621cb86..6a34be6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -152,7 +152,6 @@ vscclient$(EXESUF): $(libcacard-y) $(oslib-obj-y) 
> $(trace-obj-y) qemu-timer-comm
>         $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(libcacard_libs) 
> $(LIBS),"  LINK  $@")
>
>  ######################################################################
> -
>  qemu-img.o: qemu-img-cmds.h
>
>  tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \
> @@ -160,6 +159,9 @@ tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o 
> qemu-timer.o \
>         iohandler.o cutils.o iov.o async.o
>  tools-obj-$(CONFIG_POSIX) += compatfd.o
>
> +libqblock-test$(EXESUF): libqblock.o libqblock-test.o $(tools-obj-y) 
> $(block-obj-y)
> +       $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^ $(LIBS),"  LINK  $@")
> +
>  qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
>  qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
>  qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
> diff --git a/libqblock-test.c b/libqblock-test.c
> new file mode 100644
> index 0000000..663111e
> --- /dev/null
> +++ b/libqblock-test.c
> @@ -0,0 +1,56 @@
> +#include "libqblock.h"
> +
> +#include <stdarg.h>
> +#include <stdio.h>
> +
> +
> +unsigned char buf0[1024];
> +unsigned char buf1[1024] = {4, 0, 0, 2};

'static' for the above, 'const' for buf1. I'd use uint8_t instead of
'unsigned char'.

> +int main(int argc, char **argv)
> +{
> +    struct QBlockState i_qbs;
> +    struct QBlockOpenOption i_qboo;
> +    struct QBlockCreateOption i_qbco;
> +    struct QBlockInfo i_qbi;

The variable names are cryptic.

> +    char *filename;
> +
> +    int i;
> +    unsigned long op_size = 512;
> +    unsigned long op_start = 1024;

size_t

> +
> +    filename = argv[1];
> +    printf("qemu test, file name is %s.\n", filename);
> +
> +    libqblock_init();
> +
> +    qbs_init(&i_qbs);
> +    memset(&i_qbco, 0, sizeof(struct QBlockCreateOption));
> +
> +    i_qbco.filename = filename;
> +    i_qbco.fmt = (char *)"qcow2";

Add 'const' to fmt field and remove cast.

> +    i_qbco.flag = BDRV_O_NOCACHE;
> +    i_qbco.size = 512 * 1024 * 1024;
> +    qb_create(&i_qbs, &i_qbco);
> +
> +    i_qboo.filename = filename;
> +    i_qboo.flag = BDRV_O_RDWR;
> +    qb_open(&i_qbs, &i_qboo);
> +
> +    qb_write(&i_qbs, op_start, op_size, buf1);
> +    qb_read(&i_qbs, op_start, op_size, buf0);
> +    for (i = 0; i < op_size; i++) {
> +        if (buf0[i] != buf1[i]) {
> +            printf("unmatch found at %d.\n", i);

mismatch

> +            break;
> +        }
> +    }
> +    qbi_init(&i_qbi);
> +    qb_getinfo(&i_qbs, &i_qbi);
> +    qbi_print_test(&i_qbi);
> +    qbi_uninit(&i_qbi);
> +
> +    qb_close(&i_qbs);
> +    qb_delete(&i_qbs, filename);
> +    qbs_uninit(&i_qbs);
> +    return 0;
> +}
> diff --git a/libqblock.c b/libqblock.c
> new file mode 100644
> index 0000000..00b6649
> --- /dev/null
> +++ b/libqblock.c
> @@ -0,0 +1,199 @@
> +#include "libqblock.h"
> +
> +#include <unistd.h>
> +
> +#define QB_ERR_MEM_ERR (-1)
> +#define QB_ERR_INTERNAL_ERR (-2)
> +#define QB_ERR_INVALID_PARAM (-3)
> +
> +#define FUNC_FREE g_free

Useless.

> +
> +#define CLEAN_FREE(p) { \
> +        FUNC_FREE(p); \
> +        (p) = NULL; \
> +}
> +
> +/* try string dup and check if it succeed, dest would be freed before dup */
> +#define SAFE_STRDUP(dest, src, ret, err_v) { \
> +    if ((ret) != (err_v)) { \
> +        if ((dest) != NULL) { \
> +            FUNC_FREE(dest); \
> +        } \
> +        (dest) = strdup(src); \
> +        if ((dest) == NULL) { \
> +            (ret) = (err_v); \
> +        } \
> +    } \
> +}

Just use g_strdup().

> +
> +int libqblock_init(void)
> +{
> +    bdrv_init();
> +    return 0;
> +}
> +
> +int qbs_init(struct QBlockState *qbs)
> +{
> +    memset(qbs, 0, sizeof(struct QBlockState));
> +    qbs->bdrvs = bdrv_new("hda");
> +    if (qbs->bdrvs == NULL) {
> +        return QB_ERR_INTERNAL_ERR;
> +    }
> +    return 0;
> +}
> +
> +int qbs_uninit(struct QBlockState *qbs)
> +{
> +    CLEAN_FREE(qbs->filename);
> +    if (qbs->bdrvs == NULL) {
> +        return QB_ERR_INVALID_PARAM;
> +    }
> +    bdrv_delete(qbs->bdrvs);
> +    return 0;
> +}
> +
> +int qb_create(struct QBlockState *qbs, struct QBlockCreateOption *op)
> +{
> +    int ret;
> +    BlockDriverState *bs;
> +
> +    bs = (BlockDriverState *)qbs->bdrvs;
> +
> +    ret = bdrv_img_create(op->filename, op->fmt, op->base_filename,
> +                          op->base_fmt, op->options, op->size, op->flag);
> +    return 0;
> +}
> +
> +int qb_open(struct QBlockState *qbs, struct QBlockOpenOption *op)

const struct QBlockOpenOption *op

> +{
> +    int ret;
> +    BlockDriverState *bs;
> +
> +    bs = (BlockDriverState *)qbs->bdrvs;
> +    ret = bdrv_open(bs, op->filename, op->flag, NULL);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    SAFE_STRDUP(qbs->filename, op->filename, ret, QB_ERR_MEM_ERR);
> +    return ret;
> +}
> +
> +int qb_close(struct QBlockState *qbs)
> +{
> +    int ret = 0;
> +    BlockDriverState *bs;
> +
> +    bs = (BlockDriverState *)qbs->bdrvs;
> +    bdrv_close(bs);
> +    return ret;
> +}
> +
> +int qb_delete(struct QBlockState *qbs, const char *filename)
> +{
> +    return unlink(filename);
> +}
> +
> +/* ignore case that len is not alligned to 512 now. */

aligned

> +int qb_read(struct QBlockState *qbs, unsigned long start, unsigned long len,
> +                                                          unsigned char *buf)

I'd make this closer to pread() interface:
ssize_t qb_read(struct QBlockState *qbs, void *buf, size_t len,  off_t offset)

> +{
> +    int ret;
> +    BlockDriverState *bs;
> +
> +    bs = (BlockDriverState *)qbs->bdrvs;
> +
> +    ret = bdrv_read(bs, start / 512,
> +                        buf, len / 512);

IIRC there is a constant for 512 somewhere.

> +    return ret;
> +}
> +
> +/* ignore case that len is not alligned to 512 now. */

aligned

> +int qb_write(struct QBlockState *qbs, unsigned long start, unsigned long len,
> +                                                           unsigned char 
> *buf)

Also here match pwrite:
ssize_t qb_write(struct QBlockState *qbs, const void *buf, size_t len,
 off_t offset)

> +{
> +    int ret;
> +    BlockDriverState *bs;
> +
> +    bs = (BlockDriverState *)qbs->bdrvs;
> +    ret = bdrv_write(bs, start / 512,
> +                        buf, len / 512);
> +    return ret;
> +}
> +
> +int qb_flush(struct QBlockState *qbs)
> +{
> +    int ret = 0;
> +    BlockDriverState *bs;
> +
> +    bs = (BlockDriverState *)qbs->bdrvs;
> +    ret = bdrv_flush(bs);
> +    return ret;
> +}
> +
> +int qbi_init(struct QBlockInfo *info)
> +{
> +    memset(info, 0, sizeof(struct QBlockInfo));
> +    return 0;
> +}
> +
> +int qbi_uninit(struct QBlockInfo *info)
> +{
> +    CLEAN_FREE(info->filename);
> +    CLEAN_FREE(info->fmt);
> +    CLEAN_FREE(info->backing_filename);
> +    CLEAN_FREE(info->sn_tab);
> +    return 0;
> +}
> +
> +int qbi_print_test(struct QBlockInfo *info)
> +{
> +    printf("name:%s, fmt %s, virt_size %ld, allocated_size %ld, encryt %d, "
> +           "back_file %s, sn_tab %p, sn_num %d, cluster size %d, "
> +           "vm_state_offset %ld, dirty %d.\n",
> +           info->filename, info->fmt, info->virt_size, info->allocated_size,
> +           info->encrypt_flag,
> +           info->backing_filename, info->sn_tab, info->sn_tab_num,
> +           info->cluster_size,
> +           info->vm_state_offset, info->is_dirty);
> +    return 0;
> +}

This does not belong to the library.

> +
> +int qb_getinfo(struct QBlockState *qbs, struct QBlockInfo *info)
> +{
> +    int ret = 0;
> +    BlockDriverState *bs;
> +    const char *tmp;
> +    BlockDriverInfo bdi;
> +    uint64_t total_sectors;
> +    char backing_filename[1024];
> +
> +    bs = (BlockDriverState *)qbs->bdrvs;
> +    SAFE_STRDUP(info->filename, qbs->filename, ret, QB_ERR_MEM_ERR);
> +    tmp = bdrv_get_format_name(bs);
> +    SAFE_STRDUP(info->fmt, tmp, ret, QB_ERR_MEM_ERR);
> +    bdrv_get_geometry(bs, &total_sectors);
> +    info->virt_size = total_sectors * 512;
> +    info->allocated_size = bdrv_get_allocated_file_size(bs);
> +    info->encrypt_flag = bdrv_is_encrypted(bs);
> +    bdrv_get_full_backing_filename(bs, backing_filename,
> +                                   sizeof(backing_filename));
> +    if (backing_filename[0] != '\0') {
> +        SAFE_STRDUP(info->backing_filename, backing_filename, ret,
> +                                                   QB_ERR_MEM_ERR);
> +    }
> +    info->sn_tab_num = bdrv_snapshot_list(bs, &(info->sn_tab));
> +    if (info->sn_tab_num < 0) {
> +        info->sn_tab_num = 0;
> +    }
> +    if (bdrv_get_info(bs, &bdi) >= 0) {
> +        info->cluster_size = bdi.cluster_size;
> +        info->vm_state_offset = bdi.vm_state_offset;
> +        info->is_dirty = bdi.is_dirty;
> +    } else {
> +        info->cluster_size = -1;
> +        info->vm_state_offset = -1;
> +        info->is_dirty = -1;
> +    }
> +    return ret;
> +}
> diff --git a/libqblock.h b/libqblock.h
> new file mode 100644
> index 0000000..64a8b96
> --- /dev/null
> +++ b/libqblock.h
> @@ -0,0 +1,72 @@
> +#ifndef LIBQBLOCK_H
> +#define LIBQBLOCK_H
> +
> +#include "block.h"
> +
> +/* details should be hidden to user */
> +struct QBlockState {
> +    void *bdrvs;
> +    char *filename;
> +};
> +
> +/* libarary init or uninit */
> +int libqblock_init(void);
> +
> +/* qbs init and uninit */
> +int qbs_init(struct QBlockState *qbs);
> +int qbs_uninit(struct QBlockState *qbs);
> +
> +/* file open and close */
> +struct QBlockOpenOption {
> +    char *filename;
> +    int flag;

Possible flags should be listed as enums.

> +};
> +
> +struct QBlockCreateOption {
> +    char *filename;
> +    char *fmt;
> +    char *base_filename;
> +    char *base_fmt;
> +    char *options;

What would these be?

> +    unsigned long size;

uint64_t

> +    int flag;

Possible flags should be listed as enums.

> +};
> +
> +int qb_open(struct QBlockState *qbs, struct QBlockOpenOption *op);
> +int qb_close(struct QBlockState *qbs);
> +
> +int qb_create(struct QBlockState *qbs, struct QBlockCreateOption *op);
> +int qb_delete(struct QBlockState *qbs, const char *filename);
> +
> +/* information */
> +struct QBlockInfo {
> +    /* basic info */
> +    char *filename;
> +    char *fmt;
> +    /* advance info */
> +    unsigned long virt_size;
> +    unsigned long allocated_size;

uint64_t for both above.

> +    int encrypt_flag;

bool is_encrypted;

> +    char *backing_filename;
> +    QEMUSnapshotInfo *sn_tab;

Nack, don't export QEMU types directly.

> +    int sn_tab_num;

I'm not sure this is needed.

> +
> +    /* in bytes, 0 if irrelevant */
> +    int cluster_size;
> +    int64_t vm_state_offset;

Nack, not part of block interface.

> +    int is_dirty;

bool

> +};
> +
> +/* sync access */
> +int qb_read(struct QBlockState *qbs, unsigned long start, unsigned long len,
> +                                                          unsigned char 
> *buf);
> +int qb_write(struct QBlockState *qbs, unsigned long start, unsigned long len,
> +                                                          unsigned char 
> *buf);
> +int qb_flush(struct QBlockState *qbs);
> +
> +/* get info */

Comment is misplaced.

> +int qbi_init(struct QBlockInfo *info);
> +int qbi_uninit(struct QBlockInfo *info);
> +int qbi_print_test(struct QBlockInfo *info);
> +int qb_getinfo(struct QBlockState *qbs, struct QBlockInfo *info);
> +#endif
> --
> 1.7.1
>
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]