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