qemu-block
[Top][All Lists]
Advanced

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

Re: [Qemu-block] qemu-img: block/io.c:2122: bdrv_co_block_status: Assert


From: Eric Blake
Subject: Re: [Qemu-block] qemu-img: block/io.c:2122: bdrv_co_block_status: Assertion `*pnum && QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' failed.
Date: Thu, 28 Mar 2019 09:54:53 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.0

On 3/28/19 8:25 AM, Richard W.M. Jones wrote:
> Not sure if this is a bug in qemu or nbdkit or the NBD protocol, so I
> didn't file a bug yet.
> 
> When returning NBD_CMD_BLOCK_STATUS extents which aren't aligned to a
> sector size, qemu-img gives an assert failure.

Definite bug in qemu. The NBD protocol states:

  The server SHOULD use descriptor
    lengths that are an integer multiple of 512 bytes where possible
    (the first and last descriptor of an unaligned query being the
    most obvious places for an exception), and MUST use descriptor
    lengths that are an integer multiple of any advertised minimum
    block size.

and nbdkit does NOT advertise block sizes, so even though 512-alignment
is nice (to avoid problems like the assertion you just tripped), it is
not a hard requirement that nbdkit must enforce. Rather, qemu has the
problem that if block size was not advertised, it is slamming block size
to 512 and then asserting any time the server didn't actually comply
with the limit, even though the server is under no such obligation.

> 
> This is reproducible using the block-status branch here:
> 
>   https://github.com/rwmjones/nbdkit/tree/block-status
> 
> $ ./nbdkit --filter=log --filter=truncate -U - \
>            data data="1" size=511 truncate=64K logfile=/dev/stdout \
>            --run 'qemu-img convert $nbd /var/tmp/out'
> 2019-03-28 13:20:33.308114 connection=1 Connect size=0x10000 write=1 flush=0 
> rotational=0 trim=1 zero=1 fua=0
> 2019-03-28 13:20:33.308619 connection=1 Read id=1 offset=0x0 count=0x200 ...
> 2019-03-28 13:20:33.308644 connection=1 ...Read id=1 return=0 (Success)
> 2019-03-28 13:20:33.309073 connection=1 Extents id=2 offset=0x0 count=0x10000 
> req_one=1 ...
> 2019-03-28 13:20:33.309099 connection=1 ...Extents id=2 extents=[{ 
> offset=0x0, length=0x1ff, type=0 }, { offset=0x1ff, length=0xfe01, type=3 }] 
> return=0
> qemu-img: block/io.c:2122: bdrv_co_block_status: Assertion `*pnum && 
> QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' failed.

The block layer requires that block/nbd.c return alignment consistent
with its block_size. If the server advertised alignment, then the server
better send aligned data. But when it does not, I still have to set
block_size in block/nbd.c; either I set block_size to 1 (so this
assertion never trips, because anything the server sends is by default
aligned - but then I risk sending unaligned read/writes to an
unsuspecting server), or I set block_size to 512 (then the block layer
guarantees I never send sub-sector requests to a server, but now the NBD
layer has to take care of unaligned requests before handing it back to
the block layer).

I don't want to blindly slam qemu's block alignment to 1 for all servers
that lack block size (as that makes it too easy for qemu to send an
unaligned read or write request to an unsuspecting server), but what I
_can_ do is a heuristic: if the server advertises base:allocation
support but no block sizes, it's a new enough server that the authors
should also be aware of the NBD spec wording on block sizing even though
they chose not to advertise sizing, and therefore they should likely
support a block size of 1; while a server that does not advertise
base:allocation may predate the work in the NBD spec to document what
block sizings are portable and therefore where slamming alignment to 512
is wise (and since it doesn't support base:allocation, there's no
unaligned data to come from the server anyway).

In fact, structured reply reads could also trip up the same issue (the
NBD spec says a server that advertised block sizes should ensure its
structured read chunks are split on aligned boundaries - but if the
server didn't advertise block sizes, qemu should be prepared for read
chunks at any boundary) - but that's harder to see (with read, the
request is always aligned, and the reads are reconstructed back into a
single buffer regardless of how the alignments fell out, so the block
layer will never notice that the server didn't pay attention to 512-byte
alignment), not to mention that nbdkit does not yet fragment reads in
the first place. So it's really block status that matters the most.

I'll whip up a patch.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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