aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/swapfile.c38
1 files changed, 7 insertions, 31 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index eade24da9310..afae7b1f680b 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -506,19 +506,9 @@ unsigned int count_swap_pages(int type, int free)
506 * just let do_wp_page work it out if a write is requested later - to 506 * just let do_wp_page work it out if a write is requested later - to
507 * force COW, vm_page_prot omits write permission from any private vma. 507 * force COW, vm_page_prot omits write permission from any private vma.
508 */ 508 */
509static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, 509static void unuse_pte(struct vm_area_struct *vma, pte_t *pte,
510 unsigned long addr, swp_entry_t entry, struct page *page) 510 unsigned long addr, swp_entry_t entry, struct page *page)
511{ 511{
512 spinlock_t *ptl;
513 pte_t *pte;
514 int found = 1;
515
516 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
517 if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
518 found = 0;
519 goto out;
520 }
521
522 inc_mm_counter(vma->vm_mm, anon_rss); 512 inc_mm_counter(vma->vm_mm, anon_rss);
523 get_page(page); 513 get_page(page);
524 set_pte_at(vma->vm_mm, addr, pte, 514 set_pte_at(vma->vm_mm, addr, pte,
@@ -530,9 +520,6 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
530 * immediately swapped out again after swapon. 520 * immediately swapped out again after swapon.
531 */ 521 */
532 activate_page(page); 522 activate_page(page);
533out:
534 pte_unmap_unlock(pte, ptl);
535 return found;
536} 523}
537 524
538static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd, 525static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
@@ -541,33 +528,22 @@ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
541{ 528{
542 pte_t swp_pte = swp_entry_to_pte(entry); 529 pte_t swp_pte = swp_entry_to_pte(entry);
543 pte_t *pte; 530 pte_t *pte;
531 spinlock_t *ptl;
544 int found = 0; 532 int found = 0;
545 533
546 /* 534 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
547 * We don't actually need pte lock while scanning for swp_pte: since
548 * we hold page lock and mmap_sem, swp_pte cannot be inserted into the
549 * page table while we're scanning; though it could get zapped, and on
550 * some architectures (e.g. x86_32 with PAE) we might catch a glimpse
551 * of unmatched parts which look like swp_pte, so unuse_pte must
552 * recheck under pte lock. Scanning without pte lock lets it be
553 * preemptible whenever CONFIG_PREEMPT but not CONFIG_HIGHPTE.
554 */
555 pte = pte_offset_map(pmd, addr);
556 do { 535 do {
557 /* 536 /*
558 * swapoff spends a _lot_ of time in this loop! 537 * swapoff spends a _lot_ of time in this loop!
559 * Test inline before going to call unuse_pte. 538 * Test inline before going to call unuse_pte.
560 */ 539 */
561 if (unlikely(pte_same(*pte, swp_pte))) { 540 if (unlikely(pte_same(*pte, swp_pte))) {
562 pte_unmap(pte); 541 unuse_pte(vma, pte++, addr, entry, page);
563 found = unuse_pte(vma, pmd, addr, entry, page); 542 found = 1;
564 if (found) 543 break;
565 goto out;
566 pte = pte_offset_map(pmd, addr);
567 } 544 }
568 } while (pte++, addr += PAGE_SIZE, addr != end); 545 } while (pte++, addr += PAGE_SIZE, addr != end);
569 pte_unmap(pte - 1); 546 pte_unmap_unlock(pte - 1, ptl);
570out:
571 return found; 547 return found;
572} 548}
573 549