]>
Commit | Line | Data |
---|---|---|
70e083d2 TG |
1 | /*****************************************************************************\ |
2 | * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. | |
3 | * Copyright (C) 2007 The Regents of the University of California. | |
4 | * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). | |
5 | * Written by Brian Behlendorf <behlendorf1@llnl.gov>. | |
6 | * UCRL-CODE-235197 | |
7 | * | |
8 | * This file is part of the SPL, Solaris Porting Layer. | |
9 | * For details, see <http://zfsonlinux.org/>. | |
10 | * | |
11 | * The SPL is free software; you can redistribute it and/or modify it | |
12 | * under the terms of the GNU General Public License as published by the | |
13 | * Free Software Foundation; either version 2 of the License, or (at your | |
14 | * option) any later version. | |
15 | * | |
16 | * The SPL is distributed in the hope that it will be useful, but WITHOUT | |
17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
18 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
19 | * for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License along | |
22 | * with the SPL. If not, see <http://www.gnu.org/licenses/>. | |
23 | \*****************************************************************************/ | |
24 | ||
25 | #ifndef _SPL_MM_COMPAT_H | |
26 | #define _SPL_MM_COMPAT_H | |
27 | ||
28 | #include <linux/mm.h> | |
29 | #include <linux/fs.h> | |
30 | ||
31 | #if !defined(HAVE_SHRINK_CONTROL_STRUCT) | |
32 | struct shrink_control { | |
33 | gfp_t gfp_mask; | |
34 | unsigned long nr_to_scan; | |
35 | }; | |
36 | #endif /* HAVE_SHRINK_CONTROL_STRUCT */ | |
37 | ||
38 | /* | |
39 | * Due to frequent changes in the shrinker API the following | |
40 | * compatibility wrappers should be used. They are as follows: | |
41 | * | |
42 | * SPL_SHRINKER_DECLARE is used to declare the shrinker which is | |
43 | * passed to spl_register_shrinker()/spl_unregister_shrinker(). Use | |
44 | * shrinker_name to set the shrinker variable name, shrinker_callback | |
45 | * to set the callback function, and seek_cost to define the cost of | |
46 | * reclaiming an object. | |
47 | * | |
48 | * SPL_SHRINKER_DECLARE(shrinker_name, shrinker_callback, seek_cost); | |
49 | * | |
50 | * SPL_SHRINKER_CALLBACK_FWD_DECLARE is used when a forward declaration | |
51 | * of the shrinker callback function is required. Only the callback | |
52 | * function needs to be passed. | |
53 | * | |
54 | * SPL_SHRINKER_CALLBACK_FWD_DECLARE(shrinker_callback); | |
55 | * | |
56 | * SPL_SHRINKER_CALLBACK_WRAPPER is used to declare the callback function | |
57 | * which is registered with the shrinker. This function will call your | |
58 | * custom shrinker which must use the following prototype. Notice the | |
59 | * leading __'s, these must be appended to the callback_function name. | |
60 | * | |
61 | * int __shrinker_callback(struct shrinker *, struct shrink_control *) | |
62 | * SPL_SHRINKER_CALLBACK_WRAPPER(shrinker_callback);a | |
63 | * | |
64 | * | |
65 | * Example: | |
66 | * | |
67 | * SPL_SHRINKER_CALLBACK_FWD_DECLARE(my_shrinker_fn); | |
68 | * SPL_SHRINKER_DECLARE(my_shrinker, my_shrinker_fn, 1); | |
69 | * | |
70 | * static int | |
71 | * __my_shrinker_fn(struct shrinker *shrink, struct shrink_control *sc) | |
72 | * { | |
73 | * if (sc->nr_to_scan) { | |
74 | * ...scan objects in the cache and reclaim them... | |
75 | * } | |
76 | * | |
77 | * ...calculate number of objects in the cache... | |
78 | * | |
79 | * return (number of objects in the cache); | |
80 | * } | |
81 | * SPL_SHRINKER_CALLBACK_WRAPPER(my_shrinker_fn); | |
82 | */ | |
83 | ||
84 | #define spl_register_shrinker(x) register_shrinker(x) | |
85 | #define spl_unregister_shrinker(x) unregister_shrinker(x) | |
86 | ||
87 | /* | |
88 | * Linux 2.6.23 - 2.6.34 Shrinker API Compatibility. | |
89 | */ | |
90 | #if defined(HAVE_2ARGS_OLD_SHRINKER_CALLBACK) | |
91 | #define SPL_SHRINKER_DECLARE(s, x, y) \ | |
92 | static struct shrinker s = { \ | |
93 | .shrink = x, \ | |
94 | .seeks = y \ | |
95 | } | |
96 | ||
97 | #define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ | |
98 | static int fn(int nr_to_scan, unsigned int gfp_mask) | |
99 | ||
100 | #define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ | |
101 | static int \ | |
102 | fn(int nr_to_scan, unsigned int gfp_mask) \ | |
103 | { \ | |
104 | struct shrink_control sc; \ | |
105 | \ | |
106 | sc.nr_to_scan = nr_to_scan; \ | |
107 | sc.gfp_mask = gfp_mask; \ | |
108 | \ | |
109 | return (__ ## fn(NULL, &sc)); \ | |
110 | } | |
111 | ||
112 | /* | |
113 | * Linux 2.6.35 to 2.6.39 Shrinker API Compatibility. | |
114 | */ | |
115 | #elif defined(HAVE_3ARGS_SHRINKER_CALLBACK) | |
116 | #define SPL_SHRINKER_DECLARE(s, x, y) \ | |
117 | static struct shrinker s = { \ | |
118 | .shrink = x, \ | |
119 | .seeks = y \ | |
120 | } | |
121 | ||
122 | #define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ | |
123 | static int fn(struct shrinker *, int, unsigned int) | |
124 | ||
125 | #define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ | |
126 | static int \ | |
127 | fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \ | |
128 | { \ | |
129 | struct shrink_control sc; \ | |
130 | \ | |
131 | sc.nr_to_scan = nr_to_scan; \ | |
132 | sc.gfp_mask = gfp_mask; \ | |
133 | \ | |
134 | return (__ ## fn(shrink, &sc)); \ | |
135 | } | |
136 | ||
137 | /* | |
138 | * Linux 3.0 to 3.11 Shrinker API Compatibility. | |
139 | */ | |
140 | #elif defined(HAVE_2ARGS_NEW_SHRINKER_CALLBACK) | |
141 | #define SPL_SHRINKER_DECLARE(s, x, y) \ | |
142 | static struct shrinker s = { \ | |
143 | .shrink = x, \ | |
144 | .seeks = y \ | |
145 | } | |
146 | ||
147 | #define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ | |
148 | static int fn(struct shrinker *, struct shrink_control *) | |
149 | ||
150 | #define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ | |
151 | static int \ | |
152 | fn(struct shrinker *shrink, struct shrink_control *sc) \ | |
153 | { \ | |
154 | return (__ ## fn(shrink, sc)); \ | |
155 | } | |
156 | ||
157 | /* | |
158 | * Linux 3.12 and later Shrinker API Compatibility. | |
159 | */ | |
160 | #elif defined(HAVE_SPLIT_SHRINKER_CALLBACK) | |
161 | #define SPL_SHRINKER_DECLARE(s, x, y) \ | |
162 | static struct shrinker s = { \ | |
163 | .count_objects = x ## _count_objects, \ | |
164 | .scan_objects = x ## _scan_objects, \ | |
165 | .seeks = y \ | |
166 | } | |
167 | ||
168 | #define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ | |
169 | static unsigned long fn ## _count_objects(struct shrinker *, \ | |
170 | struct shrink_control *); \ | |
171 | static unsigned long fn ## _scan_objects(struct shrinker *, \ | |
172 | struct shrink_control *) | |
173 | ||
174 | #define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ | |
175 | static unsigned long \ | |
176 | fn ## _count_objects(struct shrinker *shrink, struct shrink_control *sc)\ | |
177 | { \ | |
178 | int __ret__; \ | |
179 | \ | |
180 | sc->nr_to_scan = 0; \ | |
181 | __ret__ = __ ## fn(NULL, sc); \ | |
182 | \ | |
183 | /* Errors may not be returned and must be converted to zeros */ \ | |
184 | return ((__ret__ < 0) ? 0 : __ret__); \ | |
185 | } \ | |
186 | \ | |
187 | static unsigned long \ | |
188 | fn ## _scan_objects(struct shrinker *shrink, struct shrink_control *sc) \ | |
189 | { \ | |
190 | int __ret__; \ | |
191 | \ | |
192 | __ret__ = __ ## fn(NULL, sc); \ | |
193 | return ((__ret__ < 0) ? SHRINK_STOP : __ret__); \ | |
194 | } | |
195 | #else | |
196 | /* | |
197 | * Linux 2.x to 2.6.22, or a newer shrinker API has been introduced. | |
198 | */ | |
199 | #error "Unknown shrinker callback" | |
200 | #endif | |
201 | ||
202 | #if defined(HAVE_SPLIT_SHRINKER_CALLBACK) | |
203 | typedef unsigned long spl_shrinker_t; | |
204 | #else | |
205 | typedef int spl_shrinker_t; | |
206 | #define SHRINK_STOP (-1) | |
207 | #endif | |
208 | ||
209 | #endif /* SPL_MM_COMPAT_H */ |