qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
To: Blue Swirl <blauwirbel@gmail.com>
Cc: pbonzini@redhat.com, aliguori@us.ibm.com, qemu-devel@nongnu.org,
	stefanha@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [PATCH] [RFC] libqblock draft code v1
Date: Thu, 02 Aug 2012 16:32:36 +0800	[thread overview]
Message-ID: <501A3B24.6000203@linux.vnet.ibm.com> (raw)
In-Reply-To: <CAAu8pHtOrDHR0nMusVJKCh6xyYyLqT6uc=uVh3PsodOfPQq34w@mail.gmail.com>

于 2012-8-2 2:04, Blue Swirl 写道:
> On Wed, Aug 1, 2012 at 9:09 AM, Wenchao Xia <xiawenc@linux.vnet.ibm.com> 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 <xiawenc@linux.vnet.ibm.com>
>> ---
>>   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'.
>
   Native C type was used to simplify test codings, will correct them to
platform across types.

>> +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
>
right.

>> +{
>> +    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
>
   will change.

>> +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)
>
   OK.

>> +{
>> +    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.
>
   will include that header.

>> +    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.
>
   right.

>> +};
>> +
>> +struct QBlockCreateOption {
>> +    char *filename;
>> +    char *fmt;
>> +    char *base_filename;
>> +    char *base_fmt;
>> +    char *options;
>
> What would these be?
>
    options is used in qemu general block layer such as -c(compress),
will try alternate it to enums.

>> +    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;
>
   Compared to bool, int may indicate some property is not available by
(-1). So I changed bool to int.

>> +    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.
>
   OK. Will remove this part, and collect it in another API more closed
to emulator usage.

>> +    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.
>
   Will corrrect it.

>> +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
>>
>>
>>
>


-- 
Best Regards

Wenchao Xia

  reply	other threads:[~2012-08-02  8:33 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-01  9:09 [Qemu-devel] [PATCH] [RFC] libqblock draft code v1 Wenchao Xia
2012-08-01 10:44 ` Paolo Bonzini
2012-08-02  7:57   ` Wenchao Xia
2012-08-02  8:59     ` Paolo Bonzini
2012-08-02 10:23       ` Stefan Hajnoczi
2012-08-01 12:49 ` Stefan Hajnoczi
2012-08-01 13:25   ` Eric Blake
2012-08-02 10:18     ` Stefan Hajnoczi
2012-08-02 11:11     ` Daniel P. Berrange
2012-08-02 11:13       ` Paolo Bonzini
2012-08-03  7:54         ` Wenchao Xia
2012-08-02  8:18   ` Wenchao Xia
2012-08-02 10:17     ` Stefan Hajnoczi
2012-08-02 11:08       ` Paolo Bonzini
2012-08-01 18:04 ` Blue Swirl
2012-08-02  8:32   ` Wenchao Xia [this message]
2012-08-02  9:00     ` Paolo Bonzini

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=501A3B24.6000203@linux.vnet.ibm.com \
    --to=xiawenc@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=blauwirbel@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@linux.vnet.ibm.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 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).