/* * "Store" data from a page to frontswap and associate it with the page's * swaptype and offset. Page must be locked and in the swap cache. * If frontswap already contains a page with matching swaptype and * offset, the frontswap implementation may either overwrite the data and * return success or invalidate the page from frontswap and return failure. */ int __frontswap_store(struct page *page) { int ret = -1, dup = 0; swp_entry_t entry = { .val = page_private(page), }; int type = swp_type(entry); struct swap_info_struct *sis = swap_info[type]; pgoff_t offset = swp_offset(entry); BUG_ON(!PageLocked(page)); BUG_ON(sis == NULL); if (frontswap_test(sis, offset)) dup = 1; ret = frontswap_ops.store(type, offset, page); if (ret == 0) { frontswap_set(sis, offset); inc_frontswap_succ_stores(); if (!dup) atomic_inc(&sis->frontswap_pages); } else { /* failed dup always results in automatic invalidate of the (older) page from frontswap */ inc_frontswap_failed_stores(); if (dup) __frontswap_clear(sis, offset); } if (frontswap_writethrough_enabled) /* report failure so swap also writes to swap device */ ret = -1; return ret; }
/* * "Put" data from a page to frontswap and associate it with the page's * swaptype and offset. Page must be locked and in the swap cache. * If frontswap already contains a page with matching swaptype and * offset, the frontswap implmentation may either overwrite the data * and return success or flush the page from frontswap and return failure */ int __frontswap_put_page(struct page *page) { int ret = -1, dup = 0; swp_entry_t entry = { .val = page_private(page), }; int type = swp_type(entry); struct swap_info_struct *sis = swap_info[type]; pgoff_t offset = swp_offset(entry); BUG_ON(!PageLocked(page)); if (frontswap_test(sis, offset)) dup = 1; ret = (*frontswap_ops.put_page)(type, offset, page); if (ret == 0) { frontswap_set(sis, offset); frontswap_succ_puts++; if (!dup) sis->frontswap_pages++; } else if (dup) { /* failed dup always results in automatic flush of the (older) page from frontswap */ frontswap_clear(sis, offset); sis->frontswap_pages--; frontswap_failed_puts++; } else frontswap_failed_puts++; return ret; }
/* * Invalidate any data from frontswap associated with the specified swaptype * and offset so that a subsequent "get" will fail. */ void __frontswap_invalidate_page(unsigned type, pgoff_t offset) { struct swap_info_struct *sis = swap_info[type]; BUG_ON(sis == NULL); if (frontswap_test(sis, offset)) { frontswap_ops.invalidate_page(type, offset); __frontswap_clear(sis, offset); inc_frontswap_invalidates(); } }
/* * Flush any data from frontswap associated with the specified swaptype * and offset so that a subsequent "get" will fail. */ void __frontswap_flush_page(unsigned type, pgoff_t offset) { struct swap_info_struct *sis = swap_info[type]; if (frontswap_test(sis, offset)) { (*frontswap_ops.flush_page)(type, offset); sis->frontswap_pages--; frontswap_clear(sis, offset); frontswap_flushes++; } }
/* * "Get" data from frontswap associated with swaptype and offset that were * specified when the data was put to frontswap and use it to fill the * specified page with data. Page must be locked and in the swap cache */ int __frontswap_get_page(struct page *page) { int ret = -1; swp_entry_t entry = { .val = page_private(page), }; int type = swp_type(entry); struct swap_info_struct *sis = swap_info[type]; pgoff_t offset = swp_offset(entry); BUG_ON(!PageLocked(page)); if (frontswap_test(sis, offset)) ret = (*frontswap_ops.get_page)(type, offset, page); if (ret == 0) frontswap_gets++; return ret; }
/* * "Get" data from frontswap associated with swaptype and offset that were * specified when the data was put to frontswap and use it to fill the * specified page with data. Page must be locked and in the swap cache. */ int __frontswap_load(struct page *page) { int ret = -1; swp_entry_t entry = { .val = page_private(page), }; int type = swp_type(entry); struct swap_info_struct *sis = swap_info[type]; pgoff_t offset = swp_offset(entry); BUG_ON(!PageLocked(page)); BUG_ON(sis == NULL); if (frontswap_test(sis, offset)) ret = frontswap_ops.load(type, offset, page); if (ret == 0) { inc_frontswap_loads(); if (frontswap_tmem_exclusive_gets_enabled) { SetPageDirty(page); frontswap_clear(sis, offset); } } return ret; }