aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-09-27 04:50:20 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 11:26:14 -0400
commit3034097a5017dd9281b1f795e80af9859627850e (patch)
treed03d6749ac52e6c23020bd9caa5fdee301ca8fa6
parentdbf8685c8e21404e3a8ed244bd0219d3c4b89101 (diff)
[PATCH] NOMMU: Order the per-mm_struct VMA list
Order the per-mm_struct VMA list by address so that searching it can be cut short when the appropriate address has been exceeded. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--mm/nommu.c104
1 files changed, 72 insertions, 32 deletions
diff --git a/mm/nommu.c b/mm/nommu.c
index 829fc904de11..4f87b2f43a2b 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -310,6 +310,48 @@ static void show_process_blocks(void)
310} 310}
311#endif /* DEBUG */ 311#endif /* DEBUG */
312 312
313/*
314 * add a VMA into a process's mm_struct in the appropriate place in the list
315 * - should be called with mm->mmap_sem held writelocked
316 */
317static void add_vma_to_mm(struct mm_struct *mm, struct vm_list_struct *vml)
318{
319 struct vm_list_struct **ppv;
320
321 for (ppv = &current->mm->context.vmlist; *ppv; ppv = &(*ppv)->next)
322 if ((*ppv)->vma->vm_start > vml->vma->vm_start)
323 break;
324
325 vml->next = *ppv;
326 *ppv = vml;
327}
328
329/*
330 * look up the first VMA in which addr resides, NULL if none
331 * - should be called with mm->mmap_sem at least held readlocked
332 */
333struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
334{
335 struct vm_list_struct *loop, *vml;
336
337 /* search the vm_start ordered list */
338 vml = NULL;
339 for (loop = mm->context.vmlist; loop; loop = loop->next) {
340 if (loop->vma->vm_start > addr)
341 break;
342 vml = loop;
343 }
344
345 if (vml && vml->vma->vm_end > addr)
346 return vml->vma;
347
348 return NULL;
349}
350EXPORT_SYMBOL(find_vma);
351
352/*
353 * find a VMA in the global tree
354 */
313static inline struct vm_area_struct *find_nommu_vma(unsigned long start) 355static inline struct vm_area_struct *find_nommu_vma(unsigned long start)
314{ 356{
315 struct vm_area_struct *vma; 357 struct vm_area_struct *vma;
@@ -329,6 +371,9 @@ static inline struct vm_area_struct *find_nommu_vma(unsigned long start)
329 return NULL; 371 return NULL;
330} 372}
331 373
374/*
375 * add a VMA in the global tree
376 */
332static void add_nommu_vma(struct vm_area_struct *vma) 377static void add_nommu_vma(struct vm_area_struct *vma)
333{ 378{
334 struct vm_area_struct *pvma; 379 struct vm_area_struct *pvma;
@@ -375,6 +420,9 @@ static void add_nommu_vma(struct vm_area_struct *vma)
375 rb_insert_color(&vma->vm_rb, &nommu_vma_tree); 420 rb_insert_color(&vma->vm_rb, &nommu_vma_tree);
376} 421}
377 422
423/*
424 * delete a VMA from the global list
425 */
378static void delete_nommu_vma(struct vm_area_struct *vma) 426static void delete_nommu_vma(struct vm_area_struct *vma)
379{ 427{
380 struct address_space *mapping; 428 struct address_space *mapping;
@@ -852,8 +900,7 @@ unsigned long do_mmap_pgoff(struct file *file,
852 realalloc += kobjsize(vml); 900 realalloc += kobjsize(vml);
853 askedalloc += sizeof(*vml); 901 askedalloc += sizeof(*vml);
854 902
855 vml->next = current->mm->context.vmlist; 903 add_vma_to_mm(current->mm, vml);
856 current->mm->context.vmlist = vml;
857 904
858 up_write(&nommu_vma_sem); 905 up_write(&nommu_vma_sem);
859 906
@@ -932,6 +979,11 @@ static void put_vma(struct vm_area_struct *vma)
932 } 979 }
933} 980}
934 981
982/*
983 * release a mapping
984 * - under NOMMU conditions the parameters must match exactly to the mapping to
985 * be removed
986 */
935int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len) 987int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
936{ 988{
937 struct vm_list_struct *vml, **parent; 989 struct vm_list_struct *vml, **parent;
@@ -941,10 +993,13 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
941 printk("do_munmap:\n"); 993 printk("do_munmap:\n");
942#endif 994#endif
943 995
944 for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next) 996 for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next) {
997 if ((*parent)->vma->vm_start > addr)
998 break;
945 if ((*parent)->vma->vm_start == addr && 999 if ((*parent)->vma->vm_start == addr &&
946 ((len == 0) || ((*parent)->vma->vm_end == end))) 1000 ((len == 0) || ((*parent)->vma->vm_end == end)))
947 goto found; 1001 goto found;
1002 }
948 1003
949 printk("munmap of non-mmaped memory by process %d (%s): %p\n", 1004 printk("munmap of non-mmaped memory by process %d (%s): %p\n",
950 current->pid, current->comm, (void *) addr); 1005 current->pid, current->comm, (void *) addr);
@@ -970,7 +1025,20 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
970 return 0; 1025 return 0;
971} 1026}
972 1027
973/* Release all mmaps. */ 1028asmlinkage long sys_munmap(unsigned long addr, size_t len)
1029{
1030 int ret;
1031 struct mm_struct *mm = current->mm;
1032
1033 down_write(&mm->mmap_sem);
1034 ret = do_munmap(mm, addr, len);
1035 up_write(&mm->mmap_sem);
1036 return ret;
1037}
1038
1039/*
1040 * Release all mappings
1041 */
974void exit_mmap(struct mm_struct * mm) 1042void exit_mmap(struct mm_struct * mm)
975{ 1043{
976 struct vm_list_struct *tmp; 1044 struct vm_list_struct *tmp;
@@ -997,17 +1065,6 @@ void exit_mmap(struct mm_struct * mm)
997 } 1065 }
998} 1066}
999 1067
1000asmlinkage long sys_munmap(unsigned long addr, size_t len)
1001{
1002 int ret;
1003 struct mm_struct *mm = current->mm;
1004
1005 down_write(&mm->mmap_sem);
1006 ret = do_munmap(mm, addr, len);
1007 up_write(&mm->mmap_sem);
1008 return ret;
1009}
1010
1011unsigned long do_brk(unsigned long addr, unsigned long len) 1068unsigned long do_brk(unsigned long addr, unsigned long len)
1012{ 1069{
1013 return -ENOMEM; 1070 return -ENOMEM;
@@ -1061,23 +1118,6 @@ unsigned long do_mremap(unsigned long addr,
1061 return vml->vma->vm_start; 1118 return vml->vma->vm_start;
1062} 1119}
1063 1120
1064/*
1065 * Look up the first VMA which satisfies addr < vm_end, NULL if none
1066 * - should be called with mm->mmap_sem at least readlocked
1067 */
1068struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
1069{
1070 struct vm_list_struct *vml;
1071
1072 for (vml = mm->context.vmlist; vml; vml = vml->next)
1073 if (addr >= vml->vma->vm_start && addr < vml->vma->vm_end)
1074 return vml->vma;
1075
1076 return NULL;
1077}
1078
1079EXPORT_SYMBOL(find_vma);
1080
1081struct page *follow_page(struct vm_area_struct *vma, unsigned long address, 1121struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
1082 unsigned int foll_flags) 1122 unsigned int foll_flags)
1083{ 1123{