| 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... |
| |
| Fixes: dd6bd0d9c7db ("swap: use bdev_read_page() / bdev_write_page()") |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Cc: Anthony Iliopoulos <ailiop@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/linux/swap.h | 1 + |
| mm/page_io.c | 5 ----- |
| mm/swapfile.c | 13 +++++++++++++ |
| 3 files changed, 14 insertions(+), 5 deletions(-) |
| |
| --- a/include/linux/swap.h |
| +++ b/include/linux/swap.h |
| @@ -482,6 +482,7 @@ struct backing_dev_info; |
| extern int init_swap_address_space(unsigned int type, unsigned long nr_pages); |
| extern void exit_swap_address_space(unsigned int type); |
| extern struct swap_info_struct *get_swap_device(swp_entry_t entry); |
| +sector_t swap_page_sector(struct page *page); |
| |
| static inline void put_swap_device(struct swap_info_struct *si) |
| { |
| --- a/mm/page_io.c |
| +++ b/mm/page_io.c |
| @@ -273,11 +273,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 |
| --- a/mm/swapfile.c |
| +++ b/mm/swapfile.c |
| @@ -220,6 +220,19 @@ offset_to_swap_extent(struct swap_info_s |
| BUG(); |
| } |
| |
| +sector_t swap_page_sector(struct page *page) |
| +{ |
| + struct swap_info_struct *sis = page_swap_info(page); |
| + struct swap_extent *se; |
| + sector_t sector; |
| + pgoff_t offset; |
| + |
| + offset = __page_file_index(page); |
| + se = offset_to_swap_extent(sis, offset); |
| + sector = se->start_block + (offset - se->start_page); |
| + return sector << (PAGE_SHIFT - 9); |
| +} |
| + |
| /* |
| * swap allocation tell device that a cluster of swap can now be discarded, |
| * to allow the swap device to optimize its wear-levelling. |