[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-block] [PATCH v2 4/7] qcow2: Split do_perform_cow() into _read
From: |
Alberto Garcia |
Subject: |
Re: [Qemu-block] [PATCH v2 4/7] qcow2: Split do_perform_cow() into _read(), _encrypt() and _write() |
Date: |
Mon, 12 Jun 2017 15:00:41 +0200 |
User-agent: |
Notmuch/0.18.2 (http://notmuchmail.org) Emacs/24.4.1 (i586-pc-linux-gnu) |
On Fri 09 Jun 2017 04:53:05 PM CEST, Eric Blake wrote:
> Let's suppose we have a guest issuing 512-byte aligned requests and a
> host that requires 4k alignment; and the guest does an operation that
> needs a COW with one sector at both the front and end of the cluster.
>
>> @@ -760,22 +776,59 @@ static int perform_cow(BlockDriverState *bs,
>> QCowL2Meta *m)
>> BDRVQcow2State *s = bs->opaque;
>> Qcow2COWRegion *start = &m->cow_start;
>> Qcow2COWRegion *end = &m->cow_end;
>> + unsigned buffer_size = start->nb_bytes + end->nb_bytes;
>
> This sets buffer_size to 1024 initially.
>
>> + uint8_t *start_buffer, *end_buffer;
>> int ret;
>>
>> + assert(start->nb_bytes <= UINT_MAX - end->nb_bytes);
>> +
>> if (start->nb_bytes == 0 && end->nb_bytes == 0) {
>> return 0;
>> }
>>
>> + /* Reserve a buffer large enough to store the data from both the
>> + * start and end COW regions */
>> + start_buffer = qemu_try_blockalign(bs, buffer_size);
>
> This is going to allocate a bigger buffer, namely one that is at least
> 4k in size (at least, that's my understanding - the block device is
> able to track its preferred IO size/alignment).
>
>> + if (start_buffer == NULL) {
>> + return -ENOMEM;
>> + }
>> + /* The part of the buffer where the end region is located */
>> + end_buffer = start_buffer + start->nb_bytes;
>
> But now end_buffer does not have optimal alignment. In the old code,
> we called qemu_try_blockalign() twice, so that both read()s were
> called on a 4k boundary; but now, the end read() is called unaligned
> to a 4k boundary. Of course, since we're only reading 512 bytes,
> instead of 4k, it MIGHT not matter, but I don't know if we are going
> to cause a bounce buffer to come into play that we could otherwise
> avoid if we were smarter with our alignments. Is that something we
> need to analyze further, or even possibly intentionally over-allocate
> our buffer to ensure optimal read alignments?
I think you're right, I actually thought about this but forgot it when
preparing the series for publishing.
If I'm not wrong it should be simply a matter of replacing
buffer_size = start->nb_bytes + end->nb_bytes;
with
buffer_size = QEMU_ALIGN_UP(start->nb_bytes, bdrv_opt_mem_align(bs))
+ end->nb_bytes;
and then
end_buffer = start_buffer + buffer_size - end->nb_bytes;
(this one we do anyway in patch 5)
Berto
- Re: [Qemu-block] [PATCH v2 2/7] qcow2: Use unsigned int for both members of Qcow2COWRegion, (continued)
- [Qemu-block] [PATCH v2 3/7] qcow2: Make perform_cow() call do_perform_cow() twice, Alberto Garcia, 2017/06/07
- [Qemu-block] [PATCH v2 6/7] qcow2: Pass a QEMUIOVector to do_perform_cow_{read, write}(), Alberto Garcia, 2017/06/07
- [Qemu-block] [PATCH v2 5/7] qcow2: Allow reading both COW regions with only one request, Alberto Garcia, 2017/06/07
- [Qemu-block] [PATCH v2 4/7] qcow2: Split do_perform_cow() into _read(), _encrypt() and _write(), Alberto Garcia, 2017/06/07
- Re: [Qemu-block] [PATCH v2 0/7] qcow2: Reduce the number of I/O ops when doing COW, Kevin Wolf, 2017/06/16