Cleanups in code and documentation. Little bit of refactoring for cleaner look.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQEcBAABAgAGBQJQDWs9AAoJEFjIrFwIi8fJ6WwH/jOuuHD4nYxLp8CdMz1N02F9 LjDXIVz8EQz68uV2Z2KTmJPObpzIrkL/01GpvGCFJ8J3LRHGQbf8q0PDfIOsrBUU A0lViBuhccoS7Bj9dF+65aoJhtmImad3cSzfEKnA9cQX/PGY/UXdmP6mw/wLmCwu mQeUKH8zBXSD2xRQt12twm47pnjUwhFSu0iN32wEL9BlPSbq1p+6vuM3NNhnLOi4 FPi8+VkO1V6HOoM5ta8/wO3FDQHEnbdVk0u49jNZdUI3qesNjt7VDyQpWBKXoAm/ 0u7SU4AMwbBG4p2tbKXdD4foHFjWdshOxQRchsvklf32M1UTv38KDlc9n2o5neE= =Lm/R -----END PGP SIGNATURE----- Merge tag 'stable/for-linus-3.6-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm Pull frontswap updates from Konrad Rzeszutek Wilk: "Cleanups in code and documentation. Little bit of refactoring for cleaner look." * tag 'stable/for-linus-3.6-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm: mm/frontswap: cleanup doc and comment error mm: frontswap: remove unneeded headers mm: frontswap: split out function to clear a page out mm: frontswap: remove unnecessary check during initialization mm: frontswap: make all branches of if statement in put page consistent mm: frontswap: split frontswap_shrink further to simplify locking mm: frontswap: split out __frontswap_unuse_pages mm: frontswap: split out __frontswap_curr_pages mm: frontswap: trivial coding convention issues mm: frontswap: remove casting from function calls through ops structure
This commit is contained in:
commit
2b84957026
|
@ -25,7 +25,7 @@ with the specified swap device number (aka "type"). A "store" will
|
|||
copy the page to transcendent memory and associate it with the type and
|
||||
offset associated with the page. A "load" will copy the page, if found,
|
||||
from transcendent memory into kernel memory, but will NOT remove the page
|
||||
from from transcendent memory. An "invalidate_page" will remove the page
|
||||
from transcendent memory. An "invalidate_page" will remove the page
|
||||
from transcendent memory and an "invalidate_area" will remove ALL pages
|
||||
associated with the swap type (e.g., like swapoff) and notify the "device"
|
||||
to refuse further stores with that swap type.
|
||||
|
@ -99,7 +99,7 @@ server configured with a large amount of RAM... without pre-configuring
|
|||
how much of the RAM is available for each of the clients!
|
||||
|
||||
In the virtual case, the whole point of virtualization is to statistically
|
||||
multiplex physical resources acrosst the varying demands of multiple
|
||||
multiplex physical resources across the varying demands of multiple
|
||||
virtual machines. This is really hard to do with RAM and efforts to do
|
||||
it well with no kernel changes have essentially failed (except in some
|
||||
well-publicized special-case workloads).
|
||||
|
|
152
mm/frontswap.c
152
mm/frontswap.c
|
@ -11,15 +11,11 @@
|
|||
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||
*/
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/swapops.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/frontswap.h>
|
||||
#include <linux/swapfile.h>
|
||||
|
@ -110,16 +106,21 @@ void __frontswap_init(unsigned type)
|
|||
BUG_ON(sis == NULL);
|
||||
if (sis->frontswap_map == NULL)
|
||||
return;
|
||||
if (frontswap_enabled)
|
||||
(*frontswap_ops.init)(type);
|
||||
frontswap_ops.init(type);
|
||||
}
|
||||
EXPORT_SYMBOL(__frontswap_init);
|
||||
|
||||
static inline void __frontswap_clear(struct swap_info_struct *sis, pgoff_t offset)
|
||||
{
|
||||
frontswap_clear(sis, offset);
|
||||
atomic_dec(&sis->frontswap_pages);
|
||||
}
|
||||
|
||||
/*
|
||||
* "Store" data from a page to frontswap and associate it with the page's
|
||||
* swaptype and offset. Page must be locked and in the swap cache.
|
||||
* If frontswap already contains a page with matching swaptype and
|
||||
* offset, the frontswap implmentation may either overwrite the data and
|
||||
* offset, the frontswap implementation may either overwrite the data and
|
||||
* return success or invalidate the page from frontswap and return failure.
|
||||
*/
|
||||
int __frontswap_store(struct page *page)
|
||||
|
@ -134,22 +135,21 @@ int __frontswap_store(struct page *page)
|
|||
BUG_ON(sis == NULL);
|
||||
if (frontswap_test(sis, offset))
|
||||
dup = 1;
|
||||
ret = (*frontswap_ops.store)(type, offset, page);
|
||||
ret = frontswap_ops.store(type, offset, page);
|
||||
if (ret == 0) {
|
||||
frontswap_set(sis, offset);
|
||||
inc_frontswap_succ_stores();
|
||||
if (!dup)
|
||||
atomic_inc(&sis->frontswap_pages);
|
||||
} else if (dup) {
|
||||
} else {
|
||||
/*
|
||||
failed dup always results in automatic invalidate of
|
||||
the (older) page from frontswap
|
||||
*/
|
||||
frontswap_clear(sis, offset);
|
||||
atomic_dec(&sis->frontswap_pages);
|
||||
inc_frontswap_failed_stores();
|
||||
} else
|
||||
inc_frontswap_failed_stores();
|
||||
if (dup)
|
||||
__frontswap_clear(sis, offset);
|
||||
}
|
||||
if (frontswap_writethrough_enabled)
|
||||
/* report failure so swap also writes to swap device */
|
||||
ret = -1;
|
||||
|
@ -173,7 +173,7 @@ int __frontswap_load(struct page *page)
|
|||
BUG_ON(!PageLocked(page));
|
||||
BUG_ON(sis == NULL);
|
||||
if (frontswap_test(sis, offset))
|
||||
ret = (*frontswap_ops.load)(type, offset, page);
|
||||
ret = frontswap_ops.load(type, offset, page);
|
||||
if (ret == 0)
|
||||
inc_frontswap_loads();
|
||||
return ret;
|
||||
|
@ -190,9 +190,8 @@ void __frontswap_invalidate_page(unsigned type, pgoff_t offset)
|
|||
|
||||
BUG_ON(sis == NULL);
|
||||
if (frontswap_test(sis, offset)) {
|
||||
(*frontswap_ops.invalidate_page)(type, offset);
|
||||
atomic_dec(&sis->frontswap_pages);
|
||||
frontswap_clear(sis, offset);
|
||||
frontswap_ops.invalidate_page(type, offset);
|
||||
__frontswap_clear(sis, offset);
|
||||
inc_frontswap_invalidates();
|
||||
}
|
||||
}
|
||||
|
@ -209,12 +208,79 @@ void __frontswap_invalidate_area(unsigned type)
|
|||
BUG_ON(sis == NULL);
|
||||
if (sis->frontswap_map == NULL)
|
||||
return;
|
||||
(*frontswap_ops.invalidate_area)(type);
|
||||
frontswap_ops.invalidate_area(type);
|
||||
atomic_set(&sis->frontswap_pages, 0);
|
||||
memset(sis->frontswap_map, 0, sis->max / sizeof(long));
|
||||
}
|
||||
EXPORT_SYMBOL(__frontswap_invalidate_area);
|
||||
|
||||
static unsigned long __frontswap_curr_pages(void)
|
||||
{
|
||||
int type;
|
||||
unsigned long totalpages = 0;
|
||||
struct swap_info_struct *si = NULL;
|
||||
|
||||
assert_spin_locked(&swap_lock);
|
||||
for (type = swap_list.head; type >= 0; type = si->next) {
|
||||
si = swap_info[type];
|
||||
totalpages += atomic_read(&si->frontswap_pages);
|
||||
}
|
||||
return totalpages;
|
||||
}
|
||||
|
||||
static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused,
|
||||
int *swapid)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct swap_info_struct *si = NULL;
|
||||
int si_frontswap_pages;
|
||||
unsigned long total_pages_to_unuse = total;
|
||||
unsigned long pages = 0, pages_to_unuse = 0;
|
||||
int type;
|
||||
|
||||
assert_spin_locked(&swap_lock);
|
||||
for (type = swap_list.head; type >= 0; type = si->next) {
|
||||
si = swap_info[type];
|
||||
si_frontswap_pages = atomic_read(&si->frontswap_pages);
|
||||
if (total_pages_to_unuse < si_frontswap_pages) {
|
||||
pages = pages_to_unuse = total_pages_to_unuse;
|
||||
} else {
|
||||
pages = si_frontswap_pages;
|
||||
pages_to_unuse = 0; /* unuse all */
|
||||
}
|
||||
/* ensure there is enough RAM to fetch pages from frontswap */
|
||||
if (security_vm_enough_memory_mm(current->mm, pages)) {
|
||||
ret = -ENOMEM;
|
||||
continue;
|
||||
}
|
||||
vm_unacct_memory(pages);
|
||||
*unused = pages_to_unuse;
|
||||
*swapid = type;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __frontswap_shrink(unsigned long target_pages,
|
||||
unsigned long *pages_to_unuse,
|
||||
int *type)
|
||||
{
|
||||
unsigned long total_pages = 0, total_pages_to_unuse;
|
||||
|
||||
assert_spin_locked(&swap_lock);
|
||||
|
||||
total_pages = __frontswap_curr_pages();
|
||||
if (total_pages <= target_pages) {
|
||||
/* Nothing to do */
|
||||
*pages_to_unuse = 0;
|
||||
return 0;
|
||||
}
|
||||
total_pages_to_unuse = total_pages - target_pages;
|
||||
return __frontswap_unuse_pages(total_pages_to_unuse, pages_to_unuse, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Frontswap, like a true swap device, may unnecessarily retain pages
|
||||
* under certain circumstances; "shrink" frontswap is essentially a
|
||||
|
@ -225,12 +291,8 @@ EXPORT_SYMBOL(__frontswap_invalidate_area);
|
|||
*/
|
||||
void frontswap_shrink(unsigned long target_pages)
|
||||
{
|
||||
struct swap_info_struct *si = NULL;
|
||||
int si_frontswap_pages;
|
||||
unsigned long total_pages = 0, total_pages_to_unuse;
|
||||
unsigned long pages = 0, pages_to_unuse = 0;
|
||||
int type;
|
||||
bool locked = false;
|
||||
unsigned long pages_to_unuse = 0;
|
||||
int type, ret;
|
||||
|
||||
/*
|
||||
* we don't want to hold swap_lock while doing a very
|
||||
|
@ -238,38 +300,10 @@ void frontswap_shrink(unsigned long target_pages)
|
|||
* so restart scan from swap_list.head each time
|
||||
*/
|
||||
spin_lock(&swap_lock);
|
||||
locked = true;
|
||||
total_pages = 0;
|
||||
for (type = swap_list.head; type >= 0; type = si->next) {
|
||||
si = swap_info[type];
|
||||
total_pages += atomic_read(&si->frontswap_pages);
|
||||
}
|
||||
if (total_pages <= target_pages)
|
||||
goto out;
|
||||
total_pages_to_unuse = total_pages - target_pages;
|
||||
for (type = swap_list.head; type >= 0; type = si->next) {
|
||||
si = swap_info[type];
|
||||
si_frontswap_pages = atomic_read(&si->frontswap_pages);
|
||||
if (total_pages_to_unuse < si_frontswap_pages)
|
||||
pages = pages_to_unuse = total_pages_to_unuse;
|
||||
else {
|
||||
pages = si_frontswap_pages;
|
||||
pages_to_unuse = 0; /* unuse all */
|
||||
}
|
||||
/* ensure there is enough RAM to fetch pages from frontswap */
|
||||
if (security_vm_enough_memory_mm(current->mm, pages))
|
||||
continue;
|
||||
vm_unacct_memory(pages);
|
||||
break;
|
||||
}
|
||||
if (type < 0)
|
||||
goto out;
|
||||
locked = false;
|
||||
ret = __frontswap_shrink(target_pages, &pages_to_unuse, &type);
|
||||
spin_unlock(&swap_lock);
|
||||
try_to_unuse(type, true, pages_to_unuse);
|
||||
out:
|
||||
if (locked)
|
||||
spin_unlock(&swap_lock);
|
||||
if (ret == 0 && pages_to_unuse)
|
||||
try_to_unuse(type, true, pages_to_unuse);
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(frontswap_shrink);
|
||||
|
@ -281,16 +315,12 @@ EXPORT_SYMBOL(frontswap_shrink);
|
|||
*/
|
||||
unsigned long frontswap_curr_pages(void)
|
||||
{
|
||||
int type;
|
||||
unsigned long totalpages = 0;
|
||||
struct swap_info_struct *si = NULL;
|
||||
|
||||
spin_lock(&swap_lock);
|
||||
for (type = swap_list.head; type >= 0; type = si->next) {
|
||||
si = swap_info[type];
|
||||
totalpages += atomic_read(&si->frontswap_pages);
|
||||
}
|
||||
totalpages = __frontswap_curr_pages();
|
||||
spin_unlock(&swap_lock);
|
||||
|
||||
return totalpages;
|
||||
}
|
||||
EXPORT_SYMBOL(frontswap_curr_pages);
|
||||
|
|
Loading…
Reference in a new issue