|
|
1.1 root 1: /*
2: * linux/mm/swap.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: /*
8: * This file should contain most things doing the swapping from/to disk.
9: * Started 18.12.91
10: */
11:
12: #include <string.h>
1.1.1.2 ! root 13: #include <errno.h>
1.1 root 14:
15: #include <linux/mm.h>
1.1.1.2 ! root 16: #include <sys/stat.h>
1.1 root 17: #include <linux/sched.h>
18: #include <linux/head.h>
19: #include <linux/kernel.h>
20:
21: #define SWAP_BITS (4096<<3)
22:
23: #define bitop(name,op) \
24: static inline int name(char * addr,unsigned int nr) \
25: { \
26: int __res; \
27: __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
28: :"=g" (__res) \
29: :"r" (nr),"m" (*(addr)),"0" (0)); \
30: return __res; \
31: }
32:
33: bitop(bit,"")
34: bitop(setbit,"s")
35: bitop(clrbit,"r")
36:
37: static char * swap_bitmap = NULL;
1.1.1.2 ! root 38: unsigned int swap_device = 0;
! 39: struct inode * swap_file = NULL;
! 40:
! 41: void rw_swap_page(int rw, unsigned int nr, char * buf)
! 42: {
! 43: unsigned int zones[4];
! 44: int i;
! 45:
! 46: if (swap_device) {
! 47: ll_rw_page(rw,swap_device,nr,buf);
! 48: return;
! 49: }
! 50: if (swap_file) {
! 51: nr <<= 2;
! 52: for (i = 0; i < 4; i++)
! 53: if (!(zones[i] = bmap(swap_file,nr++))) {
! 54: printk("rw_swap_page: bad swap file\n");
! 55: return;
! 56: }
! 57: ll_rw_swap_file(rw,swap_file->i_dev, zones,4,buf);
! 58: return;
! 59: }
! 60: printk("ll_swap_page: no swap file or device\n");
! 61: }
1.1 root 62:
63: /*
64: * We never page the pages in task[0] - kernel memory.
65: * We page all other pages.
66: */
67: #define FIRST_VM_PAGE (TASK_SIZE>>12)
68: #define LAST_VM_PAGE (1024*1024)
69: #define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)
70:
71: static int get_swap_page(void)
72: {
73: int nr;
74:
75: if (!swap_bitmap)
76: return 0;
1.1.1.2 ! root 77: for (nr = 1; nr < SWAP_BITS ; nr++)
1.1 root 78: if (clrbit(swap_bitmap,nr))
79: return nr;
80: return 0;
81: }
82:
83: void swap_free(int swap_nr)
84: {
85: if (!swap_nr)
86: return;
87: if (swap_bitmap && swap_nr < SWAP_BITS)
88: if (!setbit(swap_bitmap,swap_nr))
89: return;
1.1.1.2 ! root 90: printk("swap_free: swap-space bitmap bad\n");
1.1 root 91: return;
92: }
93:
94: void swap_in(unsigned long *table_ptr)
95: {
96: int swap_nr;
97: unsigned long page;
98:
99: if (!swap_bitmap) {
100: printk("Trying to swap in without swap bit-map");
101: return;
102: }
103: if (1 & *table_ptr) {
104: printk("trying to swap in present page\n\r");
105: return;
106: }
107: swap_nr = *table_ptr >> 1;
108: if (!swap_nr) {
109: printk("No swap page in swap_in\n\r");
110: return;
111: }
112: if (!(page = get_free_page()))
113: oom();
114: read_swap_page(swap_nr, (char *) page);
115: if (setbit(swap_bitmap,swap_nr))
116: printk("swapping in multiply from same page\n\r");
117: *table_ptr = page | (PAGE_DIRTY | 7);
118: }
119:
120: int try_to_swap_out(unsigned long * table_ptr)
121: {
122: unsigned long page;
123: unsigned long swap_nr;
124:
125: page = *table_ptr;
126: if (!(PAGE_PRESENT & page))
127: return 0;
128: if (page - LOW_MEM > PAGING_MEMORY)
129: return 0;
130: if (PAGE_DIRTY & page) {
131: page &= 0xfffff000;
132: if (mem_map[MAP_NR(page)] != 1)
133: return 0;
134: if (!(swap_nr = get_swap_page()))
135: return 0;
136: *table_ptr = swap_nr<<1;
137: invalidate();
138: write_swap_page(swap_nr, (char *) page);
139: free_page(page);
140: return 1;
141: }
1.1.1.2 ! root 142: page &= 0xfffff000;
1.1 root 143: *table_ptr = 0;
144: invalidate();
145: free_page(page);
146: return 1;
147: }
148:
149: /*
1.1.1.2 ! root 150: * Go through the page tables, searching for a user page that
! 151: * we can swap out.
1.1 root 152: */
153: int swap_out(void)
154: {
1.1.1.2 ! root 155: static int dir_entry = 1024;
1.1 root 156: static int page_entry = -1;
157: int counter = VM_PAGES;
1.1.1.2 ! root 158: int pg_table = 0;
1.1 root 159:
1.1.1.2 ! root 160: repeat:
! 161: while (counter > 0) {
1.1 root 162: counter -= 1024;
163: dir_entry++;
164: if (dir_entry >= 1024)
165: dir_entry = FIRST_VM_PAGE>>10;
1.1.1.2 ! root 166: if (pg_table = pg_dir[dir_entry])
! 167: break;
! 168: }
! 169: if (counter <= 0) {
! 170: printk("Out of swap-memory\n");
! 171: return 0;
! 172: }
! 173: if (!(pg_table & 1)) {
! 174: printk("bad page-table at pg_dir[%d]: %08x\n\r",dir_entry,
! 175: pg_table);
! 176: return 0;
1.1 root 177: }
178: pg_table &= 0xfffff000;
1.1.1.2 ! root 179: while (counter > 0) {
! 180: counter--;
1.1 root 181: page_entry++;
182: if (page_entry >= 1024) {
1.1.1.2 ! root 183: page_entry = -1;
! 184: goto repeat;
1.1 root 185: }
186: if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
187: return 1;
188: }
189: printk("Out of swap-memory\n\r");
190: return 0;
191: }
192:
193: /*
194: * Get physical address of first (actually last :-) free page, and mark it
195: * used. If no free pages left, return 0.
196: */
197: unsigned long get_free_page(void)
198: {
1.1.1.2 ! root 199: unsigned long result;
1.1 root 200:
201: repeat:
202: __asm__("std ; repne ; scasb\n\t"
203: "jne 1f\n\t"
204: "movb $1,1(%%edi)\n\t"
205: "sall $12,%%ecx\n\t"
206: "addl %2,%%ecx\n\t"
207: "movl %%ecx,%%edx\n\t"
208: "movl $1024,%%ecx\n\t"
209: "leal 4092(%%edx),%%edi\n\t"
210: "rep ; stosl\n\t"
211: "movl %%edx,%%eax\n"
1.1.1.2 ! root 212: "1:\tcld"
! 213: :"=a" (result)
1.1 root 214: :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
215: "D" (mem_map+PAGING_PAGES-1)
216: :"di","cx","dx");
1.1.1.2 ! root 217: if (result >= HIGH_MEMORY)
1.1 root 218: goto repeat;
1.1.1.2 ! root 219: if ((result && result < LOW_MEM) || (result & 0xfff)) {
! 220: printk("weird result: %08x\n",result);
! 221: result = 0;
! 222: }
! 223: if (!result && swap_out())
1.1 root 224: goto repeat;
1.1.1.2 ! root 225: return result;
1.1 root 226: }
227:
1.1.1.2 ! root 228: /*
! 229: * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
! 230: *
! 231: * The swapon system call
! 232: */
! 233:
! 234: int sys_swapon(const char * specialfile)
1.1 root 235: {
1.1.1.2 ! root 236: struct inode * swap_inode;
! 237: int i,j;
1.1 root 238:
1.1.1.2 ! root 239: if (!suser())
! 240: return -EPERM;
! 241: if (!(swap_inode = namei(specialfile)))
! 242: return -ENOENT;
! 243: if (swap_file || swap_device || swap_bitmap) {
! 244: iput(swap_inode);
! 245: return -EBUSY;
! 246: }
! 247: if (S_ISBLK(swap_inode->i_mode)) {
! 248: swap_device = swap_inode->i_rdev;
! 249: iput(swap_inode);
! 250: } else if (S_ISREG(swap_inode->i_mode))
! 251: swap_file = swap_inode;
! 252: else {
! 253: iput(swap_inode);
! 254: return -EINVAL;
1.1 root 255: }
256: swap_bitmap = (char *) get_free_page();
257: if (!swap_bitmap) {
1.1.1.2 ! root 258: iput(swap_file);
! 259: swap_device = 0;
! 260: swap_file = NULL;
! 261: printk("Unable to start swapping: out of memory :-)\n");
! 262: return -ENOMEM;
1.1 root 263: }
264: read_swap_page(0,swap_bitmap);
265: if (strncmp("SWAP-SPACE",swap_bitmap+4086,10)) {
266: printk("Unable to find swap-space signature\n\r");
267: free_page((long) swap_bitmap);
1.1.1.2 ! root 268: iput(swap_file);
! 269: swap_device = 0;
! 270: swap_file = NULL;
1.1 root 271: swap_bitmap = NULL;
1.1.1.2 ! root 272: return -EINVAL;
1.1 root 273: }
274: memset(swap_bitmap+4086,0,10);
275: j = 0;
1.1.1.2 ! root 276: for (i = 1 ; i < SWAP_BITS ; i++)
1.1 root 277: if (bit(swap_bitmap,i))
278: j++;
279: if (!j) {
1.1.1.2 ! root 280: printk("Empty swap-file\n");
1.1 root 281: free_page((long) swap_bitmap);
1.1.1.2 ! root 282: iput(swap_file);
! 283: swap_device = 0;
! 284: swap_file = NULL;
1.1 root 285: swap_bitmap = NULL;
1.1.1.2 ! root 286: return -EINVAL;
1.1 root 287: }
1.1.1.2 ! root 288: printk("Adding Swap: %d pages (%d bytes) swap-space\n\r",j,j*4096);
! 289: return 0;
1.1 root 290: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.