summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/mmzone.h1
-rw-r--r--include/linux/swap.h1
-rw-r--r--mm/page_alloc.c10
-rw-r--r--mm/vmscan.c52
4 files changed, 21 insertions, 43 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 0b14f37ca016..fc439380cb0e 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -168,6 +168,7 @@ typedef struct pglist_data {
unsigned long node_size;
int node_id;
struct pglist_data *pgdat_next;
+ wait_queue_head_t kswapd_wait;
} pg_data_t;
extern int numnodes;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 8844b1408788..f4acbd1e9b46 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -162,7 +162,6 @@ extern void FASTCALL(activate_page(struct page *));
extern void swap_setup(void);
/* linux/mm/vmscan.c */
-extern wait_queue_head_t kswapd_wait;
extern int try_to_free_pages(struct zone *, unsigned int, unsigned int);
/* linux/mm/page_io.c */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 1443104b6973..86b534cef5f8 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -348,8 +348,12 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
classzone->need_balance = 1;
mb();
/* we're somewhat low on memory, failed to find what we needed */
- if (waitqueue_active(&kswapd_wait))
- wake_up_interruptible(&kswapd_wait);
+ for (i = 0; zones[i] != NULL; i++) {
+ struct zone *z = zones[i];
+ if (z->free_pages <= z->pages_low &&
+ waitqueue_active(&z->zone_pgdat->kswapd_wait))
+ wake_up_interruptible(&z->zone_pgdat->kswapd_wait);
+ }
/* Go through the zonelist again, taking __GFP_HIGH into account */
min = 1UL << order;
@@ -836,6 +840,8 @@ void __init free_area_init_core(pg_data_t *pgdat,
unsigned long zone_start_pfn = pgdat->node_start_pfn;
pgdat->nr_zones = 0;
+ init_waitqueue_head(&pgdat->kswapd_wait);
+
local_offset = 0; /* offset within lmem_map */
for (j = 0; j < MAX_NR_ZONES; j++) {
struct zone *zone = pgdat->node_zones + j;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 4302f698a7a4..9bec21dc9f0c 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -667,8 +667,6 @@ try_to_free_pages(struct zone *classzone,
return 0;
}
-DECLARE_WAIT_QUEUE_HEAD(kswapd_wait);
-
static int check_classzone_need_balance(struct zone *classzone)
{
struct zone *first_classzone;
@@ -707,20 +705,6 @@ static int kswapd_balance_pgdat(pg_data_t * pgdat)
return need_more_balance;
}
-static void kswapd_balance(void)
-{
- int need_more_balance;
- pg_data_t * pgdat;
-
- do {
- need_more_balance = 0;
- pgdat = pgdat_list;
- do
- need_more_balance |= kswapd_balance_pgdat(pgdat);
- while ((pgdat = pgdat->pgdat_next));
- } while (need_more_balance);
-}
-
static int kswapd_can_sleep_pgdat(pg_data_t * pgdat)
{
struct zone *zone;
@@ -728,28 +712,13 @@ static int kswapd_can_sleep_pgdat(pg_data_t * pgdat)
for (i = pgdat->nr_zones-1; i >= 0; i--) {
zone = pgdat->node_zones + i;
- if (!zone->need_balance)
- continue;
- return 0;
+ if (zone->need_balance)
+ return 0;
}
return 1;
}
-static int kswapd_can_sleep(void)
-{
- pg_data_t * pgdat;
-
- pgdat = pgdat_list;
- do {
- if (kswapd_can_sleep_pgdat(pgdat))
- continue;
- return 0;
- } while ((pgdat = pgdat->pgdat_next));
-
- return 1;
-}
-
/*
* The background pageout daemon, started as a kernel thread
* from the init process.
@@ -763,13 +732,14 @@ static int kswapd_can_sleep(void)
* If there are applications that are active memory-allocators
* (most normal use), this basically shouldn't matter.
*/
-int kswapd(void *unused)
+int kswapd(void *p)
{
+ pg_data_t *pgdat = (pg_data_t*)p;
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
daemonize();
- strcpy(tsk->comm, "kswapd");
+ sprintf(tsk->comm, "kswapd%d", pgdat->node_id);
sigfillset(&tsk->blocked);
/*
@@ -793,30 +763,32 @@ int kswapd(void *unused)
if (current->flags & PF_FREEZE)
refrigerator(PF_IOTHREAD);
__set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&kswapd_wait, &wait);
+ add_wait_queue(&pgdat->kswapd_wait, &wait);
mb();
- if (kswapd_can_sleep())
+ if (kswapd_can_sleep_pgdat(pgdat))
schedule();
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&kswapd_wait, &wait);
+ remove_wait_queue(&pgdat->kswapd_wait, &wait);
/*
* If we actually get into a low-memory situation,
* the processes needing more memory will wake us
* up on a more timely basis.
*/
- kswapd_balance();
+ kswapd_balance_pgdat(pgdat);
blk_run_queues();
}
}
static int __init kswapd_init(void)
{
+ pg_data_t *pgdat;
printk("Starting kswapd\n");
swap_setup();
- kernel_thread(kswapd, NULL, CLONE_KERNEL);
+ for_each_pgdat(pgdat)
+ kernel_thread(kswapd, pgdat, CLONE_KERNEL);
return 0;
}