mirror of https://github.com/archzfs/archzfs
parent
f4f78cc145
commit
ccd4e76940
@ -1,429 +0,0 @@ |
|||||||
commit c3d9c0df3ee8d43db22815ebbfbe8b803fa46e46
|
|
||||||
Author: Richard Yao <ryao@gentoo.org>
|
|
||||||
Date: Tue Nov 5 11:35:54 2013 -0500
|
|
||||||
|
|
||||||
Linux 3.12 compat: New shrinker API
|
|
||||||
|
|
||||||
torvalds/linux@24f7c6 introduced a new shrinker API while
|
|
||||||
torvalds/linux@a0b021 dropped support for the old shrinker API.
|
|
||||||
This patch adds support for the new shrinker API by wrapping
|
|
||||||
the old one with the new one.
|
|
||||||
|
|
||||||
This change also reorganizes the autotools checks on the shrinker
|
|
||||||
API such that the configure script will fail early if an unknown
|
|
||||||
API is encountered in the future.
|
|
||||||
|
|
||||||
Support for the set_shrinker() API which was used by Linux 2.6.22
|
|
||||||
and older has been dropped. As a general rule compatibility is
|
|
||||||
only maintained back to Linux 2.6.26.
|
|
||||||
|
|
||||||
Signed-off-by: Richard Yao <ryao@gentoo.org>
|
|
||||||
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
|
|
||||||
Closes zfsonlinux/zfs#1732
|
|
||||||
Closes zfsonlinux/zfs#1822
|
|
||||||
Closes #293
|
|
||||||
Closes #307
|
|
||||||
|
|
||||||
diff --git a/config/spl-build.m4 b/config/spl-build.m4
|
|
||||||
index b0e3348..7d744db 100644
|
|
||||||
--- a/config/spl-build.m4
|
|
||||||
+++ b/config/spl-build.m4
|
|
||||||
@@ -27,8 +27,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
|
|
||||||
SPL_AC_TYPE_ATOMIC64_XCHG
|
|
||||||
SPL_AC_TYPE_UINTPTR_T
|
|
||||||
SPL_AC_2ARGS_REGISTER_SYSCTL
|
|
||||||
- SPL_AC_SET_SHRINKER
|
|
||||||
- SPL_AC_3ARGS_SHRINKER_CALLBACK
|
|
||||||
+ SPL_AC_SHRINKER_CALLBACK
|
|
||||||
SPL_AC_PATH_IN_NAMEIDATA
|
|
||||||
SPL_AC_TASK_CURR
|
|
||||||
SPL_AC_CTL_UNNUMBERED
|
|
||||||
@@ -885,37 +884,18 @@ AC_DEFUN([SPL_AC_2ARGS_REGISTER_SYSCTL],
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
-dnl #
|
|
||||||
-dnl # 2.6.23 API change
|
|
||||||
-dnl # Old set_shrinker API replaced with register_shrinker
|
|
||||||
-dnl #
|
|
||||||
-AC_DEFUN([SPL_AC_SET_SHRINKER], [
|
|
||||||
- AC_MSG_CHECKING([whether set_shrinker() available])
|
|
||||||
- SPL_LINUX_TRY_COMPILE([
|
|
||||||
- #include <linux/mm.h>
|
|
||||||
- ],[
|
|
||||||
- return set_shrinker(DEFAULT_SEEKS, NULL);
|
|
||||||
- ],[
|
|
||||||
- AC_MSG_RESULT([yes])
|
|
||||||
- AC_DEFINE(HAVE_SET_SHRINKER, 1,
|
|
||||||
- [set_shrinker() available])
|
|
||||||
- ],[
|
|
||||||
- AC_MSG_RESULT([no])
|
|
||||||
- ])
|
|
||||||
-])
|
|
||||||
-
|
|
||||||
-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])
|
|
||||||
+AC_DEFUN([SPL_AC_SHRINKER_CALLBACK],[
|
|
||||||
tmp_flags="$EXTRA_KCFLAGS"
|
|
||||||
EXTRA_KCFLAGS="-Werror"
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 2.6.23 to 2.6.34 API change
|
|
||||||
+ dnl # ->shrink(int nr_to_scan, gfp_t gfp_mask)
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING([whether old 2-argument shrinker exists])
|
|
||||||
SPL_LINUX_TRY_COMPILE([
|
|
||||||
#include <linux/mm.h>
|
|
||||||
|
|
||||||
- int shrinker_cb(struct shrinker *, int, unsigned int);
|
|
||||||
+ int shrinker_cb(int nr_to_scan, gfp_t gfp_mask);
|
|
||||||
],[
|
|
||||||
struct shrinker cache_shrinker = {
|
|
||||||
.shrink = shrinker_cb,
|
|
||||||
@@ -924,10 +904,86 @@ AC_DEFUN([SPL_AC_3ARGS_SHRINKER_CALLBACK],
|
|
||||||
register_shrinker(&cache_shrinker);
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
- AC_DEFINE(HAVE_3ARGS_SHRINKER_CALLBACK, 1,
|
|
||||||
- [shrinker callback wants 3 args])
|
|
||||||
+ AC_DEFINE(HAVE_2ARGS_OLD_SHRINKER_CALLBACK, 1,
|
|
||||||
+ [old shrinker callback wants 2 args])
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 2.6.35 - 2.6.39 API change
|
|
||||||
+ dnl # ->shrink(struct shrinker *,
|
|
||||||
+ dnl # int nr_to_scan, gfp_t gfp_mask)
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING([whether old 3-argument shrinker exists])
|
|
||||||
+ SPL_LINUX_TRY_COMPILE([
|
|
||||||
+ #include <linux/mm.h>
|
|
||||||
+
|
|
||||||
+ int shrinker_cb(struct shrinker *, int nr_to_scan,
|
|
||||||
+ gfp_t gfp_mask);
|
|
||||||
+ ],[
|
|
||||||
+ 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,
|
|
||||||
+ [old shrinker callback wants 3 args])
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(no)
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 3.0 - 3.11 API change
|
|
||||||
+ dnl # ->shrink(struct shrinker *,
|
|
||||||
+ dnl # struct shrink_control *sc)
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING(
|
|
||||||
+ [whether new 2-argument shrinker exists])
|
|
||||||
+ SPL_LINUX_TRY_COMPILE([
|
|
||||||
+ #include <linux/mm.h>
|
|
||||||
+
|
|
||||||
+ int shrinker_cb(struct shrinker *,
|
|
||||||
+ struct shrink_control *sc);
|
|
||||||
+ ],[
|
|
||||||
+ struct shrinker cache_shrinker = {
|
|
||||||
+ .shrink = shrinker_cb,
|
|
||||||
+ .seeks = DEFAULT_SEEKS,
|
|
||||||
+ };
|
|
||||||
+ register_shrinker(&cache_shrinker);
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(yes)
|
|
||||||
+ AC_DEFINE(HAVE_2ARGS_NEW_SHRINKER_CALLBACK, 1,
|
|
||||||
+ [new shrinker callback wants 2 args])
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(no)
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 3.12 API change,
|
|
||||||
+ dnl # ->shrink() is logically split in to
|
|
||||||
+ dnl # ->count_objects() and ->scan_objects()
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING(
|
|
||||||
+ [whether ->count_objects callback exists])
|
|
||||||
+ SPL_LINUX_TRY_COMPILE([
|
|
||||||
+ #include <linux/mm.h>
|
|
||||||
+
|
|
||||||
+ unsigned long shrinker_cb(
|
|
||||||
+ struct shrinker *,
|
|
||||||
+ struct shrink_control *sc);
|
|
||||||
+ ],[
|
|
||||||
+ struct shrinker cache_shrinker = {
|
|
||||||
+ .count_objects = shrinker_cb,
|
|
||||||
+ .scan_objects = shrinker_cb,
|
|
||||||
+ .seeks = DEFAULT_SEEKS,
|
|
||||||
+ };
|
|
||||||
+ register_shrinker(&cache_shrinker);
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(yes)
|
|
||||||
+ AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK,
|
|
||||||
+ 1, [->count_objects exists])
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_ERROR(error)
|
|
||||||
+ ])
|
|
||||||
+ ])
|
|
||||||
+ ])
|
|
||||||
])
|
|
||||||
EXTRA_KCFLAGS="$tmp_flags"
|
|
||||||
])
|
|
||||||
diff --git a/include/linux/mm_compat.h b/include/linux/mm_compat.h
|
|
||||||
index cb1bef9..37c9b08 100644
|
|
||||||
--- a/include/linux/mm_compat.h
|
|
||||||
+++ b/include/linux/mm_compat.h
|
|
||||||
@@ -148,107 +148,167 @@ extern shrink_icache_memory_t shrink_icache_memory_fn;
|
|
||||||
#endif /* HAVE_SHRINK_ICACHE_MEMORY */
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Due to frequent changes in the shrinker API the following
|
|
||||||
+ * compatibility wrappers should be used. They are as follows:
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_DECLARE is used to declare the shrinker which is
|
|
||||||
+ * passed to spl_register_shrinker()/spl_unregister_shrinker(). Use
|
|
||||||
+ * shrinker_name to set the shrinker variable name, shrinker_callback
|
|
||||||
+ * to set the callback function, and seek_cost to define the cost of
|
|
||||||
+ * reclaiming an object.
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_DECLARE(shrinker_name, shrinker_callback, seek_cost);
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_FWD_DECLARE is used when a forward declaration
|
|
||||||
+ * of the shrinker callback function is required. Only the callback
|
|
||||||
+ * function needs to be passed.
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_FWD_DECLARE(shrinker_callback);
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_WRAPPER is used to declare the callback function
|
|
||||||
+ * which is registered with the shrinker. This function will call your
|
|
||||||
+ * custom shrinker which must use the following prototype. Notice the
|
|
||||||
+ * leading __'s, these must be appended to the callback_function name.
|
|
||||||
+ *
|
|
||||||
+ * int __shrinker_callback(struct shrinker *, struct shrink_control *)
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_WRAPPER(shrinker_callback);a
|
|
||||||
+ *
|
|
||||||
+ *
|
|
||||||
+ * Example:
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_FWD_DECLARE(my_shrinker_fn);
|
|
||||||
+ * SPL_SHRINKER_DECLARE(my_shrinker, my_shrinker_fn, 1);
|
|
||||||
+ *
|
|
||||||
+ * static int
|
|
||||||
+ * __my_shrinker_fn(struct shrinker *shrink, struct shrink_control *sc)
|
|
||||||
+ * {
|
|
||||||
+ * if (sc->nr_to_scan) {
|
|
||||||
+ * ...scan objects in the cache and reclaim them...
|
|
||||||
+ * }
|
|
||||||
+ *
|
|
||||||
+ * ...calculate number of objects in the cache...
|
|
||||||
+ *
|
|
||||||
+ * return (number of objects in the cache);
|
|
||||||
+ * }
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_WRAPPER(my_shrinker_fn);
|
|
||||||
*/
|
|
||||||
-#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_register_shrinker(x) register_shrinker(x)
|
|
||||||
+#define spl_unregister_shrinker(x) unregister_shrinker(x)
|
|
||||||
|
|
||||||
-# define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
- static spl_shrinker_t s = { \
|
|
||||||
- .shrinker = NULL, \
|
|
||||||
- .fn = x, \
|
|
||||||
- .seeks = y \
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(int, unsigned int)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
-{ \
|
|
||||||
- struct shrink_control sc; \
|
|
||||||
- \
|
|
||||||
- sc.nr_to_scan = nr_to_scan; \
|
|
||||||
- sc.gfp_mask = gfp_mask; \
|
|
||||||
- \
|
|
||||||
- return __ ## fn(NULL, &sc); \
|
|
||||||
+/*
|
|
||||||
+ * Linux 2.6.23 - 2.6.34 Shrinker API Compatibility.
|
|
||||||
+ */
|
|
||||||
+#if defined(HAVE_2ARGS_OLD_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .shrink = x, \
|
|
||||||
+ .seeks = y \
|
|
||||||
}
|
|
||||||
|
|
||||||
-#else
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static int fn(int nr_to_scan, unsigned int gfp_mask)
|
|
||||||
|
|
||||||
-# 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 \
|
|
||||||
- }
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static int \
|
|
||||||
+fn(int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
+{ \
|
|
||||||
+ struct shrink_control sc; \
|
|
||||||
+ \
|
|
||||||
+ sc.nr_to_scan = nr_to_scan; \
|
|
||||||
+ sc.gfp_mask = gfp_mask; \
|
|
||||||
+ \
|
|
||||||
+ return (__ ## fn(NULL, &sc)); \
|
|
||||||
+}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Linux 2.6.35 to 2.6.39 Shrinker API Compatibility.
|
|
||||||
*/
|
|
||||||
-# if defined(HAVE_SHRINK_CONTROL_STRUCT)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(struct shrinker *, struct shrink_control *)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(struct shrinker *shrink, struct shrink_control *sc) { \
|
|
||||||
- return __ ## fn(shrink, sc); \
|
|
||||||
+#elif defined(HAVE_3ARGS_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .shrink = x, \
|
|
||||||
+ .seeks = y \
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static int fn(struct shrinker *, int, unsigned int)
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static int \
|
|
||||||
+fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
+{ \
|
|
||||||
+ struct shrink_control sc; \
|
|
||||||
+ \
|
|
||||||
+ sc.nr_to_scan = nr_to_scan; \
|
|
||||||
+ sc.gfp_mask = gfp_mask; \
|
|
||||||
+ \
|
|
||||||
+ return (__ ## fn(shrink, &sc)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Linux 3.0 to 3.11 Shrinker API Compatibility.
|
|
||||||
*/
|
|
||||||
-# elif defined(HAVE_3ARGS_SHRINKER_CALLBACK)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(struct shrinker *, int, unsigned int)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
-{ \
|
|
||||||
- struct shrink_control sc; \
|
|
||||||
- \
|
|
||||||
- sc.nr_to_scan = nr_to_scan; \
|
|
||||||
- sc.gfp_mask = gfp_mask; \
|
|
||||||
- \
|
|
||||||
- return __ ## fn(shrink, &sc); \
|
|
||||||
+#elif defined(HAVE_2ARGS_NEW_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .shrink = x, \
|
|
||||||
+ .seeks = y \
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static int fn(struct shrinker *, struct shrink_control *)
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static int \
|
|
||||||
+fn(struct shrinker *shrink, struct shrink_control *sc) \
|
|
||||||
+{ \
|
|
||||||
+ return (__ ## fn(shrink, sc)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Linux 3.12 and later Shrinker API Compatibility.
|
|
||||||
*/
|
|
||||||
-# else
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(int, unsigned int)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
-{ \
|
|
||||||
- struct shrink_control sc; \
|
|
||||||
- \
|
|
||||||
- sc.nr_to_scan = nr_to_scan; \
|
|
||||||
- sc.gfp_mask = gfp_mask; \
|
|
||||||
- \
|
|
||||||
- return __ ## fn(NULL, &sc); \
|
|
||||||
+#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .count_objects = x ## _count_objects, \
|
|
||||||
+ .scan_objects = x ## _scan_objects, \
|
|
||||||
+ .seeks = y \
|
|
||||||
}
|
|
||||||
|
|
||||||
-# endif
|
|
||||||
-#endif /* HAVE_SET_SHRINKER */
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static unsigned long fn ## _count_objects(struct shrinker *, \
|
|
||||||
+ struct shrink_control *); \
|
|
||||||
+static unsigned long fn ## _scan_objects(struct shrinker *, \
|
|
||||||
+ struct shrink_control *)
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static unsigned long \
|
|
||||||
+fn ## _count_objects(struct shrinker *shrink, struct shrink_control *sc)\
|
|
||||||
+{ \
|
|
||||||
+ int __ret__; \
|
|
||||||
+ \
|
|
||||||
+ sc->nr_to_scan = 0; \
|
|
||||||
+ __ret__ = __ ## fn(NULL, sc); \
|
|
||||||
+ \
|
|
||||||
+ /* Errors may not be returned and must be converted to zeros */ \
|
|
||||||
+ return ((__ret__ < 0) ? 0 : __ret__); \
|
|
||||||
+} \
|
|
||||||
+ \
|
|
||||||
+static unsigned long \
|
|
||||||
+fn ## _scan_objects(struct shrinker *shrink, struct shrink_control *sc) \
|
|
||||||
+{ \
|
|
||||||
+ int __ret__; \
|
|
||||||
+ \
|
|
||||||
+ __ret__ = __ ## fn(NULL, sc); \
|
|
||||||
+ return ((__ret__ < 0) ? SHRINK_STOP : __ret__); \
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+/*
|
|
||||||
+ * Linux 2.x to 2.6.22, or a newer shrinker API has been introduced.
|
|
||||||
+ */
|
|
||||||
+#error "Unknown shrinker callback"
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#endif /* SPL_MM_COMPAT_H */
|
|
@ -1,429 +0,0 @@ |
|||||||
commit c3d9c0df3ee8d43db22815ebbfbe8b803fa46e46
|
|
||||||
Author: Richard Yao <ryao@gentoo.org>
|
|
||||||
Date: Tue Nov 5 11:35:54 2013 -0500
|
|
||||||
|
|
||||||
Linux 3.12 compat: New shrinker API
|
|
||||||
|
|
||||||
torvalds/linux@24f7c6 introduced a new shrinker API while
|
|
||||||
torvalds/linux@a0b021 dropped support for the old shrinker API.
|
|
||||||
This patch adds support for the new shrinker API by wrapping
|
|
||||||
the old one with the new one.
|
|
||||||
|
|
||||||
This change also reorganizes the autotools checks on the shrinker
|
|
||||||
API such that the configure script will fail early if an unknown
|
|
||||||
API is encountered in the future.
|
|
||||||
|
|
||||||
Support for the set_shrinker() API which was used by Linux 2.6.22
|
|
||||||
and older has been dropped. As a general rule compatibility is
|
|
||||||
only maintained back to Linux 2.6.26.
|
|
||||||
|
|
||||||
Signed-off-by: Richard Yao <ryao@gentoo.org>
|
|
||||||
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
|
|
||||||
Closes zfsonlinux/zfs#1732
|
|
||||||
Closes zfsonlinux/zfs#1822
|
|
||||||
Closes #293
|
|
||||||
Closes #307
|
|
||||||
|
|
||||||
diff --git a/config/spl-build.m4 b/config/spl-build.m4
|
|
||||||
index b0e3348..7d744db 100644
|
|
||||||
--- a/config/spl-build.m4
|
|
||||||
+++ b/config/spl-build.m4
|
|
||||||
@@ -27,8 +27,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
|
|
||||||
SPL_AC_TYPE_ATOMIC64_XCHG
|
|
||||||
SPL_AC_TYPE_UINTPTR_T
|
|
||||||
SPL_AC_2ARGS_REGISTER_SYSCTL
|
|
||||||
- SPL_AC_SET_SHRINKER
|
|
||||||
- SPL_AC_3ARGS_SHRINKER_CALLBACK
|
|
||||||
+ SPL_AC_SHRINKER_CALLBACK
|
|
||||||
SPL_AC_PATH_IN_NAMEIDATA
|
|
||||||
SPL_AC_TASK_CURR
|
|
||||||
SPL_AC_CTL_UNNUMBERED
|
|
||||||
@@ -885,37 +884,18 @@ AC_DEFUN([SPL_AC_2ARGS_REGISTER_SYSCTL],
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
-dnl #
|
|
||||||
-dnl # 2.6.23 API change
|
|
||||||
-dnl # Old set_shrinker API replaced with register_shrinker
|
|
||||||
-dnl #
|
|
||||||
-AC_DEFUN([SPL_AC_SET_SHRINKER], [
|
|
||||||
- AC_MSG_CHECKING([whether set_shrinker() available])
|
|
||||||
- SPL_LINUX_TRY_COMPILE([
|
|
||||||
- #include <linux/mm.h>
|
|
||||||
- ],[
|
|
||||||
- return set_shrinker(DEFAULT_SEEKS, NULL);
|
|
||||||
- ],[
|
|
||||||
- AC_MSG_RESULT([yes])
|
|
||||||
- AC_DEFINE(HAVE_SET_SHRINKER, 1,
|
|
||||||
- [set_shrinker() available])
|
|
||||||
- ],[
|
|
||||||
- AC_MSG_RESULT([no])
|
|
||||||
- ])
|
|
||||||
-])
|
|
||||||
-
|
|
||||||
-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])
|
|
||||||
+AC_DEFUN([SPL_AC_SHRINKER_CALLBACK],[
|
|
||||||
tmp_flags="$EXTRA_KCFLAGS"
|
|
||||||
EXTRA_KCFLAGS="-Werror"
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 2.6.23 to 2.6.34 API change
|
|
||||||
+ dnl # ->shrink(int nr_to_scan, gfp_t gfp_mask)
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING([whether old 2-argument shrinker exists])
|
|
||||||
SPL_LINUX_TRY_COMPILE([
|
|
||||||
#include <linux/mm.h>
|
|
||||||
|
|
||||||
- int shrinker_cb(struct shrinker *, int, unsigned int);
|
|
||||||
+ int shrinker_cb(int nr_to_scan, gfp_t gfp_mask);
|
|
||||||
],[
|
|
||||||
struct shrinker cache_shrinker = {
|
|
||||||
.shrink = shrinker_cb,
|
|
||||||
@@ -924,10 +904,86 @@ AC_DEFUN([SPL_AC_3ARGS_SHRINKER_CALLBACK],
|
|
||||||
register_shrinker(&cache_shrinker);
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
- AC_DEFINE(HAVE_3ARGS_SHRINKER_CALLBACK, 1,
|
|
||||||
- [shrinker callback wants 3 args])
|
|
||||||
+ AC_DEFINE(HAVE_2ARGS_OLD_SHRINKER_CALLBACK, 1,
|
|
||||||
+ [old shrinker callback wants 2 args])
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 2.6.35 - 2.6.39 API change
|
|
||||||
+ dnl # ->shrink(struct shrinker *,
|
|
||||||
+ dnl # int nr_to_scan, gfp_t gfp_mask)
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING([whether old 3-argument shrinker exists])
|
|
||||||
+ SPL_LINUX_TRY_COMPILE([
|
|
||||||
+ #include <linux/mm.h>
|
|
||||||
+
|
|
||||||
+ int shrinker_cb(struct shrinker *, int nr_to_scan,
|
|
||||||
+ gfp_t gfp_mask);
|
|
||||||
+ ],[
|
|
||||||
+ 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,
|
|
||||||
+ [old shrinker callback wants 3 args])
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(no)
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 3.0 - 3.11 API change
|
|
||||||
+ dnl # ->shrink(struct shrinker *,
|
|
||||||
+ dnl # struct shrink_control *sc)
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING(
|
|
||||||
+ [whether new 2-argument shrinker exists])
|
|
||||||
+ SPL_LINUX_TRY_COMPILE([
|
|
||||||
+ #include <linux/mm.h>
|
|
||||||
+
|
|
||||||
+ int shrinker_cb(struct shrinker *,
|
|
||||||
+ struct shrink_control *sc);
|
|
||||||
+ ],[
|
|
||||||
+ struct shrinker cache_shrinker = {
|
|
||||||
+ .shrink = shrinker_cb,
|
|
||||||
+ .seeks = DEFAULT_SEEKS,
|
|
||||||
+ };
|
|
||||||
+ register_shrinker(&cache_shrinker);
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(yes)
|
|
||||||
+ AC_DEFINE(HAVE_2ARGS_NEW_SHRINKER_CALLBACK, 1,
|
|
||||||
+ [new shrinker callback wants 2 args])
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(no)
|
|
||||||
+ dnl #
|
|
||||||
+ dnl # 3.12 API change,
|
|
||||||
+ dnl # ->shrink() is logically split in to
|
|
||||||
+ dnl # ->count_objects() and ->scan_objects()
|
|
||||||
+ dnl #
|
|
||||||
+ AC_MSG_CHECKING(
|
|
||||||
+ [whether ->count_objects callback exists])
|
|
||||||
+ SPL_LINUX_TRY_COMPILE([
|
|
||||||
+ #include <linux/mm.h>
|
|
||||||
+
|
|
||||||
+ unsigned long shrinker_cb(
|
|
||||||
+ struct shrinker *,
|
|
||||||
+ struct shrink_control *sc);
|
|
||||||
+ ],[
|
|
||||||
+ struct shrinker cache_shrinker = {
|
|
||||||
+ .count_objects = shrinker_cb,
|
|
||||||
+ .scan_objects = shrinker_cb,
|
|
||||||
+ .seeks = DEFAULT_SEEKS,
|
|
||||||
+ };
|
|
||||||
+ register_shrinker(&cache_shrinker);
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_RESULT(yes)
|
|
||||||
+ AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK,
|
|
||||||
+ 1, [->count_objects exists])
|
|
||||||
+ ],[
|
|
||||||
+ AC_MSG_ERROR(error)
|
|
||||||
+ ])
|
|
||||||
+ ])
|
|
||||||
+ ])
|
|
||||||
])
|
|
||||||
EXTRA_KCFLAGS="$tmp_flags"
|
|
||||||
])
|
|
||||||
diff --git a/include/linux/mm_compat.h b/include/linux/mm_compat.h
|
|
||||||
index cb1bef9..37c9b08 100644
|
|
||||||
--- a/include/linux/mm_compat.h
|
|
||||||
+++ b/include/linux/mm_compat.h
|
|
||||||
@@ -148,107 +148,167 @@ extern shrink_icache_memory_t shrink_icache_memory_fn;
|
|
||||||
#endif /* HAVE_SHRINK_ICACHE_MEMORY */
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Due to frequent changes in the shrinker API the following
|
|
||||||
+ * compatibility wrappers should be used. They are as follows:
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_DECLARE is used to declare the shrinker which is
|
|
||||||
+ * passed to spl_register_shrinker()/spl_unregister_shrinker(). Use
|
|
||||||
+ * shrinker_name to set the shrinker variable name, shrinker_callback
|
|
||||||
+ * to set the callback function, and seek_cost to define the cost of
|
|
||||||
+ * reclaiming an object.
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_DECLARE(shrinker_name, shrinker_callback, seek_cost);
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_FWD_DECLARE is used when a forward declaration
|
|
||||||
+ * of the shrinker callback function is required. Only the callback
|
|
||||||
+ * function needs to be passed.
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_FWD_DECLARE(shrinker_callback);
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_WRAPPER is used to declare the callback function
|
|
||||||
+ * which is registered with the shrinker. This function will call your
|
|
||||||
+ * custom shrinker which must use the following prototype. Notice the
|
|
||||||
+ * leading __'s, these must be appended to the callback_function name.
|
|
||||||
+ *
|
|
||||||
+ * int __shrinker_callback(struct shrinker *, struct shrink_control *)
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_WRAPPER(shrinker_callback);a
|
|
||||||
+ *
|
|
||||||
+ *
|
|
||||||
+ * Example:
|
|
||||||
+ *
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_FWD_DECLARE(my_shrinker_fn);
|
|
||||||
+ * SPL_SHRINKER_DECLARE(my_shrinker, my_shrinker_fn, 1);
|
|
||||||
+ *
|
|
||||||
+ * static int
|
|
||||||
+ * __my_shrinker_fn(struct shrinker *shrink, struct shrink_control *sc)
|
|
||||||
+ * {
|
|
||||||
+ * if (sc->nr_to_scan) {
|
|
||||||
+ * ...scan objects in the cache and reclaim them...
|
|
||||||
+ * }
|
|
||||||
+ *
|
|
||||||
+ * ...calculate number of objects in the cache...
|
|
||||||
+ *
|
|
||||||
+ * return (number of objects in the cache);
|
|
||||||
+ * }
|
|
||||||
+ * SPL_SHRINKER_CALLBACK_WRAPPER(my_shrinker_fn);
|
|
||||||
*/
|
|
||||||
-#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_register_shrinker(x) register_shrinker(x)
|
|
||||||
+#define spl_unregister_shrinker(x) unregister_shrinker(x)
|
|
||||||
|
|
||||||
-# define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
- static spl_shrinker_t s = { \
|
|
||||||
- .shrinker = NULL, \
|
|
||||||
- .fn = x, \
|
|
||||||
- .seeks = y \
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(int, unsigned int)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
-{ \
|
|
||||||
- struct shrink_control sc; \
|
|
||||||
- \
|
|
||||||
- sc.nr_to_scan = nr_to_scan; \
|
|
||||||
- sc.gfp_mask = gfp_mask; \
|
|
||||||
- \
|
|
||||||
- return __ ## fn(NULL, &sc); \
|
|
||||||
+/*
|
|
||||||
+ * Linux 2.6.23 - 2.6.34 Shrinker API Compatibility.
|
|
||||||
+ */
|
|
||||||
+#if defined(HAVE_2ARGS_OLD_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .shrink = x, \
|
|
||||||
+ .seeks = y \
|
|
||||||
}
|
|
||||||
|
|
||||||
-#else
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static int fn(int nr_to_scan, unsigned int gfp_mask)
|
|
||||||
|
|
||||||
-# 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 \
|
|
||||||
- }
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static int \
|
|
||||||
+fn(int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
+{ \
|
|
||||||
+ struct shrink_control sc; \
|
|
||||||
+ \
|
|
||||||
+ sc.nr_to_scan = nr_to_scan; \
|
|
||||||
+ sc.gfp_mask = gfp_mask; \
|
|
||||||
+ \
|
|
||||||
+ return (__ ## fn(NULL, &sc)); \
|
|
||||||
+}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Linux 2.6.35 to 2.6.39 Shrinker API Compatibility.
|
|
||||||
*/
|
|
||||||
-# if defined(HAVE_SHRINK_CONTROL_STRUCT)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(struct shrinker *, struct shrink_control *)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(struct shrinker *shrink, struct shrink_control *sc) { \
|
|
||||||
- return __ ## fn(shrink, sc); \
|
|
||||||
+#elif defined(HAVE_3ARGS_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .shrink = x, \
|
|
||||||
+ .seeks = y \
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static int fn(struct shrinker *, int, unsigned int)
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static int \
|
|
||||||
+fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
+{ \
|
|
||||||
+ struct shrink_control sc; \
|
|
||||||
+ \
|
|
||||||
+ sc.nr_to_scan = nr_to_scan; \
|
|
||||||
+ sc.gfp_mask = gfp_mask; \
|
|
||||||
+ \
|
|
||||||
+ return (__ ## fn(shrink, &sc)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Linux 3.0 to 3.11 Shrinker API Compatibility.
|
|
||||||
*/
|
|
||||||
-# elif defined(HAVE_3ARGS_SHRINKER_CALLBACK)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(struct shrinker *, int, unsigned int)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
-{ \
|
|
||||||
- struct shrink_control sc; \
|
|
||||||
- \
|
|
||||||
- sc.nr_to_scan = nr_to_scan; \
|
|
||||||
- sc.gfp_mask = gfp_mask; \
|
|
||||||
- \
|
|
||||||
- return __ ## fn(shrink, &sc); \
|
|
||||||
+#elif defined(HAVE_2ARGS_NEW_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .shrink = x, \
|
|
||||||
+ .seeks = y \
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static int fn(struct shrinker *, struct shrink_control *)
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static int \
|
|
||||||
+fn(struct shrinker *shrink, struct shrink_control *sc) \
|
|
||||||
+{ \
|
|
||||||
+ return (__ ## fn(shrink, sc)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Linux 2.6. - 2.6. Shrinker API Compatibility.
|
|
||||||
+ * Linux 3.12 and later Shrinker API Compatibility.
|
|
||||||
*/
|
|
||||||
-# else
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
- static int fn(int, unsigned int)
|
|
||||||
-# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
-static int \
|
|
||||||
-fn(int nr_to_scan, unsigned int gfp_mask) \
|
|
||||||
-{ \
|
|
||||||
- struct shrink_control sc; \
|
|
||||||
- \
|
|
||||||
- sc.nr_to_scan = nr_to_scan; \
|
|
||||||
- sc.gfp_mask = gfp_mask; \
|
|
||||||
- \
|
|
||||||
- return __ ## fn(NULL, &sc); \
|
|
||||||
+#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
|
|
||||||
+#define SPL_SHRINKER_DECLARE(s, x, y) \
|
|
||||||
+static struct shrinker s = { \
|
|
||||||
+ .count_objects = x ## _count_objects, \
|
|
||||||
+ .scan_objects = x ## _scan_objects, \
|
|
||||||
+ .seeks = y \
|
|
||||||
}
|
|
||||||
|
|
||||||
-# endif
|
|
||||||
-#endif /* HAVE_SET_SHRINKER */
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \
|
|
||||||
+static unsigned long fn ## _count_objects(struct shrinker *, \
|
|
||||||
+ struct shrink_control *); \
|
|
||||||
+static unsigned long fn ## _scan_objects(struct shrinker *, \
|
|
||||||
+ struct shrink_control *)
|
|
||||||
+
|
|
||||||
+#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \
|
|
||||||
+static unsigned long \
|
|
||||||
+fn ## _count_objects(struct shrinker *shrink, struct shrink_control *sc)\
|
|
||||||
+{ \
|
|
||||||
+ int __ret__; \
|
|
||||||
+ \
|
|
||||||
+ sc->nr_to_scan = 0; \
|
|
||||||
+ __ret__ = __ ## fn(NULL, sc); \
|
|
||||||
+ \
|
|
||||||
+ /* Errors may not be returned and must be converted to zeros */ \
|
|
||||||
+ return ((__ret__ < 0) ? 0 : __ret__); \
|
|
||||||
+} \
|
|
||||||
+ \
|
|
||||||
+static unsigned long \
|
|
||||||
+fn ## _scan_objects(struct shrinker *shrink, struct shrink_control *sc) \
|
|
||||||
+{ \
|
|
||||||
+ int __ret__; \
|
|
||||||
+ \
|
|
||||||
+ __ret__ = __ ## fn(NULL, sc); \
|
|
||||||
+ return ((__ret__ < 0) ? SHRINK_STOP : __ret__); \
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+/*
|
|
||||||
+ * Linux 2.x to 2.6.22, or a newer shrinker API has been introduced.
|
|
||||||
+ */
|
|
||||||
+#error "Unknown shrinker callback"
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#endif /* SPL_MM_COMPAT_H */
|
|
Loading…
Reference in new issue