lkml.org 
[lkml]   [2015]   [Apr]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.16.y-ckt 136/144] kvm: avoid page allocation failure in kvm_set_memory_region()
    Date
    3.16.7-ckt10 -stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Igor Mammedov <imammedo@redhat.com>

    commit 744961341d472db6272ed9b42319a90f5a2aa7c4 upstream.

    KVM guest can fail to startup with following trace on host:

    qemu-system-x86: page allocation failure: order:4, mode:0x40d0
    Call Trace:
    dump_stack+0x47/0x67
    warn_alloc_failed+0xee/0x150
    __alloc_pages_direct_compact+0x14a/0x150
    __alloc_pages_nodemask+0x776/0xb80
    alloc_kmem_pages+0x3a/0x110
    kmalloc_order+0x13/0x50
    kmemdup+0x1b/0x40
    __kvm_set_memory_region+0x24a/0x9f0 [kvm]
    kvm_set_ioapic+0x130/0x130 [kvm]
    kvm_set_memory_region+0x21/0x40 [kvm]
    kvm_vm_ioctl+0x43f/0x750 [kvm]

    Failure happens when attempting to allocate pages for
    'struct kvm_memslots', however it doesn't have to be
    present in physically contiguous (kmalloc-ed) address
    space, change allocation to kvm_kvzalloc() so that
    it will be vmalloc-ed when its size is more then a page.

    Signed-off-by: Igor Mammedov <imammedo@redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
    Cc: Paolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
    ---
    virt/kvm/kvm_main.c | 14 +++++++-------
    1 file changed, 7 insertions(+), 7 deletions(-)

    diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
    index 840b6ced58bb..27e140d5f073 100644
    --- a/virt/kvm/kvm_main.c
    +++ b/virt/kvm/kvm_main.c
    @@ -470,7 +470,7 @@ static struct kvm *kvm_create_vm(unsigned long type)
    BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX);

    r = -ENOMEM;
    - kvm->memslots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
    + kvm->memslots = kvm_kvzalloc(sizeof(struct kvm_memslots));
    if (!kvm->memslots)
    goto out_err_no_srcu;

    @@ -521,7 +521,7 @@ out_err_no_srcu:
    out_err_no_disable:
    for (i = 0; i < KVM_NR_BUSES; i++)
    kfree(kvm->buses[i]);
    - kfree(kvm->memslots);
    + kvfree(kvm->memslots);
    kvm_arch_free_vm(kvm);
    return ERR_PTR(r);
    }
    @@ -577,7 +577,7 @@ static void kvm_free_physmem(struct kvm *kvm)
    kvm_for_each_memslot(memslot, slots)
    kvm_free_physmem_slot(kvm, memslot, NULL);

    - kfree(kvm->memslots);
    + kvfree(kvm->memslots);
    }

    static void kvm_destroy_devices(struct kvm *kvm)
    @@ -858,10 +858,10 @@ int __kvm_set_memory_region(struct kvm *kvm,
    goto out_free;
    }

    - slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),
    - GFP_KERNEL);
    + slots = kvm_kvzalloc(sizeof(struct kvm_memslots));
    if (!slots)
    goto out_free;
    + memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));

    if ((change == KVM_MR_DELETE) || (change == KVM_MR_MOVE)) {
    slot = id_to_memslot(slots, mem->slot);
    @@ -903,7 +903,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
    kvm_arch_commit_memory_region(kvm, mem, &old, change);

    kvm_free_physmem_slot(kvm, &old, &new);
    - kfree(old_memslots);
    + kvfree(old_memslots);

    /*
    * IOMMU mapping: New slots need to be mapped. Old slots need to be
    @@ -922,7 +922,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
    return 0;

    out_slots:
    - kfree(slots);
    + kvfree(slots);
    out_free:
    kvm_free_physmem_slot(kvm, &new, &old);
    out:

    \
     
     \ /
      Last update: 2015-04-21 17:41    [W:4.277 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site