qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 2/2] block/io: refactor padding


From: Stefan Hajnoczi
Subject: Re: [Qemu-devel] [PATCH 2/2] block/io: refactor padding
Date: Fri, 31 May 2019 11:51:01 +0100
User-agent: Mutt/1.11.4 (2019-03-13)

On Tue, May 28, 2019 at 11:45:44AM +0300, Vladimir Sementsov-Ogievskiy wrote:
> We have similar padding code in bdrv_co_pwritev,
> bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify
> it.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy <address@hidden>
> ---
>  block/io.c | 344 ++++++++++++++++++++++++++++-------------------------

Hmmm...this adds more lines than it removes.  O_o

Merging a change like this can still be useful but there's a risk of
making the code harder to understand due to the additional layers of
abstraction.

>  1 file changed, 179 insertions(+), 165 deletions(-)
> 
> diff --git a/block/io.c b/block/io.c
> index 3134a60a48..840e276269 100644
> --- a/block/io.c
> +++ b/block/io.c
> @@ -1344,28 +1344,155 @@ out:
>  }
>  
>  /*
> - * Handle a read request in coroutine context
> + * Request padding
> + *
> + *  |<---- align ---->|                     |<---- align ---->|
> + *  |<- head ->|<------------ bytes ------------>|<-- tail -->|
> + *  |          |      |                     |    |            |
> + * -*----------$------*-------- ... --------*----$------------*---
> + *  |          |      |                     |    |            |
> + *  |          offset |                     |    end          |
> + *  ALIGN_UP(offset)  ALIGN_DOWN(offset)    ALIGN_DOWN(end)   ALIGN_UP(end)

Are ALIGN_UP(offset) and ALIGN_DOWN(offset) in the wrong order?

> + *  [buf   ... )                            [tail_buf         )
> + *
> + * @buf is an aligned allocation needed to store @head and @tail paddings. 
> @head
> + * is placed at the beginning of @buf and @tail at the @end.
> + *
> + * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk
> + * around tail, if tail exists.
> + *
> + * @merge_reads is true for small requests,
> + * if @buf_len == @head + bytes + @tail. In this case it is possible that 
> both
> + * head and tail exist but @buf_len == align and @tail_buf == @buf.
>   */
> +typedef struct BdrvRequestPadding {
> +    uint8_t *buf;
> +    size_t buf_len;
> +    uint8_t *tail_buf;
> +    size_t head;
> +    size_t tail;
> +    bool merge_reads;
> +    QEMUIOVector local_qiov;
> +} BdrvRequestPadding;
> +
> +static bool bdrv_init_padding(BlockDriverState *bs,
> +                              int64_t offset, int64_t bytes,
> +                              BdrvRequestPadding *pad)
> +{
> +    uint64_t align = bs->bl.request_alignment;
> +    size_t sum;
> +
> +    memset(pad, 0, sizeof(*pad));
> +
> +    pad->head = offset & (align - 1);
> +    pad->tail = ((offset + bytes) & (align - 1));
> +    if (pad->tail) {
> +        pad->tail = align - pad->tail;
> +    }
> +
> +    if ((!pad->head && !pad->tail) || !bytes) {
> +        return false;
> +    }
> +
> +    sum = pad->head + bytes + pad->tail;
> +    pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : 
> align;
> +    pad->buf = qemu_blockalign(bs, pad->buf_len);
> +    pad->merge_reads = sum == pad->buf_len;
> +    if (pad->tail) {
> +        pad->tail_buf = pad->buf + pad->buf_len - align;
> +    }
> +
> +    return true;
> +}
> +
> +static int bdrv_padding_read(BdrvChild *child,
> +                             BdrvTrackedRequest *req,
> +                             BdrvRequestPadding *pad,
> +                             bool zero_middle)
> +{
> +    QEMUIOVector local_qiov;
> +    BlockDriverState *bs = child->bs;
> +    uint64_t align = bs->bl.request_alignment;
> +    int ret;
> +
> +    assert(req->serialising && pad->buf);
> +
> +    if (pad->head || pad->merge_reads) {
> +        uint64_t bytes = pad->merge_reads ? pad->buf_len : align;
> +
> +        qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
> +
> +        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);

PWRITEV?  That's unexpected for a function called bdrv_padding_read().
Please rename this to bdrv_padding_rmw_read() so it's clear this is part
of a read-modify-write operation, not a regular read.

> +        ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
> +                                  align, &local_qiov, 0);
> +        if (ret < 0) {
> +            return ret;
> +        }
> +        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
> +
> +        if (pad->merge_reads) {
> +            goto zero_mem;
> +        }
> +    }
> +
> +    if (pad->tail) {
> +        qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align);
> +
> +        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
> +        ret = bdrv_aligned_preadv(
> +                child, req,
> +                req->overlap_offset + req->overlap_bytes - align,
> +                align, align, &local_qiov, 0);
> +        if (ret < 0) {
> +            return ret;
> +        }
> +        bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
> +    }
> +
> +zero_mem:
> +    if (zero_middle) {
> +        memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - 
> pad->tail);
> +    }
> +
> +    return 0;
> +}
> +
> +static void bdrv_padding_destroy(BdrvRequestPadding *pad)
> +{
> +    if (pad->buf) {
> +        qemu_vfree(pad->buf);
> +        qemu_iovec_destroy(&pad->local_qiov);
> +    }
> +}
> +
> +static QEMUIOVector *bdrv_pad_request(BlockDriverState *bs, QEMUIOVector 
> *qiov,
> +                                      int64_t *offset, unsigned int *bytes,
> +                                      BdrvRequestPadding *pad)

Doc comment missing?

> +{
> +    bdrv_init_padding(bs, *offset, *bytes, pad);
> +    if (!pad->buf) {
> +        return qiov;
> +    }

I think there's no need to peek at pad->buf:

  if (!bdrv_init_padding(bs, *offset, *bytes, pad)) {
      return qiov;
  }

Attachment: signature.asc
Description: PGP signature


reply via email to

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