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: Vladimir Sementsov-Ogievskiy
Subject: Re: [Qemu-devel] [PATCH 2/2] block/io: refactor padding
Date: Fri, 31 May 2019 14:10:17 +0000

31.05.2019 13:51, Stefan Hajnoczi wrote:
> 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

It's near to be the same size, and keep in mind big comment.

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

It's a preparation for adding qiov_offset parameter to read/write path. Seems
correct to unify similar things, which I'm going to change. And I really want
to make code more understandable than it was.. But my view is not general
of course.

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

yes :(

> 
>> + *  [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;
>    }
> 


-- 
Best regards,
Vladimir



reply via email to

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