| From caf6912f3f4af7232340d500a4a2008f81b93f14 Mon Sep 17 00:00:00 2001 |
| From: Jens Axboe <axboe@kernel.dk> |
| Date: Tue, 2 Mar 2021 14:53:21 -0700 |
| Subject: swap: fix swapfile read/write offset |
| |
| From: Jens Axboe <axboe@kernel.dk> |
| |
| 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()") |
| Cc: stable@vger.kernel.org # 4.4 |
| Signed-off-by: Anthony Iliopoulos <ailiop@suse.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| mm/page_io.c | 11 +++-------- |
| mm/swapfile.c | 2 +- |
| 2 files changed, 4 insertions(+), 9 deletions(-) |
| |
| --- a/mm/page_io.c |
| +++ b/mm/page_io.c |
| @@ -32,7 +32,6 @@ static struct bio *get_swap_bio(gfp_t gf |
| bio = bio_alloc(gfp_flags, 1); |
| if (bio) { |
| bio->bi_iter.bi_sector = map_swap_page(page, &bio->bi_bdev); |
| - bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9; |
| bio->bi_end_io = end_io; |
| |
| bio_add_page(bio, page, PAGE_SIZE, 0); |
| @@ -244,11 +243,6 @@ out: |
| return ret; |
| } |
| |
| -static sector_t swap_page_sector(struct page *page) |
| -{ |
| - return (sector_t)__page_file_index(page) << (PAGE_CACHE_SHIFT - 9); |
| -} |
| - |
| int __swap_writepage(struct page *page, struct writeback_control *wbc, |
| bio_end_io_t end_write_func) |
| { |
| @@ -297,7 +291,8 @@ int __swap_writepage(struct page *page, |
| 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_vm_event(PSWPOUT); |
| return 0; |
| @@ -345,7 +340,7 @@ int swap_readpage(struct page *page) |
| 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) { |
| count_vm_event(PSWPIN); |
| return 0; |
| --- a/mm/swapfile.c |
| +++ b/mm/swapfile.c |
| @@ -1653,7 +1653,7 @@ sector_t map_swap_page(struct page *page |
| { |
| swp_entry_t entry; |
| entry.val = page_private(page); |
| - return map_swap_entry(entry, bdev); |
| + return map_swap_entry(entry, bdev) << (PAGE_SHIFT - 9); |
| } |
| |
| /* |