]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: LoongArch: Mark "struct page" pfns dirty only in "slow" page fault path
authorSean Christopherson <seanjc@google.com>
Thu, 10 Oct 2024 18:24:07 +0000 (11:24 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 25 Oct 2024 17:00:49 +0000 (13:00 -0400)
Mark pages/folios dirty only the slow page fault path, i.e. only when
mmu_lock is held and the operation is mmu_notifier-protected, as marking a
page/folio dirty after it has been written back can make some filesystems
unhappy (backing KVM guests will such filesystem files is uncommon, and
the race is minuscule, hence the lack of complaints).

See the link below for details.

Link: https://lore.kernel.org/all/cover.1683044162.git.lstoakes@gmail.com
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-ID: <20241010182427.1434605-66-seanjc@google.com>

arch/loongarch/kvm/mmu.c

index 28681dfb4b85975b04d2d81960312d929c1e3c82..cc2a5f289b1479686c575f4577de2203e5a99917 100644 (file)
@@ -608,13 +608,13 @@ static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool writ
                if (kvm_pte_young(changed))
                        kvm_set_pfn_accessed(pfn);
 
-               if (kvm_pte_dirty(changed)) {
-                       mark_page_dirty(kvm, gfn);
-                       kvm_set_pfn_dirty(pfn);
-               }
                if (page)
                        put_page(page);
        }
+
+       if (kvm_pte_dirty(changed))
+               mark_page_dirty(kvm, gfn);
+
        return ret;
 out:
        spin_unlock(&kvm->mmu_lock);
@@ -915,12 +915,14 @@ retry:
        else
                ++kvm->stat.pages;
        kvm_set_pte(ptep, new_pte);
+
+       if (writeable)
+               kvm_set_pfn_dirty(pfn);
+
        spin_unlock(&kvm->mmu_lock);
 
-       if (prot_bits & _PAGE_DIRTY) {
+       if (prot_bits & _PAGE_DIRTY)
                mark_page_dirty_in_slot(kvm, memslot, gfn);
-               kvm_set_pfn_dirty(pfn);
-       }
 
        kvm_release_pfn_clean(pfn);
 out: