]> git.proxmox.com Git - mirror_spl-debian.git/commitdiff
Merge branch 'upstream'
authorDarik Horn <dajhorn@vanadac.com>
Thu, 7 Apr 2011 17:25:05 +0000 (12:25 -0500)
committerDarik Horn <dajhorn@vanadac.com>
Thu, 7 Apr 2011 17:25:05 +0000 (12:25 -0500)
META
config/spl-build.m4
configure
include/linux/mm_compat.h
include/sys/dnlc.h
include/sys/kmem.h
include/sys/vnode.h
module/spl/spl-kmem.c
module/spl/spl-proc.c
spl_config.h.in

diff --git a/META b/META
index f33eda4ee7f9a09e6e72825d0f93e192e218fa0f..95261b3fe5b76256dcaac63e244325b9504fb508 100644 (file)
--- a/META
+++ b/META
@@ -2,5 +2,5 @@ Meta:         1
 Name:         spl
 Branch:       1.0
 Version:      0.6.0
-Release:      rc2
+Release:      rc3
 Release-Tags: relext
index 72bb3258ef3ee5ef851c9068916ca4b6adcf9ecc..94c7f3e7460382433bf4cb673cb3d87ba372a9f6 100644 (file)
@@ -76,6 +76,8 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_3ARGS_FILE_FSYNC
        SPL_AC_EXPORTED_RWSEM_IS_LOCKED
        SPL_AC_KERNEL_INVALIDATE_INODES
+       SPL_AC_SHRINK_DCACHE_MEMORY
+       SPL_AC_SHRINK_ICACHE_MEMORY
 ])
 
 AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
@@ -1717,3 +1719,33 @@ AC_DEFUN([SPL_AC_KERNEL_INVALIDATE_INODES], [
                [invalidate_inodes() is available])],
                [])
 ])
+
+dnl #
+dnl # 2.6.xx API compat,
+dnl # There currently exists no exposed API to partially shrink the dcache.
+dnl # The expected mechanism to shrink the cache is a registered shrinker
+dnl # which is called during memory pressure.
+dnl #
+AC_DEFUN([SPL_AC_SHRINK_DCACHE_MEMORY], [
+       SPL_CHECK_SYMBOL_EXPORT(
+               [shrink_dcache_memory],
+               [fs/dcache.c],
+               [AC_DEFINE(HAVE_SHRINK_DCACHE_MEMORY, 1,
+               [shrink_dcache_memory() is available])],
+               [])
+])
+
+dnl #
+dnl # 2.6.xx API compat,
+dnl # There currently exists no exposed API to partially shrink the icache.
+dnl # The expected mechanism to shrink the cache is a registered shrinker
+dnl # which is called during memory pressure.
+dnl #
+AC_DEFUN([SPL_AC_SHRINK_ICACHE_MEMORY], [
+       SPL_CHECK_SYMBOL_EXPORT(
+               [shrink_icache_memory],
+               [fs/inode.c],
+               [AC_DEFINE(HAVE_SHRINK_ICACHE_MEMORY, 1,
+               [shrink_icache_memory() is available])],
+               [])
+])
index f5c6a063a1db74528b9f10022f3964a94e94bcfb..317ab8ea72dc802d42ea90a5a29dda96f6c03835 100755 (executable)
--- a/configure
+++ b/configure
@@ -15462,6 +15462,88 @@ _ACEOF
        fi
 
 
+
+       { $as_echo "$as_me:$LINENO: checking whether symbol shrink_dcache_memory is exported" >&5
+$as_echo_n "checking whether symbol shrink_dcache_memory is exported... " >&6; }
+       grep -q -E '[[:space:]]shrink_dcache_memory[[:space:]]' \
+               $LINUX_OBJ/Module*.symvers 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in fs/dcache.c; do
+                       grep -q -E "EXPORT_SYMBOL.*(shrink_dcache_memory)" \
+                               "$LINUX_OBJ/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+               else
+                       { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_DCACHE_MEMORY 1
+_ACEOF
+
+               fi
+       else
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_DCACHE_MEMORY 1
+_ACEOF
+
+       fi
+
+
+
+       { $as_echo "$as_me:$LINENO: checking whether symbol shrink_icache_memory is exported" >&5
+$as_echo_n "checking whether symbol shrink_icache_memory is exported... " >&6; }
+       grep -q -E '[[:space:]]shrink_icache_memory[[:space:]]' \
+               $LINUX_OBJ/Module*.symvers 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in fs/inode.c; do
+                       grep -q -E "EXPORT_SYMBOL.*(shrink_icache_memory)" \
+                               "$LINUX_OBJ/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+               else
+                       { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_ICACHE_MEMORY 1
+_ACEOF
+
+               fi
+       else
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_ICACHE_MEMORY 1
+_ACEOF
+
+       fi
+
+
  ;;
                 user)
 
@@ -19285,6 +19367,88 @@ _ACEOF
 
 
 
+       { $as_echo "$as_me:$LINENO: checking whether symbol shrink_dcache_memory is exported" >&5
+$as_echo_n "checking whether symbol shrink_dcache_memory is exported... " >&6; }
+       grep -q -E '[[:space:]]shrink_dcache_memory[[:space:]]' \
+               $LINUX_OBJ/Module*.symvers 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in fs/dcache.c; do
+                       grep -q -E "EXPORT_SYMBOL.*(shrink_dcache_memory)" \
+                               "$LINUX_OBJ/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+               else
+                       { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_DCACHE_MEMORY 1
+_ACEOF
+
+               fi
+       else
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_DCACHE_MEMORY 1
+_ACEOF
+
+       fi
+
+
+
+       { $as_echo "$as_me:$LINENO: checking whether symbol shrink_icache_memory is exported" >&5
+$as_echo_n "checking whether symbol shrink_icache_memory is exported... " >&6; }
+       grep -q -E '[[:space:]]shrink_icache_memory[[:space:]]' \
+               $LINUX_OBJ/Module*.symvers 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in fs/inode.c; do
+                       grep -q -E "EXPORT_SYMBOL.*(shrink_icache_memory)" \
+                               "$LINUX_OBJ/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+               else
+                       { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_ICACHE_MEMORY 1
+_ACEOF
+
+               fi
+       else
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK_ICACHE_MEMORY 1
+_ACEOF
+
+       fi
+
+
+
 
 
        if test "x$AWK" != xgawk; then
index 5c5198b90fdea03a2405f3abc12c4b8c8b375168..522db827f805e0fbd9353a621c149c887945625f 100644 (file)
@@ -56,4 +56,86 @@ extern invalidate_inodes_t invalidate_inodes_fn;
 #define invalidate_inodes(sb)  invalidate_inodes_fn(sb)
 #endif /* HAVE_INVALIDATE_INODES */
 
+/*
+ * 2.6.xx API compat,
+ * There currently exists no exposed API to partially shrink the dcache.
+ * The expected mechanism to shrink the cache is a registered shrinker
+ * which is called during memory pressure.
+ */
+#ifndef HAVE_SHRINK_DCACHE_MEMORY
+# ifdef HAVE_3ARGS_SHRINKER_CALLBACK
+typedef int (*shrink_dcache_memory_t)(struct shrinker *, int, gfp_t);
+extern shrink_dcache_memory_t shrink_dcache_memory_fn;
+#  define shrink_dcache_memory(nr, gfp)        shrink_dcache_memory_fn(NULL, nr, gfp)
+# else
+typedef int (*shrink_dcache_memory_t)(int, gfp_t);
+extern shrink_dcache_memory_t shrink_dcache_memory_fn;
+#  define shrink_dcache_memory(nr, gfp)        shrink_dcache_memory_fn(nr, gfp)
+# endif /* HAVE_3ARGS_SHRINKER_CALLBACK */
+#endif /* HAVE_SHRINK_DCACHE_MEMORY */
+
+/*
+ * 2.6.xx API compat,
+ * There currently exists no exposed API to partially shrink the icache.
+ * The expected mechanism to shrink the cache is a registered shrinker
+ * which is called during memory pressure.
+ */
+#ifndef HAVE_SHRINK_ICACHE_MEMORY
+# ifdef HAVE_3ARGS_SHRINKER_CALLBACK
+typedef int (*shrink_icache_memory_t)(struct shrinker *, int, gfp_t);
+extern shrink_icache_memory_t shrink_icache_memory_fn;
+#  define shrink_icache_memory(nr, gfp)        shrink_icache_memory_fn(NULL, nr, gfp)
+# else
+typedef int (*shrink_icache_memory_t)(int, gfp_t);
+extern shrink_icache_memory_t shrink_icache_memory_fn;
+#  define shrink_icache_memory(nr, gfp)        shrink_icache_memory_fn(nr, gfp)
+# endif /* HAVE_3ARGS_SHRINKER_CALLBACK */
+#endif /* HAVE_SHRINK_ICACHE_MEMORY */
+
+#ifdef HAVE_SET_SHRINKER
+typedef struct spl_shrinker {
+       struct shrinker *shrinker;
+       shrinker_t fn;
+       int seeks;
+} spl_shrinker_t;
+
+static inline void
+spl_register_shrinker(spl_shrinker_t *ss)
+{
+       ss->shrinker = set_shrinker(ss->seeks, ss->fn);
+}
+
+static inline void
+spl_unregister_shrinker(spl_shrinker_t *ss)
+{
+       remove_shrinker(ss->shrinker);
+}
+
+# define SPL_SHRINKER_DECLARE(s, x, y) \
+       static spl_shrinker_t s = { .shrinker = NULL, .fn = x, .seeks = y }
+# define SPL_SHRINKER_CALLBACK_PROTO(fn, x, y, z) \
+       static int fn(int y, unsigned int z)
+# define spl_exec_shrinker(ss, nr, gfp) \
+       ((spl_shrinker_t *)ss)->fn(nr, gfp)
+
+#else /* HAVE_SET_SHRINKER */
+
+# define spl_register_shrinker(x)      register_shrinker(x)
+# define spl_unregister_shrinker(x)    unregister_shrinker(x)
+# define SPL_SHRINKER_DECLARE(s, x, y) \
+       static struct shrinker s = { .shrink = x, .seeks = y }
+
+# ifdef HAVE_3ARGS_SHRINKER_CALLBACK
+#  define SPL_SHRINKER_CALLBACK_PROTO(fn, x, y, z) \
+       static int fn(struct shrinker *x, int y, unsigned int z)
+#  define spl_exec_shrinker(ss, nr, gfp) \
+       ((struct shrinker *)ss)->shrink(NULL, nr, gfp)
+# else /* HAVE_3ARGS_SHRINKER_CALLBACK */
+#  define SPL_SHRINKER_CALLBACK_PROTO(fn, x, y, z) \
+       static int fn(int y, unsigned int z)
+#  define spl_exec_shrinker(ss, nr, gfp) \
+       ((struct shrinker *)ss)->shrink(nr, gfp)
+# endif /* HAVE_3ARGS_SHRINKER_CALLBACK */
+#endif /* HAVE_SET_SHRINKER */
+
 #endif /* SPL_MM_COMPAT_H */
index 693e3d294211fdc0cc51d7f9f75fac0003ff1876..b63c94fef8ab02197ebb9303d25be7fd09b56f0c 100644 (file)
 #ifndef _SPL_DNLC_H
 #define _SPL_DNLC_H
 
-#define dnlc_reduce_cache(percent)     ((void)0)
+/*
+ * Reduce the dcache and icache then reap the free'd slabs.  Note the
+ * interface takes a reclaim percentage but we don't have easy access to
+ * the total number of entries to calculate the reclaim count.  However,
+ * in practice this doesn't need to be even close to correct.  We simply
+ * need to reclaim some useful fraction of the cache.  The caller can
+ * determine if more needs to be done.
+ */
+static inline void
+dnlc_reduce_cache(void *reduce_percent)
+{
+       int nr = (uintptr_t)reduce_percent * 10000;
+
+       shrink_dcache_memory(nr, GFP_KERNEL);
+       shrink_icache_memory(nr, GFP_KERNEL);
+       kmem_reap();
+}
 
 #endif /* SPL_DNLC_H */
index 6b6b95c12e3192439af144aa549b3d8ef8933ca2..72f70c2820ad9fec2c3276ed934ec5f93e16028f 100644 (file)
@@ -293,6 +293,9 @@ enum {
        KMC_BIT_OFFSLAB         = 7,    /* Objects not on slab */
        KMC_BIT_REAPING         = 16,   /* Reaping in progress */
        KMC_BIT_DESTROY         = 17,   /* Destroy in progress */
+       KMC_BIT_TOTAL           = 18,   /* Proc handler helper bit */
+       KMC_BIT_ALLOC           = 19,   /* Proc handler helper bit */
+       KMC_BIT_MAX             = 20,   /* Proc handler helper bit */
 };
 
 /* kmem move callback return values */
@@ -314,6 +317,9 @@ typedef enum kmem_cbrc {
 #define KMC_OFFSLAB            (1 << KMC_BIT_OFFSLAB)
 #define KMC_REAPING            (1 << KMC_BIT_REAPING)
 #define KMC_DESTROY            (1 << KMC_BIT_DESTROY)
+#define KMC_TOTAL              (1 << KMC_BIT_TOTAL)
+#define KMC_ALLOC              (1 << KMC_BIT_ALLOC)
+#define KMC_MAX                        (1 << KMC_BIT_MAX)
 
 #define KMC_REAP_CHUNK                 INT_MAX
 #define KMC_DEFAULT_SEEKS              1
@@ -328,7 +334,7 @@ extern struct rw_semaphore spl_kmem_cache_sem;
 
 #define SPL_KMEM_CACHE_DELAY           15      /* Minimum slab release age */
 #define SPL_KMEM_CACHE_REAP            0       /* Default reap everything */
-#define SPL_KMEM_CACHE_OBJ_PER_SLAB    32      /* Target objects per slab */
+#define SPL_KMEM_CACHE_OBJ_PER_SLAB    16      /* Target objects per slab */
 #define SPL_KMEM_CACHE_OBJ_PER_SLAB_MIN        8       /* Minimum objects per slab */
 #define SPL_KMEM_CACHE_ALIGN           8       /* Default object alignment */
 
index 09c22585a0f7f2a3eea517d98237441a44cf5faf..7d655e5ef79a2826b91d5af8a6af737d844a790c 100644 (file)
@@ -140,6 +140,7 @@ typedef struct vattr {
        uint64_t        va_nblocks;     /* space used */
        uint32_t        va_blksize;     /* block size */
        uint32_t        va_seq;         /* sequence */
+       struct dentry   *va_dentry;     /* dentry to wire */
 } vattr_t;
 
 typedef struct vnode {
index 2f533bdf619b6f4f815d3e606aeb6084fb03a118..d96456cbc767f8e4f2480228425f0a5fd84c9864 100644 (file)
@@ -185,6 +185,16 @@ invalidate_inodes_t invalidate_inodes_fn = SYMBOL_POISON;
 EXPORT_SYMBOL(invalidate_inodes_fn);
 #endif /* HAVE_INVALIDATE_INODES */
 
+#ifndef HAVE_SHRINK_DCACHE_MEMORY
+shrink_dcache_memory_t shrink_dcache_memory_fn = SYMBOL_POISON;
+EXPORT_SYMBOL(shrink_dcache_memory_fn);
+#endif /* HAVE_SHRINK_DCACHE_MEMORY */
+
+#ifndef HAVE_SHRINK_ICACHE_MEMORY
+shrink_icache_memory_t shrink_icache_memory_fn = SYMBOL_POISON;
+EXPORT_SYMBOL(shrink_icache_memory_fn);
+#endif /* HAVE_SHRINK_ICACHE_MEMORY */
+
 pgcnt_t
 spl_kmem_availrmem(void)
 {
@@ -819,21 +829,10 @@ struct rw_semaphore spl_kmem_cache_sem; /* Cache list lock */
 static int spl_cache_flush(spl_kmem_cache_t *skc,
                            spl_kmem_magazine_t *skm, int flush);
 
-#ifdef HAVE_SET_SHRINKER
-static struct shrinker *spl_kmem_cache_shrinker;
-#else
-# ifdef HAVE_3ARGS_SHRINKER_CALLBACK
-static int spl_kmem_cache_generic_shrinker(struct shrinker *shrinker_cb,
-    int nr_to_scan, unsigned int gfp_mask);
-# else
-static int spl_kmem_cache_generic_shrinker(
-    int nr_to_scan, unsigned int gfp_mask);
-# endif /* HAVE_3ARGS_SHRINKER_CALLBACK */
-static struct shrinker spl_kmem_cache_shrinker = {
-       .shrink = spl_kmem_cache_generic_shrinker,
-       .seeks = KMC_DEFAULT_SEEKS,
-};
-#endif /* HAVE_SET_SHRINKER */
+SPL_SHRINKER_CALLBACK_PROTO(spl_kmem_cache_generic_shrinker,
+       shrinker_cb, nr_to_scan, gfp_mask);
+SPL_SHRINKER_DECLARE(spl_kmem_cache_shrinker,
+       spl_kmem_cache_generic_shrinker, KMC_DEFAULT_SEEKS);
 
 static void *
 kv_alloc(spl_kmem_cache_t *skc, int size, int flags)
@@ -1859,14 +1858,8 @@ EXPORT_SYMBOL(spl_kmem_cache_free);
  * objects should be freed, because Solaris semantics are to free
  * all available objects we may free more objects than requested.
  */
-#ifdef HAVE_3ARGS_SHRINKER_CALLBACK
-static int
-spl_kmem_cache_generic_shrinker(struct shrinker *shrinker_cb,
-                               int nr_to_scan, unsigned int gfp_mask)
-#else
-static int
-spl_kmem_cache_generic_shrinker(int nr_to_scan, unsigned int gfp_mask)
-#endif /* HAVE_3ARGS_SHRINKER_CALLBACK */
+SPL_SHRINKER_CALLBACK_PROTO(spl_kmem_cache_generic_shrinker,
+    shrinker_cb, nr_to_scan, gfp_mask)
 {
        spl_kmem_cache_t *skc;
        int unused = 0;
@@ -1930,11 +1923,7 @@ EXPORT_SYMBOL(spl_kmem_cache_reap_now);
 void
 spl_kmem_reap(void)
 {
-#ifdef HAVE_3ARGS_SHRINKER_CALLBACK
-       spl_kmem_cache_generic_shrinker(NULL, KMC_REAP_CHUNK, GFP_KERNEL);
-#else
-       spl_kmem_cache_generic_shrinker(KMC_REAP_CHUNK, GFP_KERNEL);
-#endif /* HAVE_3ARGS_SHRINKER_CALLBACK */
+       spl_exec_shrinker(&spl_kmem_cache_shrinker, KMC_REAP_CHUNK, GFP_KERNEL);
 }
 EXPORT_SYMBOL(spl_kmem_reap);
 
@@ -2123,6 +2112,24 @@ spl_kmem_init_kallsyms_lookup(void)
        }
 #endif /* HAVE_INVALIDATE_INODES */
 
+#ifndef HAVE_SHRINK_DCACHE_MEMORY
+       shrink_dcache_memory_fn = (shrink_dcache_memory_t)
+       spl_kallsyms_lookup_name("shrink_dcache_memory");
+       if (!shrink_dcache_memory_fn) {
+               printk(KERN_ERR "Error: Unknown symbol shrink_dcache_memory\n");
+               return -EFAULT;
+       }
+#endif /* HAVE_SHRINK_DCACHE_MEMORY */
+
+#ifndef HAVE_SHRINK_ICACHE_MEMORY
+       shrink_icache_memory_fn = (shrink_icache_memory_t)
+       spl_kallsyms_lookup_name("shrink_icache_memory");
+       if (!shrink_icache_memory_fn) {
+               printk(KERN_ERR "Error: Unknown symbol shrink_icache_memory\n");
+               return -EFAULT;
+       }
+#endif /* HAVE_SHRINK_ICACHE_MEMORY */
+
        return 0;
 }
 
@@ -2135,14 +2142,7 @@ spl_kmem_init(void)
        init_rwsem(&spl_kmem_cache_sem);
        INIT_LIST_HEAD(&spl_kmem_cache_list);
 
-#ifdef HAVE_SET_SHRINKER
-       spl_kmem_cache_shrinker = set_shrinker(KMC_DEFAULT_SEEKS,
-                                              spl_kmem_cache_generic_shrinker);
-       if (spl_kmem_cache_shrinker == NULL)
-               SRETURN(rc = -ENOMEM);
-#else
-       register_shrinker(&spl_kmem_cache_shrinker);
-#endif
+       spl_register_shrinker(&spl_kmem_cache_shrinker);
 
 #ifdef DEBUG_KMEM
        kmem_alloc_used_set(0);
@@ -2178,11 +2178,7 @@ spl_kmem_fini(void)
 #endif /* DEBUG_KMEM */
        SENTRY;
 
-#ifdef HAVE_SET_SHRINKER
-       remove_shrinker(spl_kmem_cache_shrinker);
-#else
-       unregister_shrinker(&spl_kmem_cache_shrinker);
-#endif
+       spl_unregister_shrinker(&spl_kmem_cache_shrinker);
 
        SEXIT;
 }
index 789d8e1291a1ed62a819e5ab9205db90cb94bc44..d2b295ce0aff46a4f37b110a4da5eb3ffdb49e76 100644 (file)
@@ -100,7 +100,12 @@ struct proc_dir_entry *proc_spl_kstat = NULL;
 #define CTL_KMEM_KMEMMAX       CTL_UNNUMBERED /* Max alloc'd by kmem bytes */
 #define CTL_KMEM_VMEMUSED      CTL_UNNUMBERED /* Alloc'd vmem bytes */
 #define CTL_KMEM_VMEMMAX       CTL_UNNUMBERED /* Max alloc'd by vmem bytes */
-#define CTL_KMEM_ALLOC_FAILED  CTL_UNNUMBERED /* Cache allocations failed */
+#define CTL_KMEM_SLAB_KMEMTOTAL        CTL_UNNUMBERED /* Total kmem slab size */
+#define CTL_KMEM_SLAB_KMEMALLOC        CTL_UNNUMBERED /* Alloc'd kmem slab size */
+#define CTL_KMEM_SLAB_KMEMMAX  CTL_UNNUMBERED /* Max kmem slab size */
+#define CTL_KMEM_SLAB_VMEMTOTAL        CTL_UNNUMBERED /* Total vmem slab size */
+#define CTL_KMEM_SLAB_VMEMALLOC        CTL_UNNUMBERED /* Alloc'd vmem slab size */
+#define CTL_KMEM_SLAB_VMEMMAX  CTL_UNNUMBERED /* Max vmem slab size */
 #endif
 
 #else /* HAVE_CTL_UNNUMBERED */
@@ -152,6 +157,12 @@ enum {
        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_SLAB_KMEMTOTAL,        /* Total kmem slab size */
+       CTL_KMEM_SLAB_KMEMALLOC,        /* Alloc'd kmem slab size */
+       CTL_KMEM_SLAB_KMEMMAX,          /* Max kmem slab size */
+       CTL_KMEM_SLAB_VMEMTOTAL,        /* Total vmem slab size */
+       CTL_KMEM_SLAB_VMEMALLOC,        /* Alloc'd vmem slab size */
+       CTL_KMEM_SLAB_VMEMMAX,          /* Max vmem slab size */
 #endif
 };
 #endif /* HAVE_CTL_UNNUMBERED */
@@ -424,6 +435,53 @@ SPL_PROC_HANDLER(proc_domemused)
 
         SRETURN(rc);
 }
+
+SPL_PROC_HANDLER(proc_doslab)
+{
+        int rc = 0;
+        unsigned long min = 0, max = ~0, val = 0, mask;
+        struct ctl_table dummy = *table;
+        spl_kmem_cache_t *skc;
+        SENTRY;
+
+        dummy.data = &val;
+        dummy.proc_handler = &proc_dointvec;
+        dummy.extra1 = &min;
+        dummy.extra2 = &max;
+
+        if (write) {
+                *ppos += *lenp;
+        } else {
+                down_read(&spl_kmem_cache_sem);
+                mask = (unsigned long)table->data;
+
+                list_for_each_entry(skc, &spl_kmem_cache_list, skc_list) {
+
+                       /* Only use slabs of the correct kmem/vmem type */
+                       if (!(skc->skc_flags & mask))
+                               continue;
+
+                       /* Sum the specified field for selected slabs */
+                       switch (mask & (KMC_TOTAL | KMC_ALLOC | KMC_MAX)) {
+                       case KMC_TOTAL:
+                               val += skc->skc_slab_size * skc->skc_slab_total;
+                               break;
+                       case KMC_ALLOC:
+                               val += skc->skc_obj_size * skc->skc_obj_alloc;
+                               break;
+                       case KMC_MAX:
+                               val += skc->skc_obj_size * skc->skc_obj_max;
+                               break;
+                       }
+                }
+
+                up_read(&spl_kmem_cache_sem);
+                rc = spl_proc_doulongvec_minmax(&dummy, write, filp,
+                                                buffer, lenp, ppos);
+        }
+
+        SRETURN(rc);
+}
 #endif /* DEBUG_KMEM */
 
 SPL_PROC_HANDLER(proc_dohostid)
@@ -562,12 +620,16 @@ SPL_PROC_HANDLER(proc_dofreemem)
 static void
 slab_seq_show_headers(struct seq_file *f)
 {
-        seq_printf(f, "%-36s      %-6s - %s %s %s - %s %s %s - "
-                   "%s %s %s - %s %s %s\n", "name", "flags",
-                   "obj_size", "slab_objs", "slab_size",
-                   "slab_fail", "slab_create", "slab_destroy",
-                   "slab_total", "slab_alloc", "slab_max",
-                   "obj_total", "obj_alloc", "obj_max");
+        seq_printf(f,
+            "--------------------- cache ----------"
+            "---------------------------------------------  "
+            "----- slab ------  "
+            "---- object -----\n");
+        seq_printf(f,
+            "name                                  "
+            "  flags      size     alloc slabsize  objsize  "
+            "total alloc   max  "
+            "total alloc   max\n");
 }
 
 static int
@@ -578,22 +640,20 @@ slab_seq_show(struct seq_file *f, void *p)
         ASSERT(skc->skc_magic == SKC_MAGIC);
 
         spin_lock(&skc->skc_lock);
-        seq_printf(f, "%-36s      ", skc->skc_name);
-        seq_printf(f, "0x%04lx - %u %u %u - %lu %lu %lu - "
-                   "%lu %lu %lu - %lu %lu %lu\n",
-                   (long unsigned)skc->skc_flags,
-                   (unsigned)skc->skc_obj_size,
-                   (unsigned)skc->skc_slab_objs,
-                   (unsigned)skc->skc_slab_size,
-                   (long unsigned)skc->skc_slab_fail,
-                   (long unsigned)skc->skc_slab_create,
-                   (long unsigned)skc->skc_slab_destroy,
-                   (long unsigned)skc->skc_slab_total,
-                   (long unsigned)skc->skc_slab_alloc,
-                   (long unsigned)skc->skc_slab_max,
-                   (long unsigned)skc->skc_obj_total,
-                   (long unsigned)skc->skc_obj_alloc,
-                   (long unsigned)skc->skc_obj_max);
+        seq_printf(f, "%-36s  ", skc->skc_name);
+        seq_printf(f, "0x%05lx %9lu %9lu %8u %8u  "
+            "%5lu %5lu %5lu  %5lu %5lu %5lu\n",
+            (long unsigned)skc->skc_flags,
+            (long unsigned)(skc->skc_slab_size * skc->skc_slab_total),
+            (long unsigned)(skc->skc_obj_size * skc->skc_obj_alloc),
+            (unsigned)skc->skc_slab_size,
+            (unsigned)skc->skc_obj_size,
+            (long unsigned)skc->skc_slab_total,
+            (long unsigned)skc->skc_slab_alloc,
+            (long unsigned)skc->skc_slab_max,
+            (long unsigned)skc->skc_obj_total,
+            (long unsigned)skc->skc_obj_alloc,
+            (long unsigned)skc->skc_obj_max);
 
         spin_unlock(&skc->skc_lock);
 
@@ -893,6 +953,66 @@ static struct ctl_table spl_kmem_table[] = {
                 .mode     = 0444,
                 .proc_handler = &proc_doulongvec_minmax,
         },
+        {
+                CTL_NAME    (CTL_KMEM_SLAB_KMEMTOTAL)
+                .procname = "slab_kmem_total",
+               .data     = (void *)(KMC_KMEM | KMC_TOTAL),
+                .maxlen   = sizeof(unsigned long),
+                .extra1   = &table_min,
+                .extra2   = &table_max,
+                .mode     = 0444,
+                .proc_handler = &proc_doslab,
+        },
+        {
+                CTL_NAME    (CTL_KMEM_SLAB_KMEMALLOC)
+                .procname = "slab_kmem_alloc",
+               .data     = (void *)(KMC_KMEM | KMC_ALLOC),
+                .maxlen   = sizeof(unsigned long),
+                .extra1   = &table_min,
+                .extra2   = &table_max,
+                .mode     = 0444,
+                .proc_handler = &proc_doslab,
+        },
+        {
+                CTL_NAME    (CTL_KMEM_SLAB_KMEMMAX)
+                .procname = "slab_kmem_max",
+               .data     = (void *)(KMC_KMEM | KMC_MAX),
+                .maxlen   = sizeof(unsigned long),
+                .extra1   = &table_min,
+                .extra2   = &table_max,
+                .mode     = 0444,
+                .proc_handler = &proc_doslab,
+        },
+        {
+                CTL_NAME    (CTL_KMEM_SLAB_VMEMTOTAL)
+                .procname = "slab_vmem_total",
+               .data     = (void *)(KMC_VMEM | KMC_TOTAL),
+                .maxlen   = sizeof(unsigned long),
+                .extra1   = &table_min,
+                .extra2   = &table_max,
+                .mode     = 0444,
+                .proc_handler = &proc_doslab,
+        },
+        {
+                CTL_NAME    (CTL_KMEM_SLAB_VMEMALLOC)
+                .procname = "slab_vmem_alloc",
+               .data     = (void *)(KMC_VMEM | KMC_ALLOC),
+                .maxlen   = sizeof(unsigned long),
+                .extra1   = &table_min,
+                .extra2   = &table_max,
+                .mode     = 0444,
+                .proc_handler = &proc_doslab,
+        },
+        {
+                CTL_NAME    (CTL_KMEM_SLAB_VMEMMAX)
+                .procname = "slab_vmem_max",
+               .data     = (void *)(KMC_VMEM | KMC_MAX),
+                .maxlen   = sizeof(unsigned long),
+                .extra1   = &table_min,
+                .extra2   = &table_max,
+                .mode     = 0444,
+                .proc_handler = &proc_doslab,
+        },
        {0},
 };
 #endif /* DEBUG_KMEM */
index a587841191f8e7feca79519ede9fcc7ccb750a0b..284b9b1e964d8404c86d22b1cff025863f4d8cd4 100644 (file)
 /* set_shrinker() available */
 #undef HAVE_SET_SHRINKER
 
+/* shrink_dcache_memory() is available */
+#undef HAVE_SHRINK_DCACHE_MEMORY
+
+/* shrink_icache_memory() is available */
+#undef HAVE_SHRINK_ICACHE_MEMORY
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H