]> granicus.if.org Git - zfs/commitdiff
Fix 2.6.35 shrinker callback API change
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 22 Oct 2010 21:16:43 +0000 (14:16 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 22 Oct 2010 21:51:26 +0000 (14:51 -0700)
As of linux-2.6.35 the shrinker callback API now takes an additional
argument.  The shrinker struct is passed to the callback so that users
can embed the shrinker structure in private data and use container_of()
to access it.  This removes the need to always use global state for the
shrinker.

To handle this we add the SPL_AC_3ARGS_SHRINKER_CALLBACK autoconf
check to properly detect the API.  Then we simply setup a callback
function with the correct number of arguments.  For now we do not make
use of the new 3rd argument.

config/spl-build.m4
configure
module/spl/spl-kmem.c
spl_config.h.in

index dffa0365563f14df5706d6a267ac1939f7ae1cee..ec7bda7765c17d1f0f0f6e2a91bcee223c6c0ff8 100644 (file)
@@ -27,6 +27,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_3ARGS_INIT_WORK
        SPL_AC_2ARGS_REGISTER_SYSCTL
        SPL_AC_SET_SHRINKER
+       SPL_AC_3ARGS_SHRINKER_CALLBACK
        SPL_AC_PATH_IN_NAMEIDATA
        SPL_AC_TASK_CURR
        SPL_AC_CTL_UNNUMBERED
@@ -761,6 +762,34 @@ AC_DEFUN([SPL_AC_SET_SHRINKER], [
        ])
 ])
 
+dnl #
+dnl # 2.6.35 API change,
+dnl # Add context to shrinker callback
+dnl #
+AC_DEFUN([SPL_AC_3ARGS_SHRINKER_CALLBACK],
+       [AC_MSG_CHECKING([whether shrinker callback wants 3 args])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/mm.h>
+
+               int shrinker_cb(struct shrinker *, int, unsigned int);
+       ],[
+               struct shrinker cache_shrinker = {
+                       .shrink = shrinker_cb,
+                       .seeks = DEFAULT_SEEKS,
+               };
+               register_shrinker(&cache_shrinker);
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_3ARGS_SHRINKER_CALLBACK, 1,
+                         [shrinker callback wants 3 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
+
 dnl #
 dnl # 2.6.25 API change,
 dnl # struct path entry added to struct nameidata
index 5784ec75c0fa63b2cd84f4905ff8e752eee26ae2..1a3b376886e70f4c577e6cf5b3f591e96f5d51fb 100755 (executable)
--- a/configure
+++ b/configure
 
 
 
+       { $as_echo "$as_me:$LINENO: checking whether shrinker callback wants 3 args" >&5
+$as_echo_n "checking whether shrinker callback wants 3 args... " >&6; }
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+               #include <linux/mm.h>
+
+               int shrinker_cb(struct shrinker *, int, unsigned int);
+
+int
+main (void)
+{
+
+               struct shrinker cache_shrinker = {
+                       .shrink = shrinker_cb,
+                       .seeks = DEFAULT_SEEKS,
+               };
+               register_shrinker(&cache_shrinker);
+
+  ;
+  return 0;
+}
+
+_ACEOF
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_3ARGS_SHRINKER_CALLBACK 1
+_ACEOF
+
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+       rm -Rf build
+
+
+       EXTRA_KCFLAGS="$tmp_flags"
+
        { $as_echo "$as_me:$LINENO: checking whether struct path used in struct nameidata" >&5
 $as_echo_n "checking whether struct path used in struct nameidata... " >&6; }
 
 
 
 
+       { $as_echo "$as_me:$LINENO: checking whether shrinker callback wants 3 args" >&5
+$as_echo_n "checking whether shrinker callback wants 3 args... " >&6; }
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+               #include <linux/mm.h>
+
+               int shrinker_cb(struct shrinker *, int, unsigned int);
+
+int
+main (void)
+{
+
+               struct shrinker cache_shrinker = {
+                       .shrink = shrinker_cb,
+                       .seeks = DEFAULT_SEEKS,
+               };
+               register_shrinker(&cache_shrinker);
+
+  ;
+  return 0;
+}
+
+_ACEOF
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_3ARGS_SHRINKER_CALLBACK 1
+_ACEOF
+
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+       rm -Rf build
+
+
+       EXTRA_KCFLAGS="$tmp_flags"
+
        { $as_echo "$as_me:$LINENO: checking whether struct path used in struct nameidata" >&5
 $as_echo_n "checking whether struct path used in struct nameidata... " >&6; }
 
index aefa00fa6c0758c7c682e597993abd7cee160630..1a9c1fe96f720014eb516f450337d6abc93bf84b 100644 (file)
@@ -817,13 +817,18 @@ static int spl_cache_flush(spl_kmem_cache_t *skc,
 #ifdef HAVE_SET_SHRINKER
 static struct shrinker *spl_kmem_cache_shrinker;
 #else
-static int spl_kmem_cache_generic_shrinker(int nr_to_scan,
-                                           unsigned int gfp_mask);
+# 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
+#endif /* HAVE_SET_SHRINKER */
 
 static void *
 kv_alloc(spl_kmem_cache_t *skc, int size, int flags)
@@ -1829,8 +1834,14 @@ 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_kmem_cache_t *skc;
        int unused = 0;
@@ -1894,7 +1905,11 @@ 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 */
 }
 EXPORT_SYMBOL(spl_kmem_reap);
 
index d3928f4ba9cc649b260d8df24aa5dbc11de3365f..2a08694c907a17a88abf42311c29864828947fbb 100644 (file)
@@ -27,6 +27,9 @@
 /* on_each_cpu wants 3 args */
 #undef HAVE_3ARGS_ON_EACH_CPU
 
+/* shrinker callback wants 3 args */
+#undef HAVE_3ARGS_SHRINKER_CALLBACK
+
 /* vfs_rename() wants 4 args */
 #undef HAVE_4ARGS_VFS_RENAME