This source file includes following definitions.
- inc_frontswap_loads
- inc_frontswap_succ_stores
- inc_frontswap_failed_stores
- inc_frontswap_invalidates
- inc_frontswap_loads
- inc_frontswap_succ_stores
- inc_frontswap_failed_stores
- inc_frontswap_invalidates
- frontswap_register_ops
- frontswap_writethrough
- frontswap_tmem_exclusive_gets
- __frontswap_init
- __frontswap_test
- __frontswap_set
- __frontswap_clear
- __frontswap_store
- __frontswap_load
- __frontswap_invalidate_page
- __frontswap_invalidate_area
- __frontswap_curr_pages
- __frontswap_unuse_pages
- __frontswap_shrink
- frontswap_shrink
- frontswap_curr_pages
- init_frontswap
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/mman.h>
14 #include <linux/swap.h>
15 #include <linux/swapops.h>
16 #include <linux/security.h>
17 #include <linux/module.h>
18 #include <linux/debugfs.h>
19 #include <linux/frontswap.h>
20 #include <linux/swapfile.h>
21
22 DEFINE_STATIC_KEY_FALSE(frontswap_enabled_key);
23
24
25
26
27
28
29
30 static struct frontswap_ops *frontswap_ops __read_mostly;
31
32 #define for_each_frontswap_ops(ops) \
33 for ((ops) = frontswap_ops; (ops); (ops) = (ops)->next)
34
35
36
37
38
39
40
41
42
43 static bool frontswap_writethrough_enabled __read_mostly;
44
45
46
47
48
49
50 static bool frontswap_tmem_exclusive_gets_enabled __read_mostly;
51
52 #ifdef CONFIG_DEBUG_FS
53
54
55
56
57
58 static u64 frontswap_loads;
59 static u64 frontswap_succ_stores;
60 static u64 frontswap_failed_stores;
61 static u64 frontswap_invalidates;
62
63 static inline void inc_frontswap_loads(void) {
64 frontswap_loads++;
65 }
66 static inline void inc_frontswap_succ_stores(void) {
67 frontswap_succ_stores++;
68 }
69 static inline void inc_frontswap_failed_stores(void) {
70 frontswap_failed_stores++;
71 }
72 static inline void inc_frontswap_invalidates(void) {
73 frontswap_invalidates++;
74 }
75 #else
76 static inline void inc_frontswap_loads(void) { }
77 static inline void inc_frontswap_succ_stores(void) { }
78 static inline void inc_frontswap_failed_stores(void) { }
79 static inline void inc_frontswap_invalidates(void) { }
80 #endif
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 void frontswap_register_ops(struct frontswap_ops *ops)
114 {
115 DECLARE_BITMAP(a, MAX_SWAPFILES);
116 DECLARE_BITMAP(b, MAX_SWAPFILES);
117 struct swap_info_struct *si;
118 unsigned int i;
119
120 bitmap_zero(a, MAX_SWAPFILES);
121 bitmap_zero(b, MAX_SWAPFILES);
122
123 spin_lock(&swap_lock);
124 plist_for_each_entry(si, &swap_active_head, list) {
125 if (!WARN_ON(!si->frontswap_map))
126 set_bit(si->type, a);
127 }
128 spin_unlock(&swap_lock);
129
130
131 for_each_set_bit(i, a, MAX_SWAPFILES)
132 ops->init(i);
133
134
135
136
137
138
139 do {
140 ops->next = frontswap_ops;
141 } while (cmpxchg(&frontswap_ops, ops->next, ops) != ops->next);
142
143 static_branch_inc(&frontswap_enabled_key);
144
145 spin_lock(&swap_lock);
146 plist_for_each_entry(si, &swap_active_head, list) {
147 if (si->frontswap_map)
148 set_bit(si->type, b);
149 }
150 spin_unlock(&swap_lock);
151
152
153
154
155
156
157
158 if (unlikely(!bitmap_equal(a, b, MAX_SWAPFILES))) {
159 for (i = 0; i < MAX_SWAPFILES; i++) {
160 if (!test_bit(i, a) && test_bit(i, b))
161 ops->init(i);
162 else if (test_bit(i, a) && !test_bit(i, b))
163 ops->invalidate_area(i);
164 }
165 }
166 }
167 EXPORT_SYMBOL(frontswap_register_ops);
168
169
170
171
172 void frontswap_writethrough(bool enable)
173 {
174 frontswap_writethrough_enabled = enable;
175 }
176 EXPORT_SYMBOL(frontswap_writethrough);
177
178
179
180
181 void frontswap_tmem_exclusive_gets(bool enable)
182 {
183 frontswap_tmem_exclusive_gets_enabled = enable;
184 }
185 EXPORT_SYMBOL(frontswap_tmem_exclusive_gets);
186
187
188
189
190 void __frontswap_init(unsigned type, unsigned long *map)
191 {
192 struct swap_info_struct *sis = swap_info[type];
193 struct frontswap_ops *ops;
194
195 VM_BUG_ON(sis == NULL);
196
197
198
199
200
201 if (WARN_ON(!map))
202 return;
203
204
205
206
207
208 frontswap_map_set(sis, map);
209
210 for_each_frontswap_ops(ops)
211 ops->init(type);
212 }
213 EXPORT_SYMBOL(__frontswap_init);
214
215 bool __frontswap_test(struct swap_info_struct *sis,
216 pgoff_t offset)
217 {
218 if (sis->frontswap_map)
219 return test_bit(offset, sis->frontswap_map);
220 return false;
221 }
222 EXPORT_SYMBOL(__frontswap_test);
223
224 static inline void __frontswap_set(struct swap_info_struct *sis,
225 pgoff_t offset)
226 {
227 set_bit(offset, sis->frontswap_map);
228 atomic_inc(&sis->frontswap_pages);
229 }
230
231 static inline void __frontswap_clear(struct swap_info_struct *sis,
232 pgoff_t offset)
233 {
234 clear_bit(offset, sis->frontswap_map);
235 atomic_dec(&sis->frontswap_pages);
236 }
237
238
239
240
241
242
243
244
245 int __frontswap_store(struct page *page)
246 {
247 int ret = -1;
248 swp_entry_t entry = { .val = page_private(page), };
249 int type = swp_type(entry);
250 struct swap_info_struct *sis = swap_info[type];
251 pgoff_t offset = swp_offset(entry);
252 struct frontswap_ops *ops;
253
254 VM_BUG_ON(!frontswap_ops);
255 VM_BUG_ON(!PageLocked(page));
256 VM_BUG_ON(sis == NULL);
257
258
259
260
261
262
263
264 if (__frontswap_test(sis, offset)) {
265 __frontswap_clear(sis, offset);
266 for_each_frontswap_ops(ops)
267 ops->invalidate_page(type, offset);
268 }
269
270
271 for_each_frontswap_ops(ops) {
272 ret = ops->store(type, offset, page);
273 if (!ret)
274 break;
275 }
276 if (ret == 0) {
277 __frontswap_set(sis, offset);
278 inc_frontswap_succ_stores();
279 } else {
280 inc_frontswap_failed_stores();
281 }
282 if (frontswap_writethrough_enabled)
283
284 ret = -1;
285 return ret;
286 }
287 EXPORT_SYMBOL(__frontswap_store);
288
289
290
291
292
293
294 int __frontswap_load(struct page *page)
295 {
296 int ret = -1;
297 swp_entry_t entry = { .val = page_private(page), };
298 int type = swp_type(entry);
299 struct swap_info_struct *sis = swap_info[type];
300 pgoff_t offset = swp_offset(entry);
301 struct frontswap_ops *ops;
302
303 VM_BUG_ON(!frontswap_ops);
304 VM_BUG_ON(!PageLocked(page));
305 VM_BUG_ON(sis == NULL);
306
307 if (!__frontswap_test(sis, offset))
308 return -1;
309
310
311 for_each_frontswap_ops(ops) {
312 ret = ops->load(type, offset, page);
313 if (!ret)
314 break;
315 }
316 if (ret == 0) {
317 inc_frontswap_loads();
318 if (frontswap_tmem_exclusive_gets_enabled) {
319 SetPageDirty(page);
320 __frontswap_clear(sis, offset);
321 }
322 }
323 return ret;
324 }
325 EXPORT_SYMBOL(__frontswap_load);
326
327
328
329
330
331 void __frontswap_invalidate_page(unsigned type, pgoff_t offset)
332 {
333 struct swap_info_struct *sis = swap_info[type];
334 struct frontswap_ops *ops;
335
336 VM_BUG_ON(!frontswap_ops);
337 VM_BUG_ON(sis == NULL);
338
339 if (!__frontswap_test(sis, offset))
340 return;
341
342 for_each_frontswap_ops(ops)
343 ops->invalidate_page(type, offset);
344 __frontswap_clear(sis, offset);
345 inc_frontswap_invalidates();
346 }
347 EXPORT_SYMBOL(__frontswap_invalidate_page);
348
349
350
351
352
353 void __frontswap_invalidate_area(unsigned type)
354 {
355 struct swap_info_struct *sis = swap_info[type];
356 struct frontswap_ops *ops;
357
358 VM_BUG_ON(!frontswap_ops);
359 VM_BUG_ON(sis == NULL);
360
361 if (sis->frontswap_map == NULL)
362 return;
363
364 for_each_frontswap_ops(ops)
365 ops->invalidate_area(type);
366 atomic_set(&sis->frontswap_pages, 0);
367 bitmap_zero(sis->frontswap_map, sis->max);
368 }
369 EXPORT_SYMBOL(__frontswap_invalidate_area);
370
371 static unsigned long __frontswap_curr_pages(void)
372 {
373 unsigned long totalpages = 0;
374 struct swap_info_struct *si = NULL;
375
376 assert_spin_locked(&swap_lock);
377 plist_for_each_entry(si, &swap_active_head, list)
378 totalpages += atomic_read(&si->frontswap_pages);
379 return totalpages;
380 }
381
382 static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused,
383 int *swapid)
384 {
385 int ret = -EINVAL;
386 struct swap_info_struct *si = NULL;
387 int si_frontswap_pages;
388 unsigned long total_pages_to_unuse = total;
389 unsigned long pages = 0, pages_to_unuse = 0;
390
391 assert_spin_locked(&swap_lock);
392 plist_for_each_entry(si, &swap_active_head, list) {
393 si_frontswap_pages = atomic_read(&si->frontswap_pages);
394 if (total_pages_to_unuse < si_frontswap_pages) {
395 pages = pages_to_unuse = total_pages_to_unuse;
396 } else {
397 pages = si_frontswap_pages;
398 pages_to_unuse = 0;
399 }
400
401 if (security_vm_enough_memory_mm(current->mm, pages)) {
402 ret = -ENOMEM;
403 continue;
404 }
405 vm_unacct_memory(pages);
406 *unused = pages_to_unuse;
407 *swapid = si->type;
408 ret = 0;
409 break;
410 }
411
412 return ret;
413 }
414
415
416
417
418
419
420 static int __frontswap_shrink(unsigned long target_pages,
421 unsigned long *pages_to_unuse,
422 int *type)
423 {
424 unsigned long total_pages = 0, total_pages_to_unuse;
425
426 assert_spin_locked(&swap_lock);
427
428 total_pages = __frontswap_curr_pages();
429 if (total_pages <= target_pages) {
430
431 *pages_to_unuse = 0;
432 return 1;
433 }
434 total_pages_to_unuse = total_pages - target_pages;
435 return __frontswap_unuse_pages(total_pages_to_unuse, pages_to_unuse, type);
436 }
437
438
439
440
441
442
443
444
445
446 void frontswap_shrink(unsigned long target_pages)
447 {
448 unsigned long pages_to_unuse = 0;
449 int uninitialized_var(type), ret;
450
451
452
453
454
455
456 spin_lock(&swap_lock);
457 ret = __frontswap_shrink(target_pages, &pages_to_unuse, &type);
458 spin_unlock(&swap_lock);
459 if (ret == 0)
460 try_to_unuse(type, true, pages_to_unuse);
461 return;
462 }
463 EXPORT_SYMBOL(frontswap_shrink);
464
465
466
467
468
469
470 unsigned long frontswap_curr_pages(void)
471 {
472 unsigned long totalpages = 0;
473
474 spin_lock(&swap_lock);
475 totalpages = __frontswap_curr_pages();
476 spin_unlock(&swap_lock);
477
478 return totalpages;
479 }
480 EXPORT_SYMBOL(frontswap_curr_pages);
481
482 static int __init init_frontswap(void)
483 {
484 #ifdef CONFIG_DEBUG_FS
485 struct dentry *root = debugfs_create_dir("frontswap", NULL);
486 if (root == NULL)
487 return -ENXIO;
488 debugfs_create_u64("loads", 0444, root, &frontswap_loads);
489 debugfs_create_u64("succ_stores", 0444, root, &frontswap_succ_stores);
490 debugfs_create_u64("failed_stores", 0444, root,
491 &frontswap_failed_stores);
492 debugfs_create_u64("invalidates", 0444, root, &frontswap_invalidates);
493 #endif
494 return 0;
495 }
496
497 module_init(init_frontswap);