]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
swap: fix swapfile read/write offset
authorJens Axboe <axboe@kernel.dk>
Tue, 2 Mar 2021 21:53:21 +0000 (14:53 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 7 Mar 2021 11:19:02 +0000 (12:19 +0100)
commit caf6912f3f4af7232340d500a4a2008f81b93f14 upstream.

We're not factoring in the start of the file for where to write and
read the swapfile, which leads to very unfortunate side effects of
writing where we should not be...

[This issue only affects swapfiles on filesystems on top of blockdevs
that implement rw_page ops (brd, zram, btt, pmem), and not on top of any
other block devices, in contrast to the upstream commit fix.]

Fixes: dd6bd0d9c7db ("swap: use bdev_read_page() / bdev_write_page()")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Anthony Iliopoulos <ailiop@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
mm/page_io.c
mm/swapfile.c

index 08d2eae58fcee20996ade8d81ba46b0cd384c188..9b646f07f47f1a4cb0bdd9420f4197601f7702bb 100644 (file)
@@ -38,7 +38,6 @@ static struct bio *get_swap_bio(gfp_t gfp_flags,
 
                bio->bi_iter.bi_sector = map_swap_page(page, &bdev);
                bio_set_dev(bio, bdev);
-               bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9;
                bio->bi_end_io = end_io;
 
                for (i = 0; i < nr; i++)
@@ -262,11 +261,6 @@ out:
        return ret;
 }
 
-static sector_t swap_page_sector(struct page *page)
-{
-       return (sector_t)__page_file_index(page) << (PAGE_SHIFT - 9);
-}
-
 static inline void count_swpout_vm_event(struct page *page)
 {
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -325,7 +319,8 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
                return ret;
        }
 
-       ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc);
+       ret = bdev_write_page(sis->bdev, map_swap_page(page, &sis->bdev),
+                             page, wbc);
        if (!ret) {
                count_swpout_vm_event(page);
                return 0;
@@ -376,7 +371,7 @@ int swap_readpage(struct page *page, bool synchronous)
                return ret;
        }
 
-       ret = bdev_read_page(sis->bdev, swap_page_sector(page), page);
+       ret = bdev_read_page(sis->bdev, map_swap_page(page, &sis->bdev), page);
        if (!ret) {
                if (trylock_page(page)) {
                        swap_slot_free_notify(page);
index 130e2e41a48cea8a130577ac7cd5fd90c03625d8..057e6907bf7b9a84a2478163ee2528df7f2c3f0f 100644 (file)
@@ -2305,7 +2305,7 @@ sector_t map_swap_page(struct page *page, struct block_device **bdev)
 {
        swp_entry_t entry;
        entry.val = page_private(page);
-       return map_swap_entry(entry, bdev);
+       return map_swap_entry(entry, bdev) << (PAGE_SHIFT - 9);
 }
 
 /*