From patchwork Tue Jun 15 13:55:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hansen X-Patchwork-Id: 106202 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 o5FDukLf012639 for ; Tue, 15 Jun 2010 13:56:48 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932166Ab0FON4R (ORCPT ); Tue, 15 Jun 2010 09:56:17 -0400 Received: from e32.co.us.ibm.com ([32.97.110.150]:49217 "EHLO e32.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757726Ab0FONzm (ORCPT ); Tue, 15 Jun 2010 09:55:42 -0400 Received: from d03relay04.boulder.ibm.com (d03relay04.boulder.ibm.com [9.17.195.106]) by e32.co.us.ibm.com (8.14.4/8.13.1) with ESMTP id o5FDmAOW019297; Tue, 15 Jun 2010 07:48:10 -0600 Received: from d03av03.boulder.ibm.com (d03av03.boulder.ibm.com [9.17.195.169]) by d03relay04.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o5FDtW29052460; Tue, 15 Jun 2010 07:55:34 -0600 Received: from d03av03.boulder.ibm.com (loopback [127.0.0.1]) by d03av03.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id o5FDtSPS027782; Tue, 15 Jun 2010 07:55:28 -0600 Received: from kernel.beaverton.ibm.com (kernel.beaverton.ibm.com [9.47.67.96]) by d03av03.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id o5FDtSHQ027773; Tue, 15 Jun 2010 07:55:28 -0600 Received: from localhost.localdomain (localhost [127.0.0.1]) by kernel.beaverton.ibm.com (Postfix) with ESMTP id BD5CC1E74F9; Tue, 15 Jun 2010 06:55:27 -0700 (PDT) Subject: [RFC][PATCH 7/9] make kvm_get_kvm() more robust To: linux-kernel@vger.kernel.org Cc: kvm@vger.kernel.org, Dave Hansen From: Dave Hansen Date: Tue, 15 Jun 2010 06:55:27 -0700 References: <20100615135518.BC244431@kernel.beaverton.ibm.com> In-Reply-To: <20100615135518.BC244431@kernel.beaverton.ibm.com> Message-Id: <20100615135527.262CFEA2@kernel.beaverton.ibm.com> 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]); Tue, 15 Jun 2010 13:56:48 +0000 (UTC) diff -puN include/linux/kvm_host.h~make-kvm_get_kvm-more-robust include/linux/kvm_host.h --- linux-2.6.git/include/linux/kvm_host.h~make-kvm_get_kvm-more-robust 2010-06-11 08:39:16.000000000 -0700 +++ linux-2.6.git-dave/include/linux/kvm_host.h 2010-06-11 08:39:16.000000000 -0700 @@ -247,7 +247,7 @@ int kvm_init(void *opaque, unsigned vcpu struct module *module); void kvm_exit(void); -void kvm_get_kvm(struct kvm *kvm); +int kvm_get_kvm(struct kvm *kvm); void kvm_put_kvm(struct kvm *kvm); static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm) diff -puN virt/kvm/kvm_main.c~make-kvm_get_kvm-more-robust virt/kvm/kvm_main.c --- linux-2.6.git/virt/kvm/kvm_main.c~make-kvm_get_kvm-more-robust 2010-06-11 08:39:16.000000000 -0700 +++ linux-2.6.git-dave/virt/kvm/kvm_main.c 2010-06-11 08:39:16.000000000 -0700 @@ -496,9 +496,30 @@ static void kvm_destroy_vm(struct kvm *k mmdrop(mm); } -void kvm_get_kvm(struct kvm *kvm) +/* + * Once the counter goes to 0, we destroy the + * kvm object. Do not allow additional refs + * to be obtained once this occurs. + * + * Any calls which are done via the kvm fd + * could use atomic_inc(). That is because + * ->users_count is set to 1 when the kvm fd + * is created, and stays at least 1 while + * the fd exists. + * + * But, those calls are currently rare, so do + * this (more expensive) atomic_add_unless() + * to keep the number of functions down. + * + * Returns 0 if the reference was obtained + * successfully. + */ +int kvm_get_kvm(struct kvm *kvm) { - atomic_inc(&kvm->users_count); + int did_add = atomic_add_unless(&kvm->users_count, 1, 0); + if (did_add) + return 0; + return -EBUSY; } EXPORT_SYMBOL_GPL(kvm_get_kvm); @@ -1332,7 +1353,12 @@ static int kvm_vm_ioctl_create_vcpu(stru BUG_ON(kvm->vcpus[atomic_read(&kvm->online_vcpus)]); /* Now it's all set up, let userspace reach it */ - kvm_get_kvm(kvm); + r = kvm_get_kvm(kvm); + /* + * Getting called via the kvm fd _should_ guarantee + * that we can always get a reference. + */ + WARN_ON(r); r = create_vcpu_fd(vcpu); if (r < 0) { kvm_put_kvm(kvm);