diff --git a/include/linux/swap_slots.h b/include/linux/swap_slots.h index ba5623b27c60..6ef92d17633d 100644 --- a/include/linux/swap_slots.h +++ b/include/linux/swap_slots.h @@ -25,4 +25,6 @@ void reenable_swap_slots_cache_unlock(void); int enable_swap_slots_cache(void); int free_swap_slot(swp_entry_t entry); +extern bool swap_slot_cache_enabled; + #endif /* _LINUX_SWAP_SLOTS_H */ diff --git a/mm/swap_slots.c b/mm/swap_slots.c index ebf4f1cbac04..9b5bc86f96ad 100644 --- a/mm/swap_slots.c +++ b/mm/swap_slots.c @@ -36,7 +36,7 @@ static DEFINE_PER_CPU(struct swap_slots_cache, swp_slots); static bool swap_slot_cache_active; -static bool swap_slot_cache_enabled; +bool swap_slot_cache_enabled; static bool swap_slot_cache_initialized; DEFINE_MUTEX(swap_slots_cache_mutex); /* Serialize swap slots cache enable/disable operations */ diff --git a/mm/swap_state.c b/mm/swap_state.c index e1f07cafecaa..473b71e052a8 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -324,9 +324,16 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, if (found_page) break; - /* Just skip read ahead for unused swap slot */ - if (!__swp_swapcount(entry)) - return NULL; + /* + * Just skip read ahead for unused swap slot. + * During swap_off when swap_slot_cache is disabled, + * we have to handle the race between putting + * swap entry in swap cache and marking swap slot + * as SWAP_HAS_CACHE. That's done in later part of code or + * else swap_off will be aborted if we return NULL. + */ + if (!__swp_swapcount(entry) && swap_slot_cache_enabled) + break; /* * Get a new page to read into from swap.