From ef3835974103fc52c12962d91b224fbc2edcabe6 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:50:59 +0200 Subject: mm: frontswap: remove casting from function calls through ops structure Removes unneeded casts. Reviewed-by: Minchan Kim Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index e250255..557e8af4 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -111,7 +111,7 @@ void __frontswap_init(unsigned type) if (sis->frontswap_map == NULL) return; if (frontswap_enabled) - (*frontswap_ops.init)(type); + frontswap_ops.init(type); } EXPORT_SYMBOL(__frontswap_init); @@ -134,7 +134,7 @@ 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(); @@ -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,7 +190,7 @@ void __frontswap_invalidate_page(unsigned type, pgoff_t offset) BUG_ON(sis == NULL); if (frontswap_test(sis, offset)) { - (*frontswap_ops.invalidate_page)(type, offset); + frontswap_ops.invalidate_page(type, offset); atomic_dec(&sis->frontswap_pages); frontswap_clear(sis, offset); inc_frontswap_invalidates(); @@ -209,7 +209,7 @@ 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)); } -- cgit v0.10.2 From 4bb3e31ef408a5ce460da3555c9f59dfe39636ff Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:51:00 +0200 Subject: mm: frontswap: trivial coding convention issues Reviewed-by: Minchan Kim Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index 557e8af4..7ec53d5 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -148,8 +148,9 @@ int __frontswap_store(struct page *page) frontswap_clear(sis, offset); atomic_dec(&sis->frontswap_pages); inc_frontswap_failed_stores(); - } else + } else { inc_frontswap_failed_stores(); + } if (frontswap_writethrough_enabled) /* report failure so swap also writes to swap device */ ret = -1; @@ -250,9 +251,9 @@ void frontswap_shrink(unsigned long 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) + if (total_pages_to_unuse < si_frontswap_pages) { pages = pages_to_unuse = total_pages_to_unuse; - else { + } else { pages = si_frontswap_pages; pages_to_unuse = 0; /* unuse all */ } -- cgit v0.10.2 From 96253444dbd90c6e9e9cfcb25315da5c412b058a Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:51:01 +0200 Subject: mm: frontswap: split out __frontswap_curr_pages Code was duplicated in two functions, clean it up. Also, assert that the deduplicated code runs under the swap spinlock. Reviewed-by: Minchan Kim Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index 7ec53d5..5faf840 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -216,6 +216,20 @@ void __frontswap_invalidate_area(unsigned type) } 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; +} + /* * Frontswap, like a true swap device, may unnecessarily retain pages * under certain circumstances; "shrink" frontswap is essentially a @@ -240,11 +254,7 @@ void frontswap_shrink(unsigned long target_pages) */ 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); - } + total_pages = __frontswap_curr_pages(); if (total_pages <= target_pages) goto out; total_pages_to_unuse = total_pages - target_pages; @@ -282,16 +292,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); -- cgit v0.10.2 From f116695a500cdd84cbeac68bc373e98ae729c24b Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:51:02 +0200 Subject: mm: frontswap: split out __frontswap_unuse_pages An attempt at making frontswap_shrink shorter and more readable. This patch splits out walking through the swap list to find an entry with enough pages to unuse. Also, assert that the internal __frontswap_unuse_pages is called under swap lock, since that part of code was previously directly happen inside the lock. Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index 5faf840..faa43b7 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -230,6 +230,41 @@ static unsigned long __frontswap_curr_pages(void) 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; +} + /* * Frontswap, like a true swap device, may unnecessarily retain pages * under certain circumstances; "shrink" frontswap is essentially a @@ -240,11 +275,9 @@ static unsigned long __frontswap_curr_pages(void) */ 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; + unsigned long pages_to_unuse = 0; + int type, ret; bool locked = false; /* @@ -258,22 +291,8 @@ void frontswap_shrink(unsigned long target_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) + ret = __frontswap_unuse_pages(total_pages_to_unuse, &pages_to_unuse, &type); + if (ret < 0) goto out; locked = false; spin_unlock(&swap_lock); -- cgit v0.10.2 From 69217b4cd044671b6dddcd9d33c8e4fdfd295ae3 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:51:03 +0200 Subject: mm: frontswap: split frontswap_shrink further to simplify locking Split frontswap_shrink to simplify the locking in the original code. Also, assert that the function that was split still runs under the swap spinlock. Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index faa43b7..e6353d9 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -265,6 +265,24 @@ static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused, 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 @@ -275,10 +293,8 @@ static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused, */ void frontswap_shrink(unsigned long target_pages) { - unsigned long total_pages = 0, total_pages_to_unuse; unsigned long pages_to_unuse = 0; int type, ret; - bool locked = false; /* * we don't want to hold swap_lock while doing a very @@ -286,20 +302,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 = __frontswap_curr_pages(); - if (total_pages <= target_pages) - goto out; - total_pages_to_unuse = total_pages - target_pages; - ret = __frontswap_unuse_pages(total_pages_to_unuse, &pages_to_unuse, &type); - if (ret < 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); -- cgit v0.10.2 From d9674dda1c7ed49d503d3d7308c90a9f965f0783 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:51:04 +0200 Subject: mm: frontswap: make all branches of if statement in put page consistent Currently it has a complex structure where different things are compared at each branch. Simplify that and make both branches look similar. Reviewed-by: Minchan Kim Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index e6353d9..d8dc986 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -140,16 +140,16 @@ int __frontswap_store(struct page *page) 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); + atomic_dec(&sis->frontswap_pages); + } } if (frontswap_writethrough_enabled) /* report failure so swap also writes to swap device */ -- cgit v0.10.2 From f9f08103ebd634999abfccc8ff94985530f14d74 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:51:05 +0200 Subject: mm: frontswap: remove unnecessary check during initialization The check whether frontswap is enabled or not is done in the API functions in the frontswap header, before they are passed to the internal double-underscored frontswap functions. Remove the check from __frontswap_init for consistency. Reviewed-by: Minchan Kim Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index d8dc986..7c26e89 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -110,8 +110,7 @@ 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); -- cgit v0.10.2 From 611edfed29f406eedf66030e0864b7d3fec23f21 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 10 Jun 2012 12:51:07 +0200 Subject: mm: frontswap: split out function to clear a page out Signed-off-by: Sasha Levin Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index 7c26e89..7fb9538 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -114,6 +114,12 @@ void __frontswap_init(unsigned 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. @@ -145,10 +151,8 @@ int __frontswap_store(struct page *page) the (older) page from frontswap */ inc_frontswap_failed_stores(); - if (dup) { - frontswap_clear(sis, offset); - atomic_dec(&sis->frontswap_pages); - } + if (dup) + __frontswap_clear(sis, offset); } if (frontswap_writethrough_enabled) /* report failure so swap also writes to swap device */ @@ -191,8 +195,7 @@ 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_clear(sis, offset); inc_frontswap_invalidates(); } } -- cgit v0.10.2 From 3389b530a67e8aed049a213f751b29023bd9fcce Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 19 Jul 2012 18:51:22 -0400 Subject: mm: frontswap: remove unneeded headers Signed-off-by: Sasha Levin [v1: Rebased with tracing removed] Signed-off-by: Konrad Rzeszutek Wilk diff --git a/mm/frontswap.c b/mm/frontswap.c index 7fb9538..5318b3a 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -11,15 +11,11 @@ * This work is licensed under the terms of the GNU GPL, version 2. */ -#include #include #include #include -#include #include -#include #include -#include #include #include #include -- cgit v0.10.2 From 1d00015e268f9142de0b504b3e4a4905155276f2 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Sat, 16 Jun 2012 20:37:48 +0800 Subject: mm/frontswap: cleanup doc and comment error Signed-off-by: Wanpeng Li Signed-off-by: Konrad Rzeszutek Wilk diff --git a/Documentation/vm/frontswap.txt b/Documentation/vm/frontswap.txt index 37067cf..5ef2d13 100644 --- a/Documentation/vm/frontswap.txt +++ b/Documentation/vm/frontswap.txt @@ -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). diff --git a/mm/frontswap.c b/mm/frontswap.c index 5318b3a..6b3e71a 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -120,7 +120,7 @@ static inline void __frontswap_clear(struct swap_info_struct *sis, pgoff_t offse * "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) -- cgit v0.10.2