This source file includes following definitions.
- rw_swap_page
- get_swap_page
- swap_free
- swap_in
- try_to_swap_out
- swap_out
- get_free_page
- sys_swapon
1
2
3
4
5
6
7
8
9
10
11
12 #include <errno.h>
13
14 #include <linux/stat.h>
15 #include <linux/mm.h>
16 #include <linux/string.h>
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;
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 }
62
63
64
65
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;
77 for (nr = 1; nr < SWAP_BITS ; nr++)
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;
90 printk("swap_free: swap-space bitmap bad\n");
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 }
142 page &= 0xfffff000;
143 *table_ptr = 0;
144 invalidate();
145 free_page(page);
146 return 1;
147 }
148
149
150
151
152
153
154
155
156
157
158
159 int swap_out(void)
160 {
161 static int dir_entry = 1024;
162 static int page_entry = -1;
163 int counter = VM_PAGES;
164 int pg_table;
165 struct task_struct * p;
166
167 check_dir:
168 if (counter < 0)
169 goto no_swap;
170 if (dir_entry >= 1024)
171 dir_entry = FIRST_VM_PAGE>>10;
172 if (!(p = task[dir_entry >> 4])) {
173 counter -= 1024;
174 dir_entry++;
175 goto check_dir;
176 }
177 if (!(1 & (pg_table = pg_dir[dir_entry]))) {
178 if (pg_table) {
179 printk("bad page-table at pg_dir[%d]: %08x\n\r",
180 dir_entry,pg_table);
181 pg_dir[dir_entry] = 0;
182 }
183 counter -= 1024;
184 dir_entry++;
185 goto check_dir;
186 }
187 pg_table &= 0xfffff000;
188 check_table:
189 if (counter < 0)
190 goto no_swap;
191 counter--;
192 page_entry++;
193 if (page_entry >= 1024) {
194 page_entry = -1;
195 dir_entry++;
196 goto check_dir;
197 }
198 if (try_to_swap_out(page_entry + (unsigned long *) pg_table)) {
199 p->rss--;
200 return 1;
201 }
202 goto check_table;
203 no_swap:
204 printk("Out of swap-memory\n\r");
205 return 0;
206 }
207
208
209
210
211
212 unsigned long get_free_page(void)
213 {
214 unsigned long result;
215
216 repeat:
217 __asm__("std ; repne ; scasb\n\t"
218 "jne 1f\n\t"
219 "movb $1,1(%%edi)\n\t"
220 "sall $12,%%ecx\n\t"
221 "addl %2,%%ecx\n\t"
222 "movl %%ecx,%%edx\n\t"
223 "movl $1024,%%ecx\n\t"
224 "leal 4092(%%edx),%%edi\n\t"
225 "rep ; stosl\n\t"
226 "movl %%edx,%%eax\n"
227 "1:\tcld"
228 :"=a" (result)
229 :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
230 "D" (mem_map+PAGING_PAGES-1)
231 :"di","cx","dx");
232 if (result >= HIGH_MEMORY)
233 goto repeat;
234 if ((result && result < LOW_MEM) || (result & 0xfff)) {
235 printk("weird result: %08x\n",result);
236 result = 0;
237 }
238 if (!result && swap_out())
239 goto repeat;
240 return result;
241 }
242
243
244
245
246
247
248 int sys_swapon(const char * specialfile)
249 {
250 struct inode * swap_inode;
251 char * tmp;
252 int i,j;
253
254 if (!suser())
255 return -EPERM;
256 if (!(swap_inode = namei(specialfile)))
257 return -ENOENT;
258 if (swap_file || swap_device || swap_bitmap) {
259 iput(swap_inode);
260 return -EBUSY;
261 }
262 if (S_ISBLK(swap_inode->i_mode)) {
263 swap_device = swap_inode->i_rdev;
264 iput(swap_inode);
265 } else if (S_ISREG(swap_inode->i_mode))
266 swap_file = swap_inode;
267 else {
268 iput(swap_inode);
269 return -EINVAL;
270 }
271 tmp = (char *) get_free_page();
272 if (!tmp) {
273 iput(swap_file);
274 swap_device = 0;
275 swap_file = NULL;
276 printk("Unable to start swapping: out of memory :-)\n");
277 return -ENOMEM;
278 }
279 read_swap_page(0,tmp);
280 if (strncmp("SWAP-SPACE",tmp+4086,10)) {
281 printk("Unable to find swap-space signature\n\r");
282 free_page((long) tmp);
283 iput(swap_file);
284 swap_device = 0;
285 swap_file = NULL;
286 swap_bitmap = NULL;
287 return -EINVAL;
288 }
289 memset(tmp+4086,0,10);
290 j = 0;
291 for (i = 1 ; i < SWAP_BITS ; i++)
292 if (bit(tmp,i))
293 j++;
294 if (!j) {
295 printk("Empty swap-file\n");
296 free_page((long) tmp);
297 iput(swap_file);
298 swap_device = 0;
299 swap_file = NULL;
300 swap_bitmap = NULL;
301 return -EINVAL;
302 }
303 swap_bitmap = tmp;
304 printk("Adding Swap: %d pages (%d bytes) swap-space\n\r",j,j*4096);
305 return 0;
306 }