]> git.proxmox.com Git - mirror_spl.git/commitdiff
Add dnlc_reduce_cache() support
authorBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 31 Mar 2011 00:44:35 +0000 (17:44 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 7 Apr 2011 03:06:03 +0000 (20:06 -0700)
Provide the dnlc_reduce_cache() function which attempts to prune
cached entries from the dcache and icache.  After the entries are
pruned any slabs which they may have been using are reaped.

Note the API takes a reclaim percentage but we don't have easy
access to the total number of cache entries to calculate the
reclaim count.  However, in practice this doesn't need to be
exactly correct.  We simply need to reclaim some useful fraction
(but not all) of the cache.  The caller can determine if more
needs to be done.

config/spl-build.m4
configure
include/linux/mm_compat.h
include/sys/dnlc.h
module/spl/spl-kmem.c
spl_config.h.in

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 7e2f6b8a5805306bf7b3929eb5fed8a72b754c85..522db827f805e0fbd9353a621c149c887945625f 100644 (file)
@@ -56,6 +56,42 @@ 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;
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 87594bde933980c3005c032aa041a178275dbff4..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)
 {
@@ -2102,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;
 }
 
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