KVM: Minor memory slot optimization
Alex Williamson [Mon, 10 Dec 2012 17:33:03 +0000 (10:33 -0700)]
If a slot is removed or moved in the guest physical address space, we
first allocate and install a new slot array with the invalidated
entry.  The old array is then freed.  We then proceed to allocate yet
another slot array to install the permanent replacement.  Re-use the
original array when this occurs and avoid the extra kfree/kmalloc.

Reviewed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

virt/kvm/kvm_main.c

index 9a56ca2..4c8c065 100644 (file)
@@ -716,7 +716,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
        unsigned long npages;
        struct kvm_memory_slot *memslot, *slot;
        struct kvm_memory_slot old, new;
-       struct kvm_memslots *slots, *old_memslots;
+       struct kvm_memslots *slots = NULL, *old_memslots;
 
        r = check_memory_region_flags(mem);
        if (r)
@@ -832,18 +832,25 @@ int __kvm_set_memory_region(struct kvm *kvm,
                 *      - kvm_is_visible_gfn (mmu_check_roots)
                 */
                kvm_arch_flush_shadow_memslot(kvm, slot);
-               kfree(old_memslots);
+               slots = old_memslots;
        }
 
        r = kvm_arch_prepare_memory_region(kvm, &new, old, mem, user_alloc);
        if (r)
-               goto out_free;
+               goto out_slots;
 
        r = -ENOMEM;
-       slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),
-                       GFP_KERNEL);
-       if (!slots)
-               goto out_free;
+       /*
+        * We can re-use the old_memslots from above, the only difference
+        * from the currently installed memslots is the invalid flag.  This
+        * will get overwritten by update_memslots anyway.
+        */
+       if (!slots) {
+               slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),
+                               GFP_KERNEL);
+               if (!slots)
+                       goto out_free;
+       }
 
        /* map new memory slot into the iommu */
        if (npages) {