This patch changes the get dirty log ioctl to inform the already scanned clean bitmap area to userspace. Without this patch, the information obtained by the scan in kernel is just ignored. To fix this, we use the return value of ioctl call as a hint of from where we should scan. Be careful that this value have to be used as an index of an unsigned long array. No side effect: qemu currently just checks the return value is negative(-1) or not, so you can use it without any change. Needless to say, you'd better to use an improved qemu to get more performance. Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx> --- Documentation/kvm/api.txt | 8 +++++--- arch/ia64/kvm/kvm-ia64.c | 5 ++--- arch/powerpc/kvm/book3s.c | 5 ++--- arch/s390/kvm/kvm-s390.c | 2 +- arch/x86/kvm/x86.c | 15 ++++++++++----- virt/kvm/kvm_main.c | 18 +++++++++--------- 6 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt index d170cb4..7ebfd7c 100644 --- a/Documentation/kvm/api.txt +++ b/Documentation/kvm/api.txt @@ -201,7 +201,7 @@ Capability: basic Architectures: x86 Type: vm ioctl Parameters: struct kvm_dirty_log (in/out) -Returns: 0 on success, -1 on error +Returns: first dirty page position on success, -1 on error /* for KVM_GET_DIRTY_LOG */ struct kvm_dirty_log { @@ -215,8 +215,10 @@ struct kvm_dirty_log { Given a memory slot, return a bitmap containing any pages dirtied since the last call to this ioctl. Bit 0 is the first page in the -memory slot. Ensure the entire structure is cleared to avoid padding -issues. +memory slot. The return value ensures that the contents of the +bitmap whose indexes, when you access as unsigned long array, are +less than this are clean. Ensure the entire structure is cleared +to avoid padding issues. 4.8 KVM_SET_MEMORY_ALIAS diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 26e0e08..ae78301 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -1828,7 +1828,7 @@ out: } int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log) + struct kvm_dirty_log *log) { int r; int n; @@ -1843,7 +1843,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, goto out; r = kvm_get_dirty_log(kvm, log, &is_dirty); - if (r) + if (r < 0) goto out; /* If nothing is dirty, don't bother messing with page tables. */ @@ -1853,7 +1853,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; memset(memslot->dirty_bitmap, 0, n); } - r = 0; out: mutex_unlock(&kvm->slots_lock); spin_unlock(&kvm->arch.dirty_log_lock); diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 794c94b..6ffd6f2 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -1065,7 +1065,7 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, * Get (and clear) the dirty memory log for a memory slot. */ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log) + struct kvm_dirty_log *log) { struct kvm_memory_slot *memslot; struct kvm_vcpu *vcpu; @@ -1076,7 +1076,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, mutex_lock(&kvm->slots_lock); r = kvm_get_dirty_log(kvm, log, &is_dirty); - if (r) + if (r < 0) goto out; /* If nothing is dirty, don't bother messing with page tables. */ @@ -1093,7 +1093,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, memset(memslot->dirty_bitmap, 0, n); } - r = 0; out: mutex_unlock(&kvm->slots_lock); return r; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 8f09959..640ce77 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -136,7 +136,7 @@ int kvm_dev_ioctl_check_extension(long ext) int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) { - return 0; + return -ENOSYS; } long kvm_arch_vm_ioctl(struct file *filp, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e25a522..8068ee9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2694,13 +2694,14 @@ static int kvm_vm_ioctl_reinject(struct kvm *kvm, /* * Get (and clear) the dirty memory log for a memory slot. + * Return the first dirty page position on success. */ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log) + struct kvm_dirty_log *log) { int r, n, i; struct kvm_memory_slot *memslot; - unsigned long is_dirty = 0; + bool is_dirty; unsigned long *dirty_bitmap = NULL; mutex_lock(&kvm->slots_lock); @@ -2722,8 +2723,12 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, goto out; memset(dirty_bitmap, 0, n); - for (i = 0; !is_dirty && i < n/sizeof(long); i++) - is_dirty = memslot->dirty_bitmap[i]; + for (i = 0, is_dirty = false; i < n/sizeof(long); i++) { + if (memslot->dirty_bitmap[i]) { + is_dirty = true; + break; + } + } /* If nothing is dirty, don't bother messing with page tables. */ if (is_dirty) { @@ -2747,7 +2752,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, kfree(old_slots); } - r = 0; + r = i; if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) r = -EFAULT; out_free: diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 548f925..4b715c9 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -769,7 +769,6 @@ int kvm_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot; int r, i; int n; - unsigned long any = 0; r = -EINVAL; if (log->slot >= KVM_MEMORY_SLOTS) @@ -782,17 +781,18 @@ int kvm_get_dirty_log(struct kvm *kvm, n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; - for (i = 0; !any && i < n/sizeof(long); ++i) - any = memslot->dirty_bitmap[i]; + for (i = 0; i < n/sizeof(long); ++i) { + if (memslot->dirty_bitmap[i]) { + *is_dirty = 1; + break; + } + } r = -EFAULT; if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n)) goto out; - if (any) - *is_dirty = 1; - - r = 0; + r = i; out: return r; } @@ -1592,7 +1592,7 @@ static long kvm_vm_ioctl(struct file *filp, if (copy_from_user(&log, argp, sizeof log)) goto out; r = kvm_vm_ioctl_get_dirty_log(kvm, &log); - if (r) + if (r < 0) goto out; break; } @@ -1693,7 +1693,7 @@ static long kvm_vm_compat_ioctl(struct file *filp, log.dirty_bitmap = compat_ptr(compat_log.dirty_bitmap); r = kvm_vm_ioctl_get_dirty_log(kvm, &log); - if (r) + if (r < 0) goto out; break; } -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html