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:
Linus Torvalds 2012-07-24 13:15:25 -07:00
Родитель 62c4d9afa4 1d00015e26
Коммит 2b84957026
2 изменённых файлов: 93 добавлений и 63 удалений

Просмотреть файл

@ -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).

Просмотреть файл

@ -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);