From patchwork Thu Jun 3 13:06:18 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takuya Yoshikawa X-Patchwork-Id: 104088 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o53D5wv6005060 for ; Thu, 3 Jun 2010 13:05:58 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752857Ab0FCNFz (ORCPT ); Thu, 3 Jun 2010 09:05:55 -0400 Received: from serv2.oss.ntt.co.jp ([222.151.198.100]:40436 "EHLO serv2.oss.ntt.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752510Ab0FCNFy (ORCPT ); Thu, 3 Jun 2010 09:05:54 -0400 Received: from serv2.oss.ntt.co.jp (localhost [127.0.0.1]) by serv2.oss.ntt.co.jp (Postfix) with ESMTP id D7662248310; Thu, 3 Jun 2010 22:05:53 +0900 (JST) Received: from serv1.oss.ntt.co.jp (serv1.oss.ntt.co.jp [172.19.0.2]) by serv2.oss.ntt.co.jp (Postfix) with ESMTP id BCB0224830C; Thu, 3 Jun 2010 22:05:53 +0900 (JST) Received: from yshtky3.kern.oss.ntt.co.jp (unknown [172.17.1.81]) by serv1.oss.ntt.co.jp (Postfix) with SMTP id 98F2611C130; Thu, 3 Jun 2010 22:05:53 +0900 (JST) Date: Thu, 3 Jun 2010 22:06:18 +0900 From: Takuya Yoshikawa To: avi@redhat.com, mtosatti@redhat.com Cc: kvm@vger.kernel.org, fernando@oss.ntt.co.jp, takuya.yoshikawa@gmail.com Subject: [PATCH 2/2] KVM: x86: pre-allocate one more dirty bitmap to avoid vmalloc() in kvm_vm_ioctl_get_dirty_log() Message-Id: <20100603220618.3f77e78b.yoshikawa.takuya@oss.ntt.co.jp> In-Reply-To: <20100603220137.1de53977.yoshikawa.takuya@oss.ntt.co.jp> References: <20100603220137.1de53977.yoshikawa.takuya@oss.ntt.co.jp> X-Mailer: Sylpheed 3.0.2 (GTK+ 2.20.1; i486-pc-linux-gnu) Mime-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 03 Jun 2010 13:05:58 +0000 (UTC) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0cd0f29..c516f1c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -81,6 +81,8 @@ #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8 +#define __KVM_DIRTY_LOG_DOUBLE_BUFFERING + extern spinlock_t kvm_lock; extern struct list_head vm_list; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5e5cd8d..0871ef8 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2804,18 +2804,15 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, kvm_mmu_slot_remove_write_access(kvm, log->slot); spin_unlock(&kvm->mmu_lock); - r = -ENOMEM; - dirty_bitmap = vmalloc(n); - if (!dirty_bitmap) - goto out; + dirty_bitmap = memslot->dirty_bitmap_head; + if (memslot->dirty_bitmap == dirty_bitmap) + dirty_bitmap += n / sizeof(long); memset(dirty_bitmap, 0, n); r = -ENOMEM; slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL); - if (!slots) { - vfree(dirty_bitmap); + if (!slots) goto out; - } memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots)); slots->memslots[log->slot].dirty_bitmap = dirty_bitmap; @@ -2826,11 +2823,8 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, kfree(old_slots); r = -EFAULT; - if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) { - vfree(dirty_bitmap); + if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) goto out; - } - vfree(dirty_bitmap); } else { r = -EFAULT; if (clear_user(log->dirty_bitmap, n)) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 2c62319..199a464 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -118,6 +118,9 @@ struct kvm_memory_slot { unsigned long flags; unsigned long *rmap; unsigned long *dirty_bitmap; +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + unsigned long *dirty_bitmap_head; +#endif struct { unsigned long rmap_pde; int write_count; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index e4f5762..6f73b42 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -443,7 +443,10 @@ static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot) { if (!memslot->dirty_bitmap) return; - +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + memslot->dirty_bitmap = memslot->dirty_bitmap_head; + memslot->dirty_bitmap_head = NULL; +#endif vfree(memslot->dirty_bitmap); memslot->dirty_bitmap = NULL; } @@ -535,12 +538,17 @@ static int kvm_vm_release(struct inode *inode, struct file *filp) static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot) { unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(memslot); - +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + dirty_bytes *= 2; +#endif memslot->dirty_bitmap = vmalloc(dirty_bytes); if (!memslot->dirty_bitmap) return -ENOMEM; memset(memslot->dirty_bitmap, 0, dirty_bytes); +#ifdef __KVM_DIRTY_LOG_DOUBLE_BUFFERING + memslot->dirty_bitmap_head = memslot->dirty_bitmap; +#endif return 0; }