@@ -736,7 +736,6 @@ enum clear_refs_types {
736
736
};
737
737
738
738
struct clear_refs_private {
739
- struct vm_area_struct * vma ;
740
739
enum clear_refs_types type ;
741
740
};
742
741
@@ -767,7 +766,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
767
766
unsigned long end , struct mm_walk * walk )
768
767
{
769
768
struct clear_refs_private * cp = walk -> private ;
770
- struct vm_area_struct * vma = cp -> vma ;
769
+ struct vm_area_struct * vma = walk -> vma ;
771
770
pte_t * pte , ptent ;
772
771
spinlock_t * ptl ;
773
772
struct page * page ;
@@ -801,6 +800,25 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
801
800
return 0 ;
802
801
}
803
802
803
+ static int clear_refs_test_walk (unsigned long start , unsigned long end ,
804
+ struct mm_walk * walk )
805
+ {
806
+ struct clear_refs_private * cp = walk -> private ;
807
+ struct vm_area_struct * vma = walk -> vma ;
808
+
809
+ /*
810
+ * Writing 1 to /proc/pid/clear_refs affects all pages.
811
+ * Writing 2 to /proc/pid/clear_refs only affects anonymous pages.
812
+ * Writing 3 to /proc/pid/clear_refs only affects file mapped pages.
813
+ * Writing 4 to /proc/pid/clear_refs affects all pages.
814
+ */
815
+ if (cp -> type == CLEAR_REFS_ANON && vma -> vm_file )
816
+ return 1 ;
817
+ if (cp -> type == CLEAR_REFS_MAPPED && !vma -> vm_file )
818
+ return 1 ;
819
+ return 0 ;
820
+ }
821
+
804
822
static ssize_t clear_refs_write (struct file * file , const char __user * buf ,
805
823
size_t count , loff_t * ppos )
806
824
{
@@ -841,6 +859,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
841
859
};
842
860
struct mm_walk clear_refs_walk = {
843
861
.pmd_entry = clear_refs_pte_range ,
862
+ .test_walk = clear_refs_test_walk ,
844
863
.mm = mm ,
845
864
.private = & cp ,
846
865
};
@@ -860,28 +879,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
860
879
}
861
880
mmu_notifier_invalidate_range_start (mm , 0 , -1 );
862
881
}
863
- for (vma = mm -> mmap ; vma ; vma = vma -> vm_next ) {
864
- cp .vma = vma ;
865
- if (is_vm_hugetlb_page (vma ))
866
- continue ;
867
- /*
868
- * Writing 1 to /proc/pid/clear_refs affects all pages.
869
- *
870
- * Writing 2 to /proc/pid/clear_refs only affects
871
- * Anonymous pages.
872
- *
873
- * Writing 3 to /proc/pid/clear_refs only affects file
874
- * mapped pages.
875
- *
876
- * Writing 4 to /proc/pid/clear_refs affects all pages.
877
- */
878
- if (type == CLEAR_REFS_ANON && vma -> vm_file )
879
- continue ;
880
- if (type == CLEAR_REFS_MAPPED && !vma -> vm_file )
881
- continue ;
882
- walk_page_range (vma -> vm_start , vma -> vm_end ,
883
- & clear_refs_walk );
884
- }
882
+ walk_page_range (0 , ~0UL , & clear_refs_walk );
885
883
if (type == CLEAR_REFS_SOFT_DIRTY )
886
884
mmu_notifier_invalidate_range_end (mm , 0 , -1 );
887
885
flush_tlb_mm (mm );
0 commit comments