]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blobdiff - mm/swapfile.c
mm/swapfile.c: put_swap_page: share more between huge/normal code path
[mirror_ubuntu-kernels.git] / mm / swapfile.c
index d44b2d60a66a6502a0b364af5381d92ef5e939f9..d954b71c4f9c2e842e142713e1a921addb6a4c9d 100644 (file)
@@ -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