This source file includes following definitions.
- try_to_swap_out
- swap_out_pmd
- swap_out_pgd
- swap_out_vma
- swap_out_process
- swap_out
- try_to_free_page
- kswapd
- swap_tick
- init_swap_timer
1
2
3
4
5
6
7
8
9
10
11 #include <linux/mm.h>
12 #include <linux/sched.h>
13 #include <linux/head.h>
14 #include <linux/kernel.h>
15 #include <linux/kernel_stat.h>
16 #include <linux/errno.h>
17 #include <linux/string.h>
18 #include <linux/stat.h>
19 #include <linux/swap.h>
20 #include <linux/fs.h>
21 #include <linux/swapctl.h>
22 #include <linux/smp_lock.h>
23
24 #include <asm/dma.h>
25 #include <asm/system.h>
26 #include <asm/segment.h>
27 #include <asm/bitops.h>
28 #include <asm/pgtable.h>
29
30
31
32
33 static int next_swap_jiffies = 0;
34
35
36
37
38
39 int swapout_interval = HZ / 4;
40
41
42
43
44 static struct wait_queue * kswapd_wait = NULL;
45
46
47
48
49 static int kswapd_awake = 0;
50
51
52
53
54
55 kswapd_control_t kswapd_ctl = {4, -1, -1, -1, -1};
56
57 static void init_swap_timer(void);
58
59
60
61
62
63
64
65
66
67
68
69
70 static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struct* vma,
71 unsigned long address, pte_t * page_table, int dma, int wait)
72 {
73 pte_t pte;
74 unsigned long entry;
75 unsigned long page;
76 struct page * page_map;
77
78 pte = *page_table;
79 if (!pte_present(pte))
80 return 0;
81 page = pte_page(pte);
82 if (MAP_NR(page) >= MAP_NR(high_memory))
83 return 0;
84
85 page_map = mem_map + MAP_NR(page);
86 if (PageReserved(page_map)
87 || PageLocked(page_map)
88 || (dma && !PageDMA(page_map)))
89 return 0;
90
91
92
93 if ((pte_dirty(pte) && delete_from_swap_cache(MAP_NR(page)))
94 || pte_young(pte)) {
95 set_pte(page_table, pte_mkold(pte));
96 touch_page(page_map);
97 return 0;
98 }
99 age_page(page_map);
100 if (page_map->age)
101 return 0;
102 if (pte_dirty(pte)) {
103 if (vma->vm_ops && vma->vm_ops->swapout) {
104 pid_t pid = tsk->pid;
105 vma->vm_mm->rss--;
106 if (vma->vm_ops->swapout(vma, address - vma->vm_start + vma->vm_offset, page_table))
107 kill_proc(pid, SIGBUS, 1);
108 } else {
109 if (page_map->count != 1)
110 return 0;
111 if (!(entry = get_swap_page()))
112 return 0;
113 vma->vm_mm->rss--;
114 flush_cache_page(vma, address);
115 set_pte(page_table, __pte(entry));
116 flush_tlb_page(vma, address);
117 tsk->nswap++;
118 rw_swap_page(WRITE, entry, (char *) page, wait);
119 }
120 free_page(page);
121 return 1;
122 }
123 if ((entry = find_in_swap_cache(MAP_NR(page)))) {
124 if (page_map->count != 1) {
125 set_pte(page_table, pte_mkdirty(pte));
126 printk("Aiee.. duplicated cached swap-cache entry\n");
127 return 0;
128 }
129 vma->vm_mm->rss--;
130 flush_cache_page(vma, address);
131 set_pte(page_table, __pte(entry));
132 flush_tlb_page(vma, address);
133 free_page(page);
134 return 1;
135 }
136 vma->vm_mm->rss--;
137 flush_cache_page(vma, address);
138 pte_clear(page_table);
139 flush_tlb_page(vma, address);
140 entry = page_unuse(page);
141 free_page(page);
142 return entry;
143 }
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct * vma,
160 pmd_t *dir, unsigned long address, unsigned long end, int dma, int wait)
161 {
162 pte_t * pte;
163 unsigned long pmd_end;
164
165 if (pmd_none(*dir))
166 return 0;
167 if (pmd_bad(*dir)) {
168 printk("swap_out_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
169 pmd_clear(dir);
170 return 0;
171 }
172
173 pte = pte_offset(dir, address);
174
175 pmd_end = (address + PMD_SIZE) & PMD_MASK;
176 if (end > pmd_end)
177 end = pmd_end;
178
179 do {
180 int result;
181 tsk->swap_address = address + PAGE_SIZE;
182 result = try_to_swap_out(tsk, vma, address, pte, dma, wait);
183 if (result)
184 return result;
185 address += PAGE_SIZE;
186 pte++;
187 } while (address < end);
188 return 0;
189 }
190
191 static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct * vma,
192 pgd_t *dir, unsigned long address, unsigned long end, int dma, int wait)
193 {
194 pmd_t * pmd;
195 unsigned long pgd_end;
196
197 if (pgd_none(*dir))
198 return 0;
199 if (pgd_bad(*dir)) {
200 printk("swap_out_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
201 pgd_clear(dir);
202 return 0;
203 }
204
205 pmd = pmd_offset(dir, address);
206
207 pgd_end = (address + PGDIR_SIZE) & PGDIR_MASK;
208 if (end > pgd_end)
209 end = pgd_end;
210
211 do {
212 int result = swap_out_pmd(tsk, vma, pmd, address, end, dma, wait);
213 if (result)
214 return result;
215 address = (address + PMD_SIZE) & PMD_MASK;
216 pmd++;
217 } while (address < end);
218 return 0;
219 }
220
221 static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
222 pgd_t *pgdir, unsigned long start, int dma, int wait)
223 {
224 unsigned long end;
225
226
227
228 if (vma->vm_flags & (VM_SHM | VM_LOCKED))
229 return 0;
230
231 end = vma->vm_end;
232 while (start < end) {
233 int result = swap_out_pgd(tsk, vma, pgdir, start, end, dma, wait);
234 if (result)
235 return result;
236 start = (start + PGDIR_SIZE) & PGDIR_MASK;
237 pgdir++;
238 }
239 return 0;
240 }
241
242 static int swap_out_process(struct task_struct * p, int dma, int wait)
243 {
244 unsigned long address;
245 struct vm_area_struct* vma;
246
247
248
249
250 address = p->swap_address;
251 p->swap_address = 0;
252
253
254
255
256 vma = find_vma(p, address);
257 if (!vma)
258 return 0;
259 if (address < vma->vm_start)
260 address = vma->vm_start;
261
262 for (;;) {
263 int result = swap_out_vma(p, vma, pgd_offset(p->mm, address), address, dma, wait);
264 if (result)
265 return result;
266 vma = vma->vm_next;
267 if (!vma)
268 break;
269 address = vma->vm_start;
270 }
271 p->swap_address = 0;
272 return 0;
273 }
274
275 static int swap_out(unsigned int priority, int dma, int wait)
276 {
277 static int swap_task;
278 int loop, counter;
279 struct task_struct *p;
280
281 counter = ((PAGEOUT_WEIGHT * nr_tasks) >> 10) >> priority;
282 for(; counter >= 0; counter--) {
283
284
285
286
287 loop = 0;
288 while(1) {
289 if (swap_task >= NR_TASKS) {
290 swap_task = 1;
291 if (loop)
292
293 return 0;
294 loop = 1;
295 }
296
297 p = task[swap_task];
298 if (p && p->swappable && p->mm->rss)
299 break;
300
301 swap_task++;
302 }
303
304
305
306
307 if (!p->swap_cnt) {
308
309
310 p->swap_cnt = AGE_CLUSTER_SIZE(p->mm->rss);
311 }
312 if (!--p->swap_cnt)
313 swap_task++;
314 switch (swap_out_process(p, dma, wait)) {
315 case 0:
316 if (p->swap_cnt)
317 swap_task++;
318 break;
319 case 1:
320 return 1;
321 default:
322 break;
323 }
324 }
325 return 0;
326 }
327
328
329
330
331
332
333 int try_to_free_page(int priority, int dma, int wait)
334 {
335 static int state = 0;
336 int i=6;
337
338 switch (state) {
339 do {
340 case 0:
341 if (shrink_mmap(i, dma))
342 return 1;
343 state = 1;
344 case 1:
345 if (shm_swap(i, dma))
346 return 1;
347 state = 2;
348 default:
349 if (swap_out(i, dma, wait))
350 return 1;
351 state = 0;
352 } while (i--);
353 }
354 return 0;
355 }
356
357
358
359
360
361
362 int kswapd(void *unused)
363 {
364 int i;
365 char *revision="$Revision: 1.4.2.2 $", *s, *e;
366
367 current->session = 1;
368 current->pgrp = 1;
369 sprintf(current->comm, "kswapd");
370 current->blocked = ~0UL;
371
372
373
374
375
376
377
378 #ifdef __SMP__
379 lock_kernel();
380 syscall_count++;
381 #endif
382
383
384 current->policy = SCHED_FIFO;
385 current->priority = 32;
386
387
388
389 init_swap_timer();
390
391 if ((s = strchr(revision, ':')) &&
392 (e = strchr(s, '$')))
393 s++, i = e - s;
394 else
395 s = revision, i = -1;
396 printk ("Started kswapd v%.*s\n", i, s);
397
398 while (1) {
399 kswapd_awake = 0;
400 current->signal = 0;
401 interruptible_sleep_on(&kswapd_wait);
402 kswapd_awake = 1;
403 swapstats.wakeups++;
404
405 for (i=0; i < kswapd_ctl.maxpages; i++)
406 try_to_free_page(GFP_KERNEL, 0, 0);
407 }
408 }
409
410
411
412
413
414 void swap_tick(void)
415 {
416 if ((nr_free_pages + nr_async_pages) < free_pages_low ||
417 ((nr_free_pages + nr_async_pages) < free_pages_high &&
418 jiffies >= next_swap_jiffies)) {
419 if (!kswapd_awake && kswapd_ctl.maxpages > 0) {
420 wake_up(&kswapd_wait);
421 need_resched = 1;
422 kswapd_awake = 1;
423 }
424 next_swap_jiffies = jiffies + swapout_interval;
425 }
426 timer_active |= (1<<SWAP_TIMER);
427 }
428
429
430
431
432
433
434 void init_swap_timer(void)
435 {
436 timer_table[SWAP_TIMER].expires = 0;
437 timer_table[SWAP_TIMER].fn = swap_tick;
438 timer_active |= (1<<SWAP_TIMER);
439 }