This source file includes following definitions.
- rw_swap_page
- get_swap_page
- swap_duplicate
- swap_free
- swap_in
- try_to_swap_out
- sys_idle
- swap_out
- try_to_free_page
- add_mem_queue
- free_page
- __get_free_page
- try_to_unuse
- sys_swapoff
- sys_swapon
- si_swapinfo
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/mm.h>
13 #include <linux/sched.h>
14 #include <linux/head.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/string.h>
18 #include <linux/stat.h>
19
20 #include <asm/system.h>
21 #include <asm/bitops.h>
22
23 #define MAX_SWAPFILES 8
24
25 #define SWP_USED 1
26 #define SWP_WRITEOK 3
27
28 #define SWP_TYPE(entry) (((entry) & 0xffe) >> 1)
29 #define SWP_OFFSET(entry) ((entry) >> PAGE_SHIFT)
30 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << PAGE_SHIFT))
31
32 static int nr_swapfiles = 0;
33 static struct wait_queue * lock_queue = NULL;
34
35 static struct swap_info_struct {
36 unsigned long flags;
37 struct inode * swap_file;
38 unsigned int swap_device;
39 unsigned char * swap_map;
40 char * swap_lockmap;
41 int lowest_bit;
42 int highest_bit;
43 } swap_info[MAX_SWAPFILES];
44
45 extern unsigned long free_page_list;
46
47
48
49
50
51 #define NR_LAST_FREE_PAGES 32
52 static unsigned long last_free_pages[NR_LAST_FREE_PAGES] = {0,};
53
54 #define SWAP_BITS 4096
55
56 void rw_swap_page(int rw, unsigned long entry, char * buf)
57 {
58 unsigned long type, offset;
59 struct swap_info_struct * p;
60
61 type = SWP_TYPE(entry);
62 if (type >= nr_swapfiles) {
63 printk("Internal error: bad swap-device\n");
64 return;
65 }
66 p = &swap_info[type];
67 offset = SWP_OFFSET(entry);
68 if (offset >= SWAP_BITS) {
69 printk("rw_swap_page: weirdness\n");
70 return;
71 }
72 if (!(p->flags & SWP_USED)) {
73 printk("Trying to swap to unused swap-device\n");
74 return;
75 }
76 while (set_bit(offset,p->swap_lockmap))
77 sleep_on(&lock_queue);
78 if (p->swap_device) {
79 ll_rw_page(rw,p->swap_device,offset,buf);
80 } else if (p->swap_file) {
81 unsigned int zones[4];
82 unsigned int block = offset << 2;
83 int i;
84
85 for (i = 0; i < 4; i++)
86 if (!(zones[i] = bmap(p->swap_file,block++))) {
87 printk("rw_swap_page: bad swap file\n");
88 return;
89 }
90 ll_rw_swap_file(rw,p->swap_file->i_dev, zones,4,buf);
91 } else
92 printk("re_swap_page: no swap file or device\n");
93 if (clear_bit(offset,p->swap_lockmap))
94 printk("rw_swap_page: lock already cleared\n");
95 wake_up(&lock_queue);
96 }
97
98 static unsigned int get_swap_page(void)
99 {
100 struct swap_info_struct * p;
101 unsigned int offset, type;
102
103 p = swap_info;
104 for (type = 0 ; type < nr_swapfiles ; type++,p++) {
105 if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
106 continue;
107 for (offset = p->lowest_bit; offset <= p->highest_bit ; offset++) {
108 if (p->swap_map[offset])
109 continue;
110 p->swap_map[offset] = 1;
111 if (offset == p->highest_bit)
112 p->highest_bit--;
113 p->lowest_bit = offset;
114 return SWP_ENTRY(type,offset);
115 }
116 }
117 return 0;
118 }
119
120 unsigned long swap_duplicate(unsigned long entry)
121 {
122 struct swap_info_struct * p;
123 unsigned long offset, type;
124
125 if (!entry)
126 return 0;
127 offset = SWP_OFFSET(entry);
128 type = SWP_TYPE(entry);
129 if (type >= nr_swapfiles) {
130 printk("Trying to duplicate nonexistent swap-page\n");
131 return 0;
132 }
133 p = type + swap_info;
134 if (offset >= SWAP_BITS) {
135 printk("swap_free: weirness\n");
136 return 0;
137 }
138 if (!p->swap_map[offset]) {
139 printk("swap_duplicate: trying to duplicate unused page\n");
140 return 0;
141 }
142 p->swap_map[offset]++;
143 return entry;
144 }
145
146 void swap_free(unsigned long entry)
147 {
148 struct swap_info_struct * p;
149 unsigned long offset, type;
150
151 if (!entry)
152 return;
153 type = SWP_TYPE(entry);
154 if (type >= nr_swapfiles) {
155 printk("Trying to free nonexistent swap-page\n");
156 return;
157 }
158 p = & swap_info[type];
159 offset = SWP_OFFSET(entry);
160 if (offset >= SWAP_BITS) {
161 printk("swap_free: weirness\n");
162 return;
163 }
164 if (!(p->flags & SWP_USED)) {
165 printk("Trying to free swap from unused swap-device\n");
166 return;
167 }
168 while (set_bit(offset,p->swap_lockmap))
169 sleep_on(&lock_queue);
170 if (offset < p->lowest_bit)
171 p->lowest_bit = offset;
172 if (offset > p->highest_bit)
173 p->highest_bit = offset;
174 if (!p->swap_map[offset])
175 printk("swap_free: swap-space map bad (entry %08x)\n",entry);
176 else
177 p->swap_map[offset]--;
178 if (clear_bit(offset,p->swap_lockmap))
179 printk("swap_free: lock already cleared\n");
180 wake_up(&lock_queue);
181 }
182
183 void swap_in(unsigned long *table_ptr)
184 {
185 unsigned long entry;
186 unsigned long page;
187
188 entry = *table_ptr;
189 if (PAGE_PRESENT & entry) {
190 printk("trying to swap in present page\n");
191 return;
192 }
193 if (!entry) {
194 printk("No swap page in swap_in\n");
195 return;
196 }
197 page = get_free_page(GFP_KERNEL);
198 if (!page) {
199 oom(current);
200 page = BAD_PAGE;
201 } else
202 read_swap_page(entry, (char *) page);
203 if (*table_ptr != entry) {
204 free_page(page);
205 return;
206 }
207 *table_ptr = page | (PAGE_DIRTY | PAGE_PRIVATE);
208 swap_free(entry);
209 }
210
211 static int try_to_swap_out(unsigned long * table_ptr)
212 {
213 int i;
214 unsigned long page;
215 unsigned long entry;
216
217 page = *table_ptr;
218 if (!(PAGE_PRESENT & page))
219 return 0;
220 if (page >= high_memory) {
221 printk("try_to_swap_out: bad page (%08x)\n",page);
222 *table_ptr = 0;
223 return 0;
224 }
225 if (mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED)
226 return 0;
227 if (PAGE_ACCESSED & page) {
228 *table_ptr &= ~PAGE_ACCESSED;
229 return 0;
230 }
231 for (i = 0; i < NR_LAST_FREE_PAGES; i++)
232 if (last_free_pages[i] == (page & 0xfffff000))
233 return 0;
234 if (PAGE_DIRTY & page) {
235 page &= 0xfffff000;
236 if (mem_map[MAP_NR(page)] != 1)
237 return 0;
238 if (!(entry = get_swap_page()))
239 return 0;
240 *table_ptr = entry;
241 invalidate();
242 write_swap_page(entry, (char *) page);
243 free_page(page);
244 return 1;
245 }
246 page &= 0xfffff000;
247 *table_ptr = 0;
248 invalidate();
249 free_page(page);
250 return 1 + mem_map[MAP_NR(page)];
251 }
252
253
254
255
256
257
258 int sys_idle(void)
259 {
260 need_resched = 1;
261 return 0;
262 }
263
264
265
266
267
268
269
270
271
272 static int swap_out(unsigned int priority)
273 {
274 static int swap_task = 1;
275 static int swap_table = 0;
276 static int swap_page = 0;
277 int counter = NR_TASKS*8;
278 int pg_table;
279 struct task_struct * p;
280
281 counter >>= priority;
282 check_task:
283 if (counter-- < 0)
284 return 0;
285 if (swap_task >= NR_TASKS) {
286 swap_task = 1;
287 goto check_task;
288 }
289 p = task[swap_task];
290 if (!p || !p->swappable) {
291 swap_task++;
292 goto check_task;
293 }
294 check_dir:
295 if (swap_table >= 1024) {
296 swap_table = 0;
297 swap_task++;
298 goto check_task;
299 }
300 pg_table = ((unsigned long *) p->tss.cr3)[swap_table];
301 if (pg_table >= high_memory || (mem_map[MAP_NR(pg_table)] & MAP_PAGE_RESERVED)) {
302 swap_table++;
303 goto check_dir;
304 }
305 if (!(PAGE_PRESENT & pg_table)) {
306 printk("bad page-table at pg_dir[%d]: %08x\n",
307 swap_table,pg_table);
308 ((unsigned long *) p->tss.cr3)[swap_table] = 0;
309 swap_table++;
310 goto check_dir;
311 }
312 pg_table &= 0xfffff000;
313 check_table:
314 if (swap_page >= 1024) {
315 swap_page = 0;
316 swap_table++;
317 goto check_dir;
318 }
319 switch (try_to_swap_out(swap_page + (unsigned long *) pg_table)) {
320 case 0: break;
321 case 1: p->rss--; return 1;
322 default: p->rss--;
323 }
324 swap_page++;
325 goto check_table;
326 }
327
328 static int try_to_free_page(void)
329 {
330 int i=6;
331
332 while (i--) {
333 if (shrink_buffers(i))
334 return 1;
335 if (swap_out(i))
336 return 1;
337 }
338 return 0;
339 }
340
341
342
343
344
345
346 static inline void add_mem_queue(unsigned long addr, unsigned long * queue)
347 {
348 addr &= 0xfffff000;
349 *(unsigned long *) addr = *queue;
350 *queue = addr;
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364 void free_page(unsigned long addr)
365 {
366 if (addr < high_memory) {
367 unsigned short * map = mem_map + MAP_NR(addr);
368
369 if (*map) {
370 if (!(*map & MAP_PAGE_RESERVED)) {
371 unsigned long flag;
372
373 save_flags(flag);
374 cli();
375 if (!--*map) {
376 if (nr_secondary_pages < MAX_SECONDARY_PAGES) {
377 add_mem_queue(addr,&secondary_page_list);
378 nr_secondary_pages++;
379 restore_flags(flag);
380 return;
381 }
382 add_mem_queue(addr,&free_page_list);
383 nr_free_pages++;
384 }
385 restore_flags(flag);
386 }
387 return;
388 }
389 printk("Trying to free free memory (%08x): memory probabably corrupted\n",addr);
390 printk("PC = %08x\n",*(((unsigned long *)&addr)-1));
391 return;
392 }
393 printk("Trying to free nonexistent page %08x\n",addr);
394 return;
395 }
396
397
398
399
400
401
402
403
404
405
406
407 #define REMOVE_FROM_MEM_QUEUE(queue,nr) \
408 cli(); \
409 if ((result = queue) != 0) { \
410 if (!(result & 0xfff) && result < high_memory) { \
411 queue = *(unsigned long *) result; \
412 if (!mem_map[MAP_NR(result)]) { \
413 mem_map[MAP_NR(result)] = 1; \
414 nr--; \
415 last_free_pages[index = (index + 1) & (NR_LAST_FREE_PAGES - 1)] = result; \
416 restore_flags(flag); \
417 return result; \
418 } \
419 printk("Free page %08x has mem_map = %d\n", \
420 result,mem_map[MAP_NR(result)]); \
421 } else \
422 printk("Result = 0x%08x - memory map destroyed\n", result); \
423 queue = 0; \
424 nr = 0; \
425 } else if (nr) { \
426 printk(#nr " is %d, but " #queue " is empty\n",nr); \
427 nr = 0; \
428 } \
429 restore_flags(flag)
430
431
432
433
434
435
436
437
438
439
440 unsigned long __get_free_page(int priority)
441 {
442 unsigned long result, flag;
443 static unsigned long index = 0;
444
445
446
447
448
449
450 save_flags(flag);
451 repeat:
452 REMOVE_FROM_MEM_QUEUE(free_page_list,nr_free_pages);
453 if (priority == GFP_BUFFER)
454 return 0;
455 if (priority != GFP_ATOMIC)
456 if (try_to_free_page())
457 goto repeat;
458 REMOVE_FROM_MEM_QUEUE(secondary_page_list,nr_secondary_pages);
459 return 0;
460 }
461
462
463
464
465
466
467 static int try_to_unuse(unsigned int type)
468 {
469 int nr, pgt, pg;
470 unsigned long page, *ppage;
471 unsigned long tmp = 0;
472 struct task_struct *p;
473
474 nr = 0;
475
476
477
478
479 repeat:
480 for (; nr < NR_TASKS ; nr++) {
481 p = task[nr];
482 if (!p)
483 continue;
484 for (pgt = 0 ; pgt < 1024 ; pgt++) {
485 ppage = pgt + ((unsigned long *) p->tss.cr3);
486 page = *ppage;
487 if (!page)
488 continue;
489 if (!(page & PAGE_PRESENT) || (page >= high_memory)) {
490 printk("try_to_unuse: bad page directory (%d,%d:%08x)\n",nr,pgt,page);
491 *ppage = 0;
492 continue;
493 }
494 if (mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED)
495 continue;
496 ppage = (unsigned long *) (page & 0xfffff000);
497 for (pg = 0 ; pg < 1024 ; pg++,ppage++) {
498 page = *ppage;
499 if (!page)
500 continue;
501 if (page & PAGE_PRESENT) {
502 if (page >= high_memory) {
503 printk("try_to_unuse: bad page table (%d,%d,%d:%08x)\n",nr,pgt,pg,page);
504 *ppage = 0;
505 }
506 continue;
507 }
508 if (SWP_TYPE(page) != type)
509 continue;
510 if (!tmp) {
511 tmp = get_free_page(GFP_KERNEL);
512 if (!tmp)
513 return -ENOMEM;
514 goto repeat;
515 }
516 read_swap_page(page, (char *) tmp);
517 if (*ppage == page) {
518 *ppage = tmp | (PAGE_DIRTY | PAGE_PRIVATE);
519 ++p->rss;
520 swap_free(page);
521 tmp = 0;
522 }
523 goto repeat;
524 }
525 }
526 }
527 free_page(tmp);
528 return 0;
529 }
530
531 int sys_swapoff(const char * specialfile)
532 {
533 struct swap_info_struct * p;
534 struct inode * inode;
535 unsigned int type;
536 int i;
537
538 if (!suser())
539 return -EPERM;
540 i = namei(specialfile,&inode);
541 if (i)
542 return i;
543 p = swap_info;
544 for (type = 0 ; type < nr_swapfiles ; type++,p++) {
545 if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
546 continue;
547 if (p->swap_file) {
548 if (p->swap_file == inode)
549 break;
550 } else {
551 if (!S_ISBLK(inode->i_mode))
552 continue;
553 if (p->swap_device == inode->i_rdev)
554 break;
555 }
556 }
557 iput(inode);
558 if (type >= nr_swapfiles)
559 return -EINVAL;
560 p->flags = SWP_USED;
561 i = try_to_unuse(type);
562 if (i) {
563 p->flags = SWP_WRITEOK;
564 return i;
565 }
566 iput(p->swap_file);
567 p->swap_file = NULL;
568 p->swap_device = 0;
569 free_page((long) p->swap_map);
570 p->swap_map = NULL;
571 free_page((long) p->swap_lockmap);
572 p->swap_lockmap = NULL;
573 p->flags = 0;
574 return 0;
575 }
576
577
578
579
580
581
582 int sys_swapon(const char * specialfile)
583 {
584 struct swap_info_struct * p;
585 struct inode * swap_inode;
586 unsigned int type;
587 char * tmp;
588 int i,j;
589
590 if (!suser())
591 return -EPERM;
592 p = swap_info;
593 for (type = 0 ; type < nr_swapfiles ; type++,p++)
594 if (!(p->flags & SWP_USED))
595 break;
596 if (type >= MAX_SWAPFILES)
597 return -EPERM;
598 if (type >= nr_swapfiles)
599 nr_swapfiles = type+1;
600 p->flags = SWP_USED;
601 p->swap_file = NULL;
602 p->swap_device = 0;
603 p->swap_map = NULL;
604 p->swap_lockmap = NULL;
605 p->lowest_bit = 0;
606 p->highest_bit = 0;
607 i = namei(specialfile,&swap_inode);
608 if (i) {
609 p->flags = 0;
610 return i;
611 }
612 if (swap_inode->i_count != 1) {
613 iput(swap_inode);
614 p->flags = 0;
615 return -EBUSY;
616 }
617 if (S_ISBLK(swap_inode->i_mode)) {
618 p->swap_device = swap_inode->i_rdev;
619 iput(swap_inode);
620 if (!p->swap_device) {
621 p->flags = 0;
622 return -ENODEV;
623 }
624 for (i = 0 ; i < nr_swapfiles ; i++) {
625 if (i == type)
626 continue;
627 if (p->swap_device == swap_info[i].swap_device) {
628 p->swap_device = 0;
629 p->flags = 0;
630 return -EBUSY;
631 }
632 }
633 } else if (S_ISREG(swap_inode->i_mode))
634 p->swap_file = swap_inode;
635 else {
636 iput(swap_inode);
637 p->flags = 0;
638 return -EINVAL;
639 }
640 tmp = (char *) get_free_page(GFP_USER);
641 p->swap_lockmap = (char *) get_free_page(GFP_USER);
642 if (!tmp || !p->swap_lockmap) {
643 printk("Unable to start swapping: out of memory :-)\n");
644 free_page((long) tmp);
645 free_page((long) p->swap_lockmap);
646 iput(p->swap_file);
647 p->swap_device = 0;
648 p->swap_file = NULL;
649 p->swap_map = NULL;
650 p->swap_lockmap = NULL;
651 p->flags = 0;
652 return -ENOMEM;
653 }
654 read_swap_page(SWP_ENTRY(type,0),tmp);
655 if (strncmp("SWAP-SPACE",tmp+4086,10)) {
656 printk("Unable to find swap-space signature\n");
657 free_page((long) tmp);
658 free_page((long) p->swap_lockmap);
659 iput(p->swap_file);
660 p->swap_device = 0;
661 p->swap_file = NULL;
662 p->swap_map = NULL;
663 p->swap_lockmap = NULL;
664 p->flags = 0;
665 return -EINVAL;
666 }
667 memset(tmp+4086,0,10);
668 j = 0;
669 p->lowest_bit = 0;
670 p->highest_bit = 0;
671 for (i = 1 ; i < SWAP_BITS ; i++)
672 if (test_bit(i,tmp)) {
673 if (!p->lowest_bit)
674 p->lowest_bit = i;
675 p->highest_bit = i;
676 j++;
677 }
678 if (!j) {
679 printk("Empty swap-file\n");
680 free_page((long) tmp);
681 free_page((long) p->swap_lockmap);
682 iput(p->swap_file);
683 p->swap_device = 0;
684 p->swap_file = NULL;
685 p->swap_map = NULL;
686 p->swap_lockmap = NULL;
687 p->flags = 0;
688 return -EINVAL;
689 }
690 i = SWAP_BITS;
691 while (i--)
692 if (test_bit(i,tmp))
693 tmp[i] = 0;
694 else
695 tmp[i] = 128;
696 tmp[0] = 128;
697 p->swap_map = tmp;
698 p->flags = SWP_WRITEOK;
699 printk("Adding Swap: %dk swap-space\n",j<<2);
700 return 0;
701 }
702
703 void si_swapinfo(struct sysinfo *val)
704 {
705 unsigned int i, j;
706
707 val->freeswap = val->totalswap = 0;
708 for (i = 0; i < nr_swapfiles; i++) {
709 if (!(swap_info[i].flags & SWP_USED))
710 continue;
711 for (j = 0; j < 4096; ++j)
712 switch (swap_info[i].swap_map[j]) {
713 case 128:
714 continue;
715 case 0:
716 ++val->freeswap;
717 default:
718 ++val->totalswap;
719 }
720 }
721 val->freeswap <<= PAGE_SHIFT;
722 val->totalswap <<= PAGE_SHIFT;
723 return;
724 }