aboutsummaryrefslogtreecommitdiffstats
path: root/mm/nommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/nommu.c')
-rw-r--r--mm/nommu.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/mm/nommu.c b/mm/nommu.c
index 4f87b2f43a2b..23cfa8ec914a 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -350,6 +350,26 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
350EXPORT_SYMBOL(find_vma); 350EXPORT_SYMBOL(find_vma);
351 351
352/* 352/*
353 * look up the first VMA exactly that exactly matches addr
354 * - should be called with mm->mmap_sem at least held readlocked
355 */
356static inline struct vm_area_struct *find_vma_exact(struct mm_struct *mm,
357 unsigned long addr)
358{
359 struct vm_list_struct *vml;
360
361 /* search the vm_start ordered list */
362 for (vml = mm->context.vmlist; vml; vml = vml->next) {
363 if (vml->vma->vm_start == addr)
364 return vml->vma;
365 if (vml->vma->vm_start > addr)
366 break;
367 }
368
369 return NULL;
370}
371
372/*
353 * find a VMA in the global tree 373 * find a VMA in the global tree
354 */ 374 */
355static inline struct vm_area_struct *find_nommu_vma(unsigned long start) 375static inline struct vm_area_struct *find_nommu_vma(unsigned long start)
@@ -1071,20 +1091,20 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
1071} 1091}
1072 1092
1073/* 1093/*
1074 * Expand (or shrink) an existing mapping, potentially moving it at the 1094 * expand (or shrink) an existing mapping, potentially moving it at the same
1075 * same time (controlled by the MREMAP_MAYMOVE flag and available VM space) 1095 * time (controlled by the MREMAP_MAYMOVE flag and available VM space)
1076 * 1096 *
1077 * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise 1097 * under NOMMU conditions, we only permit changing a mapping's size, and only
1078 * This option implies MREMAP_MAYMOVE. 1098 * as long as it stays within the hole allocated by the kmalloc() call in
1099 * do_mmap_pgoff() and the block is not shareable
1079 * 1100 *
1080 * on uClinux, we only permit changing a mapping's size, and only as long as it stays within the 1101 * MREMAP_FIXED is not supported under NOMMU conditions
1081 * hole allocated by the kmalloc() call in do_mmap_pgoff() and the block is not shareable
1082 */ 1102 */
1083unsigned long do_mremap(unsigned long addr, 1103unsigned long do_mremap(unsigned long addr,
1084 unsigned long old_len, unsigned long new_len, 1104 unsigned long old_len, unsigned long new_len,
1085 unsigned long flags, unsigned long new_addr) 1105 unsigned long flags, unsigned long new_addr)
1086{ 1106{
1087 struct vm_list_struct *vml = NULL; 1107 struct vm_area_struct *vma;
1088 1108
1089 /* insanity checks first */ 1109 /* insanity checks first */
1090 if (new_len == 0) 1110 if (new_len == 0)
@@ -1093,29 +1113,38 @@ unsigned long do_mremap(unsigned long addr,
1093 if (flags & MREMAP_FIXED && new_addr != addr) 1113 if (flags & MREMAP_FIXED && new_addr != addr)
1094 return (unsigned long) -EINVAL; 1114 return (unsigned long) -EINVAL;
1095 1115
1096 for (vml = current->mm->context.vmlist; vml; vml = vml->next) 1116 vma = find_vma_exact(current->mm, addr);
1097 if (vml->vma->vm_start == addr) 1117 if (!vma)
1098 goto found; 1118 return (unsigned long) -EINVAL;
1099
1100 return (unsigned long) -EINVAL;
1101 1119
1102 found: 1120 if (vma->vm_end != vma->vm_start + old_len)
1103 if (vml->vma->vm_end != vml->vma->vm_start + old_len)
1104 return (unsigned long) -EFAULT; 1121 return (unsigned long) -EFAULT;
1105 1122
1106 if (vml->vma->vm_flags & VM_MAYSHARE) 1123 if (vma->vm_flags & VM_MAYSHARE)
1107 return (unsigned long) -EPERM; 1124 return (unsigned long) -EPERM;
1108 1125
1109 if (new_len > kobjsize((void *) addr)) 1126 if (new_len > kobjsize((void *) addr))
1110 return (unsigned long) -ENOMEM; 1127 return (unsigned long) -ENOMEM;
1111 1128
1112 /* all checks complete - do it */ 1129 /* all checks complete - do it */
1113 vml->vma->vm_end = vml->vma->vm_start + new_len; 1130 vma->vm_end = vma->vm_start + new_len;
1114 1131
1115 askedalloc -= old_len; 1132 askedalloc -= old_len;
1116 askedalloc += new_len; 1133 askedalloc += new_len;
1117 1134
1118 return vml->vma->vm_start; 1135 return vma->vm_start;
1136}
1137
1138asmlinkage unsigned long sys_mremap(unsigned long addr,
1139 unsigned long old_len, unsigned long new_len,
1140 unsigned long flags, unsigned long new_addr)
1141{
1142 unsigned long ret;
1143
1144 down_write(&current->mm->mmap_sem);
1145 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
1146 up_write(&current->mm->mmap_sem);
1147 return ret;
1119} 1148}
1120 1149
1121struct page *follow_page(struct vm_area_struct *vma, unsigned long address, 1150struct page *follow_page(struct vm_area_struct *vma, unsigned long address,