qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v9] Support vhd type VHD_DIFFERENCING


From: Xiaodong Gong
Subject: Re: [Qemu-devel] [PATCH v9] Support vhd type VHD_DIFFERENCING
Date: Fri, 27 Feb 2015 13:49:09 +0800


2015年2月25日 22:58于 "Stefan Hajnoczi" <address@hidden>写道:
>
> On Sun, Feb 15, 2015 at 09:35:49PM +0800, Xiaodong Gong wrote:
> > Now qemu only supports vhd type VHD_FIXED and VHD_DYNAMIC, so qemu
> > can't read snapshot volume of vhd, and can't support other storage
> > features of vhd file.
> >
> > This patch add read parent information in function "vpc_open", read
> > bitmap in "vpc_read", and change bitmap in "vpc_write".
> >
> > Signed-off-by: Xiaodong Gong <address@hidden>
> > Reviewed-by: Ding xiao <address@hidden>
> > ---
> > Changes since v8
> > - use backing_format to avoid being probed to format of raw
> >
> > Changes since v7:
> > - use iconv to decode UTF-16LE(w2u) and UTF-8(macx) to ASCII
> >   (Stefan Hajnoczi)
>
> I suggested glib's character set conversion functions, not iconv.
>
> glib abstracts the dependency character set conversion so it will work
> across platforms.  That way we don't have to add iconv library detection
> to ./configure.  Please use glib since QEMU already depends on it.
>
> https://developer.gnome.org/glib/stable/glib-Character-Set-Conversion.html
>

iconv is a buildin fuction in libc.And I greped,but no use of g_conv*.
I will exchange icovn with g_conv

> >  #define HEADER_SIZE 512
> > +#define DYNAMIC_HEADER_SIZE 1024
> > +#define PARENT_LOCATOR_NUM 8
> > +#define TBBATMAP_HEAD_SIZE 28
> > +
> > +#define MACX_PREFIX_LEN 7 /* file:// */
> > +
> > +#define PLATFORM_MACX 0x5863614d /* big endian */
>
> This comment doesn't make sense.  The constant is just a C integer
> literal, it doesn't have endianness.
>

It is the source of mistake,I will change it to value to graft

> > +static int vpc_decode_parent_loc(uint32_t platform,
> > +                                 BlockDriverState *bs,
> > +                                 int data_length)
> > +{
> > +    int ret;
> > +
> > +    switch (platform) {
> > +    case PLATFORM_MACX:
> > +        ret = vpc_decode_maxc_loc(bs, data_length);
> > +        if (ret < 0) {
> > +            return ret;
> > +        }
> > +        break;
> > +
> > +    case PLATFORM_W2RU:
> > +        /* fall through! */
> > +    case PLATFORM_W2KU:
> > +        ret = vpc_decode_w2u_loc(bs, data_length);
> > +        if (ret < 0) {
> > +            return ret;
> > +        }
> > +        break;
> > +
> > +    default:
> > +        return 0;
>
> This should fail.  There are unimplemented platform codes.  We should
> not attempt to open the file any further.
>

yes

> In the PLATFORM_NONE (0x0) case it may be cleanest to
> vpc_read_backing_loc()'s for loop to skip empty platform locators
> instead of trying to read 0 bytes and then calling
> vpc_decode_parent_loc() with no data.
>
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int vpc_read_backing_loc(VHDDynDiskHeader *dyndisk_header,
> > +                                BlockDriverState *bs,
> > +                                Error **errp)
> > +{
> > +    BDRVVPCState *s = bs->opaque;
> > +    int64_t data_offset = 0;
> > +    int data_length = 0;
> > +    uint32_t platform;
> > +    bool done = false;
> > +    int parent_locator_offset = 0;
> > +    int i;
> > +    int ret = 0;
> > +
> > +    for (i = 0; i < PARENT_LOCATOR_NUM; i++) {
> > +        /* The PLATFORM_* is big ending, and the dyndisk_header
> > +         * is always big ending. So whatever this platform in cpu
> > +         * is, it works. */
>
> This comment is incorrect.  dyndisk_header is big endian but PLATFORM_*
> is not big endian.  Please drop the comment.
>

the same as the upper commant of “big ending”

> > +        platform =
> > +            dyndisk_header->parent_locator[i].platform;
>
> Missing be32_to_cpu().
>
> > +        data_offset =
> > +            be64_to_cpu(dyndisk_header->parent_locator[i].data_offset);
> > +        data_length =
> > +            be32_to_cpu(dyndisk_header->parent_locator[i].data_length);
> > +
> > +        /* Extend the location offset */
> > +        if (parent_locator_offset < data_offset) {
> > +            parent_locator_offset = data_offset;
>
> Why is parent_locator_offset and this function's return value int?
>
> data_offset is uint64_t and it seems like values could get truncated if
> int is used.
>

This var is a water line of offset,it is directly a uint64. Is this the worrest code I ever did?

> > @@ -278,7 +523,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
> >          s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
> >
> >          ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
> > -                         s->max_table_entries * 4);
> > +            s->max_table_entries * 4);
> >          if (ret < 0) {
> >              goto fail;
> >          }
>
> Unnecessary whitespace change?
>

yes,to pass checkpatch

> > @@ -286,6 +531,48 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
> >          s->free_data_block_offset =
> >              (s->bat_offset + (s->max_table_entries * 4) + 511) & ~511;
> >
> > +        /* Read tdbatmap header by offset */
> > +        if (be32_to_cpu(footer->version) >= VHD_VERSION(1, 2)) {
> > +            ret = bdrv_pread(bs->file, s->free_data_block_offset,
> > +                tdbatmap_header_buf, TBBATMAP_HEAD_SIZE);
> > +            if (ret < 0) {
> > +                goto fail;
> > +            }
> > +
> > +            tdbatmap_header = (VHDTdBatmapHeader *) tdbatmap_header_buf;
> > +            if (!strncmp(tdbatmap_header->magic, "tdbatmap", 8)) {
> > +                s->free_data_block_offset =
> > +                    be32_to_cpu(tdbatmap_header->batmap_size) * 512
> > +                    + be64_to_cpu(tdbatmap_header->batmap_offset);
> > +            }
> > +        }
> > +
> > +        if (dyndisk_header->parent_name[0] || dyndisk_header->parent_name[1]) {
> > +            int len;
> > +
> > +            /* Read parent location from dyn header table */
> > +            ret = parent_locator_offset = vpc_read_backing_loc(dyndisk_header,
> > +                bs, errp);
> > +            if (ret < 0) {
> > +                goto fail;
> > +            }
> > +
> > +            /* Fix me : Set parent format to avoid probing to raw in
> > +             * format probe framework */
> > +            len = strlen("vpc");
> > +            if (sizeof(bs->backing_format) - 1 < len) {
> > +                goto fail;
> > +            }
> > +            pstrcpy(bs->backing_format, sizeof(bs->backing_format), "vpc");
> > +            bs->backing_format[len] = '\0';
>
> pstrcpy() always NUL-terminates so this is not necessary.
>

yes

> > @@ -376,7 +704,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs,
> >          bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
> >      }
> >
> > -//    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
> > +//  printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
> >  //   sector_num, pagetable_index, pageentry_index,
> >  //   bitmap_offset, block_offset);
> >
>
> Unnecessary whitespace change?

recover it


reply via email to

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