diff -ur /md0/kernels/2.4/v2.4.8-ac5/mm/mremap.c work-v2.4.8-ac5/mm/mremap.c --- /md0/kernels/2.4/v2.4.8-ac5/mm/mremap.c Wed Aug 15 12:57:40 2001 +++ work-v2.4.8-ac5/mm/mremap.c Wed Aug 15 14:59:02 2001 @@ -132,10 +132,23 @@ unsigned long new_addr) { struct vm_area_struct * new_vma; + int allocated_vma = 0; - new_vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); - if (new_vma) { - if (!move_page_tables(current->mm, new_addr, addr, old_len)) { + /* First, check if we can merge a mapping. -ben */ + new_vma = find_vma(current->mm, new_addr-1); + if (new_vma && new_vma->vm_end == new_addr && !new_vma->vm_file && + new_vma->vm_flags == vma->vm_flags) { + new_vma->vm_end = new_addr + new_len; +printk("merged!\n"); + } else { + new_vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + if (!new_vma) + goto no_mem; + allocated_vma = 1; + } + + if (!move_page_tables(current->mm, new_addr, addr, old_len)) { + if (allocated_vma) { *new_vma = *vma; new_vma->vm_start = new_addr; new_vma->vm_end = new_addr+new_len; @@ -146,17 +159,20 @@ if (new_vma->vm_ops && new_vma->vm_ops->open) new_vma->vm_ops->open(new_vma); insert_vm_struct(current->mm, new_vma); - do_munmap(current->mm, addr, old_len); - current->mm->total_vm += new_len >> PAGE_SHIFT; - if (new_vma->vm_flags & VM_LOCKED) { - current->mm->locked_vm += new_len >> PAGE_SHIFT; - make_pages_present(new_vma->vm_start, - new_vma->vm_end); - } - return new_addr; } - kmem_cache_free(vm_area_cachep, new_vma); + do_munmap(current->mm, addr, old_len); + current->mm->total_vm += new_len >> PAGE_SHIFT; + if (new_vma->vm_flags & VM_LOCKED) { + current->mm->locked_vm += new_len >> PAGE_SHIFT; + make_pages_present(new_vma->vm_start, + new_vma->vm_end); + } + return new_addr; } + if (allocated_vma) + kmem_cache_free(vm_area_cachep, new_vma); + +no_mem: return -ENOMEM; }