/* * linux/mm/swap_state.c * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * Swap reorganised 29.12.95, Stephen Tweedie * * Rewritten to use page cache, (C) 1998 Stephen Tweedie */ #include <linux/mm.h> #include <linux/kernel_stat.h> #include <linux/swap.h> #include <linux/swapctl.h> #include <linux/init.h> #include <linux/pagemap.h> #include <linux/smp_lock.h> #include <asm/pgtable.h> 20 static int swap_writepage(struct page *page) { rw_swap_page(WRITE, page, 0); 23 return 0; } static struct address_space_operations swap_aops = { writepage: swap_writepage, sync_page: block_sync_page, }; struct address_space swapper_space = { LIST_HEAD_INIT(swapper_space.clean_pages), LIST_HEAD_INIT(swapper_space.dirty_pages), LIST_HEAD_INIT(swapper_space.locked_pages), 0, /* nrpages */ &swap_aops, }; #ifdef SWAP_CACHE_INFO unsigned long swap_cache_add_total; unsigned long swap_cache_del_total; unsigned long swap_cache_find_total; unsigned long swap_cache_find_success; 45 void show_swap_cache_info(void) { printk("Swap cache: add %ld, delete %ld, find %ld/%ld\n", swap_cache_add_total, swap_cache_del_total, swap_cache_find_success, swap_cache_find_total); } #endif 54 void add_to_swap_cache(struct page *page, swp_entry_t entry) { unsigned long flags; #ifdef SWAP_CACHE_INFO swap_cache_add_total++; #endif 61 if (!PageLocked(page)) 62 BUG(); 63 if (PageTestandSetSwapCache(page)) 64 BUG(); 65 if (page->mapping) 66 BUG(); flags = page->flags & ~((1 << PG_error) | (1 << PG_arch_1)); page->flags = flags | (1 << PG_uptodate); add_to_page_cache_locked(page, &swapper_space, entry.val); } 72 static inline void remove_from_swap_cache(struct page *page) { struct address_space *mapping = page->mapping; 76 if (mapping != &swapper_space) 77 BUG(); 78 if (!PageSwapCache(page) || !PageLocked(page)) 79 PAGE_BUG(page); PageClearSwapCache(page); ClearPageDirty(page); __remove_inode_page(page); } /* * This must be called only on pages that have * been verified to be in the swap cache. */ 90 void __delete_from_swap_cache(struct page *page) { swp_entry_t entry; entry.val = page->index; #ifdef SWAP_CACHE_INFO swap_cache_del_total++; #endif remove_from_swap_cache(page); swap_free(entry); } /* * This will never put the page into the free list, the caller has * 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)) lru_cache_del(page); spin_lock(&pagecache_lock); ClearPageDirty(page); __delete_from_swap_cache(page); 118 spin_unlock(&pagecache_lock); page_cache_release(page); } /* * This must be called only on pages that have * been verified to be in the swap cache and locked. */ 126 void delete_from_swap_cache(struct page *page) { lock_page(page); delete_from_swap_cache_nolock(page); 130 UnlockPage(page); } /* * Perform a free_page(), also freeing any swap cache associated with * this page if it is the last user of the page. Can not do a lock_page, * as we are holding the page_table_lock spinlock. */ 138 void free_page_and_swap_cache(struct page *page) { /* * 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)) { delete_from_swap_cache_nolock(page); } 147 UnlockPage(page); } page_cache_release(page); } /* * Lookup a swap entry in the swap cache. A found page will be returned * unlocked and with its refcount incremented - we rely on the kernel * lock getting page table operations atomic even if we drop the page * lock before returning. */ 160 struct page * lookup_swap_cache(swp_entry_t entry) { struct page *found; #ifdef SWAP_CACHE_INFO swap_cache_find_total++; #endif 167 while (1) { /* * Right now the pagecache is 32-bit only. But it's a 32 bit index. =) */ repeat: found = find_lock_page(&swapper_space, entry.val); 173 if (!found) 174 return 0; /* * Though the "found" page was in the swap cache an instant * earlier, it might have been removed by refill_inactive etc. * Re search ... Since find_lock_page grabs a reference on * the page, it can not be reused for anything else, namely * it can not be associated with another swaphandle, so it * is enough to check whether the page is still in the scache. */ 183 if (!PageSwapCache(found)) { 184 UnlockPage(found); page_cache_release(found); 186 goto repeat; } 188 if (found->mapping != &swapper_space) 189 goto out_bad; #ifdef SWAP_CACHE_INFO swap_cache_find_success++; #endif 193 UnlockPage(found); 194 return found; } out_bad: printk (KERN_ERR "VM: Found a non-swapper swap page!\n"); 199 UnlockPage(found); page_cache_release(found); 201 return 0; } /* * Locate a page of swap in physical memory, reserving swap cache space * and reading the disk if it is not already cached. If wait==0, we are * only doing readahead, so don't worry if the page is already locked. * * A failure return means that either the page allocation failed or that * the swap entry is no longer in use. */ 213 struct page * read_swap_cache_async(swp_entry_t entry, int wait) { struct page *found_page = 0, *new_page; unsigned long new_page_addr; /* * Make sure the swap entry is still in use. */ 221 if (!swap_duplicate(entry)) /* Account for the swap cache */ 222 goto out; /* * Look for the page in the swap cache. */ found_page = lookup_swap_cache(entry); 227 if (found_page) 228 goto out_free_swap; new_page_addr = __get_free_page(GFP_USER); 231 if (!new_page_addr) 232 goto out_free_swap; /* Out of memory */ new_page = virt_to_page(new_page_addr); /* * Check the swap cache again, in case we stalled above. */ found_page = lookup_swap_cache(entry); 239 if (found_page) 240 goto out_free_page; /* * Add it to the swap cache and read its contents. */ lock_page(new_page); add_to_swap_cache(new_page, entry); rw_swap_page(READ, new_page, wait); 247 return new_page; out_free_page: page_cache_release(new_page); out_free_swap: swap_free(entry); out: 254 return found_page; }