summaryrefslogtreecommitdiffstats
path: root/mm/swap_state.c
diff options
context:
space:
mode:
authorHuang Ying <huang.ying.caritas@gmail.com>2017-11-15 20:33:15 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-15 21:21:02 -0500
commite9a6effa500526e2a19d5ad042cb758b55b1ef93 (patch)
tree76661a69d59b8b08d0717f2c68490a7c978dab9d /mm/swap_state.c
parentaa8d22a11da933dbf880b4933b58931f4aefe91c (diff)
mm, swap: fix false error message in __swp_swapcount()
When a page fault occurs for a swap entry, the physical swap readahead (not the VMA base swap readahead) may readahead several swap entries after the fault swap entry. The readahead algorithm calculates some of the swap entries to readahead via increasing the offset of the fault swap entry without checking whether they are beyond the end of the swap device and it relys on the __swp_swapcount() and swapcache_prepare() to check it. Although __swp_swapcount() checks for the swap entry passed in, it will complain with the error message as follow for the expected invalid swap entry. This may make the end users confused. swap_info_get: Bad swap offset entry 0200f8a7 To fix the false error message, the swap entry checking is added in swapin_readahead() to avoid to pass the out-of-bound swap entries and the swap entry reserved for the swap header to __swp_swapcount() and swapcache_prepare(). Link: http://lkml.kernel.org/r/20171102054225.22897-1-ying.huang@intel.com Fixes: e8c26ab60598 ("mm/swap: skip readahead for unreferenced swap slots") Signed-off-by: "Huang, Ying" <ying.huang@intel.com> Reported-by: Christian Kujau <lists@nerdbynature.de> Acked-by: Minchan Kim <minchan@kernel.org> Suggested-by: Minchan Kim <minchan@kernel.org> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Hugh Dickins <hughd@google.com> Cc: <stable@vger.kernel.org> [4.11+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swap_state.c')
-rw-r--r--mm/swap_state.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 326439428daf..f2face8b889e 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -559,6 +559,7 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
559 unsigned long offset = entry_offset; 559 unsigned long offset = entry_offset;
560 unsigned long start_offset, end_offset; 560 unsigned long start_offset, end_offset;
561 unsigned long mask; 561 unsigned long mask;
562 struct swap_info_struct *si = swp_swap_info(entry);
562 struct blk_plug plug; 563 struct blk_plug plug;
563 bool do_poll = true, page_allocated; 564 bool do_poll = true, page_allocated;
564 565
@@ -572,6 +573,8 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
572 end_offset = offset | mask; 573 end_offset = offset | mask;
573 if (!start_offset) /* First page is swap header. */ 574 if (!start_offset) /* First page is swap header. */
574 start_offset++; 575 start_offset++;
576 if (end_offset >= si->max)
577 end_offset = si->max - 1;
575 578
576 blk_start_plug(&plug); 579 blk_start_plug(&plug);
577 for (offset = start_offset; offset <= end_offset ; offset++) { 580 for (offset = start_offset; offset <= end_offset ; offset++) {