/* * This will never put the page into the free list, the caller has * a reference on the page. */ void delete_from_swap_cache_nolock(struct page *page) { if (!PageLocked(page)) BUG(); if (block_flushpage(page, 0)) lru_cache_del(page); spin_lock(&pagecache_lock); ClearPageDirty(page); __delete_from_swap_cache(page); spin_unlock(&pagecache_lock); page_cache_release(page); }
/* * The swap lock map insists that pages be in the page cache! * Therefore we can't use it. Later when we can remove the need for the * lock map and we can reduce the number of functions exported. */ void rw_swap_page_nolock(int rw, swp_entry_t entry, char *buf) { struct page *page = virt_to_page(buf); if (!PageLocked(page)) PAGE_BUG(page); if (page->mapping) PAGE_BUG(page); /* needs sync_page to wait I/O completation */ page->mapping = &swapper_space; if (rw_swap_page_base(rw, entry, page)) lock_page(page); if (!block_flushpage(page, 0)) PAGE_BUG(page); page->mapping = NULL; UnlockPage(page); }
/* * This must be called only on pages that have * been verified to be in the swap cache and locked. * It will never put the page into the free list, * the caller has a reference on the page. */ void delete_from_swap_cache(struct page *page) { swp_entry_t entry; if (!PageLocked(page)) BUG(); block_flushpage(page, 0); entry.val = page->index; spin_lock(&pagecache_lock); __delete_from_swap_cache(page); spin_unlock(&pagecache_lock); swap_free(entry); page_cache_release(page); }
/* * Work out if there are any other processes sharing this * swap cache page. Free it if you can. Return success. */ int remove_exclusive_swap_page(struct page *page) { int retval; struct swap_info_struct * p; swp_entry_t entry; if (!PageLocked(page)) BUG(); if (!PageSwapCache(page)) return 0; if (page_count(page) - !!page->buffers != 2) /* 2: us + cache */ return 0; entry.val = page->index; p = swap_info_get(entry); if (!p) return 0; /* Is the only swap cache user the cache itself? */ retval = 0; if (p->swap_map[SWP_OFFSET(entry)] == 1) { /* Recheck the page count with the pagecache lock held.. */ spin_lock(&pagecache_lock); if (page_count(page) - !!page->buffers == 2) { __delete_from_swap_cache(page); SetPageDirty(page); retval = 1; } spin_unlock(&pagecache_lock); } swap_info_put(p); if (retval) { block_flushpage(page, 0); swap_free(entry); page_cache_release(page); } return retval; }