OLD | NEW |
1 #include <linux/mm.h> | 1 #include <linux/mm.h> |
2 #include <linux/vmacache.h> | 2 #include <linux/vmacache.h> |
3 #include <linux/hugetlb.h> | 3 #include <linux/hugetlb.h> |
4 #include <linux/huge_mm.h> | 4 #include <linux/huge_mm.h> |
5 #include <linux/mount.h> | 5 #include <linux/mount.h> |
6 #include <linux/seq_file.h> | 6 #include <linux/seq_file.h> |
7 #include <linux/highmem.h> | 7 #include <linux/highmem.h> |
8 #include <linux/ptrace.h> | 8 #include <linux/ptrace.h> |
9 #include <linux/slab.h> | 9 #include <linux/slab.h> |
10 #include <linux/pagemap.h> | 10 #include <linux/pagemap.h> |
(...skipping 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 * of page-shift in pagemap entries. | 740 * of page-shift in pagemap entries. |
741 */ | 741 */ |
742 | 742 |
743 static bool soft_dirty_cleared __read_mostly; | 743 static bool soft_dirty_cleared __read_mostly; |
744 | 744 |
745 enum clear_refs_types { | 745 enum clear_refs_types { |
746 CLEAR_REFS_ALL = 1, | 746 CLEAR_REFS_ALL = 1, |
747 CLEAR_REFS_ANON, | 747 CLEAR_REFS_ANON, |
748 CLEAR_REFS_MAPPED, | 748 CLEAR_REFS_MAPPED, |
749 CLEAR_REFS_SOFT_DIRTY, | 749 CLEAR_REFS_SOFT_DIRTY, |
| 750 CLEAR_REFS_MM_HIWATER_RSS, |
750 CLEAR_REFS_LAST, | 751 CLEAR_REFS_LAST, |
751 }; | 752 }; |
752 | 753 |
753 struct clear_refs_private { | 754 struct clear_refs_private { |
754 struct vm_area_struct *vma; | 755 struct vm_area_struct *vma; |
755 enum clear_refs_types type; | 756 enum clear_refs_types type; |
756 }; | 757 }; |
757 | 758 |
758 static inline void clear_soft_dirty(struct vm_area_struct *vma, | 759 static inline void clear_soft_dirty(struct vm_area_struct *vma, |
759 unsigned long addr, pte_t *pte) | 760 unsigned long addr, pte_t *pte) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
845 soft_dirty_cleared = true; | 846 soft_dirty_cleared = true; |
846 pr_warn_once("The pagemap bits 55-60 has changed their meaning!" | 847 pr_warn_once("The pagemap bits 55-60 has changed their meaning!" |
847 " See the linux/Documentation/vm/pagemap.txt for " | 848 " See the linux/Documentation/vm/pagemap.txt for " |
848 "details.\n"); | 849 "details.\n"); |
849 } | 850 } |
850 | 851 |
851 task = get_proc_task(file_inode(file)); | 852 task = get_proc_task(file_inode(file)); |
852 if (!task) | 853 if (!task) |
853 return -ESRCH; | 854 return -ESRCH; |
854 mm = get_task_mm(task); | 855 mm = get_task_mm(task); |
855 » if (mm) { | 856 » if (!mm) |
856 » » struct clear_refs_private cp = { | 857 » » goto out_task; |
857 » » » .type = type, | 858 |
858 » » }; | 859 » if (type == CLEAR_REFS_MM_HIWATER_RSS) { |
859 » » struct mm_walk clear_refs_walk = { | 860 » » /* |
860 » » » .pmd_entry = clear_refs_pte_range, | 861 » » * Writing 5 to /proc/pid/clear_refs resets the peak resident |
861 » » » .mm = mm, | 862 » » * set size. |
862 » » » .private = &cp, | 863 » » */ |
863 » » }; | 864 » » down_write(&mm->mmap_sem); |
864 » » down_read(&mm->mmap_sem); | 865 » » reset_mm_hiwater_rss(mm); |
865 » » if (type == CLEAR_REFS_SOFT_DIRTY) { | 866 » » up_write(&mm->mmap_sem); |
| 867 » » goto out_mm; |
| 868 » } |
| 869 |
| 870 » struct clear_refs_private cp = { |
| 871 » » .type = type, |
| 872 » }; |
| 873 » struct mm_walk clear_refs_walk = { |
| 874 » » .pmd_entry = clear_refs_pte_range, |
| 875 » » .mm = mm, |
| 876 » » .private = &cp, |
| 877 » }; |
| 878 » down_read(&mm->mmap_sem); |
| 879 » if (type == CLEAR_REFS_SOFT_DIRTY) { |
| 880 » » for (vma = mm->mmap; vma; vma = vma->vm_next) { |
| 881 » » » if (!(vma->vm_flags & VM_SOFTDIRTY)) |
| 882 » » » » continue; |
| 883 » » » up_read(&mm->mmap_sem); |
| 884 » » » down_write(&mm->mmap_sem); |
866 for (vma = mm->mmap; vma; vma = vma->vm_next) { | 885 for (vma = mm->mmap; vma; vma = vma->vm_next) { |
867 » » » » if (!(vma->vm_flags & VM_SOFTDIRTY)) | 886 » » » » vma->vm_flags &= ~VM_SOFTDIRTY; |
868 » » » » » continue; | 887 » » » » vma_set_page_prot(vma); |
869 » » » » up_read(&mm->mmap_sem); | |
870 » » » » down_write(&mm->mmap_sem); | |
871 » » » » for (vma = mm->mmap; vma; vma = vma->vm_next) { | |
872 » » » » » vma->vm_flags &= ~VM_SOFTDIRTY; | |
873 » » » » » vma_set_page_prot(vma); | |
874 » » » » } | |
875 » » » » downgrade_write(&mm->mmap_sem); | |
876 » » » » break; | |
877 } | 888 } |
878 » » » mmu_notifier_invalidate_range_start(mm, 0, -1); | 889 » » » downgrade_write(&mm->mmap_sem); |
| 890 » » » break; |
879 } | 891 } |
880 » » for (vma = mm->mmap; vma; vma = vma->vm_next) { | 892 » » mmu_notifier_invalidate_range_start(mm, 0, -1); |
881 » » » cp.vma = vma; | |
882 » » » if (is_vm_hugetlb_page(vma)) | |
883 » » » » continue; | |
884 » » » /* | |
885 » » » * Writing 1 to /proc/pid/clear_refs affects all pages. | |
886 » » » * | |
887 » » » * Writing 2 to /proc/pid/clear_refs only affects | |
888 » » » * Anonymous pages. | |
889 » » » * | |
890 » » » * Writing 3 to /proc/pid/clear_refs only affects file | |
891 » » » * mapped pages. | |
892 » » » * | |
893 » » » * Writing 4 to /proc/pid/clear_refs affects all pages. | |
894 » » » */ | |
895 » » » if (type == CLEAR_REFS_ANON && vma->vm_file) | |
896 » » » » continue; | |
897 » » » if (type == CLEAR_REFS_MAPPED && !vma->vm_file) | |
898 » » » » continue; | |
899 » » » walk_page_range(vma->vm_start, vma->vm_end, | |
900 » » » » » &clear_refs_walk); | |
901 » » } | |
902 » » if (type == CLEAR_REFS_SOFT_DIRTY) | |
903 » » » mmu_notifier_invalidate_range_end(mm, 0, -1); | |
904 » » flush_tlb_mm(mm); | |
905 » » up_read(&mm->mmap_sem); | |
906 » » mmput(mm); | |
907 } | 893 } |
| 894 for (vma = mm->mmap; vma; vma = vma->vm_next) { |
| 895 cp.vma = vma; |
| 896 if (is_vm_hugetlb_page(vma)) |
| 897 continue; |
| 898 /* |
| 899 * Writing 1 to /proc/pid/clear_refs affects all pages. |
| 900 * |
| 901 * Writing 2 to /proc/pid/clear_refs only affects anonymous |
| 902 * pages. |
| 903 * |
| 904 * Writing 3 to /proc/pid/clear_refs only affects file mapped |
| 905 * pages. |
| 906 * |
| 907 * Writing 4 to /proc/pid/clear_refs affects all pages. |
| 908 */ |
| 909 if (type == CLEAR_REFS_ANON && vma->vm_file) |
| 910 continue; |
| 911 if (type == CLEAR_REFS_MAPPED && !vma->vm_file) |
| 912 continue; |
| 913 walk_page_range(vma->vm_start, vma->vm_end, &clear_refs_walk); |
| 914 } |
| 915 if (type == CLEAR_REFS_SOFT_DIRTY) |
| 916 mmu_notifier_invalidate_range_end(mm, 0, -1); |
| 917 flush_tlb_mm(mm); |
| 918 up_read(&mm->mmap_sem); |
| 919 |
| 920 out_mm: |
| 921 mmput(mm); |
| 922 out_task: |
908 put_task_struct(task); | 923 put_task_struct(task); |
909 | 924 |
910 return count; | 925 return count; |
911 } | 926 } |
912 | 927 |
913 const struct file_operations proc_clear_refs_operations = { | 928 const struct file_operations proc_clear_refs_operations = { |
914 .write = clear_refs_write, | 929 .write = clear_refs_write, |
915 .llseek = noop_llseek, | 930 .llseek = noop_llseek, |
916 }; | 931 }; |
917 | 932 |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1611 .release = proc_map_release, | 1626 .release = proc_map_release, |
1612 }; | 1627 }; |
1613 | 1628 |
1614 const struct file_operations proc_tid_numa_maps_operations = { | 1629 const struct file_operations proc_tid_numa_maps_operations = { |
1615 .open = tid_numa_maps_open, | 1630 .open = tid_numa_maps_open, |
1616 .read = seq_read, | 1631 .read = seq_read, |
1617 .llseek = seq_lseek, | 1632 .llseek = seq_lseek, |
1618 .release = proc_map_release, | 1633 .release = proc_map_release, |
1619 }; | 1634 }; |
1620 #endif /* CONFIG_NUMA */ | 1635 #endif /* CONFIG_NUMA */ |
OLD | NEW |