Import 2.2.7
[davej-history.git] / mm / swap_state.c
blob8c5e7176c5aa668ccfc4ad0997af4f47380386ad
1 /*
2 * linux/mm/swap_state.c
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
5 * Swap reorganised 29.12.95, Stephen Tweedie
7 * Rewritten to use page cache, (C) 1998 Stephen Tweedie
8 */
10 #include <linux/mm.h>
11 #include <linux/kernel_stat.h>
12 #include <linux/swap.h>
13 #include <linux/swapctl.h>
14 #include <linux/init.h>
15 #include <linux/pagemap.h>
17 #include <asm/pgtable.h>
19 /*
20 * Keep a reserved false inode which we will use to mark pages in the
21 * page cache are acting as swap cache instead of file cache.
23 * We only need a unique pointer to satisfy the page cache, but we'll
24 * reserve an entire zeroed inode structure for the purpose just to
25 * ensure that any mistaken dereferences of this structure cause a
26 * kernel oops.
28 struct inode swapper_inode;
30 #ifdef SWAP_CACHE_INFO
31 unsigned long swap_cache_add_total = 0;
32 unsigned long swap_cache_del_total = 0;
33 unsigned long swap_cache_find_total = 0;
34 unsigned long swap_cache_find_success = 0;
36 void show_swap_cache_info(void)
38 printk("Swap cache: add %ld, delete %ld, find %ld/%ld\n",
39 swap_cache_add_total,
40 swap_cache_del_total,
41 swap_cache_find_success, swap_cache_find_total);
43 #endif
45 int add_to_swap_cache(struct page *page, unsigned long entry)
47 #ifdef SWAP_CACHE_INFO
48 swap_cache_add_total++;
49 #endif
50 #ifdef DEBUG_SWAP
51 printk("DebugVM: add_to_swap_cache(%08lx count %d, entry %08lx)\n",
52 page_address(page), atomic_read(&page->count), entry);
53 #endif
54 if (PageTestandSetSwapCache(page)) {
55 printk(KERN_ERR "swap_cache: replacing non-empty entry %08lx "
56 "on page %08lx\n",
57 page->offset, page_address(page));
58 return 0;
60 if (page->inode) {
61 printk(KERN_ERR "swap_cache: replacing page-cached entry "
62 "on page %08lx\n", page_address(page));
63 return 0;
65 atomic_inc(&page->count);
66 page->inode = &swapper_inode;
67 page->offset = entry;
68 add_page_to_hash_queue(page, &swapper_inode, entry);
69 add_page_to_inode_queue(&swapper_inode, page);
70 return 1;
74 * Verify that a swap entry is valid and increment its swap map count.
76 * Note: if swap_map[] reaches SWAP_MAP_MAX the entries are treated as
77 * "permanent", but will be reclaimed by the next swapoff.
79 int swap_duplicate(unsigned long entry)
81 struct swap_info_struct * p;
82 unsigned long offset, type;
83 int result = 0;
85 if (!entry)
86 goto out;
87 type = SWP_TYPE(entry);
88 if (type & SHM_SWP_TYPE)
89 goto out;
90 if (type >= nr_swapfiles)
91 goto bad_file;
92 p = type + swap_info;
93 offset = SWP_OFFSET(entry);
94 if (offset >= p->max)
95 goto bad_offset;
96 if (!p->swap_map[offset])
97 goto bad_unused;
99 * Entry is valid, so increment the map count.
101 if (p->swap_map[offset] < SWAP_MAP_MAX)
102 p->swap_map[offset]++;
103 else {
104 static int overflow = 0;
105 if (overflow++ < 5)
106 printk(KERN_WARNING
107 "swap_duplicate: entry %08lx map count=%d\n",
108 entry, p->swap_map[offset]);
109 p->swap_map[offset] = SWAP_MAP_MAX;
111 result = 1;
112 #ifdef DEBUG_SWAP
113 printk("DebugVM: swap_duplicate(entry %08lx, count now %d)\n",
114 entry, p->swap_map[offset]);
115 #endif
116 out:
117 return result;
119 bad_file:
120 printk(KERN_ERR
121 "swap_duplicate: entry %08lx, nonexistent swap file\n", entry);
122 goto out;
123 bad_offset:
124 printk(KERN_ERR
125 "swap_duplicate: entry %08lx, offset exceeds max\n", entry);
126 goto out;
127 bad_unused:
128 printk(KERN_ERR
129 "swap_duplicate at %8p: entry %08lx, unused page\n",
130 __builtin_return_address(0), entry);
131 goto out;
134 int swap_count(unsigned long entry)
136 struct swap_info_struct * p;
137 unsigned long offset, type;
138 int retval = 0;
140 if (!entry)
141 goto bad_entry;
142 type = SWP_TYPE(entry);
143 if (type & SHM_SWP_TYPE)
144 goto out;
145 if (type >= nr_swapfiles)
146 goto bad_file;
147 p = type + swap_info;
148 offset = SWP_OFFSET(entry);
149 if (offset >= p->max)
150 goto bad_offset;
151 if (!p->swap_map[offset])
152 goto bad_unused;
153 retval = p->swap_map[offset];
154 #ifdef DEBUG_SWAP
155 printk("DebugVM: swap_count(entry %08lx, count %d)\n",
156 entry, retval);
157 #endif
158 out:
159 return retval;
161 bad_entry:
162 printk(KERN_ERR "swap_count: null entry!\n");
163 goto out;
164 bad_file:
165 printk(KERN_ERR
166 "swap_count: entry %08lx, nonexistent swap file!\n", entry);
167 goto out;
168 bad_offset:
169 printk(KERN_ERR
170 "swap_count: entry %08lx, offset exceeds max!\n", entry);
171 goto out;
172 bad_unused:
173 printk(KERN_ERR
174 "swap_count at %8p: entry %08lx, unused page!\n",
175 __builtin_return_address(0), entry);
176 goto out;
179 static inline void remove_from_swap_cache(struct page *page)
181 if (!page->inode) {
182 printk ("VM: Removing swap cache page with zero inode hash "
183 "on page %08lx\n", page_address(page));
184 return;
186 if (page->inode != &swapper_inode) {
187 printk ("VM: Removing swap cache page with wrong inode hash "
188 "on page %08lx\n", page_address(page));
191 #ifdef DEBUG_SWAP
192 printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n",
193 page_address(page), atomic_read(&page->count));
194 #endif
195 PageClearSwapCache (page);
196 remove_inode_page(page);
201 * This must be called only on pages that have
202 * been verified to be in the swap cache.
204 void delete_from_swap_cache(struct page *page)
206 long entry = page->offset;
208 #ifdef SWAP_CACHE_INFO
209 swap_cache_del_total++;
210 #endif
211 #ifdef DEBUG_SWAP
212 printk("DebugVM: delete_from_swap_cache(%08lx count %d, "
213 "entry %08lx)\n",
214 page_address(page), atomic_read(&page->count), entry);
215 #endif
216 remove_from_swap_cache (page);
217 swap_free (entry);
221 * Perform a free_page(), also freeing any swap cache associated with
222 * this page if it is the last user of the page.
225 void free_page_and_swap_cache(unsigned long addr)
227 struct page *page = mem_map + MAP_NR(addr);
230 * If we are the only user, then free up the swap cache.
232 if (PageSwapCache(page) && !is_page_shared(page)) {
233 delete_from_swap_cache(page);
236 __free_page(page);
241 * Lookup a swap entry in the swap cache. We need to be careful about
242 * locked pages. A found page will be returned with its refcount
243 * incremented.
246 struct page * lookup_swap_cache(unsigned long entry)
248 struct page *found;
250 #ifdef SWAP_CACHE_INFO
251 swap_cache_find_total++;
252 #endif
253 while (1) {
254 found = find_page(&swapper_inode, entry);
255 if (!found)
256 return 0;
257 if (found->inode != &swapper_inode || !PageSwapCache(found))
258 goto out_bad;
259 if (!PageLocked(found)) {
260 #ifdef SWAP_CACHE_INFO
261 swap_cache_find_success++;
262 #endif
263 return found;
265 __free_page(found);
266 __wait_on_page(found);
269 out_bad:
270 printk (KERN_ERR "VM: Found a non-swapper swap page!\n");
271 __free_page(found);
272 return 0;
276 * Locate a page of swap in physical memory, reserving swap cache space
277 * and reading the disk if it is not already cached. If wait==0, we are
278 * only doing readahead, so don't worry if the page is already locked.
280 * A failure return means that either the page allocation failed or that
281 * the swap entry is no longer in use.
284 struct page * read_swap_cache_async(unsigned long entry, int wait)
286 struct page *found_page = 0, *new_page;
287 unsigned long new_page_addr;
289 #ifdef DEBUG_SWAP
290 printk("DebugVM: read_swap_cache_async entry %08lx%s\n",
291 entry, wait ? ", wait" : "");
292 #endif
294 * Make sure the swap entry is still in use.
296 if (!swap_duplicate(entry)) /* Account for the swap cache */
297 goto out;
299 * Look for the page in the swap cache.
301 found_page = lookup_swap_cache(entry);
302 if (found_page)
303 goto out_free_swap;
305 new_page_addr = __get_free_page(GFP_USER);
306 if (!new_page_addr)
307 goto out_free_swap; /* Out of memory */
308 new_page = mem_map + MAP_NR(new_page_addr);
311 * Check the swap cache again, in case we stalled above.
313 found_page = lookup_swap_cache(entry);
314 if (found_page)
315 goto out_free_page;
317 * Add it to the swap cache and read its contents.
319 if (!add_to_swap_cache(new_page, entry))
320 goto out_free_page;
322 set_bit(PG_locked, &new_page->flags);
323 rw_swap_page(READ, entry, (char *) new_page_addr, wait);
324 #ifdef DEBUG_SWAP
325 printk("DebugVM: read_swap_cache_async created "
326 "entry %08lx at %p\n",
327 entry, (char *) page_address(new_page));
328 #endif
329 return new_page;
331 out_free_page:
332 __free_page(new_page);
333 out_free_swap:
334 swap_free(entry);
335 out:
336 return found_page;