diff options
Diffstat (limited to 'include/spl/sys/shrinker.h')
-rw-r--r-- | include/spl/sys/shrinker.h | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/include/spl/sys/shrinker.h b/include/spl/sys/shrinker.h new file mode 100644 index 000000000..28c1fa78c --- /dev/null +++ b/include/spl/sys/shrinker.h @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf <[email protected]>. + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see <http://zfsonlinux.org/>. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SPL_SHRINKER_H +#define _SPL_SHRINKER_H + +#include <linux/mm.h> +#include <linux/fs.h> + +#if !defined(HAVE_SHRINK_CONTROL_STRUCT) +struct shrink_control { + gfp_t gfp_mask; + unsigned long nr_to_scan; +}; +#endif /* HAVE_SHRINK_CONTROL_STRUCT */ + +/* + * 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); + */ + +#define spl_register_shrinker(x) register_shrinker(x) +#define spl_unregister_shrinker(x) unregister_shrinker(x) + +/* + * 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 \ +} + +#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.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) \ +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 3.0 to 3.11 Shrinker API Compatibility. + */ +#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 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 + +#if defined(HAVE_SPLIT_SHRINKER_CALLBACK) +typedef unsigned long spl_shrinker_t; +#else +typedef int spl_shrinker_t; +#define SHRINK_STOP (-1) +#endif + +#endif /* SPL_SHRINKER_H */ |