On 12/19/25 19:08, Denis V. Lunev wrote:
qcow2_header_updated() is the final call during image close. This means
after this point we will have no IO operations on this file descriptor.
This assumption has been validated via 'strace' which clearly confirms
that this is very final write and there is no sync after this point.

There is almost no problem when the image is residing in local
filesystem except that we will have image check if the chage will
not reach disk before powerloss, but with a network or distributed
filesystem we come to trouble. The change could be in flight and we
can miss this data on other node like during migration.

The patch adds BDRV_REQ_FUA to the write request to do the trick.

Signed-off-by: Denis V. Lunev <[email protected]>
CC: Kevin Wolf <[email protected]>
CC: Hanna Reitz <[email protected]>
---
  block/qcow2.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index e29810d86a..abbc4e82ba 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3252,7 +3252,7 @@ int qcow2_update_header(BlockDriverState *bs)
      }
/* Write the new header */
-    ret = bdrv_pwrite(bs->file, 0, s->cluster_size, header, 0);
+    ret = bdrv_pwrite(bs->file, 0, s->cluster_size, header, BDRV_REQ_FUA);
      if (ret < 0) {
          goto fail;
      }
(attempt #2, mailer has rotten the mail. sorry).

Thanks a lot for Andrey Drobyshev who has attempted to review and
test this patch.

The patch is non-working due to broken BDRV_REQ_FUA processing in QEMU code and this looks more severe than the original problem. bdrv_pwrite() endups in bdrv_aligned_pwritev() which internally calls bdrv_driver_pwritev() -> bdrv_co_flush() bdrv_co_write_req_finish() Please note, that bdrv_co_flush() is in reality noop until bs->write_gen is incremented, which happened only late inside bdrv_co_write_req_finish(). This means that BDRV_REQ_FUA request will be flushed only on the NEXT flush operation, which is definitely wrong. Den

Reply via email to