- Kai Germaschewski: ymfpci cleanups and resource leak fixes
[davej-history.git] / mm / swap_state.c
blobdf45b34af84fb62e62112779e5277640ed3ef42e
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>
16 #include <linux/smp_lock.h>
18 #include <asm/pgtable.h>
20 static int swap_writepage(struct page *page)
22 rw_swap_page(WRITE, page, 0);
23 return 0;
26 static struct address_space_operations swap_aops = {
27 writepage: swap_writepage,
28 sync_page: block_sync_page,
31 struct address_space swapper_space = {
32 { /* pages */
33 &swapper_space.pages, /* .next */
34 &swapper_space.pages /* .prev */
36 0, /* nrpages */
37 &swap_aops,
40 #ifdef SWAP_CACHE_INFO
41 unsigned long swap_cache_add_total;
42 unsigned long swap_cache_del_total;
43 unsigned long swap_cache_find_total;
44 unsigned long swap_cache_find_success;
46 void show_swap_cache_info(void)
48 printk("Swap cache: add %ld, delete %ld, find %ld/%ld\n",
49 swap_cache_add_total,
50 swap_cache_del_total,
51 swap_cache_find_success, swap_cache_find_total);
53 #endif
55 void add_to_swap_cache(struct page *page, swp_entry_t entry)
57 unsigned long flags;
59 #ifdef SWAP_CACHE_INFO
60 swap_cache_add_total++;
61 #endif
62 if (!PageLocked(page))
63 BUG();
64 if (PageTestandSetSwapCache(page))
65 BUG();
66 if (page->mapping)
67 BUG();
68 flags = page->flags & ~((1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced) | (1 << PG_arch_1));
69 page->flags = flags | (1 << PG_uptodate);
70 add_to_page_cache_locked(page, &swapper_space, entry.val);
73 static inline void remove_from_swap_cache(struct page *page)
75 struct address_space *mapping = page->mapping;
77 if (mapping != &swapper_space)
78 BUG();
79 if (!PageSwapCache(page) || !PageLocked(page))
80 PAGE_BUG(page);
82 PageClearSwapCache(page);
83 __remove_inode_page(page);
87 * This must be called only on pages that have
88 * been verified to be in the swap cache.
90 void __delete_from_swap_cache(struct page *page)
92 swp_entry_t entry;
94 entry.val = page->index;
96 #ifdef SWAP_CACHE_INFO
97 swap_cache_del_total++;
98 #endif
99 remove_from_swap_cache(page);
100 swap_free(entry);
104 * This will never put the page into the free list, the caller has
105 * a reference on the page.
107 void delete_from_swap_cache_nolock(struct page *page)
109 if (!PageLocked(page))
110 BUG();
112 if (block_flushpage(page, 0))
113 lru_cache_del(page);
115 spin_lock(&pagecache_lock);
116 ClearPageDirty(page);
117 __delete_from_swap_cache(page);
118 spin_unlock(&pagecache_lock);
119 page_cache_release(page);
123 * This must be called only on pages that have
124 * been verified to be in the swap cache and locked.
126 void delete_from_swap_cache(struct page *page)
128 lock_page(page);
129 delete_from_swap_cache_nolock(page);
130 UnlockPage(page);
134 * Perform a free_page(), also freeing any swap cache associated with
135 * this page if it is the last user of the page. Can not do a lock_page,
136 * as we are holding the page_table_lock spinlock.
138 void free_page_and_swap_cache(struct page *page)
141 * If we are the only user, then try to free up the swap cache.
143 if (PageSwapCache(page) && !TryLockPage(page)) {
144 if (!is_page_shared(page)) {
145 delete_from_swap_cache_nolock(page);
147 UnlockPage(page);
149 page_cache_release(page);
154 * Lookup a swap entry in the swap cache. A found page will be returned
155 * unlocked and with its refcount incremented - we rely on the kernel
156 * lock getting page table operations atomic even if we drop the page
157 * lock before returning.
160 struct page * lookup_swap_cache(swp_entry_t entry)
162 struct page *found;
164 #ifdef SWAP_CACHE_INFO
165 swap_cache_find_total++;
166 #endif
167 while (1) {
169 * Right now the pagecache is 32-bit only. But it's a 32 bit index. =)
171 repeat:
172 found = find_lock_page(&swapper_space, entry.val);
173 if (!found)
174 return 0;
176 * Though the "found" page was in the swap cache an instant
177 * earlier, it might have been removed by refill_inactive etc.
178 * Re search ... Since find_lock_page grabs a reference on
179 * the page, it can not be reused for anything else, namely
180 * it can not be associated with another swaphandle, so it
181 * is enough to check whether the page is still in the scache.
183 if (!PageSwapCache(found)) {
184 UnlockPage(found);
185 page_cache_release(found);
186 goto repeat;
188 if (found->mapping != &swapper_space)
189 goto out_bad;
190 #ifdef SWAP_CACHE_INFO
191 swap_cache_find_success++;
192 #endif
193 UnlockPage(found);
194 return found;
197 out_bad:
198 printk (KERN_ERR "VM: Found a non-swapper swap page!\n");
199 UnlockPage(found);
200 page_cache_release(found);
201 return 0;
205 * Locate a page of swap in physical memory, reserving swap cache space
206 * and reading the disk if it is not already cached. If wait==0, we are
207 * only doing readahead, so don't worry if the page is already locked.
209 * A failure return means that either the page allocation failed or that
210 * the swap entry is no longer in use.
213 struct page * read_swap_cache_async(swp_entry_t entry, int wait)
215 struct page *found_page = 0, *new_page;
216 unsigned long new_page_addr;
219 * Make sure the swap entry is still in use.
221 if (!swap_duplicate(entry)) /* Account for the swap cache */
222 goto out;
224 * Look for the page in the swap cache.
226 found_page = lookup_swap_cache(entry);
227 if (found_page)
228 goto out_free_swap;
230 new_page_addr = __get_free_page(GFP_USER);
231 if (!new_page_addr)
232 goto out_free_swap; /* Out of memory */
233 new_page = virt_to_page(new_page_addr);
236 * Check the swap cache again, in case we stalled above.
238 found_page = lookup_swap_cache(entry);
239 if (found_page)
240 goto out_free_page;
242 * Add it to the swap cache and read its contents.
244 lock_page(new_page);
245 add_to_swap_cache(new_page, entry);
246 rw_swap_page(READ, new_page, wait);
247 return new_page;
249 out_free_page:
250 page_cache_release(new_page);
251 out_free_swap:
252 swap_free(entry);
253 out:
254 return found_page;