summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/swap.h3
-rw-r--r--mm/swapfile.c20
2 files changed, 21 insertions, 2 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 09f4be179ff3..7f47b7098b1b 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -150,8 +150,9 @@ enum {
150 SWP_FILE = (1 << 7), /* set after swap_activate success */ 150 SWP_FILE = (1 << 7), /* set after swap_activate success */
151 SWP_AREA_DISCARD = (1 << 8), /* single-time swap area discards */ 151 SWP_AREA_DISCARD = (1 << 8), /* single-time swap area discards */
152 SWP_PAGE_DISCARD = (1 << 9), /* freed swap page-cluster discards */ 152 SWP_PAGE_DISCARD = (1 << 9), /* freed swap page-cluster discards */
153 SWP_STABLE_WRITES = (1 << 10), /* no overwrite PG_writeback pages */
153 /* add others here before... */ 154 /* add others here before... */
154 SWP_SCANNING = (1 << 10), /* refcount in scan_swap_map */ 155 SWP_SCANNING = (1 << 11), /* refcount in scan_swap_map */
155}; 156};
156 157
157#define SWAP_CLUSTER_MAX 32UL 158#define SWAP_CLUSTER_MAX 32UL
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 1c6e0321205d..4761701d1721 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -943,11 +943,25 @@ bool reuse_swap_page(struct page *page, int *total_mapcount)
943 count = page_trans_huge_mapcount(page, total_mapcount); 943 count = page_trans_huge_mapcount(page, total_mapcount);
944 if (count <= 1 && PageSwapCache(page)) { 944 if (count <= 1 && PageSwapCache(page)) {
945 count += page_swapcount(page); 945 count += page_swapcount(page);
946 if (count == 1 && !PageWriteback(page)) { 946 if (count != 1)
947 goto out;
948 if (!PageWriteback(page)) {
947 delete_from_swap_cache(page); 949 delete_from_swap_cache(page);
948 SetPageDirty(page); 950 SetPageDirty(page);
951 } else {
952 swp_entry_t entry;
953 struct swap_info_struct *p;
954
955 entry.val = page_private(page);
956 p = swap_info_get(entry);
957 if (p->flags & SWP_STABLE_WRITES) {
958 spin_unlock(&p->lock);
959 return false;
960 }
961 spin_unlock(&p->lock);
949 } 962 }
950 } 963 }
964out:
951 return count <= 1; 965 return count <= 1;
952} 966}
953 967
@@ -2448,6 +2462,10 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
2448 error = -ENOMEM; 2462 error = -ENOMEM;
2449 goto bad_swap; 2463 goto bad_swap;
2450 } 2464 }
2465
2466 if (bdi_cap_stable_pages_required(inode_to_bdi(inode)))
2467 p->flags |= SWP_STABLE_WRITES;
2468
2451 if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) { 2469 if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) {
2452 int cpu; 2470 int cpu;
2453 2471