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 --- mm/frontswap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index e25025574a02..557e8af4a7d7 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 v1.2.3 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 --- mm/frontswap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index 557e8af4a7d7..7ec53d53c13a 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 v1.2.3 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 --- mm/frontswap.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index 7ec53d53c13a..5faf840f8726 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 v1.2.3 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 --- mm/frontswap.c | 59 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 20 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index 5faf840f8726..faa43b7eea6f 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 v1.2.3 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 --- mm/frontswap.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index faa43b7eea6f..e6353d9151ee 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 v1.2.3 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 --- mm/frontswap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index e6353d9151ee..d8dc9867b005 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 v1.2.3 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 --- mm/frontswap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index d8dc9867b005..7c26e899cec9 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 v1.2.3 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 --- mm/frontswap.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index 7c26e899cec9..7fb9538bec23 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 v1.2.3 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 --- mm/frontswap.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'mm') diff --git a/mm/frontswap.c b/mm/frontswap.c index 7fb9538bec23..5318b3a57080 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 v1.2.3 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 --- Documentation/vm/frontswap.txt | 4 ++-- mm/frontswap.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'mm') diff --git a/Documentation/vm/frontswap.txt b/Documentation/vm/frontswap.txt index 37067cf455f4..5ef2d1366425 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 5318b3a57080..6b3e71a2cd48 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 v1.2.3