⬢ DragonFlyBSD Kernel Audit
DF-4507 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h
index 1111111..2222222 100644
--- a/sys/sys/eventhandler.h
+++ b/sys/sys/eventhandler.h
@@ -158,6 +158,9 @@ struct image_params;
 struct proc;
 
+/* Low memory events */
+typedef void (*vm_lowmem_fn)(void *, int);
+
 /* Shutdown events */
 typedef void (*shutdown_fn) (void *, int);
 
@@ -170,6 +173,7 @@ typedef void (*shutdown_fn) (void *, int);
 typedef void (*execlist_fn)(void *, struct image_params *);
 typedef void (*exit_list_fn)(void *, struct proc *);
 
+EVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_fn);		/* low on memory */
 EVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn);	/* before fs sync */
 EVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn);	/* after fs sync */
 EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn);
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 1111111..2222222 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -1792,6 +1792,13 @@
 	 */
 	if (swap_pager_almost_full &&
 	    pass > 0 &&
 	    isep == 0 &&
 	    (vm_paging_min_dnc(recycle_count) || avail_shortage > 0)) {
+
+		/*
+		 * System is critically short of memory.  Give caches
+		 * (e.g. the TTM page pools) a chance to release pages
+		 * before we start killing processes.
+		 */
+		EVENTHANDLER_INVOKE(vm_lowmem, 0);
+
 		kprintf("Warning: system low on memory+swap "
 			"shortage %ld for %d ticks!\n",
 			avail_shortage, ticks - swap_fail_ticks);
diff --git a/sys/dev/drm/ttm/ttm_page_alloc.c b/sys/dev/drm/ttm/ttm_page_alloc.c
index 1111111..2222222 100644
--- a/sys/dev/drm/ttm/ttm_page_alloc.c
+++ b/sys/dev/drm/ttm/ttm_page_alloc.c
@@ -382,7 +382,18 @@
  *
  * XXX: (dchinner) Deadlock warning!
  *
  * This code is crying out for a shrinker per pool....
  */
+/*
+ * vm_lowmem adapter: eventhandlers are invoked as func(arg, flags) and
+ * cannot be passed directly as a shrinker callback.  Build a local
+ * shrink_control instead of casting the event argument to a pointer
+ * (which would dereference the integer flags argument).
+ */
+static void
+ttm_pool_lowmem(void *arg, int flags)
+{
+	struct shrink_control sc;
+
+	sc.gfp_mask = M_WAITOK;
+	sc.nr_to_scan = ~0UL;
+	ttm_pool_shrink_scan((struct shrinker *)arg, &sc);
+}
+
 static unsigned long
 ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
 {
@@ -439,11 +450,9 @@
 static void ttm_pool_mm_shrink_init(struct ttm_pool_manager *manager)
 {
-	manager->mm_shrink.count_objects = ttm_pool_shrink_count;
-	manager->mm_shrink.scan_objects = ttm_pool_shrink_scan;
-	manager->mm_shrink.seeks = 1;
-	manager->lowmem_handler = EVENTHANDLER_REGISTER(vm_lowmem,
-	    ttm_pool_shrink_scan, manager, EVENTHANDLER_PRI_ANY);
+	manager->lowmem_handler = EVENTHANDLER_REGISTER(vm_lowmem,
+	    ttm_pool_lowmem, manager, EVENTHANDLER_PRI_ANY);
 }