From: Takuya Yoshikawa <yoshikawa.tak...@oss.ntt.co.jp>

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.tak...@oss.ntt.co.jp>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to