4 * This code provides the generic "frontend" layer to call a matching
5 * "backend" driver implementation of frontswap. See
6 * Documentation/vm/frontswap.txt for more information.
8 * Copyright (C) 2009-2010 Oracle Corp. All rights reserved.
9 * Author: Dan Magenheimer
11 * This work is licensed under the terms of the GNU GPL, version 2.
15 #include <linux/mman.h>
16 #include <linux/sysctl.h>
17 #include <linux/swap.h>
18 #include <linux/swapops.h>
19 #include <linux/proc_fs.h>
20 #include <linux/security.h>
21 #include <linux/capability.h>
22 #include <linux/module.h>
23 #include <linux/uaccess.h>
24 #include <linux/frontswap.h>
25 #include <linux/swapfile.h>
28 * frontswap_ops is set by frontswap_register_ops to contain the pointers
29 * to the frontswap "backend" implementation functions.
31 static struct frontswap_ops frontswap_ops
;
34 * This global enablement flag reduces overhead on systems where frontswap_ops
35 * has not been registered, so is preferred to the slower alternative: a
36 * function call that checks a non-global.
38 int frontswap_enabled
;
39 EXPORT_SYMBOL(frontswap_enabled
);
41 /* useful stats available in /sys/kernel/mm/frontswap */
42 static unsigned long frontswap_gets
;
43 static unsigned long frontswap_succ_puts
;
44 static unsigned long frontswap_failed_puts
;
45 static unsigned long frontswap_flushes
;
48 * register operations for frontswap, returning previous thus allowing
49 * detection of multiple backends and possible nesting
51 struct frontswap_ops
frontswap_register_ops(struct frontswap_ops
*ops
)
53 struct frontswap_ops old
= frontswap_ops
;
56 frontswap_enabled
= 1;
59 EXPORT_SYMBOL(frontswap_register_ops
);
61 /* Called when a swap device is swapon'd */
62 void __frontswap_init(unsigned type
)
64 if (frontswap_enabled
)
65 (*frontswap_ops
.init
)(type
);
67 EXPORT_SYMBOL(__frontswap_init
);
70 * "Put" data from a page to frontswap and associate it with the page's
71 * swaptype and offset. Page must be locked and in the swap cache.
72 * If frontswap already contains a page with matching swaptype and
73 * offset, the frontswap implmentation may either overwrite the data
74 * and return success or flush the page from frontswap and return failure
76 int __frontswap_put_page(struct page
*page
)
78 int ret
= -1, dup
= 0;
79 swp_entry_t entry
= { .val
= page_private(page
), };
80 int type
= swp_type(entry
);
81 struct swap_info_struct
*sis
= swap_info
[type
];
82 pgoff_t offset
= swp_offset(entry
);
84 BUG_ON(!PageLocked(page
));
85 if (frontswap_test(sis
, offset
))
87 ret
= (*frontswap_ops
.put_page
)(type
, offset
, page
);
89 frontswap_set(sis
, offset
);
90 frontswap_succ_puts
++;
92 sis
->frontswap_pages
++;
95 failed dup always results in automatic flush of
96 the (older) page from frontswap
98 frontswap_clear(sis
, offset
);
99 sis
->frontswap_pages
--;
100 frontswap_failed_puts
++;
102 frontswap_failed_puts
++;
105 EXPORT_SYMBOL(__frontswap_put_page
);
108 * "Get" data from frontswap associated with swaptype and offset that were
109 * specified when the data was put to frontswap and use it to fill the
110 * specified page with data. Page must be locked and in the swap cache
112 int __frontswap_get_page(struct page
*page
)
115 swp_entry_t entry
= { .val
= page_private(page
), };
116 int type
= swp_type(entry
);
117 struct swap_info_struct
*sis
= swap_info
[type
];
118 pgoff_t offset
= swp_offset(entry
);
120 BUG_ON(!PageLocked(page
));
121 if (frontswap_test(sis
, offset
))
122 ret
= (*frontswap_ops
.get_page
)(type
, offset
, page
);
127 EXPORT_SYMBOL(__frontswap_get_page
);
130 * Flush any data from frontswap associated with the specified swaptype
131 * and offset so that a subsequent "get" will fail.
133 void __frontswap_flush_page(unsigned type
, pgoff_t offset
)
135 struct swap_info_struct
*sis
= swap_info
[type
];
137 if (frontswap_test(sis
, offset
)) {
138 (*frontswap_ops
.flush_page
)(type
, offset
);
139 sis
->frontswap_pages
--;
140 frontswap_clear(sis
, offset
);
144 EXPORT_SYMBOL(__frontswap_flush_page
);
147 * Flush all data from frontswap associated with all offsets for the
148 * specified swaptype.
150 void __frontswap_flush_area(unsigned type
)
152 struct swap_info_struct
*sis
= swap_info
[type
];
154 (*frontswap_ops
.flush_area
)(type
);
155 sis
->frontswap_pages
= 0;
156 memset(sis
->frontswap_map
, 0, sis
->max
/ sizeof(long));
158 EXPORT_SYMBOL(__frontswap_flush_area
);
161 * Frontswap, like a true swap device, may unnecessarily retain pages
162 * under certain circumstances; "shrink" frontswap is essentially a
163 * "partial swapoff" and works by calling try_to_unuse to attempt to
164 * unuse enough frontswap pages to attempt to -- subject to memory
165 * constraints -- reduce the number of pages in frontswap
167 void frontswap_shrink(unsigned long target_pages
)
172 for (wrapped
= 0; wrapped
<= 3; wrapped
++) {
174 struct swap_info_struct
*si
= NULL
;
175 unsigned long total_pages
= 0, total_pages_to_unuse
;
176 unsigned long pages
= 0, unuse_pages
= 0;
180 * we don't want to hold swap_lock while doing a very
181 * lengthy try_to_unuse, but swap_list may change
182 * so restart scan from swap_list.head each time
184 spin_lock(&swap_lock
);
187 for (type
= swap_list
.head
; type
>= 0; type
= si
->next
) {
188 si
= swap_info
[type
];
189 total_pages
+= si
->frontswap_pages
;
191 if (total_pages
<= target_pages
)
193 total_pages_to_unuse
= total_pages
- target_pages
;
194 for (type
= swap_list
.head
; type
>= 0; type
= si
->next
) {
195 si
= swap_info
[type
];
196 if (total_pages_to_unuse
< si
->frontswap_pages
)
197 pages
= unuse_pages
= total_pages_to_unuse
;
199 pages
= si
->frontswap_pages
;
200 unuse_pages
= 0; /* unuse all */
202 if (security_vm_enough_memory_kern(pages
))
204 vm_unacct_memory(pages
);
210 spin_unlock(&swap_lock
);
211 try_to_unuse(type
, true, unuse_pages
);
216 spin_unlock(&swap_lock
);
219 EXPORT_SYMBOL(frontswap_shrink
);
222 * count and return the number of pages frontswap pages across all
223 * swap devices. This is exported so that a kernel module can
224 * determine current usage without reading sysfs.
226 unsigned long frontswap_curr_pages(void)
229 unsigned long totalpages
= 0;
230 struct swap_info_struct
*si
= NULL
;
232 spin_lock(&swap_lock
);
233 for (type
= swap_list
.head
; type
>= 0; type
= si
->next
) {
234 si
= swap_info
[type
];
235 totalpages
+= si
->frontswap_pages
;
237 spin_unlock(&swap_lock
);
240 EXPORT_SYMBOL(frontswap_curr_pages
);
244 /* see Documentation/ABI/xxx/sysfs-kernel-mm-frontswap */
246 #define FRONTSWAP_ATTR_RO(_name) \
247 static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
248 #define FRONTSWAP_ATTR(_name) \
249 static struct kobj_attribute _name##_attr = \
250 __ATTR(_name, 0644, _name##_show, _name##_store)
252 static ssize_t
curr_pages_show(struct kobject
*kobj
,
253 struct kobj_attribute
*attr
, char *buf
)
255 return sprintf(buf
, "%lu\n", frontswap_curr_pages());
258 static ssize_t
curr_pages_store(struct kobject
*kobj
,
259 struct kobj_attribute
*attr
,
260 const char *buf
, size_t count
)
262 unsigned long target_pages
;
265 err
= strict_strtoul(buf
, 10, &target_pages
);
269 frontswap_shrink(target_pages
);
273 FRONTSWAP_ATTR(curr_pages
);
275 static ssize_t
succ_puts_show(struct kobject
*kobj
,
276 struct kobj_attribute
*attr
, char *buf
)
278 return sprintf(buf
, "%lu\n", frontswap_succ_puts
);
280 FRONTSWAP_ATTR_RO(succ_puts
);
282 static ssize_t
failed_puts_show(struct kobject
*kobj
,
283 struct kobj_attribute
*attr
, char *buf
)
285 return sprintf(buf
, "%lu\n", frontswap_failed_puts
);
287 FRONTSWAP_ATTR_RO(failed_puts
);
289 static ssize_t
gets_show(struct kobject
*kobj
,
290 struct kobj_attribute
*attr
, char *buf
)
292 return sprintf(buf
, "%lu\n", frontswap_gets
);
294 FRONTSWAP_ATTR_RO(gets
);
296 static ssize_t
flushes_show(struct kobject
*kobj
,
297 struct kobj_attribute
*attr
, char *buf
)
299 return sprintf(buf
, "%lu\n", frontswap_flushes
);
301 FRONTSWAP_ATTR_RO(flushes
);
303 static struct attribute
*frontswap_attrs
[] = {
304 &curr_pages_attr
.attr
,
305 &succ_puts_attr
.attr
,
306 &failed_puts_attr
.attr
,
312 static struct attribute_group frontswap_attr_group
= {
313 .attrs
= frontswap_attrs
,
317 #endif /* CONFIG_SYSFS */
319 static int __init
init_frontswap(void)
324 err
= sysfs_create_group(mm_kobj
, &frontswap_attr_group
);
325 #endif /* CONFIG_SYSFS */
329 static void __exit
exit_frontswap(void)
331 frontswap_shrink(0UL);
334 module_init(init_frontswap
);
335 module_exit(exit_frontswap
);