[PATCH 4/4] KVM: MMU: Make mmu_shrink() scan nr_to_scan shadow pages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx>

Currently, mmu_shrink() tries to free a shadow page from one kvm and
does not use nr_to_scan correctly.

This patch fixes this by making it try to free some shadow pages from
each kvm.  The number of shadow pages each kvm frees becomes
proportional to the number of shadow pages it is using.

Note: an easy way to see how this code works is to do
  echo 3 > /proc/sys/vm/drop_caches
during some virtual machines are running.  Shadow pages will be zapped
as expected by this.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx>
---
 arch/x86/kvm/mmu.c |   23 ++++++++++++++---------
 1 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index fcd0dd1..c6c61dd 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3921,7 +3921,7 @@ restart:
 static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
 {
 	struct kvm *kvm;
-	struct kvm *kvm_freed = NULL;
+	int nr_to_zap, nr_total;
 	int nr_to_scan = sc->nr_to_scan;
 
 	if (nr_to_scan == 0)
@@ -3929,25 +3929,30 @@ static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
 
 	raw_spin_lock(&kvm_lock);
 
+	nr_total = percpu_counter_read_positive(&kvm_total_used_mmu_pages);
+
 	list_for_each_entry(kvm, &kvm_list, list) {
 		int idx;
 		LIST_HEAD(invalid_list);
 
+		if (nr_to_scan <= 0) {
+			/* next time from this kvm */
+			list_move_tail(&kvm_list, &kvm->list);
+			break;
+		}
+
 		idx = srcu_read_lock(&kvm->srcu);
 		spin_lock(&kvm->mmu_lock);
-		if (!kvm_freed && nr_to_scan > 0 &&
-		    kvm->arch.n_used_mmu_pages > 0) {
-			pre_zap_one_sp(kvm, &invalid_list);
-			kvm_freed = kvm;
-		}
-		nr_to_scan--;
 
+		/* proportional to how many shadow pages this kvm is using */
+		nr_to_zap = sc->nr_to_scan * kvm->arch.n_used_mmu_pages;
+		nr_to_zap /= nr_total;
+		nr_to_scan -= pre_zap_some_sp(kvm, &invalid_list, nr_to_zap);
 		kvm_mmu_commit_zap_page(kvm, &invalid_list);
+
 		spin_unlock(&kvm->mmu_lock);
 		srcu_read_unlock(&kvm->srcu, idx);
 	}
-	if (kvm_freed)
-		list_move_tail(&kvm_freed->list, &kvm_list);
 
 	raw_spin_unlock(&kvm_lock);
 
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux