diff options
-rw-r--r-- | include/linux/swap.h | 3 | ||||
-rw-r--r-- | mm/swapfile.c | 20 |
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 | } |
964 | out: | ||
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 | ||