git: 7d05e01b3e59 - stable/13 - vm_pager: add method to veto page allocation

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Fri, 20 Jan 2023 03:23:30 UTC
The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=7d05e01b3e59c12f1b7a07dbf3b0ed11ac62ed13

commit 7d05e01b3e59c12f1b7a07dbf3b0ed11ac62ed13
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-10-20 13:15:46 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-01-20 03:19:29 +0000

    vm_pager: add method to veto page allocation
    
    Tested by:      pho
    
    (cherry picked from commit ec201dddfbddd3a77dd3f3afc9b007d0e13e7ad1)
---
 sys/vm/vm_fault.c |  4 ++++
 sys/vm/vm_page.c  |  4 ++++
 sys/vm/vm_pager.c |  1 +
 sys/vm/vm_pager.h | 11 +++++++++++
 4 files changed, 20 insertions(+)

diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 32b09fc469d7..605cf1203554 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -1192,6 +1192,10 @@ vm_fault_allocate(struct faultstate *fs)
 #if VM_NRESERVLEVEL > 0
 		vm_object_color(fs->object, atop(fs->vaddr) - fs->pindex);
 #endif
+		if (!vm_pager_can_alloc_page(fs->object, fs->pindex)) {
+			unlock_and_deallocate(fs);
+			return (FAULT_FAILURE);
+		}
 		alloc_req = P_KILLED(curproc) ?
 		    VM_ALLOC_SYSTEM : VM_ALLOC_NORMAL;
 		if (fs->object->type != OBJT_VNODE &&
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 0030bf47c814..736b25a1f2b5 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -2029,6 +2029,8 @@ vm_page_alloc_domain_after(vm_object_t object, vm_pindex_t pindex, int domain,
 
 	flags = 0;
 	m = NULL;
+	if (!vm_pager_can_alloc_page(object, pindex))
+		return (NULL);
 	pool = object != NULL ? VM_FREEPOOL_DEFAULT : VM_FREEPOOL_DIRECT;
 again:
 #if VM_NRESERVLEVEL > 0
@@ -4676,6 +4678,8 @@ retrylookup:
 		*mp = NULL;
 		return (VM_PAGER_FAIL);
 	} else if ((m = vm_page_alloc(object, pindex, pflags)) == NULL) {
+		if (!vm_pager_can_alloc_page(object, pindex))
+			return (VM_PAGER_AGAIN);
 		goto retrylookup;
 	}
 
diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c
index 5ba37189a273..ea5ce36f1963 100644
--- a/sys/vm/vm_pager.c
+++ b/sys/vm/vm_pager.c
@@ -424,6 +424,7 @@ vm_pager_alloc_dyn_type(struct pagerops *ops, int base_type)
 		FIX(freespace);
 		FIX(page_inserted);
 		FIX(page_removed);
+		FIX(can_alloc_page);
 #undef FIX
 	}
 	pagertab[res] = ops;	/* XXXKIB should be rel, but acq is too much */
diff --git a/sys/vm/vm_pager.h b/sys/vm/vm_pager.h
index 5917bf651760..0e248d871250 100644
--- a/sys/vm/vm_pager.h
+++ b/sys/vm/vm_pager.h
@@ -71,6 +71,7 @@ typedef void pgo_freespace_t(vm_object_t object, vm_pindex_t start,
     vm_size_t size);
 typedef void pgo_page_inserted_t(vm_object_t object, vm_page_t m);
 typedef void pgo_page_removed_t(vm_object_t object, vm_page_t m);
+typedef boolean_t pgo_can_alloc_page_t(vm_object_t object, vm_pindex_t pindex);
 
 struct pagerops {
 	int			pgo_kvme_type;
@@ -91,6 +92,7 @@ struct pagerops {
 	pgo_freespace_t		*pgo_freespace;
 	pgo_page_inserted_t	*pgo_page_inserted;
 	pgo_page_removed_t	*pgo_page_removed;
+	pgo_can_alloc_page_t	*pgo_can_alloc_page;
 };
 
 extern const struct pagerops defaultpagerops;
@@ -273,6 +275,15 @@ vm_pager_page_removed(vm_object_t object, vm_page_t m)
 		method(object, m);
 }
 
+static __inline bool
+vm_pager_can_alloc_page(vm_object_t object, vm_pindex_t pindex)
+{
+	pgo_can_alloc_page_t *method;
+
+	method = pagertab[object->type]->pgo_can_alloc_page;
+	return (method != NULL ? method(object, pindex) : true);
+}
+
 int vm_pager_alloc_dyn_type(struct pagerops *ops, int base_type);
 void vm_pager_free_dyn_type(objtype_t type);