|
|
1.1 root 1: /*
2: * linux/mm/swap.c
3: *
1.1.1.7 ! root 4: * Copyright (C) 1991, 1992 Linus Torvalds
1.1 root 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 <linux/mm.h>
13: #include <linux/sched.h>
14: #include <linux/head.h>
15: #include <linux/kernel.h>
1.1.1.7 ! root 16: #include <linux/errno.h>
! 17: #include <linux/string.h>
! 18: #include <linux/stat.h>
! 19:
! 20: static int lowest_bit = 0;
! 21: static int highest_bit = 0;
! 22:
! 23: /*
! 24: * The following are used to make sure we don't thrash too much...
! 25: */
! 26: #define NR_LAST_FREE_PAGES 32
! 27: static unsigned long last_free_pages[NR_LAST_FREE_PAGES] = {0,};
1.1 root 28:
29: #define SWAP_BITS (4096<<3)
30:
31: #define bitop(name,op) \
32: static inline int name(char * addr,unsigned int nr) \
33: { \
34: int __res; \
35: __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
36: :"=g" (__res) \
37: :"r" (nr),"m" (*(addr)),"0" (0)); \
38: return __res; \
39: }
40:
41: bitop(bit,"")
42: bitop(setbit,"s")
43: bitop(clrbit,"r")
44:
45: static char * swap_bitmap = NULL;
1.1.1.7 ! root 46: static char * swap_lockmap = NULL;
1.1.1.2 root 47: unsigned int swap_device = 0;
48: struct inode * swap_file = NULL;
49:
50: void rw_swap_page(int rw, unsigned int nr, char * buf)
51: {
1.1.1.7 ! root 52: static struct wait_queue * lock_queue = NULL;
1.1.1.2 root 53:
1.1.1.7 ! root 54: if (!swap_lockmap) {
! 55: printk("No swap lock-map\n");
1.1.1.2 root 56: return;
57: }
1.1.1.7 ! root 58: while (setbit(swap_lockmap,nr))
! 59: sleep_on(&lock_queue);
! 60: if (swap_device) {
! 61: ll_rw_page(rw,swap_device,nr,buf);
! 62: } else if (swap_file) {
! 63: unsigned int zones[4];
! 64: unsigned int block = nr << 2;
! 65: int i;
! 66:
1.1.1.2 root 67: for (i = 0; i < 4; i++)
1.1.1.7 ! root 68: if (!(zones[i] = bmap(swap_file,block++))) {
1.1.1.2 root 69: printk("rw_swap_page: bad swap file\n");
70: return;
71: }
72: ll_rw_swap_file(rw,swap_file->i_dev, zones,4,buf);
1.1.1.7 ! root 73: } else
! 74: printk("re_swap_page: no swap file or device\n");
! 75: if (!clrbit(swap_lockmap,nr))
! 76: printk("rw_swap_page: lock already cleared\n");
! 77: wake_up(&lock_queue);
1.1.1.2 root 78: }
1.1 root 79:
1.1.1.7 ! root 80: static unsigned int get_swap_page(void)
1.1 root 81: {
1.1.1.7 ! root 82: unsigned int nr;
1.1 root 83:
84: if (!swap_bitmap)
85: return 0;
1.1.1.7 ! root 86: for (nr = lowest_bit; nr <= highest_bit ; nr++)
! 87: if (clrbit(swap_bitmap,nr)) {
! 88: if (nr == highest_bit)
! 89: highest_bit--;
! 90: return lowest_bit = nr;
! 91: }
1.1 root 92: return 0;
93: }
94:
1.1.1.7 ! root 95: void swap_free(unsigned int swap_nr)
1.1 root 96: {
97: if (!swap_nr)
98: return;
1.1.1.7 ! root 99: if (swap_bitmap && swap_nr < SWAP_BITS) {
! 100: if (swap_nr < lowest_bit)
! 101: lowest_bit = swap_nr;
! 102: if (swap_nr > highest_bit)
! 103: highest_bit = swap_nr;
1.1 root 104: if (!setbit(swap_bitmap,swap_nr))
105: return;
1.1.1.7 ! root 106: }
! 107: printk("swap_free: swap-space bitmap bad (bit %d)\n",swap_nr);
1.1 root 108: return;
109: }
110:
111: void swap_in(unsigned long *table_ptr)
112: {
1.1.1.7 ! root 113: unsigned long swap_nr;
1.1 root 114: unsigned long page;
115:
1.1.1.7 ! root 116: swap_nr = *table_ptr;
! 117: if (1 & swap_nr) {
1.1 root 118: printk("trying to swap in present page\n\r");
119: return;
120: }
121: if (!swap_nr) {
122: printk("No swap page in swap_in\n\r");
123: return;
124: }
1.1.1.7 ! root 125: if (!swap_bitmap) {
! 126: printk("Trying to swap in without swap bit-map");
! 127: *table_ptr = BAD_PAGE;
! 128: return;
! 129: }
! 130: page = get_free_page(GFP_KERNEL);
! 131: if (!page) {
! 132: oom(current);
! 133: page = BAD_PAGE;
! 134: } else
! 135: read_swap_page(swap_nr>>1, (char *) page);
! 136: if (*table_ptr != swap_nr) {
! 137: free_page(page);
! 138: return;
! 139: }
! 140: swap_free(swap_nr>>1);
1.1 root 141: *table_ptr = page | (PAGE_DIRTY | 7);
142: }
143:
144: int try_to_swap_out(unsigned long * table_ptr)
145: {
1.1.1.7 ! root 146: int i;
1.1 root 147: unsigned long page;
148: unsigned long swap_nr;
149:
150: page = *table_ptr;
151: if (!(PAGE_PRESENT & page))
152: return 0;
1.1.1.7 ! root 153: if (page < low_memory || page >= high_memory)
1.1 root 154: return 0;
1.1.1.7 ! root 155: for (i = 0; i < NR_LAST_FREE_PAGES; i++)
! 156: if (last_free_pages[i] == (page & 0xfffff000))
! 157: return 0;
1.1 root 158: if (PAGE_DIRTY & page) {
159: page &= 0xfffff000;
160: if (mem_map[MAP_NR(page)] != 1)
161: return 0;
162: if (!(swap_nr = get_swap_page()))
163: return 0;
164: *table_ptr = swap_nr<<1;
165: invalidate();
166: write_swap_page(swap_nr, (char *) page);
167: free_page(page);
168: return 1;
169: }
1.1.1.2 root 170: page &= 0xfffff000;
1.1 root 171: *table_ptr = 0;
172: invalidate();
173: free_page(page);
174: return 1;
175: }
176:
177: /*
1.1.1.7 ! root 178: * We never page the pages in task[0] - kernel memory.
! 179: * We page all other pages.
! 180: */
! 181: #define FIRST_VM_PAGE (TASK_SIZE>>12)
! 182: #define LAST_VM_PAGE (1024*1024)
! 183: #define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)
! 184:
! 185: /*
1.1.1.2 root 186: * Go through the page tables, searching for a user page that
187: * we can swap out.
1.1.1.5 root 188: *
1.1.1.7 ! root 189: * We now check that the process is swappable (normally only 'init'
! 190: * is un-swappable), allowing high-priority processes which cannot be
! 191: * swapped out (things like user-level device drivers (Not implemented)).
1.1 root 192: */
193: int swap_out(void)
194: {
1.1.1.2 root 195: static int dir_entry = 1024;
1.1 root 196: static int page_entry = -1;
197: int counter = VM_PAGES;
1.1.1.3 root 198: int pg_table;
1.1.1.5 root 199: struct task_struct * p;
1.1 root 200:
1.1.1.3 root 201: check_dir:
202: if (counter < 0)
203: goto no_swap;
204: if (dir_entry >= 1024)
205: dir_entry = FIRST_VM_PAGE>>10;
1.1.1.5 root 206: if (!(p = task[dir_entry >> 4])) {
207: counter -= 1024;
208: dir_entry++;
209: goto check_dir;
210: }
1.1.1.3 root 211: if (!(1 & (pg_table = pg_dir[dir_entry]))) {
212: if (pg_table) {
213: printk("bad page-table at pg_dir[%d]: %08x\n\r",
214: dir_entry,pg_table);
215: pg_dir[dir_entry] = 0;
216: }
1.1 root 217: counter -= 1024;
218: dir_entry++;
1.1.1.3 root 219: goto check_dir;
1.1 root 220: }
221: pg_table &= 0xfffff000;
1.1.1.3 root 222: check_table:
223: if (counter < 0)
224: goto no_swap;
225: counter--;
226: page_entry++;
227: if (page_entry >= 1024) {
228: page_entry = -1;
229: dir_entry++;
230: goto check_dir;
1.1 root 231: }
1.1.1.7 ! root 232: if (p->swappable && try_to_swap_out(page_entry + (unsigned long *) pg_table)) {
1.1.1.5 root 233: p->rss--;
1.1.1.7 ! root 234: dir_entry++;
1.1.1.3 root 235: return 1;
1.1.1.4 root 236: }
1.1.1.3 root 237: goto check_table;
238: no_swap:
1.1 root 239: printk("Out of swap-memory\n\r");
240: return 0;
241: }
242:
243: /*
244: * Get physical address of first (actually last :-) free page, and mark it
245: * used. If no free pages left, return 0.
246: */
1.1.1.7 ! root 247: unsigned long get_free_page(int priority)
1.1 root 248: {
1.1.1.2 root 249: unsigned long result;
1.1.1.7 ! root 250: static unsigned long index = 0;
1.1 root 251:
252: repeat:
253: __asm__("std ; repne ; scasb\n\t"
254: "jne 1f\n\t"
255: "movb $1,1(%%edi)\n\t"
256: "sall $12,%%ecx\n\t"
257: "addl %2,%%ecx\n\t"
258: "movl %%ecx,%%edx\n\t"
259: "movl $1024,%%ecx\n\t"
260: "leal 4092(%%edx),%%edi\n\t"
261: "rep ; stosl\n\t"
262: "movl %%edx,%%eax\n"
1.1.1.2 root 263: "1:\tcld"
264: :"=a" (result)
1.1.1.7 ! root 265: :"0" (0),"b" (low_memory),"c" (paging_pages),
! 266: "D" (mem_map+paging_pages-1)
1.1 root 267: :"di","cx","dx");
1.1.1.7 ! root 268: if (result >= high_memory)
1.1 root 269: goto repeat;
1.1.1.7 ! root 270: if ((result && result < low_memory) || (result & 0xfff)) {
1.1.1.2 root 271: printk("weird result: %08x\n",result);
272: result = 0;
273: }
1.1.1.7 ! root 274: if (result) {
! 275: --nr_free_pages;
! 276: if (index >= NR_LAST_FREE_PAGES)
! 277: index = 0;
! 278: last_free_pages[index] = result;
! 279: index++;
! 280: return result;
! 281: }
! 282: if (nr_free_pages) {
! 283: printk("Damn. mm_free_page count is off by %d\r\n",
! 284: nr_free_pages);
! 285: nr_free_pages = 0;
! 286: }
! 287: if (priority <= GFP_BUFFER)
! 288: return 0;
! 289: if (shrink_buffers()) {
! 290: schedule();
! 291: goto repeat;
! 292: }
! 293: if (swap_out()) {
! 294: schedule();
1.1 root 295: goto repeat;
1.1.1.7 ! root 296: }
! 297: return 0;
1.1 root 298: }
299:
1.1.1.2 root 300: /*
301: * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
302: *
303: * The swapon system call
304: */
305: int sys_swapon(const char * specialfile)
1.1 root 306: {
1.1.1.2 root 307: struct inode * swap_inode;
1.1.1.5 root 308: char * tmp;
1.1.1.2 root 309: int i,j;
1.1 root 310:
1.1.1.2 root 311: if (!suser())
312: return -EPERM;
313: if (!(swap_inode = namei(specialfile)))
314: return -ENOENT;
1.1.1.7 ! root 315: if (swap_file || swap_device || swap_bitmap || swap_lockmap) {
1.1.1.2 root 316: iput(swap_inode);
317: return -EBUSY;
318: }
319: if (S_ISBLK(swap_inode->i_mode)) {
320: swap_device = swap_inode->i_rdev;
321: iput(swap_inode);
322: } else if (S_ISREG(swap_inode->i_mode))
323: swap_file = swap_inode;
324: else {
325: iput(swap_inode);
326: return -EINVAL;
1.1 root 327: }
1.1.1.7 ! root 328: tmp = (char *) get_free_page(GFP_USER);
! 329: swap_lockmap = (char *) get_free_page(GFP_USER);
! 330: if (!tmp || !swap_lockmap) {
! 331: printk("Unable to start swapping: out of memory :-)\n");
! 332: free_page((long) tmp);
! 333: free_page((long) swap_lockmap);
1.1.1.2 root 334: iput(swap_file);
335: swap_device = 0;
336: swap_file = NULL;
1.1.1.7 ! root 337: swap_bitmap = NULL;
! 338: swap_lockmap = NULL;
1.1.1.2 root 339: return -ENOMEM;
1.1 root 340: }
1.1.1.5 root 341: read_swap_page(0,tmp);
342: if (strncmp("SWAP-SPACE",tmp+4086,10)) {
1.1 root 343: printk("Unable to find swap-space signature\n\r");
1.1.1.5 root 344: free_page((long) tmp);
1.1.1.7 ! root 345: free_page((long) swap_lockmap);
1.1.1.2 root 346: iput(swap_file);
347: swap_device = 0;
348: swap_file = NULL;
1.1 root 349: swap_bitmap = NULL;
1.1.1.7 ! root 350: swap_lockmap = NULL;
1.1.1.2 root 351: return -EINVAL;
1.1 root 352: }
1.1.1.5 root 353: memset(tmp+4086,0,10);
1.1 root 354: j = 0;
1.1.1.7 ! root 355: lowest_bit = 0;
! 356: highest_bit = 0;
1.1.1.2 root 357: for (i = 1 ; i < SWAP_BITS ; i++)
1.1.1.7 ! root 358: if (bit(tmp,i)) {
! 359: if (!lowest_bit)
! 360: lowest_bit = i;
! 361: highest_bit = i;
1.1 root 362: j++;
1.1.1.7 ! root 363: }
1.1 root 364: if (!j) {
1.1.1.2 root 365: printk("Empty swap-file\n");
1.1.1.5 root 366: free_page((long) tmp);
1.1.1.7 ! root 367: free_page((long) swap_lockmap);
1.1.1.2 root 368: iput(swap_file);
369: swap_device = 0;
370: swap_file = NULL;
1.1 root 371: swap_bitmap = NULL;
1.1.1.7 ! root 372: swap_lockmap = NULL;
1.1.1.2 root 373: return -EINVAL;
1.1 root 374: }
1.1.1.5 root 375: swap_bitmap = tmp;
1.1.1.2 root 376: printk("Adding Swap: %d pages (%d bytes) swap-space\n\r",j,j*4096);
377: return 0;
1.1 root 378: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.