diff options
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index d44b2d60a66a..d954b71c4f9c 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1223,8 +1223,8 @@ void put_swap_page(struct page *page, swp_entry_t entry) if (!si) return; + ci = lock_cluster_or_swap_info(si, offset); if (size == SWAPFILE_CLUSTER) { - ci = lock_cluster(si, offset); VM_BUG_ON(!cluster_is_huge(ci)); map = si->swap_map + offset; for (i = 0; i < SWAPFILE_CLUSTER; i++) { @@ -1233,13 +1233,9 @@ void put_swap_page(struct page *page, swp_entry_t entry) if (val == SWAP_HAS_CACHE) free_entries++; } - if (!free_entries) { - for (i = 0; i < SWAPFILE_CLUSTER; i++) - map[i] &= ~SWAP_HAS_CACHE; - } cluster_clear_huge(ci); - unlock_cluster(ci); if (free_entries == SWAPFILE_CLUSTER) { + unlock_cluster_or_swap_info(si, ci); spin_lock(&si->lock); ci = lock_cluster(si, offset); memset(map, 0, SWAPFILE_CLUSTER); @@ -1250,12 +1246,16 @@ void put_swap_page(struct page *page, swp_entry_t entry) return; } } - if (size == 1 || free_entries) { - for (i = 0; i < size; i++, entry.val++) { - if (!__swap_entry_free(si, entry, SWAP_HAS_CACHE)) - free_swap_slot(entry); + for (i = 0; i < size; i++, entry.val++) { + if (!__swap_entry_free_locked(si, offset + i, SWAP_HAS_CACHE)) { + unlock_cluster_or_swap_info(si, ci); + free_swap_slot(entry); + if (i == size - 1) + return; + lock_cluster_or_swap_info(si, offset); } } + unlock_cluster_or_swap_info(si, ci); } #ifdef CONFIG_THP_SWAP |