aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/frontswap.h2
-rw-r--r--mm/frontswap.c34
2 files changed, 32 insertions, 4 deletions
diff --git a/include/linux/frontswap.h b/include/linux/frontswap.h
index 0e4e2eec5c1d..30442547b9e6 100644
--- a/include/linux/frontswap.h
+++ b/include/linux/frontswap.h
@@ -19,6 +19,8 @@ extern struct frontswap_ops
19extern void frontswap_shrink(unsigned long); 19extern void frontswap_shrink(unsigned long);
20extern unsigned long frontswap_curr_pages(void); 20extern unsigned long frontswap_curr_pages(void);
21extern void frontswap_writethrough(bool); 21extern void frontswap_writethrough(bool);
22#define FRONTSWAP_HAS_EXCLUSIVE_GETS
23extern void frontswap_tmem_exclusive_gets(bool);
22 24
23extern void __frontswap_init(unsigned type); 25extern void __frontswap_init(unsigned type);
24extern int __frontswap_store(struct page *page); 26extern int __frontswap_store(struct page *page);
diff --git a/mm/frontswap.c b/mm/frontswap.c
index 6b3e71a2cd48..2890e67d6026 100644
--- a/mm/frontswap.c
+++ b/mm/frontswap.c
@@ -44,6 +44,13 @@ EXPORT_SYMBOL(frontswap_enabled);
44 */ 44 */
45static bool frontswap_writethrough_enabled __read_mostly; 45static bool frontswap_writethrough_enabled __read_mostly;
46 46
47/*
48 * If enabled, the underlying tmem implementation is capable of doing
49 * exclusive gets, so frontswap_load, on a successful tmem_get must
50 * mark the page as no longer in frontswap AND mark it dirty.
51 */
52static bool frontswap_tmem_exclusive_gets_enabled __read_mostly;
53
47#ifdef CONFIG_DEBUG_FS 54#ifdef CONFIG_DEBUG_FS
48/* 55/*
49 * Counters available via /sys/kernel/debug/frontswap (if debugfs is 56 * Counters available via /sys/kernel/debug/frontswap (if debugfs is
@@ -97,6 +104,15 @@ void frontswap_writethrough(bool enable)
97EXPORT_SYMBOL(frontswap_writethrough); 104EXPORT_SYMBOL(frontswap_writethrough);
98 105
99/* 106/*
107 * Enable/disable frontswap exclusive gets (see above).
108 */
109void frontswap_tmem_exclusive_gets(bool enable)
110{
111 frontswap_tmem_exclusive_gets_enabled = enable;
112}
113EXPORT_SYMBOL(frontswap_tmem_exclusive_gets);
114
115/*
100 * Called when a swap device is swapon'd. 116 * Called when a swap device is swapon'd.
101 */ 117 */
102void __frontswap_init(unsigned type) 118void __frontswap_init(unsigned type)
@@ -174,8 +190,13 @@ int __frontswap_load(struct page *page)
174 BUG_ON(sis == NULL); 190 BUG_ON(sis == NULL);
175 if (frontswap_test(sis, offset)) 191 if (frontswap_test(sis, offset))
176 ret = frontswap_ops.load(type, offset, page); 192 ret = frontswap_ops.load(type, offset, page);
177 if (ret == 0) 193 if (ret == 0) {
178 inc_frontswap_loads(); 194 inc_frontswap_loads();
195 if (frontswap_tmem_exclusive_gets_enabled) {
196 SetPageDirty(page);
197 frontswap_clear(sis, offset);
198 }
199 }
179 return ret; 200 return ret;
180} 201}
181EXPORT_SYMBOL(__frontswap_load); 202EXPORT_SYMBOL(__frontswap_load);
@@ -263,6 +284,11 @@ static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused,
263 return ret; 284 return ret;
264} 285}
265 286
287/*
288 * Used to check if it's necessory and feasible to unuse pages.
289 * Return 1 when nothing to do, 0 when need to shink pages,
290 * error code when there is an error.
291 */
266static int __frontswap_shrink(unsigned long target_pages, 292static int __frontswap_shrink(unsigned long target_pages,
267 unsigned long *pages_to_unuse, 293 unsigned long *pages_to_unuse,
268 int *type) 294 int *type)
@@ -275,7 +301,7 @@ static int __frontswap_shrink(unsigned long target_pages,
275 if (total_pages <= target_pages) { 301 if (total_pages <= target_pages) {
276 /* Nothing to do */ 302 /* Nothing to do */
277 *pages_to_unuse = 0; 303 *pages_to_unuse = 0;
278 return 0; 304 return 1;
279 } 305 }
280 total_pages_to_unuse = total_pages - target_pages; 306 total_pages_to_unuse = total_pages - target_pages;
281 return __frontswap_unuse_pages(total_pages_to_unuse, pages_to_unuse, type); 307 return __frontswap_unuse_pages(total_pages_to_unuse, pages_to_unuse, type);
@@ -292,7 +318,7 @@ static int __frontswap_shrink(unsigned long target_pages,
292void frontswap_shrink(unsigned long target_pages) 318void frontswap_shrink(unsigned long target_pages)
293{ 319{
294 unsigned long pages_to_unuse = 0; 320 unsigned long pages_to_unuse = 0;
295 int type, ret; 321 int uninitialized_var(type), ret;
296 322
297 /* 323 /*
298 * we don't want to hold swap_lock while doing a very 324 * we don't want to hold swap_lock while doing a very
@@ -302,7 +328,7 @@ void frontswap_shrink(unsigned long target_pages)
302 spin_lock(&swap_lock); 328 spin_lock(&swap_lock);
303 ret = __frontswap_shrink(target_pages, &pages_to_unuse, &type); 329 ret = __frontswap_shrink(target_pages, &pages_to_unuse, &type);
304 spin_unlock(&swap_lock); 330 spin_unlock(&swap_lock);
305 if (ret == 0 && pages_to_unuse) 331 if (ret == 0)
306 try_to_unuse(type, true, pages_to_unuse); 332 try_to_unuse(type, true, pages_to_unuse);
307 return; 333 return;
308} 334}