Contents of /trunk/kernel26-tinyalx/patches-2.6.21-r14/0016-2.6.21-mm-background_scan-2.patch
Parent Directory | Revision Log
Revision 453 -
(show annotations)
(download)
Fri Jan 25 23:34:48 2008 UTC (16 years, 8 months ago) by niro
File size: 4567 byte(s)
Fri Jan 25 23:34:48 2008 UTC (16 years, 8 months ago) by niro
File size: 4567 byte(s)
-tiny-alx 2.6.21-tinyalx-r14
1 | Add a background scanning timer to restore the watermarks to the pages_lots |
2 | level and only call on it if kswapd has not been called upon for the last 5 |
3 | seconds. This allows us to balance all zones to the more generous pages_lots |
4 | watermark at a time unrelated to page allocation thus leading to lighter |
5 | levels of vm load when called upon under page allocation. |
6 | |
7 | Signed-off-by: Con Kolivas <kernel@kolivas.org> |
8 | |
9 | The -ck patches modify mm/vmscan.c and add a timer to wake up kswapd every 5 |
10 | seconds. This timer is initialized after the creation of the kswapd thread. |
11 | |
12 | The kswapd() thread function calls mod_timer at the front of its infinite |
13 | service loop (to reset the timer to 5 seconds in the future). mod_timer() |
14 | includes a BUG_ON() to assert that the timer's callback function is set. |
15 | |
16 | Since the wakeup timer is initialized after the kswapd thread is created, if |
17 | kswapd gets scheduled before kswapd_run() has prepared the timer, the |
18 | BUG_ON() check will throw a stack trace and immediately terminate the kswapd |
19 | thread. |
20 | |
21 | This patch modifies the kswapd_run() function in mm/vmscan.c to initialize the |
22 | watermark timer before starting the kswapd thread. |
23 | |
24 | Signed-off-by: Chase Venters <chase.venters at clientec.com> |
25 | |
26 | include/linux/mmzone.h | 2 ++ |
27 | mm/vmscan.c | 42 ++++++++++++++++++++++++++++++++++++++++++ |
28 | 2 files changed, 44 insertions(+) |
29 | |
30 | Index: linux-2.6.21-ck2/include/linux/mmzone.h |
31 | =================================================================== |
32 | --- linux-2.6.21-ck2.orig/include/linux/mmzone.h 2007-05-14 19:49:55.000000000 +1000 |
33 | +++ linux-2.6.21-ck2/include/linux/mmzone.h 2007-05-14 19:49:56.000000000 +1000 |
34 | @@ -13,6 +13,7 @@ |
35 | #include <linux/init.h> |
36 | #include <linux/seqlock.h> |
37 | #include <linux/nodemask.h> |
38 | +#include <linux/timer.h> |
39 | #include <asm/atomic.h> |
40 | #include <asm/page.h> |
41 | |
42 | @@ -449,6 +450,7 @@ typedef struct pglist_data { |
43 | wait_queue_head_t kswapd_wait; |
44 | struct task_struct *kswapd; |
45 | int kswapd_max_order; |
46 | + struct timer_list watermark_timer; |
47 | } pg_data_t; |
48 | |
49 | #define node_present_pages(nid) (NODE_DATA(nid)->node_present_pages) |
50 | Index: linux-2.6.21-ck2/mm/vmscan.c |
51 | =================================================================== |
52 | --- linux-2.6.21-ck2.orig/mm/vmscan.c 2007-05-14 19:49:56.000000000 +1000 |
53 | +++ linux-2.6.21-ck2/mm/vmscan.c 2007-05-14 19:49:56.000000000 +1000 |
54 | @@ -37,6 +37,7 @@ |
55 | #include <linux/rwsem.h> |
56 | #include <linux/delay.h> |
57 | #include <linux/kthread.h> |
58 | +#include <linux/timer.h> |
59 | #include <linux/freezer.h> |
60 | |
61 | #include <asm/tlbflush.h> |
62 | @@ -1335,6 +1336,8 @@ out: |
63 | return nr_reclaimed; |
64 | } |
65 | |
66 | +#define WT_EXPIRY (HZ * 5) /* Time to wakeup watermark_timer */ |
67 | + |
68 | /* |
69 | * The background pageout daemon, started as a kernel thread |
70 | * from the init process. |
71 | @@ -1384,6 +1387,8 @@ static int kswapd(void *p) |
72 | |
73 | try_to_freeze(); |
74 | |
75 | + /* kswapd has been busy so delay watermark_timer */ |
76 | + mod_timer(&pgdat->watermark_timer, jiffies + WT_EXPIRY); |
77 | prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); |
78 | new_order = pgdat->kswapd_max_order; |
79 | pgdat->kswapd_max_order = 0; |
80 | @@ -1604,20 +1609,57 @@ static int __devinit cpu_callback(struct |
81 | } |
82 | |
83 | /* |
84 | + * We wake up kswapd every WT_EXPIRY till free ram is above pages_lots |
85 | + */ |
86 | +static void watermark_wakeup(unsigned long data) |
87 | +{ |
88 | + pg_data_t *pgdat = (pg_data_t *)data; |
89 | + struct timer_list *wt = &pgdat->watermark_timer; |
90 | + int i; |
91 | + |
92 | + if (!waitqueue_active(&pgdat->kswapd_wait) || above_background_load()) |
93 | + goto out; |
94 | + for (i = pgdat->nr_zones - 1; i >= 0; i--) { |
95 | + struct zone *z = pgdat->node_zones + i; |
96 | + |
97 | + if (!populated_zone(z) || is_highmem(z)) { |
98 | + /* We are better off leaving highmem full */ |
99 | + continue; |
100 | + } |
101 | + if (!zone_watermark_ok(z, 0, z->pages_lots, 0, 0)) { |
102 | + wake_up_interruptible(&pgdat->kswapd_wait); |
103 | + goto out; |
104 | + } |
105 | + } |
106 | +out: |
107 | + mod_timer(wt, jiffies + WT_EXPIRY); |
108 | + return; |
109 | +} |
110 | + |
111 | +/* |
112 | * This kswapd start function will be called by init and node-hot-add. |
113 | * On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added. |
114 | */ |
115 | int kswapd_run(int nid) |
116 | { |
117 | pg_data_t *pgdat = NODE_DATA(nid); |
118 | + struct timer_list *wt; |
119 | int ret = 0; |
120 | |
121 | if (pgdat->kswapd) |
122 | return 0; |
123 | |
124 | + wt = &pgdat->watermark_timer; |
125 | + init_timer(wt); |
126 | + wt->data = (unsigned long)pgdat; |
127 | + wt->function = watermark_wakeup; |
128 | + wt->expires = jiffies + WT_EXPIRY; |
129 | + add_timer(wt); |
130 | + |
131 | pgdat->kswapd = kthread_run(kswapd, pgdat, "kswapd%d", nid); |
132 | if (IS_ERR(pgdat->kswapd)) { |
133 | /* failure at boot is fatal */ |
134 | + del_timer(wt); |
135 | BUG_ON(system_state == SYSTEM_BOOTING); |
136 | printk("Failed to start kswapd on node %d\n",nid); |
137 | ret = -1; |