aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/task_mmu.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2013-07-03 18:01:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:07:25 -0400
commit2b0a9f017548f05e42fbf7e67c4a626c1ebd5e12 (patch)
tree37536aced29420e37521bb8bfaacf678b4acb397 /fs/proc/task_mmu.c
parentaf9de7eb180fa9b74c2cdc256349304a58c63c02 (diff)
pagemap: introduce pagemap_entry_t without pmshift bits
These bits are always constant (== PAGE_SHIFT) and just occupy space in the entry. Moreover, in next patch we will need to report one more bit in the pagemap, but all bits are already busy on it. That said, describe the pagemap entry that has 6 more free zero bits. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Cc: Matt Mackall <mpm@selenic.com> Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> Cc: Glauber Costa <glommer@parallels.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc/task_mmu.c')
-rw-r--r--fs/proc/task_mmu.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index ef6f6c62dfee..39d641292579 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -807,6 +807,7 @@ typedef struct {
807struct pagemapread { 807struct pagemapread {
808 int pos, len; 808 int pos, len;
809 pagemap_entry_t *buffer; 809 pagemap_entry_t *buffer;
810 bool v2;
810}; 811};
811 812
812#define PAGEMAP_WALK_SIZE (PMD_SIZE) 813#define PAGEMAP_WALK_SIZE (PMD_SIZE)
@@ -820,14 +821,16 @@ struct pagemapread {
820#define PM_PSHIFT_BITS 6 821#define PM_PSHIFT_BITS 6
821#define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) 822#define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
822#define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) 823#define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET)
823#define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) 824#define __PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
824#define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) 825#define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1)
825#define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) 826#define PM_PFRAME(x) ((x) & PM_PFRAME_MASK)
827/* in "new" pagemap pshift bits are occupied with more status bits */
828#define PM_STATUS2(v2, x) (__PM_PSHIFT(v2 ? x : PAGE_SHIFT))
826 829
827#define PM_PRESENT PM_STATUS(4LL) 830#define PM_PRESENT PM_STATUS(4LL)
828#define PM_SWAP PM_STATUS(2LL) 831#define PM_SWAP PM_STATUS(2LL)
829#define PM_FILE PM_STATUS(1LL) 832#define PM_FILE PM_STATUS(1LL)
830#define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT) 833#define PM_NOT_PRESENT(v2) PM_STATUS2(v2, 0)
831#define PM_END_OF_BUFFER 1 834#define PM_END_OF_BUFFER 1
832 835
833static inline pagemap_entry_t make_pme(u64 val) 836static inline pagemap_entry_t make_pme(u64 val)
@@ -850,7 +853,7 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
850 struct pagemapread *pm = walk->private; 853 struct pagemapread *pm = walk->private;
851 unsigned long addr; 854 unsigned long addr;
852 int err = 0; 855 int err = 0;
853 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT); 856 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
854 857
855 for (addr = start; addr < end; addr += PAGE_SIZE) { 858 for (addr = start; addr < end; addr += PAGE_SIZE) {
856 err = add_to_pagemap(addr, &pme, pm); 859 err = add_to_pagemap(addr, &pme, pm);
@@ -860,7 +863,7 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
860 return err; 863 return err;
861} 864}
862 865
863static void pte_to_pagemap_entry(pagemap_entry_t *pme, 866static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
864 struct vm_area_struct *vma, unsigned long addr, pte_t pte) 867 struct vm_area_struct *vma, unsigned long addr, pte_t pte)
865{ 868{
866 u64 frame, flags; 869 u64 frame, flags;
@@ -879,18 +882,18 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme,
879 if (is_migration_entry(entry)) 882 if (is_migration_entry(entry))
880 page = migration_entry_to_page(entry); 883 page = migration_entry_to_page(entry);
881 } else { 884 } else {
882 *pme = make_pme(PM_NOT_PRESENT); 885 *pme = make_pme(PM_NOT_PRESENT(pm->v2));
883 return; 886 return;
884 } 887 }
885 888
886 if (page && !PageAnon(page)) 889 if (page && !PageAnon(page))
887 flags |= PM_FILE; 890 flags |= PM_FILE;
888 891
889 *pme = make_pme(PM_PFRAME(frame) | PM_PSHIFT(PAGE_SHIFT) | flags); 892 *pme = make_pme(PM_PFRAME(frame) | PM_STATUS2(pm->v2, 0) | flags);
890} 893}
891 894
892#ifdef CONFIG_TRANSPARENT_HUGEPAGE 895#ifdef CONFIG_TRANSPARENT_HUGEPAGE
893static void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, 896static void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
894 pmd_t pmd, int offset) 897 pmd_t pmd, int offset)
895{ 898{
896 /* 899 /*
@@ -900,12 +903,12 @@ static void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme,
900 */ 903 */
901 if (pmd_present(pmd)) 904 if (pmd_present(pmd))
902 *pme = make_pme(PM_PFRAME(pmd_pfn(pmd) + offset) 905 *pme = make_pme(PM_PFRAME(pmd_pfn(pmd) + offset)
903 | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT); 906 | PM_STATUS2(pm->v2, 0) | PM_PRESENT);
904 else 907 else
905 *pme = make_pme(PM_NOT_PRESENT); 908 *pme = make_pme(PM_NOT_PRESENT(pm->v2));
906} 909}
907#else 910#else
908static inline void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, 911static inline void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
909 pmd_t pmd, int offset) 912 pmd_t pmd, int offset)
910{ 913{
911} 914}
@@ -918,7 +921,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
918 struct pagemapread *pm = walk->private; 921 struct pagemapread *pm = walk->private;
919 pte_t *pte; 922 pte_t *pte;
920 int err = 0; 923 int err = 0;
921 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT); 924 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
922 925
923 /* find the first VMA at or above 'addr' */ 926 /* find the first VMA at or above 'addr' */
924 vma = find_vma(walk->mm, addr); 927 vma = find_vma(walk->mm, addr);
@@ -928,7 +931,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
928 931
929 offset = (addr & ~PAGEMAP_WALK_MASK) >> 932 offset = (addr & ~PAGEMAP_WALK_MASK) >>
930 PAGE_SHIFT; 933 PAGE_SHIFT;
931 thp_pmd_to_pagemap_entry(&pme, *pmd, offset); 934 thp_pmd_to_pagemap_entry(&pme, pm, *pmd, offset);
932 err = add_to_pagemap(addr, &pme, pm); 935 err = add_to_pagemap(addr, &pme, pm);
933 if (err) 936 if (err)
934 break; 937 break;
@@ -945,7 +948,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
945 * and need a new, higher one */ 948 * and need a new, higher one */
946 if (vma && (addr >= vma->vm_end)) { 949 if (vma && (addr >= vma->vm_end)) {
947 vma = find_vma(walk->mm, addr); 950 vma = find_vma(walk->mm, addr);
948 pme = make_pme(PM_NOT_PRESENT); 951 pme = make_pme(PM_NOT_PRESENT(pm->v2));
949 } 952 }
950 953
951 /* check that 'vma' actually covers this address, 954 /* check that 'vma' actually covers this address,
@@ -953,7 +956,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
953 if (vma && (vma->vm_start <= addr) && 956 if (vma && (vma->vm_start <= addr) &&
954 !is_vm_hugetlb_page(vma)) { 957 !is_vm_hugetlb_page(vma)) {
955 pte = pte_offset_map(pmd, addr); 958 pte = pte_offset_map(pmd, addr);
956 pte_to_pagemap_entry(&pme, vma, addr, *pte); 959 pte_to_pagemap_entry(&pme, pm, vma, addr, *pte);
957 /* unmap before userspace copy */ 960 /* unmap before userspace copy */
958 pte_unmap(pte); 961 pte_unmap(pte);
959 } 962 }
@@ -968,14 +971,14 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
968} 971}
969 972
970#ifdef CONFIG_HUGETLB_PAGE 973#ifdef CONFIG_HUGETLB_PAGE
971static void huge_pte_to_pagemap_entry(pagemap_entry_t *pme, 974static void huge_pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
972 pte_t pte, int offset) 975 pte_t pte, int offset)
973{ 976{
974 if (pte_present(pte)) 977 if (pte_present(pte))
975 *pme = make_pme(PM_PFRAME(pte_pfn(pte) + offset) 978 *pme = make_pme(PM_PFRAME(pte_pfn(pte) + offset)
976 | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT); 979 | PM_STATUS2(pm->v2, 0) | PM_PRESENT);
977 else 980 else
978 *pme = make_pme(PM_NOT_PRESENT); 981 *pme = make_pme(PM_NOT_PRESENT(pm->v2));
979} 982}
980 983
981/* This function walks within one hugetlb entry in the single call */ 984/* This function walks within one hugetlb entry in the single call */
@@ -989,7 +992,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
989 992
990 for (; addr != end; addr += PAGE_SIZE) { 993 for (; addr != end; addr += PAGE_SIZE) {
991 int offset = (addr & ~hmask) >> PAGE_SHIFT; 994 int offset = (addr & ~hmask) >> PAGE_SHIFT;
992 huge_pte_to_pagemap_entry(&pme, *pte, offset); 995 huge_pte_to_pagemap_entry(&pme, pm, *pte, offset);
993 err = add_to_pagemap(addr, &pme, pm); 996 err = add_to_pagemap(addr, &pme, pm);
994 if (err) 997 if (err)
995 return err; 998 return err;
@@ -1051,6 +1054,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
1051 if (!count) 1054 if (!count)
1052 goto out_task; 1055 goto out_task;
1053 1056
1057 pm.v2 = false;
1054 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); 1058 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
1055 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); 1059 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
1056 ret = -ENOMEM; 1060 ret = -ENOMEM;