/* * "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; }
/* * 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_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; }
static inline void __frontswap_clear(struct swap_info_struct *sis, pgoff_t offset) { frontswap_clear(sis, offset); atomic_dec(&sis->frontswap_pages); }