+
+ /* add the VMA to the master list */
+ while (*p) {
+ parent = *p;
+ pvma = rb_entry(parent, struct vm_area_struct, vm_rb);
+
+ if (vma->vm_start < pvma->vm_start) {
+ p = &(*p)->rb_left;
+ }
+ else if (vma->vm_start > pvma->vm_start) {
+ p = &(*p)->rb_right;
+ }
+ else {
+ /* mappings are at the same address - this can only
+ * happen for shared-mem chardevs and shared file
+ * mappings backed by ramfs/tmpfs */
+ BUG_ON(!(pvma->vm_flags & VM_SHARED));
+
+ if (vma < pvma)
+ p = &(*p)->rb_left;
+ else if (vma > pvma)
+ p = &(*p)->rb_right;
+ else
+ BUG();
+ }
+ }
+
+ rb_link_node(&vma->vm_rb, parent, p);
+ rb_insert_color(&vma->vm_rb, &nommu_vma_tree);
+}
+
+static void delete_nommu_vma(struct vm_area_struct *vma)
+{
+ struct address_space *mapping;
+
+ /* remove the VMA from the mapping */
+ if (vma->vm_file) {
+ mapping = vma->vm_file->f_mapping;
+
+ flush_dcache_mmap_lock(mapping);
+ vma_prio_tree_remove(vma, &mapping->i_mmap);
+ flush_dcache_mmap_unlock(mapping);
+ }
+
+ /* remove from the master list */
+ rb_erase(&vma->vm_rb, &nommu_vma_tree);
+}
+
+/*
+ * handle mapping creation for uClinux
+ */
+unsigned long do_mmap_pgoff(struct file *file,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long prot,
+ unsigned long flags,
+ unsigned long pgoff)
+{
+ struct vm_list_struct *vml = NULL;
+ struct vm_area_struct *vma = NULL;
+ struct rb_node *rb;
+ unsigned int vm_flags;
+ void *result;
+ int ret, membacked;
+
+ /* do the simple checks first */
+ if (flags & MAP_FIXED || addr) {
+ printk(KERN_DEBUG "%d: Can't do fixed-address/overlay mmap of RAM\n",
+ current->pid);