]> git.proxmox.com Git - mirror_spl.git/commitdiff
Linux VM integration / device special files
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 4 Feb 2009 23:15:41 +0000 (15:15 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 4 Feb 2009 23:15:41 +0000 (15:15 -0800)
Support added to provide reasonable values for the global Solaris
VM variables: minfree, desfree, lotsfree, needfree.  These values
are set to the sum of their per-zone linux counterparts which
should be close enough for Solaris consumers.

When a non-GPL app links against the SPL we cannot use the udev
interfaces, which means non of the device special files are created.
Because of this I had added a poor mans udev which cause the SPL
to invoke an upcall and create the basic devices when a minor
is registered.  When a minor is unregistered we use the vnode
interface to unlink the special file.

13 files changed:
config/spl-build.m4
configure
configure.ac
include/sys/dnlc.h
include/sys/kmem.h
include/sys/sunddi.h
include/sys/sysmacros.h
include/sys/vmsystm.h
module/spl/spl-generic.c
module/spl/spl-kmem.c
module/spl/spl-module.c
module/spl/spl-proc.c
spl_config.h.in

index 2f346f6c8b6dffedaad3bcf72081fbba41a8a1bb..b7aa024e436b1e5d48a075df520e75e4e319b9fc 100644 (file)
@@ -705,3 +705,39 @@ AC_DEFUN([SPL_AC_3ARGS_ON_EACH_CPU], [
                AC_MSG_RESULT(no)
        ])
 ])
+
+dnl #
+dnl # Distro specific first_online_pgdat symbol export.
+dnl #
+AC_DEFUN([SPL_AC_FIRST_ONLINE_PGDAT], [
+       SPL_CHECK_SYMBOL_EXPORT(
+               [first_online_pgdat],
+               [],
+               [AC_DEFINE(HAVE_FIRST_ONLINE_PGDAT, 1,
+               [first_online_pgdat() is available])],
+               [])
+])
+
+dnl #
+dnl # Distro specific next_online_pgdat symbol export.
+dnl #
+AC_DEFUN([SPL_AC_NEXT_ONLINE_PGDAT], [
+       SPL_CHECK_SYMBOL_EXPORT(
+               [next_online_pgdat],
+               [],
+               [AC_DEFINE(HAVE_NEXT_ONLINE_PGDAT, 1,
+               [next_online_pgdat() is available])],
+               [])
+])
+
+dnl #
+dnl # Distro specific next_zone symbol export.
+dnl #
+AC_DEFUN([SPL_AC_NEXT_ZONE], [
+       SPL_CHECK_SYMBOL_EXPORT(
+               [next_zone],
+               [],
+               [AC_DEFINE(HAVE_NEXT_ZONE, 1,
+               [next_zone() is available])],
+               [])
+])
index 8acd0502324def5ea29793899fd6da957734a872..7e59d67fdd89e9435e8684daf779c92e49e2eddf 100755 (executable)
--- a/configure
+++ b/configure
@@ -20481,6 +20481,123 @@ rm -f build/conftest.o build/conftest.mod.c build/conftest.mod.o build/conftest.
 
 
 
+       echo "$as_me:$LINENO: checking whether symbol first_online_pgdat is exported" >&5
+echo $ECHO_N "checking whether symbol first_online_pgdat is exported... $ECHO_C" >&6
+       grep -q -E '[[:space:]]first_online_pgdat[[:space:]]' $LINUX/Module.symvers 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in ; do
+                       grep -q -E "EXPORT_SYMBOL.*(first_online_pgdat)" "$LINUX/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+               else
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FIRST_ONLINE_PGDAT 1
+_ACEOF
+
+               fi
+       else
+               echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FIRST_ONLINE_PGDAT 1
+_ACEOF
+
+       fi
+
+
+
+       echo "$as_me:$LINENO: checking whether symbol next_online_pgdat is exported" >&5
+echo $ECHO_N "checking whether symbol next_online_pgdat is exported... $ECHO_C" >&6
+       grep -q -E '[[:space:]]next_online_pgdat[[:space:]]' $LINUX/Module.symvers 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in ; do
+                       grep -q -E "EXPORT_SYMBOL.*(next_online_pgdat)" "$LINUX/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+               else
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NEXT_ONLINE_PGDAT 1
+_ACEOF
+
+               fi
+       else
+               echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NEXT_ONLINE_PGDAT 1
+_ACEOF
+
+       fi
+
+
+
+       echo "$as_me:$LINENO: checking whether symbol next_zone is exported" >&5
+echo $ECHO_N "checking whether symbol next_zone is exported... $ECHO_C" >&6
+       grep -q -E '[[:space:]]next_zone[[:space:]]' $LINUX/Module.symvers 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in ; do
+                       grep -q -E "EXPORT_SYMBOL.*(next_zone)" "$LINUX/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+               else
+                       echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NEXT_ZONE 1
+_ACEOF
+
+               fi
+       else
+               echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NEXT_ZONE 1
+_ACEOF
+
+       fi
+
+
+
 TOPDIR=`/bin/pwd`
 
 # Add "V=1" to KERNELMAKE_PARAMS to enable verbose module build
index e0fcb60772500c0be28712a3b0d71f4edf8785cf..bd4f699769457bbbb2afd95425facfeb6ca9895c 100644 (file)
@@ -69,6 +69,9 @@ SPL_AC_MONOTONIC_CLOCK
 SPL_AC_INODE_I_MUTEX
 SPL_AC_DIV64_64
 SPL_AC_3ARGS_ON_EACH_CPU
+SPL_AC_FIRST_ONLINE_PGDAT
+SPL_AC_NEXT_ONLINE_PGDAT
+SPL_AC_NEXT_ZONE
 
 TOPDIR=`/bin/pwd`
 
index 91fb57e06c49ea47a62a28f3b8fac8249f7b1df4..38f8dd6b1c670b13089b0a10ef0f9dc99aea1273 100644 (file)
@@ -1,4 +1,6 @@
 #ifndef _SPL_DNLC_H
 #define _SPL_DNLC_H
 
+#define dnlc_reduce_cache(percent)     ((void)0)
+
 #endif /* SPL_DNLC_H */
index 5f2695d521d47122a1f0e861e2f5e6538c4fae01..7281f1063df54bff3d9bef2bdda8795212a704e0 100644 (file)
@@ -45,6 +45,7 @@ extern "C" {
 #include <asm/atomic_compat.h>
 #include <sys/types.h>
 #include <sys/debug.h>
+#include <sys/vmsystm.h>
 
 /*
  * Memory allocation interfaces
index d2e71ebd5044f3239a8404d3ee5aa742d19a9504..404b14b383597ccc33350055f6ed38af2251030a 100644 (file)
 #include <sys/sunldi.h>
 #include <sys/mutex.h>
 #include <sys/u8_textprep.h>
+#include <sys/vnode.h>
 #include <linux/kdev_t.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
 #include <linux/list.h>
 #include <spl-device.h>
 
+#define DDI_MAX_NAME_LEN       32
+
 typedef int ddi_devid_t;
 
 typedef enum {
@@ -80,6 +83,7 @@ typedef struct pollhead {
 
 typedef struct dev_info {
        kmutex_t di_lock;
+       char di_name[DDI_MAX_NAME_LEN];
        struct dev_ops *di_ops;
        struct cdev *di_cdev;
        spl_class *di_class;
@@ -202,6 +206,7 @@ extern void __ddi_remove_minor_node(dev_info_t *dip, char *name);
 extern int ddi_quiesce_not_needed(dev_info_t *dip);
 extern int __mod_install(struct modlinkage *modlp);
 extern int __mod_remove(struct modlinkage *modlp);
+extern int __mod_mknod(char *name, char *type, int major, int minor);
 
 extern int ddi_strtoul(const char *, char **, int, unsigned long *);
 extern int ddi_strtol(const char *, char **, int, long *);
@@ -226,7 +231,16 @@ ddi_remove_minor_node(dev_info_t *di, char *name)
                di->di_class = NULL;
                di->di_dev = 0;
        }
-#endif
+#else
+       /* When we do not have access to the GPL-only device interfaces we
+        * are forced to do something crude.  We unlink the special device
+        * file in /dev/ ourselves from within the kernel.  On the upside we
+        * are already providing this functionality for Solaris, and it is
+        * easy to leverage the Solaris API to perform the unlink. */
+       if (strlen(di->di_name) > 0)
+               vn_remove(di->di_name, UIO_SYSSPACE, RMFILE);
+
+#endif /* HAVE_GPL_ONLY_SYMBOLS */
 
        __ddi_remove_minor_node(di, name);
 }
@@ -254,14 +268,28 @@ ddi_create_minor_node(dev_info_t *di, char *name, int spec_type,
                di->di_class = NULL;
                ddi_remove_minor_node(di, name);
                CERROR("Error creating %s class, %d\n", name, rc);
-               RETURN(DDI_FAILURE);
+               return DDI_FAILURE;
        }
 
        /* Do not append a 0 to devices with minor nums of 0 */
        di->di_device = spl_device_create(di->di_class, NULL, di->di_dev, NULL,
                                          (di->di_minor == 0) ? "%s" : "%s%d",
                                          name, di->di_minor);
-#endif
+#else
+       /* When we do not have access to the GPL-only device interfaces we
+        * are forced to do something horible.  We use a user mode helper to
+        * create the special device file in /dev/.  By futher extending the
+        * Solaris vnode implementation we could potentially do a vn_create()
+        * from within the kernel but that's still a hack. */
+       if (name) {
+               rc = __mod_mknod(di->di_name, "c", di->di_major, di->di_minor);
+               if (rc) {
+                       CERROR("Error mknod %s, %d\n", di->di_name, rc);
+                       ddi_remove_minor_node(di, name);
+               }
+       }
+
+#endif /* HAVE_GPL_ONLY_SYMBOLS */
 
        return rc;
 }
index b8281238574cbb1cb6140c40d40ed8c414f62404..65c10258573a495d73c74b012d8f097f78c044f7 100644 (file)
@@ -67,10 +67,13 @@ extern "C" {
 #define DEV_BSIZE                      512
 #define DEV_BSHIFT                     9 /* log2(DEV_BSIZE) */
 
+#define curproc                                current
+#define proc_pageout                   NULL
 #define max_ncpus                       64
 #define CPU_SEQID                      smp_processor_id() /* I think... */
 #define _NOTE(x)
 
+
 #define RLIM64_INFINITY                        RLIM_INFINITY
 
 /* 0..MAX_PRIO-1:              Process priority
@@ -135,8 +138,6 @@ extern int p0;
 
 /* Missing misc functions */
 extern int highbit(unsigned long i);
-extern int ddi_strtoul(const char *str, char **nptr,
-                      int base, unsigned long *result);
 
 #define makedevice(maj,min) makedev(maj,min)
 
index 1cb716f13c7a537fa77fe42732cf2ef8aa27bc00..a6e9e7d7e4c373c24667f0f7fb354e3eb68ef830 100644 (file)
 #ifndef _SPL_VMSYSTM_H
 #define _SPL_VMSYSTM_H
 
+#include <linux/mmzone.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <sys/types.h>
 #include <asm/uaccess.h>
 
-extern vmem_t *zio_alloc_arena;                /* arena for zio caches */
+/* These values are loosely coupled with the the VM page reclaim.
+ * Linux uses its own heuristics to trigger page reclamation, and
+ * because those interface are difficult to interface with.  These
+ * values should only be considered as a rough guide to the system
+ * memory state and not as direct evidence that page reclaimation
+ * is or is not currently in progress.
+ */
+#define ptob(pages)                    (pages * PAGE_SIZE)
+#define membar_producer()              smp_wmb()
 
 #define physmem                                num_physpages
 #define freemem                                nr_free_pages()
-#define minfree                                0
-#define needfree                       0       /* # of needed pages */
-#define ptob(pages)                    (pages * PAGE_SIZE)
-#define membar_producer()              smp_wmb()
+
+extern pgcnt_t minfree;                        /* Sum of zone->pages_min */
+extern pgcnt_t desfree;                        /* Sum of zone->pages_low */
+extern pgcnt_t lotsfree;               /* Sum of zone->pages_high */
+extern pgcnt_t needfree;               /* Always 0 */
+extern pgcnt_t swapfs_minfree;
+extern pgcnt_t swapfs_desfree;
+extern pgcnt_t swapfs_reserve;
+extern pgcnt_t availrmem;
+
+extern vmem_t *heap_arena;             /* primary kernel heap arena */
+extern vmem_t *zio_alloc_arena;                /* arena for zio caches */
+extern vmem_t *zio_arena;              /* arena for allocating zio memory */
+
+#define VMEM_ALLOC                     0x01
+#define VMEM_FREE                      0x02
+
+static __inline__ size_t
+vmem_size(vmem_t *vmp, int typemask)
+{
+       /* Arena's unsupported */
+       ASSERT(vmp == NULL);
+       ASSERT(typemask & (VMEM_ALLOC | VMEM_FREE));
+
+       return 0;
+}
 
 #define xcopyin(from, to, size)                copy_from_user(to, from, size)
 #define xcopyout(from, to, size)       copy_to_user(to, from, size)
@@ -82,25 +113,4 @@ copyinstr(const void *from, void *to, size_t len, size_t *done)
        return 0;
 }
 
-#if 0
-/* The average number of free pages over the last 5 seconds */
-#define avefree                                0
-
-/* The average number of free pages over the last 30 seconds */
-#define avefree30                      0
-
-/* A guess as to how much memory has been promised to
- * processes but not yet allocated */
-#define deficit                                0
-
-/* A bootlean the controls the setting of deficit */
-#define desperate
-
-/* When free memory is above this limit, no paging or swapping is done */
-#define lotsfree                       0
-
-/* When free memory is above this limit, swapping is not performed */
-#define desfree                                0
-#endif
-
 #endif /* SPL_VMSYSTM_H */
index c09d9d4e36c335bb3db55efe526dbcce258250ee..a15cac41ecf7677b0d5a27240bb9a39e88df8b9e 100644 (file)
@@ -53,9 +53,6 @@ EXPORT_SYMBOL(hw_serial);
 int p0 = 0;
 EXPORT_SYMBOL(p0);
 
-vmem_t *zio_alloc_arena = NULL;
-EXPORT_SYMBOL(zio_alloc_arena);
-
 int
 highbit(unsigned long i)
 {
index 79f7872715f7a8cdc21777af1cb47debd1713d34..c39636e06bb934b9de6f08666e093bacfcd1ae41 100644 (file)
 
 #define DEBUG_SUBSYSTEM S_KMEM
 
+/*
+ * The minimum amount of memory measured in pages to be free at all
+ * times on the system.  This is similar to Linux's zone->pages_min
+ * multipled by the number of zones and is sized based on that.
+ */
+pgcnt_t minfree = 0;
+EXPORT_SYMBOL(minfree);
+
+/*
+ * The desired amount of memory measured in pages to be free at all
+ * times on the system.  This is similar to Linux's zone->pages_low
+ * multipled by the number of zones and is sized based on that.
+ * Assuming all zones are being used roughly equally, when we drop
+ * below this threshold async page reclamation is triggered.
+ */
+pgcnt_t desfree = 0;
+EXPORT_SYMBOL(desfree);
+
+/*
+ * When above this amount of memory measures in pages the system is
+ * determined to have enough free memory.  This is similar to Linux's
+ * zone->pages_high multipled by the number of zones and is sized based
+ * on that.  Assuming all zones are being used roughly equally, when
+ * async page reclamation reaches this threshold it stops.
+ */
+pgcnt_t lotsfree = 0;
+EXPORT_SYMBOL(lotsfree);
+
+/* Unused always 0 in this implementation */
+pgcnt_t needfree = 0;
+EXPORT_SYMBOL(needfree);
+
+pgcnt_t swapfs_desfree = 0;
+EXPORT_SYMBOL(swapfs_desfree);
+
+pgcnt_t swapfs_minfree = 0;
+EXPORT_SYMBOL(swapfs_minfree);
+
+pgcnt_t swapfs_reserve = 0;
+EXPORT_SYMBOL(swapfs_reserve);
+
+pgcnt_t availrmem = 0;
+EXPORT_SYMBOL(availrmem);
+
+vmem_t *heap_arena = NULL;
+EXPORT_SYMBOL(heap_arena);
+
+vmem_t *zio_alloc_arena = NULL;
+EXPORT_SYMBOL(zio_alloc_arena);
+
+vmem_t *zio_arena = NULL;
+EXPORT_SYMBOL(zio_arena);
+
+#ifndef HAVE_FIRST_ONLINE_PGDAT
+struct pglist_data *first_online_pgdat(void)
+{
+       return NODE_DATA(first_online_node);
+}
+#endif /* HAVE_FIRST_ONLINE_PGDAT */
+
+#ifndef HAVE_NEXT_ONLINE_PGDAT
+struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
+{
+       int nid = next_online_node(pgdat->node_id);
+
+       if (nid == MAX_NUMNODES)
+               return NULL;
+
+       return NODE_DATA(nid);
+}
+#endif /* HAVE_NEXT_ONLINE_PGDAT */
+
+#ifndef HAVE_NEXT_ZONE
+struct zone *next_zone(struct zone *zone)
+{
+       pg_data_t *pgdat = zone->zone_pgdat;
+
+       if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
+       zone++;
+       else {
+               pgdat = next_online_pgdat(pgdat);
+               if (pgdat)
+                       zone = pgdat->node_zones;
+               else
+                       zone = NULL;
+       }
+       return zone;
+}
+#endif /* HAVE_NEXT_ZONE */
+
 /*
  * Memory allocation interfaces and debugging for basic kmem_*
  * and vmem_* style memory allocation.  When DEBUG_KMEM is enable
@@ -1601,6 +1691,24 @@ spl_kmem_fini_tracking(struct list_head *list, spinlock_t *lock)
 #define spl_kmem_fini_tracking(list, lock)
 #endif /* DEBUG_KMEM && DEBUG_KMEM_TRACKING */
 
+static void
+spl_kmem_init_globals(void)
+{
+       struct zone *zone;
+
+       /* For now all zones are includes, it may be wise to restrict
+        * this to normal and highmem zones if we see problems. */
+        for_each_zone(zone) {
+
+                if (!populated_zone(zone))
+                        continue;
+
+               minfree += zone->pages_min;
+               desfree += zone->pages_low;
+               lotsfree += zone->pages_high;
+       }
+}
+
 int
 spl_kmem_init(void)
 {
@@ -1609,6 +1717,7 @@ spl_kmem_init(void)
 
        init_rwsem(&spl_kmem_cache_sem);
        INIT_LIST_HEAD(&spl_kmem_cache_list);
+       spl_kmem_init_globals();
 
 #ifdef HAVE_SET_SHRINKER
        spl_kmem_cache_shrinker = set_shrinker(KMC_DEFAULT_SEEKS,
index c1d030f240d768f0b6ef645862b7fd21af95c67e..4a2be89dab26a9745bf4f58536a0aba046d615a4 100644 (file)
@@ -140,6 +140,7 @@ __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type,
        ASSERT(cb_ops->cb_aread == NULL);
        ASSERT(cb_ops->cb_awrite == NULL);
 
+       snprintf(di->di_name, DDI_MAX_NAME_LEN-1, "/dev/%s", name);
        di->di_cdev  = cdev;
        di->di_flags = flags;
        di->di_minor = minor_num;
@@ -281,6 +282,30 @@ __mod_install(struct modlinkage *modlp)
 }
 EXPORT_SYMBOL(__mod_install);
 
+int
+__mod_mknod(char *name, char *type, int major, int minor)
+{
+       char cmd[] = "/bin/mknod";
+       char major_str[8];
+       char minor_str[8];
+       char *argv[] = { cmd,
+                        name,
+                        type,
+                        major_str,
+                        minor_str,
+                        NULL };
+       char *envp[] = { "HOME=/",
+                        "TERM=linux",
+                        "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+                        NULL };
+
+       snprintf(major_str, 8, "%d", major);
+       snprintf(minor_str, 8, "%d", minor);
+
+       return call_usermodehelper(cmd, argv, envp, 1);
+}
+EXPORT_SYMBOL(__mod_mknod);
+
 int
 __mod_remove(struct modlinkage *modlp)
 {
index bf185c60ec32704d850c39313abc089c56b18d44..024118a9f9b7dca1c519b8c1500c2cdd60921b7c 100644 (file)
@@ -60,6 +60,7 @@ struct proc_dir_entry *proc_spl_kstat = NULL;
 
 #define CTL_SPL                        CTL_UNNUMBERED
 #define CTL_SPL_DEBUG          CTL_UNNUMBERED
+#define CTL_SPL_VM             CTL_UNNUMBERED
 #define CTL_SPL_MUTEX          CTL_UNNUMBERED
 #define CTL_SPL_KMEM           CTL_UNNUMBERED
 #define CTL_SPL_KSTAT          CTL_UNNUMBERED
@@ -85,6 +86,15 @@ struct proc_dir_entry *proc_spl_kstat = NULL;
 #define CTL_CONSOLE_MIN_DELAY_CS CTL_UNNUMBERED /* Init delay skip messages */
 #define CTL_CONSOLE_BACKOFF    CTL_UNNUMBERED /* Delay increase factor */
 
+#define CTL_VM_MINFREE         CTL_UNNUMBERED /* Minimum free memory */
+#define CTL_VM_DESFREE         CTL_UNNUMBERED /* Desired free memory */
+#define CTL_VM_LOTSFREE                CTL_UNNUMBERED /* Lots of free memory */
+#define CTL_VM_NEEDFREE                CTL_UNNUMBERED /* Need free memory */
+#define CTL_VM_SWAPFS_MINFREE  CTL_UNNUMBERED /* Minimum swapfs memory */
+#define CTL_VM_SWAPFS_DESFREE  CTL_UNNUMBERED /* Desired swapfs memory */
+#define CTL_VM_SWAPFS_RESERVE  CTL_UNNUMBERED /* Reserved swapfs memory */
+#define CTL_VM_AVAILRMEM       CTL_UNNUMBERED /* Available reserved memory */
+
 #ifdef DEBUG_KMEM
 #define CTL_KMEM_KMEMUSED      CTL_UNNUMBERED /* Alloc'd kmem bytes */
 #define CTL_KMEM_KMEMMAX       CTL_UNNUMBERED /* Max alloc'd by kmem bytes */
@@ -99,44 +109,56 @@ struct proc_dir_entry *proc_spl_kstat = NULL;
 
 #else /* HAVE_CTL_UNNUMBERED */
 
-#define CTL_SPL                0x87
-#define CTL_SPL_DEBUG  0x88
-#define CTL_SPL_MUTEX  0x89
-#define CTL_SPL_KMEM   0x90
-#define CTL_SPL_KSTAT  0x91
+enum {
+       CTL_SPL = 0x87,
+       CTL_SPL_DEBUG = 0x88,
+       CTL_SPL_VM = 0x89,
+       CTL_SPL_MUTEX = 0x90,
+       CTL_SPL_KMEM = 0x91,
+       CTL_SPL_KSTAT = 0x92,
+};
 
 enum {
-       CTL_VERSION = 1,          /* Version */
-       CTL_HOSTID,               /* Host id reported by /usr/bin/hostid */
-       CTL_HW_SERIAL,            /* Hardware serial number from hostid */
-
-       CTL_DEBUG_SUBSYS,         /* Debug subsystem */
-        CTL_DEBUG_MASK,           /* Debug mask */
-        CTL_DEBUG_PRINTK,         /* Force all messages to console */
-        CTL_DEBUG_MB,             /* Debug buffer size */
-        CTL_DEBUG_BINARY,         /* Include binary data in buffer */
-        CTL_DEBUG_CATASTROPHE,    /* Set if we have BUG'd or panic'd */
-        CTL_DEBUG_PANIC_ON_BUG,   /* Set if we should panic on BUG */
-        CTL_DEBUG_PATH,           /* Dump log location */
-        CTL_DEBUG_DUMP,           /* Dump debug buffer to file */
-        CTL_DEBUG_FORCE_BUG,      /* Hook to force a BUG */
-        CTL_DEBUG_STACK_SIZE,     /* Max observed stack size */
-
-       CTL_CONSOLE_RATELIMIT,    /* Ratelimit console messages */
-        CTL_CONSOLE_MAX_DELAY_CS, /* Max delay at which we skip messages */
-        CTL_CONSOLE_MIN_DELAY_CS, /* Init delay at which we skip messages */
-        CTL_CONSOLE_BACKOFF,      /* Delay increase factor */
+       CTL_VERSION = 1,                /* Version */
+       CTL_HOSTID,                     /* Host id reported by /usr/bin/hostid */
+       CTL_HW_SERIAL,                  /* Hardware serial number from hostid */
+
+       CTL_DEBUG_SUBSYS,               /* Debug subsystem */
+       CTL_DEBUG_MASK,                 /* Debug mask */
+       CTL_DEBUG_PRINTK,               /* Force all messages to console */
+       CTL_DEBUG_MB,                   /* Debug buffer size */
+       CTL_DEBUG_BINARY,               /* Include binary data in buffer */
+       CTL_DEBUG_CATASTROPHE,          /* Set if we have BUG'd or panic'd */
+       CTL_DEBUG_PANIC_ON_BUG,         /* Set if we should panic on BUG */
+       CTL_DEBUG_PATH,                 /* Dump log location */
+       CTL_DEBUG_DUMP,                 /* Dump debug buffer to file */
+       CTL_DEBUG_FORCE_BUG,            /* Hook to force a BUG */
+       CTL_DEBUG_STACK_SIZE,           /* Max observed stack size */
+
+       CTL_CONSOLE_RATELIMIT,          /* Ratelimit console messages */
+       CTL_CONSOLE_MAX_DELAY_CS,       /* Max delay which we skip messages */
+       CTL_CONSOLE_MIN_DELAY_CS,       /* Init delay which we skip messages */
+       CTL_CONSOLE_BACKOFF,            /* Delay increase factor */
+
+       CTL_VM_MINFREE,                 /* Minimum free memory threshold */
+       CTL_VM_DESFREE,                 /* Desired free memory threshold */
+       CTL_VM_LOTSFREE,                /* Lots of free memory threshold */
+       CTL_VM_NEEDFREE,                /* Need free memory deficit */
+       CTL_VM_SWAPFS_MINFREE,          /* Minimum swapfs memory */
+       CTL_VM_SWAPFS_DESFREE,          /* Desired swapfs memory */
+       CTL_VM_SWAPFS_RESERVE,          /* Reserved swapfs memory */
+       CTL_VM_AVAILRMEM,               /* Available reserved memory */
 
 #ifdef DEBUG_KMEM
-        CTL_KMEM_KMEMUSED,        /* Alloc'd kmem bytes */
-        CTL_KMEM_KMEMMAX,         /* Max alloc'd by kmem bytes */
-        CTL_KMEM_VMEMUSED,        /* Alloc'd vmem bytes */
-        CTL_KMEM_VMEMMAX,         /* Max alloc'd by vmem bytes */
+       CTL_KMEM_KMEMUSED,              /* Alloc'd kmem bytes */
+       CTL_KMEM_KMEMMAX,               /* Max alloc'd by kmem bytes */
+       CTL_KMEM_VMEMUSED,              /* Alloc'd vmem bytes */
+       CTL_KMEM_VMEMMAX,               /* Max alloc'd by vmem bytes */
 #endif
 
-       CTL_MUTEX_STATS,          /* Global mutex statistics */
-       CTL_MUTEX_STATS_PER,      /* Per mutex statistics */
-       CTL_MUTEX_SPIN_MAX,       /* Maximum mutex spin iterations */
+       CTL_MUTEX_STATS,                /* Global mutex statistics */
+       CTL_MUTEX_STATS_PER,            /* Per mutex statistics */
+       CTL_MUTEX_SPIN_MAX,             /* Maximum mutex spin iterations */
 };
 #endif /* HAVE_CTL_UNNUMBERED */
 
@@ -769,6 +791,74 @@ static struct ctl_table spl_debug_table[] = {
        {0},
 };
 
+static struct ctl_table spl_vm_table[] = {
+        {
+                .ctl_name = CTL_VM_MINFREE,
+                .procname = "minfree",
+                .data     = &minfree,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec,
+        },
+        {
+                .ctl_name = CTL_VM_DESFREE,
+                .procname = "desfree",
+                .data     = &desfree,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec,
+        },
+        {
+                .ctl_name = CTL_VM_LOTSFREE,
+                .procname = "lotsfree",
+                .data     = &lotsfree,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec,
+        },
+        {
+                .ctl_name = CTL_VM_NEEDFREE,
+                .procname = "needfree",
+                .data     = &needfree,
+                .maxlen   = sizeof(int),
+                .mode     = 0444,
+                .proc_handler = &proc_dointvec,
+        },
+        {
+                .ctl_name = CTL_VM_SWAPFS_MINFREE,
+                .procname = "swapfs_minfree",
+                .data     = &swapfs_minfree,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec,
+        },
+        {
+                .ctl_name = CTL_VM_SWAPFS_DESFREE,
+                .procname = "swapfs_desfree",
+                .data     = &swapfs_desfree,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec,
+        },
+        {
+                .ctl_name = CTL_VM_SWAPFS_RESERVE,
+                .procname = "swapfs_reserve",
+                .data     = &swapfs_reserve,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec,
+        },
+        {
+                .ctl_name = CTL_VM_AVAILRMEM,
+                .procname = "availrmem",
+                .data     = &availrmem,
+                .maxlen   = sizeof(int),
+                .mode     = 0444,
+                .proc_handler = &proc_dointvec,
+        },
+       {0},
+};
+
 #ifdef DEBUG_MUTEX
 static struct ctl_table spl_mutex_table[] = {
         {
@@ -873,6 +963,12 @@ static struct ctl_table spl_table[] = {
                .mode     = 0555,
                .child    = spl_debug_table,
        },
+       {
+               .ctl_name = CTL_SPL_VM,
+               .procname = "vm",
+               .mode     = 0555,
+               .child    = spl_vm_table,
+       },
 #ifdef DEBUG_MUTEX
        {
                .ctl_name = CTL_SPL_MUTEX,
index a4a8ccd321d84cfb94ea7eb189338ba79b918a6a..2bfb5c48733147154a82ca911bd46f9b828c1ee0 100644 (file)
@@ -45,6 +45,9 @@
 /* files_fdtable() is available */
 #undef HAVE_FILES_FDTABLE
 
+/* first_online_pgdat() is available */
+#undef HAVE_FIRST_ONLINE_PGDAT
+
 /* fls64() is available */
 #undef HAVE_FLS64
 
 /* monotonic_clock() is available */
 #undef HAVE_MONOTONIC_CLOCK
 
+/* next_online_pgdat() is available */
+#undef HAVE_NEXT_ONLINE_PGDAT
+
+/* next_zone() is available */
+#undef HAVE_NEXT_ZONE
+
 /* struct path used in struct nameidata */
 #undef HAVE_PATH_IN_NAMEIDATA