diff options
author | Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp> | 2010-04-28 05:50:36 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:35:27 -0400 |
commit | 914ebccd2d8fa439e01fe93b5229534b9e179a69 (patch) | |
tree | 13341c1b1fcd6d4eeb39576c75417cccbcdee748 /arch/x86/kvm/x86.c | |
parent | c332c83ae736c72dcf072e96e98a774fce39e722 (diff) |
KVM: x86: avoid unnecessary bitmap allocation when memslot is clean
Although we always allocate a new dirty bitmap in x86's get_dirty_log(),
it is only used as a zero-source of copy_to_user() and freed right after
that when memslot is clean. This patch uses clear_user() instead of doing
this unnecessary zero-source allocation.
Performance improvement: as we can expect easily, the time needed to
allocate a bitmap is completely reduced. In my test, the improved ioctl
was about 4 to 10 times faster than the original one for clean slots.
Furthermore, reducing memory allocations and copies will produce good
effects to caches too.
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7fa89c39c64f..1b270fd60634 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -2797,7 +2797,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
2797 | struct kvm_memory_slot *memslot; | 2797 | struct kvm_memory_slot *memslot; |
2798 | unsigned long n; | 2798 | unsigned long n; |
2799 | unsigned long is_dirty = 0; | 2799 | unsigned long is_dirty = 0; |
2800 | unsigned long *dirty_bitmap = NULL; | ||
2801 | 2800 | ||
2802 | mutex_lock(&kvm->slots_lock); | 2801 | mutex_lock(&kvm->slots_lock); |
2803 | 2802 | ||
@@ -2812,27 +2811,30 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
2812 | 2811 | ||
2813 | n = kvm_dirty_bitmap_bytes(memslot); | 2812 | n = kvm_dirty_bitmap_bytes(memslot); |
2814 | 2813 | ||
2815 | r = -ENOMEM; | ||
2816 | dirty_bitmap = vmalloc(n); | ||
2817 | if (!dirty_bitmap) | ||
2818 | goto out; | ||
2819 | memset(dirty_bitmap, 0, n); | ||
2820 | |||
2821 | for (i = 0; !is_dirty && i < n/sizeof(long); i++) | 2814 | for (i = 0; !is_dirty && i < n/sizeof(long); i++) |
2822 | is_dirty = memslot->dirty_bitmap[i]; | 2815 | is_dirty = memslot->dirty_bitmap[i]; |
2823 | 2816 | ||
2824 | /* If nothing is dirty, don't bother messing with page tables. */ | 2817 | /* If nothing is dirty, don't bother messing with page tables. */ |
2825 | if (is_dirty) { | 2818 | if (is_dirty) { |
2826 | struct kvm_memslots *slots, *old_slots; | 2819 | struct kvm_memslots *slots, *old_slots; |
2820 | unsigned long *dirty_bitmap; | ||
2827 | 2821 | ||
2828 | spin_lock(&kvm->mmu_lock); | 2822 | spin_lock(&kvm->mmu_lock); |
2829 | kvm_mmu_slot_remove_write_access(kvm, log->slot); | 2823 | kvm_mmu_slot_remove_write_access(kvm, log->slot); |
2830 | spin_unlock(&kvm->mmu_lock); | 2824 | spin_unlock(&kvm->mmu_lock); |
2831 | 2825 | ||
2832 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); | 2826 | r = -ENOMEM; |
2833 | if (!slots) | 2827 | dirty_bitmap = vmalloc(n); |
2834 | goto out_free; | 2828 | if (!dirty_bitmap) |
2829 | goto out; | ||
2830 | memset(dirty_bitmap, 0, n); | ||
2835 | 2831 | ||
2832 | r = -ENOMEM; | ||
2833 | slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); | ||
2834 | if (!slots) { | ||
2835 | vfree(dirty_bitmap); | ||
2836 | goto out; | ||
2837 | } | ||
2836 | memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); | 2838 | memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); |
2837 | slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; | 2839 | slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; |
2838 | 2840 | ||
@@ -2841,13 +2843,20 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
2841 | synchronize_srcu_expedited(&kvm->srcu); | 2843 | synchronize_srcu_expedited(&kvm->srcu); |
2842 | dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; | 2844 | dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; |
2843 | kfree(old_slots); | 2845 | kfree(old_slots); |
2846 | |||
2847 | r = -EFAULT; | ||
2848 | if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) { | ||
2849 | vfree(dirty_bitmap); | ||
2850 | goto out; | ||
2851 | } | ||
2852 | vfree(dirty_bitmap); | ||
2853 | } else { | ||
2854 | r = -EFAULT; | ||
2855 | if (clear_user(log->dirty_bitmap, n)) | ||
2856 | goto out; | ||
2844 | } | 2857 | } |
2845 | 2858 | ||
2846 | r = 0; | 2859 | r = 0; |
2847 | if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) | ||
2848 | r = -EFAULT; | ||
2849 | out_free: | ||
2850 | vfree(dirty_bitmap); | ||
2851 | out: | 2860 | out: |
2852 | mutex_unlock(&kvm->slots_lock); | 2861 | mutex_unlock(&kvm->slots_lock); |
2853 | return r; | 2862 | return r; |