diff options
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 39252c732db2..c512cc911e22 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -242,6 +242,9 @@ static int | |||
242 | verify_pages(struct mm_struct *mm, | 242 | verify_pages(struct mm_struct *mm, |
243 | unsigned long addr, unsigned long end, unsigned long *nodes) | 243 | unsigned long addr, unsigned long end, unsigned long *nodes) |
244 | { | 244 | { |
245 | int err = 0; | ||
246 | |||
247 | spin_lock(&mm->page_table_lock); | ||
245 | while (addr < end) { | 248 | while (addr < end) { |
246 | struct page *p; | 249 | struct page *p; |
247 | pte_t *pte; | 250 | pte_t *pte; |
@@ -268,17 +271,23 @@ verify_pages(struct mm_struct *mm, | |||
268 | } | 271 | } |
269 | p = NULL; | 272 | p = NULL; |
270 | pte = pte_offset_map(pmd, addr); | 273 | pte = pte_offset_map(pmd, addr); |
271 | if (pte_present(*pte)) | 274 | if (pte_present(*pte)) { |
272 | p = pte_page(*pte); | 275 | unsigned long pfn = pte_pfn(*pte); |
276 | if (pfn_valid(pfn)) | ||
277 | p = pfn_to_page(pfn); | ||
278 | } | ||
273 | pte_unmap(pte); | 279 | pte_unmap(pte); |
274 | if (p) { | 280 | if (p) { |
275 | unsigned nid = page_to_nid(p); | 281 | unsigned nid = page_to_nid(p); |
276 | if (!test_bit(nid, nodes)) | 282 | if (!test_bit(nid, nodes)) { |
277 | return -EIO; | 283 | err = -EIO; |
284 | break; | ||
285 | } | ||
278 | } | 286 | } |
279 | addr += PAGE_SIZE; | 287 | addr += PAGE_SIZE; |
280 | } | 288 | } |
281 | return 0; | 289 | spin_unlock(&mm->page_table_lock); |
290 | return err; | ||
282 | } | 291 | } |
283 | 292 | ||
284 | /* Step 1: check the range */ | 293 | /* Step 1: check the range */ |