aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-05-19 18:58:33 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2014-05-20 14:38:42 -0400
commita62c34bd2a8a3f159945becd57401e478818d51c (patch)
tree8721aca251b468606e52376fc811dd0c8beeaeb8 /mm
parent78d683e838a60ec4ba4591cca4364cba84a9e626 (diff)
x86, mm: Improve _install_special_mapping and fix x86 vdso naming
Using arch_vma_name to give special mappings a name is awkward. x86 currently implements it by comparing the start address of the vma to the expected address of the vdso. This requires tracking the start address of special mappings and is probably buggy if a special vma is split or moved. Improve _install_special_mapping to just name the vma directly. Use it to give the x86 vvar area a name, which should make CRIU's life easier. As a side effect, the vvar area will show up in core dumps. This could be considered weird and is fixable. [hpa: I say we accept this as-is but be prepared to deal with knocking out the vvars from core dumps if this becomes a problem.] Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: Andy Lutomirski <luto@amacapital.net> Link: http://lkml.kernel.org/r/276b39b6b645fb11e345457b503f17b83c2c6fd0.1400538962.git.luto@amacapital.net Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'mm')
-rw-r--r--mm/mmap.c89
1 files changed, 60 insertions, 29 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index b1202cf81f4b..52bbc9514d9d 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2872,6 +2872,31 @@ int may_expand_vm(struct mm_struct *mm, unsigned long npages)
2872 return 1; 2872 return 1;
2873} 2873}
2874 2874
2875static int special_mapping_fault(struct vm_area_struct *vma,
2876 struct vm_fault *vmf);
2877
2878/*
2879 * Having a close hook prevents vma merging regardless of flags.
2880 */
2881static void special_mapping_close(struct vm_area_struct *vma)
2882{
2883}
2884
2885static const char *special_mapping_name(struct vm_area_struct *vma)
2886{
2887 return ((struct vm_special_mapping *)vma->vm_private_data)->name;
2888}
2889
2890static const struct vm_operations_struct special_mapping_vmops = {
2891 .close = special_mapping_close,
2892 .fault = special_mapping_fault,
2893 .name = special_mapping_name,
2894};
2895
2896static const struct vm_operations_struct legacy_special_mapping_vmops = {
2897 .close = special_mapping_close,
2898 .fault = special_mapping_fault,
2899};
2875 2900
2876static int special_mapping_fault(struct vm_area_struct *vma, 2901static int special_mapping_fault(struct vm_area_struct *vma,
2877 struct vm_fault *vmf) 2902 struct vm_fault *vmf)
@@ -2887,7 +2912,13 @@ static int special_mapping_fault(struct vm_area_struct *vma,
2887 */ 2912 */
2888 pgoff = vmf->pgoff - vma->vm_pgoff; 2913 pgoff = vmf->pgoff - vma->vm_pgoff;
2889 2914
2890 for (pages = vma->vm_private_data; pgoff && *pages; ++pages) 2915 if (vma->vm_ops == &legacy_special_mapping_vmops)
2916 pages = vma->vm_private_data;
2917 else
2918 pages = ((struct vm_special_mapping *)vma->vm_private_data)->
2919 pages;
2920
2921 for (; pgoff && *pages; ++pages)
2891 pgoff--; 2922 pgoff--;
2892 2923
2893 if (*pages) { 2924 if (*pages) {
@@ -2900,30 +2931,11 @@ static int special_mapping_fault(struct vm_area_struct *vma,
2900 return VM_FAULT_SIGBUS; 2931 return VM_FAULT_SIGBUS;
2901} 2932}
2902 2933
2903/* 2934static struct vm_area_struct *__install_special_mapping(
2904 * Having a close hook prevents vma merging regardless of flags. 2935 struct mm_struct *mm,
2905 */ 2936 unsigned long addr, unsigned long len,
2906static void special_mapping_close(struct vm_area_struct *vma) 2937 unsigned long vm_flags, const struct vm_operations_struct *ops,
2907{ 2938 void *priv)
2908}
2909
2910static const struct vm_operations_struct special_mapping_vmops = {
2911 .close = special_mapping_close,
2912 .fault = special_mapping_fault,
2913};
2914
2915/*
2916 * Called with mm->mmap_sem held for writing.
2917 * Insert a new vma covering the given region, with the given flags.
2918 * Its pages are supplied by the given array of struct page *.
2919 * The array can be shorter than len >> PAGE_SHIFT if it's null-terminated.
2920 * The region past the last page supplied will always produce SIGBUS.
2921 * The array pointer and the pages it points to are assumed to stay alive
2922 * for as long as this mapping might exist.
2923 */
2924struct vm_area_struct *_install_special_mapping(struct mm_struct *mm,
2925 unsigned long addr, unsigned long len,
2926 unsigned long vm_flags, struct page **pages)
2927{ 2939{
2928 int ret; 2940 int ret;
2929 struct vm_area_struct *vma; 2941 struct vm_area_struct *vma;
@@ -2940,8 +2952,8 @@ struct vm_area_struct *_install_special_mapping(struct mm_struct *mm,
2940 vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND | VM_SOFTDIRTY; 2952 vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND | VM_SOFTDIRTY;
2941 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 2953 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
2942 2954
2943 vma->vm_ops = &special_mapping_vmops; 2955 vma->vm_ops = ops;
2944 vma->vm_private_data = pages; 2956 vma->vm_private_data = priv;
2945 2957
2946 ret = insert_vm_struct(mm, vma); 2958 ret = insert_vm_struct(mm, vma);
2947 if (ret) 2959 if (ret)
@@ -2958,12 +2970,31 @@ out:
2958 return ERR_PTR(ret); 2970 return ERR_PTR(ret);
2959} 2971}
2960 2972
2973/*
2974 * Called with mm->mmap_sem held for writing.
2975 * Insert a new vma covering the given region, with the given flags.
2976 * Its pages are supplied by the given array of struct page *.
2977 * The array can be shorter than len >> PAGE_SHIFT if it's null-terminated.
2978 * The region past the last page supplied will always produce SIGBUS.
2979 * The array pointer and the pages it points to are assumed to stay alive
2980 * for as long as this mapping might exist.
2981 */
2982struct vm_area_struct *_install_special_mapping(
2983 struct mm_struct *mm,
2984 unsigned long addr, unsigned long len,
2985 unsigned long vm_flags, const struct vm_special_mapping *spec)
2986{
2987 return __install_special_mapping(mm, addr, len, vm_flags,
2988 &special_mapping_vmops, (void *)spec);
2989}
2990
2961int install_special_mapping(struct mm_struct *mm, 2991int install_special_mapping(struct mm_struct *mm,
2962 unsigned long addr, unsigned long len, 2992 unsigned long addr, unsigned long len,
2963 unsigned long vm_flags, struct page **pages) 2993 unsigned long vm_flags, struct page **pages)
2964{ 2994{
2965 struct vm_area_struct *vma = _install_special_mapping(mm, 2995 struct vm_area_struct *vma = __install_special_mapping(
2966 addr, len, vm_flags, pages); 2996 mm, addr, len, vm_flags, &legacy_special_mapping_vmops,
2997 (void *)pages);
2967 2998
2968 if (IS_ERR(vma)) 2999 if (IS_ERR(vma))
2969 return PTR_ERR(vma); 3000 return PTR_ERR(vma);