From 3bfba820c09dfbf04d40a3f9cac08ad3e00d4b6d Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 5 Nov 2013 11:35:54 -0500 Subject: [PATCH] Linux 3.12 compat: New shrinker API torvalds/linux@24f7c6b981fb70084757382da464ea85d72af300 introduced a new shrinker API while torvalds/linux@a0b02131c5fcd8545b867db72224b3659e813f10 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. It 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. Build tests were done against Linux 2.6.26.8, Linux 3.11.6 and Linux 3.12.0. Other kernels between 2.6.26 and Linux 3.12 are expected to work as well. Signed-off-by: Richard Yao --- config/spl-build.m4 | 90 ++++++++++++++++++++++++++++++++----- include/linux/mm_compat.h | 95 ++++++++++++++++++++++++++++----------- 2 files changed, 150 insertions(+), 35 deletions(-) diff --git a/config/spl-build.m4 b/config/spl-build.m4 index b0e33481..7f8679ba 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -28,7 +28,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ 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 @@ -904,18 +904,18 @@ 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]) +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([for old 2-argument ->shrink callback]) SPL_LINUX_TRY_COMPILE([ #include - 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 +924,80 @@ 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, + [shrinker callback wants 2 args]) ],[ AC_MSG_RESULT(no) + dnl # + dnl # 2.6.35 - 2.6.39 API change + dnl # ->shrink(struct shrinker *, int nr_to_scan, gfp_t gfp_mask) + dnl # + AC_MSG_CHECKING([whether shrinker callback wants 3 args]) + SPL_LINUX_TRY_COMPILE([ + #include + + 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, + [shrinker callback wants 3 args]) + ],[ + AC_MSG_RESULT(no) + dnl # + dnl # 3.0 - 3.11 API change + dnl # ->shrink(struct shrinker *, struct shrink_control *sc) + dnl # + AC_MSG_CHECKING([for new 2-argument ->shrink callback]) + SPL_LINUX_TRY_COMPILE([ + #include + + 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, + [->shrink defined in linux/shrinker.h]) + ],[ + AC_MSG_RESULT(no) + dnl # + dnl # 3.12 API change, + dnl # ->shrink becomes ->count_objects and ->scan_objects + dnl # + AC_MSG_CHECKING([whether ->count_objects callback exists]) + SPL_LINUX_TRY_COMPILE([ + #include + + 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 defined in linux/shrinker.h]) + ],[ + AC_MSG_ERROR(error) + ]) + ]) + ]) ]) EXTRA_KCFLAGS="$tmp_flags" ]) diff --git a/include/linux/mm_compat.h b/include/linux/mm_compat.h index cb1bef9a..39416fd2 100644 --- a/include/linux/mm_compat.h +++ b/include/linux/mm_compat.h @@ -148,7 +148,7 @@ extern shrink_icache_memory_t shrink_icache_memory_fn; #endif /* HAVE_SHRINK_ICACHE_MEMORY */ /* - * Linux 2.6. - 2.6. Shrinker API Compatibility. + * Linux 2.6.22 and earlier Shrinker API Compatibility. */ #ifdef HAVE_SET_SHRINKER typedef struct spl_shrinker { @@ -194,28 +194,38 @@ 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) \ + +/* + * 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 \ } - -/* - * Linux 2.6. - 2.6. 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); \ +# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ + static int fn(int nr_to_scan, unsigned int gfp_mask) +# 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. */ # 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) \ @@ -231,23 +241,58 @@ fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \ } /* - * Linux 2.6. - 2.6. Shrinker API Compatibility. + * Linux 3.0 to 3.11 Shrinker API Compatibility. */ -# else +# 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 3.12 and later Shrinker API Compatibility. + */ +# 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 \ + } # define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ - static int fn(int, unsigned int) + 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 int \ -fn(int nr_to_scan, unsigned int gfp_mask) \ +static unsigned long \ +fn ## _count_objects(struct shrinker *shrink, \ + struct shrink_control *sc) \ { \ - struct shrink_control sc; \ + int ret; \ + sc->nr_to_scan = 0; \ \ - sc.nr_to_scan = nr_to_scan; \ - sc.gfp_mask = gfp_mask; \ + ret = __ ## fn(NULL, sc); \ + return (ret < 0) ? 0 : ret; \ +} \ +static unsigned long \ +fn ## _scan_objects(struct shrinker *shrink, \ + struct shrink_control *sc) \ +{ \ + int ret; \ \ - return __ ## fn(NULL, &sc); \ + ret = __ ## fn(NULL, sc); \ + return (ret < 0) ? 0 : ret; \ } - +# else +# error "Unknown shrinker callback" # endif #endif /* HAVE_SET_SHRINKER */