On 5/14/19 12:28 PM, Max Reitz wrote: >>> >>> The tail of an unaligned file is generally inaccessible to O_DIRECT, >> >> Especially with this. >> >>> where it is easier to use ftruncate() up to an aligned boundary if you >>> really must play with that region of the file, and then ftruncate() back >>> to the intended size after I/O. But that sounds hairy. We could also >>> round down and silently ignore the tail of the file, but that is at odds >>> with our practice of rounding size up. So for the short term, I'd be >>> happy with a patch that just rejects any attempt to use cache.direct=on >>> (O_DIRECT) with a file that is not already a multiple of the alignment >>> required thereby. (For reference, that's what qemu as NBD client >>> recently did when talking to a server that advertises a size >>> inconsistent with forced minimum block access: commit 3add3ab7) >> >> OK, I’ll send a patch. Thanks for you explanation! > Well, or maybe not. > > $ ./qemu-img create -f qcow2 foo.qcow2 64M > $ ./qemu-img map --image-opts \ > driver=qcow2,file.filename=foo.qcow2,cache.direct=on > qemu-img: Could not open > 'driver=qcow2,file.filename=foo.qcow2,cache.direct=on': File length > (196616 bytes) is not a multiple of the O_DIRECT alignment (512 bytes) > Try cache.direct=off, or increasing the file size to match the alignment > > That may be considered a bug in qcow2. Maybe it should always fill all > clusters. But even if we did so and fixed it now, we can’t disallow > qemu from opening such images. > > Also, well, the tail is accessible, we just need to access it with the > proper alignment (and then we get a short read). This seems to be > handled just fine.
Oh. Yeah, short reads with O_DIRECT are possible (short writes not so much; for those, you have to write a full buffer then ftruncate back down). But we DO want to support short reads because of pre-existing images, whether or not we also improve qcow2 to always create aligned image sizes. The qcow2 spec allows unaligned images, even if we quit creating new ones. > > So I think file-posix should just return a rounded result. Well, or > bdrv_co_Block_status() could ignore it for the EOF, because it throws > away everything past the EOF anyway with: > > if (*pnum > bytes) { > *pnum = bytes; > } > > On one hand, I agree that file-posix should return an aligned result. > On the other, it doesn’t make a difference, so I don’t think we need to > enforce it (at EOF). My thoughts: Right now, only io.c sets (or even reads) BDRV_BLOCK_EOF, and it is documented as an internal flag for optimizations. But it would be very easy to amend the contract of driver's .bdrv_co_block_status to state that a driver may set BDRV_BLOCK_EOF at the end of a file, and MUST set that flag if the end of the file also happens to be unaligned with respect to the driver's request_alignment. (Most drivers won't need to care, but file-posix.c under O_DIRECT would have to start caring). Then fix io.c to relax the assertion - the result must either be aligned (current condition) OR the driver must have reported BDRV_BLOCK_EOF (new condition). At that point, the block layer can take care of rounding out the block status for the unaligned tail beyond EOF up to the alignment boundary (similar to the rounding I have proposed in my other patches). If you don't get to that first, then it looks like I'll have to fold that in to my v2 patches when I get back to addressing those block status alignment problems. Thanks again for testing, and forcing me to think about the issue. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
signature.asc
Description: OpenPGP digital signature