Commit bb2f1f7ae0 for qemu.org
commit bb2f1f7ae00356b0924a124151ab4a25fce1d692
Author: Aadeshveer Singh <aadeshveer07@gmail.com>
Date: Sun Aug 16 23:16:25 2026 +0530
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>
diff --git a/migration/qemu-file.c b/migration/qemu-file.c
index f30e13c66d..7735e61854 100644
--- a/migration/qemu-file.c
+++ b/migration/qemu-file.c
@@ -550,17 +550,16 @@ void qemu_put_buffer_at(QEMUFile *f, const uint8_t *buf, size_t buflen,
}
-size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen,
- off_t pos)
+size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen, off_t pos,
+ Error **errp)
{
- Error *err = NULL;
-
if (f->last_error) {
+ error_setg(errp, "Cannot read from file: stream is in error state %d",
+ f->last_error);
return 0;
}
- if (qio_channel_pread_all(f->ioc, buf, buflen, pos, &err) < 0) {
- qemu_file_set_error_obj(f, -EIO, err);
+ if (qio_channel_pread_all(f->ioc, buf, buflen, pos, errp) < 0) {
return 0;
}
diff --git a/migration/qemu-file.h b/migration/qemu-file.h
index 8f824c124d..966766788d 100644
--- a/migration/qemu-file.h
+++ b/migration/qemu-file.h
@@ -76,8 +76,8 @@ void qemu_set_offset(QEMUFile *f, off_t off, int whence);
off_t qemu_get_offset(QEMUFile *f);
void qemu_put_buffer_at(QEMUFile *f, const uint8_t *buf, size_t buflen,
off_t pos);
-size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen,
- off_t pos);
+size_t qemu_get_buffer_at(QEMUFile *f, uint8_t *buf, size_t buflen, off_t pos,
+ Error **errp);
QIOChannel *qemu_file_get_ioc(QEMUFile *file);
int qemu_file_put_fd(QEMUFile *f, int fd);
diff --git a/migration/ram.c b/migration/ram.c
index 7fa4774246..60ad435215 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -4133,7 +4133,7 @@ static bool read_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
block->pages_offset + offset);
} else {
read = qemu_get_buffer_at(f, host, size,
- block->pages_offset + offset);
+ block->pages_offset + offset, errp);
}
if (!read) {
@@ -4202,8 +4202,8 @@ static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
bitmap_size = BITS_TO_LONGS(num_pages) * sizeof(unsigned long);
if (qemu_get_buffer_at(f, (uint8_t *)block->file_bmap, bitmap_size,
- header.bitmap_offset) != bitmap_size) {
- error_setg(errp, "Error reading dirty bitmap");
+ header.bitmap_offset, errp) != bitmap_size) {
+ error_prepend(errp, "Error reading dirty bitmap");
return;
}