On 10.10.19 17:17, Max Reitz wrote: > Hi everyone, > > (CCs just based on tags in the commit in question) > > I have two bug reports which claim problems of qcow2 on XFS on ppc64le > machines since qemu 4.1.0. One of those is about bad performance > (sorry, is isn’t public :-/), the other about data corruption > (https://bugzilla.redhat.com/show_bug.cgi?id=1751934). > > It looks like in both cases reverting c8bb23cbdbe3 solves the problem > (which optimized COW of unallocated areas). > > I think I’ve looked at every angle but can‘t find what could be wrong > with it. Do any of you have any idea? :-/ It looks to me like an XFS bug. On XFS, if you do FALLOC_FL_ZERO_RANGE past the EOF and an AIO pwrite even further after that range, the pwrite will be discarded if the fallocate settles after the pwrite (and both have been started before either as finished). That is, the file length will be increased as if only the fallocate had been executed, but not the pwrite, so the pwrite’s data is lost. (Interestingly, this is pretty similar to the bug I introduced in qemu in 50ba5b2d994853b38fed10e0841b119da0f8b8e5, where the ftruncate() would not consider parallel in-flight writes.) I’ve attached a C program to show the problem. It creates an empty file, issues FALLOC_FL_ZERO_RANGE on the first 4 kB in a thread, and an AIO pwrite in parallel on the second 4 kB. It then runs hexdump -C on the file. On XFS, the hexdump shows only 4 kB of 0s. On ext4 and btrfs, it shows 4 kB of 0s and 4 kB of 42s. (You can uncomment the IN_ORDER to execute the fallocate and pwrite sequentially, then XFS will show the same output.) (Note that it is possible that pwrite and fallocate are not issued before the other is finished, or that fallocate settles before pwrite. In such cases, the file will probably be written correctly. However, I see the wrong result pretty much 100 % of the time. (So on my machine, pwrite and fallocate pretty much always run in parallel and fallocate finishes after pwrite.)) Compile the program like so: $ gcc parallel-falloc-and-pwrite.c -pthread -laio -Wall -Wextra -pedantic -std=c11 And run it like so: $ ./a.out tmp-file Max