@samitouri / QOSamiQemu / commits / bb2f1f7ae0

migration: Make qemu_get_buffer_at() thread-safe

Remove the internal QEMUFile error state modification from qemu_get_buffer_at(). This function is called by two functions, both of which already check for unexpected return values and handle their own error reporting. Removing this shared state modification makes qemu_get_buffer_at() strictly thread-safe for concurrent disk reads, serving as a preparatory change for the upcoming fast snapshot load feature. Removed local error by passing errp to improve on error handling, consequently also change caller to use error_prevent and not error_setg. Set errp in case of f->last_error as function should set errp in case it fails, and caller can simply use error_prepend without checking errp in case of error. Signed-off-by: Aadeshveer Singh <aadeshveer07@gmail.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juraj Marcin <jmarcin@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Fabiano Rosas <farosas@suse.de>

Aadeshveer Singh committed Aug 16, 2026 at 23:16 UTC bb2f1f7ae00356b0924a124151ab4a25fce1d692
3 files changed +10 -11
migration/qemu-file.c
+5 -6
@@ -550,17 +550,16 @@ void qemu_put_buffer_at(QEMUFile *f, const uint8_t *buf, size_t buflen,
550 }
551
552
553 -size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen,
554 - off_t pos)
553 +size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen, off_t pos,
554 + Error **errp)
555 {
556 - Error *err = NULL;
557 -
556 if (f->last_error) {
557 + error_setg(errp, "Cannot read from file: stream is in error state %d",
558 + f->last_error);
559 return 0;
560 }
561
562 - if (qio_channel_pread_all(f->ioc, buf, buflen, pos, &err) < 0) {
563 - qemu_file_set_error_obj(f, -EIO, err);
562 + if (qio_channel_pread_all(f->ioc, buf, buflen, pos, errp) < 0) {
563 return 0;
564 }
565
migration/qemu-file.h
+2 -2
@@ -76,8 +76,8 @@ void qemu_set_offset(QEMUFile *f, off_t off, int whence);
76 off_t qemu_get_offset(QEMUFile *f);
77 void qemu_put_buffer_at(QEMUFile *f, const uint8_t *buf, size_t buflen,
78 off_t pos);
79 -size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen,
80 - off_t pos);
79 +size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen, off_t pos,
80 + Error **errp);
81
82 QIOChannel *qemu_file_get_ioc(QEMUFile *file);
83 int qemu_file_put_fd(QEMUFile *f, int fd);
migration/ram.c
+3 -3
@@ -4133,7 +4133,7 @@ static bool read_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
4133 block->pages_offset + offset);
4134 } else {
4135 read = qemu_get_buffer_at(f, host, size,
4136 - block->pages_offset + offset);
4136 + block->pages_offset + offset, errp);
4137 }
4138
4139 if (!read) {
@@ -4202,8 +4202,8 @@ static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
4202 bitmap_size = BITS_TO_LONGS(num_pages) * sizeof(unsigned long);
4203
4204 if (qemu_get_buffer_at(f, (uint8_t *)block->file_bmap, bitmap_size,
4205 - header.bitmap_offset) != bitmap_size) {
4206 - error_setg(errp, "Error reading dirty bitmap");
4205 + header.bitmap_offset, errp) != bitmap_size) {
4206 + error_prepend(errp, "Error reading dirty bitmap");
4207 return;
4208 }
4209