summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2021-03-02 14:53:21 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-07 12:35:56 +0100
commitd7697c29f2ced2dc148e0ad0f7584df5405f7007 (patch)
tree55f8d2a0f8d1c4452dbbd827eaaf805e81c3d71d
parent1b357dd6f062ed343f0300c04a0531f35f338ab2 (diff)
swap: fix swapfile read/write offset
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>
-rw-r--r--include/linux/swap.h1
-rw-r--r--mm/page_io.c5
-rw-r--r--mm/swapfile.c13
3 files changed, 14 insertions, 5 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 596bc2f4d9b0..55fe2f5b6f5f 100644
--- 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)
{
diff --git a/mm/page_io.c b/mm/page_io.c
index 9bca17ecc4df..21f3160d39a8 100644
--- 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
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 9fffc5af29d1..348f6665c06c 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -220,6 +220,19 @@ offset_to_swap_extent(struct swap_info_struct *sis, unsigned long offset)
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.