Commit 8ead40f5 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] page freeing function for swsusp

Software suspend needs a way of forcing page reclaim, up to the point
where 50% of memory is free.

This patch implements a function to do that:

	int shrink_all_memory(int nr_pages);

Will attempt to reclaim `nr_pages' pages and return them to the free
pages pool.  It returns the number of pages which it actually freed.

If called with a "large" number of pages it will only free up to a few
hundred, so the caller needs to loop on it.

If it returns zero then there is no point in calling it again.
parent 5aa6ba1a
...@@ -163,6 +163,7 @@ extern void swap_setup(void); ...@@ -163,6 +163,7 @@ extern void swap_setup(void);
/* linux/mm/vmscan.c */ /* linux/mm/vmscan.c */
extern int try_to_free_pages(struct zone *, unsigned int, unsigned int); extern int try_to_free_pages(struct zone *, unsigned int, unsigned int);
int shrink_all_memory(int nr_pages);
/* linux/mm/page_io.c */ /* linux/mm/page_io.c */
int swap_readpage(struct file *file, struct page *page); int swap_readpage(struct file *file, struct page *page);
......
...@@ -695,12 +695,19 @@ try_to_free_pages(struct zone *classzone, ...@@ -695,12 +695,19 @@ try_to_free_pages(struct zone *classzone,
} }
/* /*
* kswapd will work across all this node's zones until they are all at * For kswapd, balance_pgdat() will work across all this node's zones until
* pages_high. * they are all at pages_high.
*
* If `nr_pages' is non-zero then it is the number of pages which are to be
* reclaimed, regardless of the zone occupancies. This is a software suspend
* special.
*
* Returns the number of pages which were actually freed.
*/ */
static void kswapd_balance_pgdat(pg_data_t *pgdat) static int balance_pgdat(pg_data_t *pgdat, int nr_pages)
{ {
int priority = DEF_PRIORITY; int to_free = nr_pages;
int priority;
int i; int i;
for (priority = DEF_PRIORITY; priority; priority--) { for (priority = DEF_PRIORITY; priority; priority--) {
...@@ -713,20 +720,23 @@ static void kswapd_balance_pgdat(pg_data_t *pgdat) ...@@ -713,20 +720,23 @@ static void kswapd_balance_pgdat(pg_data_t *pgdat)
int to_reclaim; int to_reclaim;
to_reclaim = zone->pages_high - zone->free_pages; to_reclaim = zone->pages_high - zone->free_pages;
if (nr_pages && to_free > 0)
to_reclaim = min(to_free, SWAP_CLUSTER_MAX*8);
if (to_reclaim <= 0) if (to_reclaim <= 0)
continue; continue;
success = 0; success = 0;
max_scan = zone->nr_inactive >> priority; max_scan = zone->nr_inactive >> priority;
if (max_scan < to_reclaim * 2) if (max_scan < to_reclaim * 2)
max_scan = to_reclaim * 2; max_scan = to_reclaim * 2;
shrink_zone(zone, max_scan, GFP_KSWAPD, to_free -= shrink_zone(zone, max_scan, GFP_KSWAPD,
to_reclaim, &nr_mapped); to_reclaim, &nr_mapped);
shrink_slab(max_scan + nr_mapped, GFP_KSWAPD); shrink_slab(max_scan + nr_mapped, GFP_KSWAPD);
} }
if (success) if (success)
break; /* All zones are at pages_high */ break;
blk_congestion_wait(WRITE, HZ/4); blk_congestion_wait(WRITE, HZ/4);
} }
return nr_pages - to_free;
} }
/* /*
...@@ -773,11 +783,35 @@ int kswapd(void *p) ...@@ -773,11 +783,35 @@ int kswapd(void *p)
prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
schedule(); schedule();
finish_wait(&pgdat->kswapd_wait, &wait); finish_wait(&pgdat->kswapd_wait, &wait);
kswapd_balance_pgdat(pgdat); balance_pgdat(pgdat, 0);
blk_run_queues(); blk_run_queues();
} }
} }
#ifdef CONFIG_SOFTWARE_SUSPEND
/*
* Try to free `nr_pages' of memory, system-wide. Returns the number of freed
* pages.
*/
int shrink_all_memory(int nr_pages)
{
pg_data_t *pgdat;
int nr_to_free = nr_pages;
int ret = 0;
for_each_pgdat(pgdat) {
int freed;
freed = balance_pgdat(pgdat, nr_to_free);
ret += freed;
nr_to_free -= freed;
if (nr_to_free <= 0)
break;
}
return ret;
}
#endif
static int __init kswapd_init(void) static int __init kswapd_init(void)
{ {
pg_data_t *pgdat; pg_data_t *pgdat;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment