qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v6 08/20] block: vhdx - log parsing, replay, and


From: Stefan Hajnoczi
Subject: Re: [Qemu-devel] [PATCH v6 08/20] block: vhdx - log parsing, replay, and flush support
Date: Tue, 1 Oct 2013 13:31:36 +0200
User-agent: Mutt/1.5.21 (2010-09-15)

On Wed, Sep 25, 2013 at 05:02:53PM -0400, Jeff Cody wrote:
> +static int vhdx_log_read_desc(BlockDriverState *bs, BDRVVHDXState *s,
> +                              VHDXLogEntries *log, VHDXLogDescEntries 
> **buffer)
> +{
> +    int ret = 0;
> +    uint32_t desc_sectors;
> +    uint32_t sectors_read;
> +    VHDXLogEntryHeader hdr;
> +    VHDXLogDescEntries *desc_entries = NULL;
> +    int i;
> +
> +    assert(*buffer == NULL);
> +
> +    ret = vhdx_log_peek_hdr(bs, log, &hdr);
> +    if (ret < 0) {
> +        goto exit;
> +    }
> +    vhdx_log_entry_hdr_le_import(&hdr);
> +    if (vhdx_log_hdr_is_valid(log, &hdr, s) == false) {
> +        ret = -EINVAL;
> +        goto exit;
> +    }
> +
> +    desc_sectors = vhdx_compute_desc_sectors(hdr.descriptor_count);

I don't see input validation for hdr.descriptor_count.  It not exceed
log length.

> +static int vhdx_log_flush_desc(BlockDriverState *bs, VHDXLogDescriptor *desc,
> +                               VHDXLogDataSector *data)
> +{
> +    int ret = 0;
> +    uint64_t seq, file_offset;
> +    uint32_t offset = 0;
> +    void *buffer = NULL;
> +    uint64_t count = 1;
> +    int i;
> +
> +    buffer = qemu_blockalign(bs, VHDX_LOG_SECTOR_SIZE);
> +
> +    if (!memcmp(&desc->signature, "desc", 4)) {
> +        /* data sector */
> +        if (data == NULL) {
> +            ret = -EFAULT;
> +            goto exit;
> +        }
> +
> +        /* The sequence number of the data sector must match that
> +         * in the descriptor */
> +        seq = data->sequence_high;
> +        seq <<= 32;
> +        seq |= data->sequence_low & 0xffffffff;
> +
> +        if (seq != desc->sequence_number) {
> +            ret = -EINVAL;
> +            goto exit;
> +        }
> +
> +        /* Each data sector is in total 4096 bytes, however the first
> +         * 8 bytes, and last 4 bytes, are located in the descriptor */
> +        memcpy(buffer, &desc->leading_bytes, 8);
> +        offset += 8;
> +
> +        memcpy(buffer+offset, data->data, 4084);
> +        offset += 4084;
> +
> +        memcpy(buffer+offset, &desc->trailing_bytes, 4);
> +
> +    } else if (!memcmp(&desc->signature, "zero", 4)) {
> +        /* write 'count' sectors of sector */
> +        memset(buffer, 0, VHDX_LOG_SECTOR_SIZE);
> +        count = desc->zero_length / VHDX_LOG_SECTOR_SIZE;

Zero descriptors also have a sequence number that should be checked.

> +/* Parse the replay log.  Per the VHDX spec, if the log is present
> + * it must be replayed prior to opening the file, even read-only.
> + *
> + * If read-only, we must replay the log in RAM (or refuse to open
> + * a dirty VHDX file read-only */

read-only) <-- missing parenthesis

> @@ -794,10 +753,12 @@ static int vhdx_open(BlockDriverState *bs, QDict 
> *options, int flags,
>      uint32_t i;
>      uint64_t signature;
>      uint32_t data_blocks_cnt, bitmap_blocks_cnt;
> +    bool log_flushed = false;
>  
>  
>      s->bat = NULL;
>      s->first_visible_write = true;
> +    s->log.write = s->log.read = 0;

This is not really necessary since bs->opaque is zeroed before block.c
calls vhdx_open().

>  
>      qemu_co_mutex_init(&s->lock);
>  
> @@ -821,20 +782,33 @@ static int vhdx_open(BlockDriverState *bs, QDict 
> *options, int flags,
>          goto fail;
>      }
>  
> -    ret = vhdx_parse_log(bs, s);
> +    ret = vhdx_open_region_tables(bs, s);
>      if (ret) {
>          goto fail;
>      }
>  
> -    ret = vhdx_open_region_tables(bs, s);
> +    ret = vhdx_parse_metadata(bs, s);
>      if (ret) {
>          goto fail;
>      }
>  
> -    ret = vhdx_parse_metadata(bs, s);
> +    ret = vhdx_parse_log(bs, s, &log_flushed);
>      if (ret) {
>          goto fail;
>      }

Why replay the log *after* reading logged metadata?  We could read stale
or corrupted values.

I guess there is a dependency here - the log replay code needs some
field that vhdx_open_region_tables() or vhdx_parse_metadata() load?



reply via email to

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