From: Matthew Wilcox <willy@infradead.org>
To: linux-mm@kvack.org
Cc: Matthew Wilcox <mawilcox@microsoft.com>,
Huang Ying <ying.huang@intel.com>
Subject: [PATCH] mm: Report bad PTEs in lookup_swap_cache()
Date: Fri, 23 Feb 2018 12:03:41 -0800 [thread overview]
Message-ID: <20180223200341.17627-1-willy@infradead.org> (raw)
From: Matthew Wilcox <mawilcox@microsoft.com>
If we have garbage in the PTE, we can call the radix tree code with a
NULL radix tree head which leads to an OOPS. Detect the case where
we've found a PTE that refers to a non-existent swap device and report
the error correctly.
Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
---
include/linux/swap.h | 10 ++++------
mm/memory.c | 4 +---
mm/shmem.c | 2 +-
mm/swap_state.c | 35 ++++++++++++++++++++++-------------
4 files changed, 28 insertions(+), 23 deletions(-)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 7b6a59f722a3..045edb2ca8d0 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -415,9 +415,8 @@ extern void __delete_from_swap_cache(struct page *);
extern void delete_from_swap_cache(struct page *);
extern void free_page_and_swap_cache(struct page *);
extern void free_pages_and_swap_cache(struct page **, int);
-extern struct page *lookup_swap_cache(swp_entry_t entry,
- struct vm_area_struct *vma,
- unsigned long addr);
+extern struct page *lookup_swap_cache(swp_entry_t entry, bool vma_ra,
+ struct vm_fault *vmf);
extern struct page *read_swap_cache_async(swp_entry_t, gfp_t,
struct vm_area_struct *vma, unsigned long addr,
bool do_poll);
@@ -568,9 +567,8 @@ static inline int swap_writepage(struct page *p, struct writeback_control *wbc)
return 0;
}
-static inline struct page *lookup_swap_cache(swp_entry_t swp,
- struct vm_area_struct *vma,
- unsigned long addr)
+static inline struct page *lookup_swap_cache(swp_entry_t swp, bool vma_ra,
+ struct vm_fault *vmf)
{
return NULL;
}
diff --git a/mm/memory.c b/mm/memory.c
index 5fcfc24904d1..1cfc4699db42 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2926,11 +2926,9 @@ int do_swap_page(struct vm_fault *vmf)
goto out;
}
-
delayacct_set_flag(DELAYACCT_PF_SWAPIN);
if (!page) {
- page = lookup_swap_cache(entry, vma_readahead ? vma : NULL,
- vmf->address);
+ page = lookup_swap_cache(entry, vma_readahead, vmf);
swapcache = page;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index 1907688b75ee..8976f05823ba 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1650,7 +1650,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
if (swap.val) {
/* Look it up and read it in.. */
- page = lookup_swap_cache(swap, NULL, 0);
+ page = lookup_swap_cache(swap, false, NULL);
if (!page) {
/* Or update major stats only when swapin succeeds?? */
if (fault_type) {
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 39ae7cfad90f..5a7755ecbb03 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -328,14 +328,22 @@ void free_pages_and_swap_cache(struct page **pages, int nr)
* lock getting page table operations atomic even if we drop the page
* lock before returning.
*/
-struct page *lookup_swap_cache(swp_entry_t entry, struct vm_area_struct *vma,
- unsigned long addr)
+struct page *lookup_swap_cache(swp_entry_t entry, bool vma_ra,
+ struct vm_fault *vmf)
{
struct page *page;
- unsigned long ra_info;
- int win, hits, readahead;
+ int readahead;
+ struct address_space *swapper_space = swap_address_space(entry);
- page = find_get_page(swap_address_space(entry), swp_offset(entry));
+ if (!swapper_space) {
+ if (vmf)
+ pte_ERROR(vmf->orig_pte);
+ else
+ pr_err("Bad swp_entry: %lx\n", entry.val);
+ return NULL;
+ }
+
+ page = find_get_page(swapper_space, swp_offset(entry));
INC_CACHE_INFO(find_total);
if (page) {
@@ -343,18 +351,19 @@ struct page *lookup_swap_cache(swp_entry_t entry, struct vm_area_struct *vma,
if (unlikely(PageTransCompound(page)))
return page;
readahead = TestClearPageReadahead(page);
- if (vma) {
- ra_info = GET_SWAP_RA_VAL(vma);
- win = SWAP_RA_WIN(ra_info);
- hits = SWAP_RA_HITS(ra_info);
+ if (vma_ra) {
+ unsigned long ra_info = GET_SWAP_RA_VAL(vmf->vma);
+ int win = SWAP_RA_WIN(ra_info);
+ int hits = SWAP_RA_HITS(ra_info);
+
if (readahead)
hits = min_t(int, hits + 1, SWAP_RA_HITS_MAX);
- atomic_long_set(&vma->swap_readahead_info,
- SWAP_RA_VAL(addr, win, hits));
+ atomic_long_set(&vmf->vma->swap_readahead_info,
+ SWAP_RA_VAL(vmf->address, win, hits));
}
if (readahead) {
count_vm_event(SWAP_RA_HIT);
- if (!vma)
+ if (!vma_ra)
atomic_inc(&swapin_readahead_hits);
}
}
@@ -675,7 +684,7 @@ struct page *swap_readahead_detect(struct vm_fault *vmf,
entry = pte_to_swp_entry(vmf->orig_pte);
if ((unlikely(non_swap_entry(entry))))
return NULL;
- page = lookup_swap_cache(entry, vma, faddr);
+ page = lookup_swap_cache(entry, true, vmf);
if (page)
return page;
--
2.16.1
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next reply other threads:[~2018-02-23 20:03 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-23 20:03 Matthew Wilcox [this message]
2018-02-24 0:49 ` [PATCH] mm: Report bad PTEs in lookup_swap_cache() Huang, Ying
2018-02-25 4:43 ` kbuild test robot
2018-02-25 6:27 ` kbuild test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180223200341.17627-1-willy@infradead.org \
--to=willy@infradead.org \
--cc=linux-mm@kvack.org \
--cc=mawilcox@microsoft.com \
--cc=ying.huang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).