From: Jens Axboe axboe@kernel.dk
stable inclusion from linux-4.19.179 commit 6ceea9a764b422e32d9028e35d37ad68761ffd2c
--------------------------------
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 Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- mm/page_io.c | 11 +++-------- mm/swapfile.c | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/mm/page_io.c b/mm/page_io.c index 97aaf9bb6a9e..17cff71a9304 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -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 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) 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); diff --git a/mm/swapfile.c b/mm/swapfile.c index c54b0afd8c87..4028994a51ae 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2381,7 +2381,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); }
/*