Page MenuHomeFreeBSD

D27728.diff
No OneTemporary

D27728.diff

diff --git a/sys/compat/linuxkpi/common/include/linux/shrinker.h b/sys/compat/linuxkpi/common/include/linux/shrinker.h
new file mode 100644
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/shrinker.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2020 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LINUX_SHRINKER_H__
+#define __LINUX_SHRINKER_H__
+
+#include <sys/queue.h>
+
+struct shrink_control {
+ unsigned long nr_to_scan;
+ unsigned long nr_scanned;
+};
+
+struct shrinker {
+ unsigned long (*count_objects)(struct shrinker *, struct shrink_control *);
+ unsigned long (*scan_objects)(struct shrinker *, struct shrink_control *);
+ int seeks;
+ long batch;
+ TAILQ_ENTRY(shrinker) next;
+};
+
+#define SHRINK_STOP (~0UL)
+
+#define DEFAULT_SEEKS 2
+
+int linuxkpi_register_shrinker(struct shrinker *s);
+void linuxkpi_unregister_shrinker(struct shrinker *s);
+
+#define register_shrinker(s) linuxkpi_register_shrinker(s)
+#define unregister_shrinker(s) linuxkpi_unregister_shrinker(s)
+
+#endif /* __LINUX_SHRINKER_H__ */
diff --git a/sys/compat/linuxkpi/common/src/linux_shrinker.c b/sys/compat/linuxkpi/common/src/linux_shrinker.c
new file mode 100644
--- /dev/null
+++ b/sys/compat/linuxkpi/common/src/linux_shrinker.c
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2020 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/eventhandler.h>
+#include <sys/mutex.h>
+
+#include <linux/shrinker.h>
+
+TAILQ_HEAD(, shrinker) lkpi_shrinkers = TAILQ_HEAD_INITIALIZER(lkpi_shrinkers);
+static struct mtx mtx_shrinker;
+
+int
+linuxkpi_register_shrinker(struct shrinker *s)
+{
+
+ KASSERT(s != NULL, ("NULL shrinker"));
+ KASSERT(s->count_objects != NULL, ("NULL shrinker"));
+ KASSERT(s->scan_objects != NULL, ("NULL shrinker"));
+ mtx_lock(&mtx_shrinker);
+ TAILQ_INSERT_TAIL(&lkpi_shrinkers, s, next);
+ mtx_unlock(&mtx_shrinker);
+ return (0);
+}
+
+void
+linuxkpi_unregister_shrinker(struct shrinker *s)
+{
+
+ mtx_lock(&mtx_shrinker);
+ TAILQ_REMOVE(&lkpi_shrinkers, s, next);
+ mtx_unlock(&mtx_shrinker);
+}
+
+#define SHRINKER_BATCH 512
+
+static void
+shrinker_shrink(struct shrinker *s)
+{
+ struct shrink_control sc;
+ unsigned long can_free;
+ unsigned long batch;
+ unsigned long freeed = 0;
+ unsigned long ret;
+
+ can_free = s->count_objects(s, &sc);
+ if (can_free <= 0)
+ return;
+
+ batch = s->batch ? s->batch : SHRINKER_BATCH;
+ while (freeed <= can_free) {
+ sc.nr_to_scan = batch;
+ ret = s->scan_objects(s, &sc);
+ if (ret == SHRINK_STOP)
+ break;
+ freeed += ret;
+ }
+}
+
+static void
+linuxkpi_vm_lowmem(void *arg __unused)
+{
+ struct shrinker *s;
+
+ mtx_lock(&mtx_shrinker);
+ TAILQ_FOREACH(s, &lkpi_shrinkers, next) {
+ shrinker_shrink(s);
+ }
+ mtx_unlock(&mtx_shrinker);
+}
+
+static eventhandler_tag lowmem_tag;
+
+static void
+linuxkpi_sysinit_shrinker(void *arg __unused)
+{
+
+ mtx_init(&mtx_shrinker, "lkpi-shrinker", NULL, MTX_DEF);
+ lowmem_tag = EVENTHANDLER_REGISTER(vm_lowmem, linuxkpi_vm_lowmem,
+ NULL, EVENTHANDLER_PRI_FIRST);
+}
+
+static void
+linuxkpi_sysuninit_shrinker(void *arg __unused)
+{
+
+ mtx_destroy(&mtx_shrinker);
+ EVENTHANDLER_DEREGISTER(vm_lowmem, lowmem_tag);
+}
+
+SYSINIT(linuxkpi_shrinker, SI_SUB_DRIVERS, SI_ORDER_ANY,
+ linuxkpi_sysinit_shrinker, NULL);
+SYSUNINIT(linuxkpi_shrinker, SI_SUB_DRIVERS, SI_ORDER_ANY,
+ linuxkpi_sysuninit_shrinker, NULL);
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4576,6 +4576,8 @@
compile-with "${LINUXKPI_C}"
compat/linuxkpi/common/src/linux_shmemfs.c optional compat_linuxkpi \
compile-with "${LINUXKPI_C}"
+compat/linuxkpi/common/src/linux_shrinker.c optional compat_linuxkpi \
+ compile-with "${LINUXKPI_C}"
compat/linuxkpi/common/src/linux_slab.c optional compat_linuxkpi \
compile-with "${LINUXKPI_C}"
compat/linuxkpi/common/src/linux_usb.c optional compat_linuxkpi usb \
diff --git a/sys/modules/linuxkpi/Makefile b/sys/modules/linuxkpi/Makefile
--- a/sys/modules/linuxkpi/Makefile
+++ b/sys/modules/linuxkpi/Makefile
@@ -17,6 +17,7 @@
linux_seq_file.c \
linux_schedule.c \
linux_shmemfs.c \
+ linux_shrinker.c \
linux_slab.c \
linux_tasklet.c \
linux_usb.c \

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 5, 7:34 AM (22 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13623522
Default Alt Text
D27728.diff (6 KB)

Event Timeline