Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147766768
D45043.1784316072.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D45043.1784316072.diff
View Options
diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c
--- a/sys/vm/vm_reserv.c
+++ b/sys/vm/vm_reserv.c
@@ -118,12 +118,16 @@
* speculatively allocated to an object. The reservation provides the small
* physical pages for the range [pindex, pindex + VM_LEVEL_0_NPAGES) of offsets
* within that object. The reservation's "popcnt" tracks the number of these
- * small physical pages that are in use at any given time. When and if the
- * reservation is not fully utilized, it appears in the queue of partially
- * populated reservations. The reservation always appears on the containing
- * object's list of reservations.
+ * small physical pages that are in use at any given time. When and if a
+ * managed reservation is not fully utilized, it appears in the queue of
+ * partially populated managed reservations. The managed reservation always
+ * appears on the containing object's list of reservations.
*
- * A partially populated reservation can be broken and reclaimed at any time.
+ * A partially populated managed reservation can be broken and reclaimed at any
+ * time.
+ *
+ * Unmanaged reservations are not a part of any vm_object reservation lists and
+ * should be distinguished by setting "isnoobj" to true.
*
* c - constant after boot
* d - vm_reserv_domain_lock
@@ -140,7 +144,8 @@
vm_page_t pages; /* (c) first page */
uint16_t popcnt; /* (r) # of pages in use */
uint8_t domain; /* (c) NUMA domain. */
- char inpartpopq; /* (d, r) */
+ unsigned int inpartpopq : 4; /* (d, r) */
+ unsigned int isnoobj : 4; /* (r) unmanaged? */
int lasttick; /* (r) last pop update tick. */
bitstr_t bit_decl(popmap, VM_LEVEL_0_NPAGES_MAX);
/* (r) bit vector, used pages */
@@ -171,19 +176,22 @@
* array by computing a physical reservation number from the page's physical
* address. The physical reservation number is used as the array index.
*
- * An "active" reservation is a valid reservation structure that has a non-NULL
- * "object" field and a non-zero "popcnt" field. In other words, every active
- * reservation belongs to a particular object. Moreover, every active
- * reservation has an entry in the containing object's list of reservations.
+ * An "active" reservation is a valid reservation structure that is either
+ * managed or unmanaged. Active managed reservations have a non-NULL "object"
+ * field and a non-zero "popcnt" field, while active unmanaged reservations have
+ * a NULL "object" field, a "isnoobj" field set to true, and non-zero "popcnt"
+ * field. In other words, every active managed reservation belongs to a
+ * particular object. Moreover, every active managed reservation has an entry
+ * in the containing object's list of reservations.
*/
static vm_reserv_t vm_reserv_array;
/*
- * The per-domain partially populated reservation queues
+ * The per-domain partially populated managed reservation queues
*
* These queues enable the fast recovery of an unused free small page from a
* partially populated reservation. The reservation at the head of a queue
- * is the least recently changed, partially populated reservation.
+ * is the least recently changed, partially populated managed reservation.
*
* Access to this queue is synchronized by the per-domain reservation lock.
* Threads reclaiming free pages from the queue must hold the per-domain scan
@@ -365,7 +373,7 @@
"%s: rv %p(%p) object %p new %p popcnt %d",
__FUNCTION__, rv, rv->pages, rv->object, object,
rv->popcnt);
- KASSERT(rv->object == NULL,
+ KASSERT(rv->object == NULL && rv->isnoobj == 0,
("vm_reserv_insert: reserv %p isn't free", rv));
KASSERT(rv->popcnt == 0,
("vm_reserv_insert: reserv %p's popcnt is corrupted", rv));
@@ -515,7 +523,7 @@
vm_reserv_assert_locked(rv);
CTR5(KTR_VM, "%s: rv %p object %p popcnt %d inpartpop %d",
__FUNCTION__, rv, rv->object, rv->popcnt, rv->inpartpopq);
- KASSERT(rv->object != NULL,
+ KASSERT(rv->object != NULL && rv->isnoobj == 0,
("vm_reserv_populate: reserv %p is free", rv));
KASSERT(!bit_test(rv->popmap, index),
("vm_reserv_populate: reserv %p's popmap[%d] is set", rv,
@@ -966,6 +974,7 @@
if (rv->object == NULL)
return (FALSE);
vm_reserv_lock(rv);
+ KASSERT(rv->isnoobj == 0, ("%s: reserv %p is noobj ", __func__, rv));
/* Re-validate after lock. */
if (rv->object != NULL) {
vm_reserv_depopulate(rv, m - rv->pages);
@@ -1440,4 +1449,145 @@
return (m);
}
+/*
+ * Returns true if 'rv' is unmanaged, false otherwise.
+ */
+static boolean_t
+vm_reserv_is_noobj(vm_reserv_t rv)
+{
+ boolean_t ret = false;
+
+ vm_reserv_assert_locked(rv);
+ if (rv->isnoobj != 0) {
+ KASSERT(rv->object == NULL,
+ ("%s: noobj reservation %p has an object %p", __func__, rv,
+ rv->object));
+ ret = true;
+ }
+ return (ret);
+}
+
+/*
+ * Marks a reservation as unmanaged.
+ */
+static void
+vm_reserv_mark_noobj(vm_reserv_t rv)
+{
+
+ vm_reserv_assert_locked(rv);
+ KASSERT(!vm_reserv_is_noobj(rv),
+ ("%s: reservation %p already marked as noobj", __func__, rv));
+ KASSERT(rv->object == NULL, ("%s: reserv %p is managed", __func__, rv));
+ rv->isnoobj = 1;
+}
+
+/*
+ * Clears unmanaged status for a reservation.
+ */
+static void
+vm_reserv_clear_noobj(vm_reserv_t rv)
+{
+
+ vm_reserv_assert_locked(rv);
+ KASSERT(vm_reserv_is_noobj(rv),
+ ("%s: reserv %p is managed", __func__, rv));
+ rv->isnoobj = 0;
+}
+
+/*
+ * Tries to fetch an empty reservation from the specified domain
+ * and marks it as unmanaged.
+ */
+static vm_reserv_t
+vm_reserv_fetch_noobj(int domain, int req)
+{
+ vm_reserv_t rv = NULL;
+ struct vm_domain *vmd;
+ vm_page_t m;
+
+ vmd = VM_DOMAIN(domain);
+ vm_domain_free_lock(vmd);
+ m = vm_phys_alloc_pages(domain, VM_FREEPOOL_DEFAULT, VM_LEVEL_0_ORDER);
+ vm_domain_free_unlock(vmd);
+
+ if (m != NULL) {
+ rv = vm_reserv_from_page(m);
+ vm_reserv_lock(rv);
+ vm_reserv_mark_noobj(rv);
+ KASSERT(rv->pages == m,
+ ("vm_reserv_alloc_page: reserv %p's pages is corrupted",
+ rv));
+ vm_reserv_unlock(rv);
+ }
+ return (rv);
+}
+
+/*
+ * Allocates a 0-order page from an unmanaged reservation 'rv'.
+ */
+static vm_page_t
+vm_reserv_alloc_page_noobj(vm_reserv_t rv, int req)
+{
+ struct vm_domain *vmd;
+ ssize_t i;
+
+ vm_reserv_assert_locked(rv);
+ KASSERT(rv->object == NULL && rv->isnoobj != 0,
+ ("%s: reserv %p is not a noobj reserv", __func__, rv));
+ KASSERT(rv->pages->psind == 0,
+ ("%s: reserv %p is already promoted", __func__, rv));
+ KASSERT(rv->domain < vm_ndomains,
+ ("%s: reserv %p's domain is corrupted %d", __func__, rv,
+ rv->domain));
+
+ if (rv->popcnt == VM_LEVEL_0_NPAGES)
+ return (NULL);
+ vmd = VM_DOMAIN(rv->domain);
+ if (vm_domain_allocate(vmd, req, 1) == 0)
+ return (NULL);
+ /* Scan bitmap and allocate page. */
+ bit_ffc(rv->popmap, VM_LEVEL_0_NPAGES, &i);
+ KASSERT(i != -1,
+ ("%s: no free pages found after passing 'popcnt < VM_LEVEL_0_NPAGES' check",
+ __func__));
+ KASSERT(!bit_test(rv->popmap, i),
+ ("%s: bit %zd is allocated", __func__, i));
+ bit_set(rv->popmap, i);
+ rv->popcnt++;
+
+ return (&rv->pages[i]);
+}
+
+/*
+ * Frees a 0-order page belonging to an unmanaged reservation 'rv'.
+ */
+static void
+vm_reserv_free_page_noobj(vm_reserv_t rv, vm_page_t m)
+{
+ struct vm_domain *vmd;
+ int index;
+
+ KASSERT(rv->object == NULL && rv->isnoobj != 0,
+ ("%s: reserv %p is not a noobj reserv", __func__, rv));
+ KASSERT(rv->popcnt > 0,
+ ("%s: reserv %p's popcnt is corrupted", __func__, rv));
+ KASSERT(rv->domain < vm_ndomains,
+ ("%s: reserv %p's domain is corrupted %d", __func__, rv,
+ rv->domain));
+ vmd = VM_DOMAIN(rv->domain);
+ index = m - rv->pages;
+ KASSERT(bit_test(rv->popmap, index),
+ ("%s: reserv %p's popmap[%d] is clear", __func__, rv, index));
+ bit_clear(rv->popmap, index);
+ rv->popcnt--;
+ if (rv->popcnt == 0) {
+ /* Reservation is empty - release it. */
+ vm_domain_free_lock(vmd);
+ vm_phys_free_pages(rv->pages, VM_LEVEL_0_ORDER);
+ vm_domain_free_unlock(vmd);
+ counter_u64_add(vm_reserv_freed, 1);
+ vm_reserv_clear_noobj(rv);
+ }
+ vm_domain_freecnt_inc(vmd, 1);
+}
#endif /* VM_NRESERVLEVEL > 0 */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 17, 7:21 PM (53 m, 2 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29172470
Default Alt Text
D45043.1784316072.diff (7 KB)
Attached To
Mode
D45043: vm_reserv: introduce unmanaged reservations
Attached
Detach File
Event Timeline
Log In to Comment