diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2013-04-30 18:26:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 20:04:00 -0400 |
commit | 1e01c968db3d0aebd48e31db15f24516b03128df (patch) | |
tree | 6f8ebed201fdc426a6926b4a2235e8dd2538f025 /mm | |
parent | 905cd0e1bf9ffe82d6906a01fd974ea0f70be97a (diff) |
frontswap: make frontswap_init use a pointer for the ops
This simplifies the code in the frontswap - we can get rid of the
'backend_registered' test and instead check against frontswap_ops.
[v1: Rebase on top of 703ba7fe5e0 (ramster->zcache move]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Bob Liu <lliubbo@gmail.com>
Cc: Wanpeng Li <liwanp@linux.vnet.ibm.com>
Cc: Andor Daam <andor.daam@googlemail.com>
Cc: Dan Magenheimer <dan.magenheimer@oracle.com>
Cc: Florian Schmaus <fschmaus@gmail.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Stefan Hengelein <ilendir@googlemail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/frontswap.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/mm/frontswap.c b/mm/frontswap.c index cbd2b8af8129..e44c9cbd1443 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * frontswap_ops is set by frontswap_register_ops to contain the pointers | 24 | * frontswap_ops is set by frontswap_register_ops to contain the pointers |
25 | * to the frontswap "backend" implementation functions. | 25 | * to the frontswap "backend" implementation functions. |
26 | */ | 26 | */ |
27 | static struct frontswap_ops frontswap_ops __read_mostly; | 27 | static struct frontswap_ops *frontswap_ops __read_mostly; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * This global enablement flag reduces overhead on systems where frontswap_ops | 30 | * This global enablement flag reduces overhead on systems where frontswap_ops |
@@ -108,41 +108,39 @@ static inline void inc_frontswap_invalidates(void) { } | |||
108 | * | 108 | * |
109 | * The time between the backend being registered and the swap file system | 109 | * The time between the backend being registered and the swap file system |
110 | * calling the backend (via the frontswap_* functions) is indeterminate as | 110 | * calling the backend (via the frontswap_* functions) is indeterminate as |
111 | * backend_registered is not atomic_t (or a value guarded by a spinlock). | 111 | * frontswap_ops is not atomic_t (or a value guarded by a spinlock). |
112 | * That is OK as we are comfortable missing some of these calls to the newly | 112 | * That is OK as we are comfortable missing some of these calls to the newly |
113 | * registered backend. | 113 | * registered backend. |
114 | * | 114 | * |
115 | * Obviously the opposite (unloading the backend) must be done after all | 115 | * Obviously the opposite (unloading the backend) must be done after all |
116 | * the frontswap_[store|load|invalidate_area|invalidate_page] start | 116 | * the frontswap_[store|load|invalidate_area|invalidate_page] start |
117 | * ignorning or failing the requests - at which point backend_registered | 117 | * ignorning or failing the requests - at which point frontswap_ops |
118 | * would have to be made in some fashion atomic. | 118 | * would have to be made in some fashion atomic. |
119 | */ | 119 | */ |
120 | static DECLARE_BITMAP(need_init, MAX_SWAPFILES); | 120 | static DECLARE_BITMAP(need_init, MAX_SWAPFILES); |
121 | static bool backend_registered __read_mostly; | ||
122 | 121 | ||
123 | /* | 122 | /* |
124 | * Register operations for frontswap, returning previous thus allowing | 123 | * Register operations for frontswap, returning previous thus allowing |
125 | * detection of multiple backends and possible nesting. | 124 | * detection of multiple backends and possible nesting. |
126 | */ | 125 | */ |
127 | struct frontswap_ops frontswap_register_ops(struct frontswap_ops *ops) | 126 | struct frontswap_ops *frontswap_register_ops(struct frontswap_ops *ops) |
128 | { | 127 | { |
129 | struct frontswap_ops old = frontswap_ops; | 128 | struct frontswap_ops *old = frontswap_ops; |
130 | int i; | 129 | int i; |
131 | 130 | ||
132 | frontswap_ops = *ops; | ||
133 | frontswap_enabled = true; | 131 | frontswap_enabled = true; |
134 | 132 | ||
135 | for (i = 0; i < MAX_SWAPFILES; i++) { | 133 | for (i = 0; i < MAX_SWAPFILES; i++) { |
136 | if (test_and_clear_bit(i, need_init)) | 134 | if (test_and_clear_bit(i, need_init)) |
137 | (*frontswap_ops.init)(i); | 135 | ops->init(i); |
138 | } | 136 | } |
139 | /* | 137 | /* |
140 | * We MUST have backend_registered set _after_ the frontswap_init's | 138 | * We MUST have frontswap_ops set _after_ the frontswap_init's |
141 | * have been called. Otherwise __frontswap_store might fail. Hence | 139 | * have been called. Otherwise __frontswap_store might fail. Hence |
142 | * the barrier to make sure compiler does not re-order us. | 140 | * the barrier to make sure compiler does not re-order us. |
143 | */ | 141 | */ |
144 | barrier(); | 142 | barrier(); |
145 | backend_registered = true; | 143 | frontswap_ops = ops; |
146 | return old; | 144 | return old; |
147 | } | 145 | } |
148 | EXPORT_SYMBOL(frontswap_register_ops); | 146 | EXPORT_SYMBOL(frontswap_register_ops); |
@@ -172,11 +170,11 @@ void __frontswap_init(unsigned type) | |||
172 | { | 170 | { |
173 | struct swap_info_struct *sis = swap_info[type]; | 171 | struct swap_info_struct *sis = swap_info[type]; |
174 | 172 | ||
175 | if (backend_registered) { | 173 | if (frontswap_ops) { |
176 | BUG_ON(sis == NULL); | 174 | BUG_ON(sis == NULL); |
177 | if (sis->frontswap_map == NULL) | 175 | if (sis->frontswap_map == NULL) |
178 | return; | 176 | return; |
179 | (*frontswap_ops.init)(type); | 177 | frontswap_ops->init(type); |
180 | } else { | 178 | } else { |
181 | BUG_ON(type > MAX_SWAPFILES); | 179 | BUG_ON(type > MAX_SWAPFILES); |
182 | set_bit(type, need_init); | 180 | set_bit(type, need_init); |
@@ -206,7 +204,7 @@ int __frontswap_store(struct page *page) | |||
206 | struct swap_info_struct *sis = swap_info[type]; | 204 | struct swap_info_struct *sis = swap_info[type]; |
207 | pgoff_t offset = swp_offset(entry); | 205 | pgoff_t offset = swp_offset(entry); |
208 | 206 | ||
209 | if (!backend_registered) { | 207 | if (!frontswap_ops) { |
210 | inc_frontswap_failed_stores(); | 208 | inc_frontswap_failed_stores(); |
211 | return ret; | 209 | return ret; |
212 | } | 210 | } |
@@ -215,7 +213,7 @@ int __frontswap_store(struct page *page) | |||
215 | BUG_ON(sis == NULL); | 213 | BUG_ON(sis == NULL); |
216 | if (frontswap_test(sis, offset)) | 214 | if (frontswap_test(sis, offset)) |
217 | dup = 1; | 215 | dup = 1; |
218 | ret = frontswap_ops.store(type, offset, page); | 216 | ret = frontswap_ops->store(type, offset, page); |
219 | if (ret == 0) { | 217 | if (ret == 0) { |
220 | frontswap_set(sis, offset); | 218 | frontswap_set(sis, offset); |
221 | inc_frontswap_succ_stores(); | 219 | inc_frontswap_succ_stores(); |
@@ -250,13 +248,13 @@ int __frontswap_load(struct page *page) | |||
250 | struct swap_info_struct *sis = swap_info[type]; | 248 | struct swap_info_struct *sis = swap_info[type]; |
251 | pgoff_t offset = swp_offset(entry); | 249 | pgoff_t offset = swp_offset(entry); |
252 | 250 | ||
253 | if (!backend_registered) | 251 | if (!frontswap_ops) |
254 | return ret; | 252 | return ret; |
255 | 253 | ||
256 | BUG_ON(!PageLocked(page)); | 254 | BUG_ON(!PageLocked(page)); |
257 | BUG_ON(sis == NULL); | 255 | BUG_ON(sis == NULL); |
258 | if (frontswap_test(sis, offset)) | 256 | if (frontswap_test(sis, offset)) |
259 | ret = frontswap_ops.load(type, offset, page); | 257 | ret = frontswap_ops->load(type, offset, page); |
260 | if (ret == 0) { | 258 | if (ret == 0) { |
261 | inc_frontswap_loads(); | 259 | inc_frontswap_loads(); |
262 | if (frontswap_tmem_exclusive_gets_enabled) { | 260 | if (frontswap_tmem_exclusive_gets_enabled) { |
@@ -276,12 +274,12 @@ void __frontswap_invalidate_page(unsigned type, pgoff_t offset) | |||
276 | { | 274 | { |
277 | struct swap_info_struct *sis = swap_info[type]; | 275 | struct swap_info_struct *sis = swap_info[type]; |
278 | 276 | ||
279 | if (!backend_registered) | 277 | if (!frontswap_ops) |
280 | return; | 278 | return; |
281 | 279 | ||
282 | BUG_ON(sis == NULL); | 280 | BUG_ON(sis == NULL); |
283 | if (frontswap_test(sis, offset)) { | 281 | if (frontswap_test(sis, offset)) { |
284 | frontswap_ops.invalidate_page(type, offset); | 282 | frontswap_ops->invalidate_page(type, offset); |
285 | __frontswap_clear(sis, offset); | 283 | __frontswap_clear(sis, offset); |
286 | inc_frontswap_invalidates(); | 284 | inc_frontswap_invalidates(); |
287 | } | 285 | } |
@@ -296,11 +294,11 @@ void __frontswap_invalidate_area(unsigned type) | |||
296 | { | 294 | { |
297 | struct swap_info_struct *sis = swap_info[type]; | 295 | struct swap_info_struct *sis = swap_info[type]; |
298 | 296 | ||
299 | if (backend_registered) { | 297 | if (frontswap_ops) { |
300 | BUG_ON(sis == NULL); | 298 | BUG_ON(sis == NULL); |
301 | if (sis->frontswap_map == NULL) | 299 | if (sis->frontswap_map == NULL) |
302 | return; | 300 | return; |
303 | (*frontswap_ops.invalidate_area)(type); | 301 | frontswap_ops->invalidate_area(type); |
304 | atomic_set(&sis->frontswap_pages, 0); | 302 | atomic_set(&sis->frontswap_pages, 0); |
305 | memset(sis->frontswap_map, 0, sis->max / sizeof(long)); | 303 | memset(sis->frontswap_map, 0, sis->max / sizeof(long)); |
306 | } | 304 | } |