diff options
author | Thomas Huth <thuth@redhat.com> | 2021-01-29 09:43:54 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2021-02-08 14:43:55 +0100 |
commit | 38e0b7904eca7cd32f8953c33701e1f226ecc3fe (patch) | |
tree | d5e411627ca6dbaa92e87f2cd7c3d0bcdc84e49f | |
parent | c2651c0eaa1920f6478b4d371ad13c5e1409cccd (diff) |
accel/kvm/kvm-all: Fix wrong return code handling in dirty log code
The kvm_vm_ioctl() wrapper already returns -errno if the ioctl itself
returned -1, so the callers of kvm_vm_ioctl() should not check for -1
but for a value < 0 instead.
This problem has been fixed once already in commit b533f658a98325d0e4
but that commit missed that the ENOENT error code is not fatal for
this ioctl, so the commit has been reverted in commit 50212d6346f33d6e
since the problem occurred close to a pending release at that point
in time. The plan was to fix it properly after the release, but it
seems like this has been forgotten. So let's do it now finally instead.
Resolves: https://bugs.launchpad.net/qemu/+bug/1294227
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20210129084354.42928-1-thuth@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | accel/kvm/kvm-all.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index e72a19aaf8..47516913b7 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -644,16 +644,19 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml, d.dirty_bitmap = mem->dirty_bmap; d.slot = mem->slot | (kml->as_id << 16); - if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) { - DPRINTF("ioctl failed %d\n", errno); - ret = -1; + ret = kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d); + if (ret == -ENOENT) { + /* kernel does not have dirty bitmap in this slot */ + ret = 0; + } else if (ret < 0) { + error_report("ioctl KVM_GET_DIRTY_LOG failed: %d", errno); goto out; + } else { + subsection.offset_within_region += slot_offset; + subsection.size = int128_make64(slot_size); + kvm_get_dirty_pages_log_range(&subsection, d.dirty_bitmap); } - subsection.offset_within_region += slot_offset; - subsection.size = int128_make64(slot_size); - kvm_get_dirty_pages_log_range(&subsection, d.dirty_bitmap); - slot_offset += slot_size; start_addr += slot_size; size -= slot_size; @@ -750,8 +753,8 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start, d.num_pages = bmap_npages; d.slot = mem->slot | (as_id << 16); - if (kvm_vm_ioctl(s, KVM_CLEAR_DIRTY_LOG, &d) == -1) { - ret = -errno; + ret = kvm_vm_ioctl(s, KVM_CLEAR_DIRTY_LOG, &d); + if (ret < 0 && ret != -ENOENT) { error_report("%s: KVM_CLEAR_DIRTY_LOG failed, slot=%d, " "start=0x%"PRIx64", size=0x%"PRIx32", errno=%d", __func__, d.slot, (uint64_t)d.first_page, |