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