diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/swapfile.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index f30438970cd1..d76b2a18f044 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 | ||
@@ -2449,6 +2463,10 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
2449 | error = -ENOMEM; | 2463 | error = -ENOMEM; |
2450 | goto bad_swap; | 2464 | goto bad_swap; |
2451 | } | 2465 | } |
2466 | |||
2467 | if (bdi_cap_stable_pages_required(inode_to_bdi(inode))) | ||
2468 | p->flags |= SWP_STABLE_WRITES; | ||
2469 | |||
2452 | if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) { | 2470 | if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) { |
2453 | int cpu; | 2471 | int cpu; |
2454 | 2472 | ||