+ /* allocate some memory to hold the mapping
+ * - note that this may not return a page-aligned address if the object
+ * we're allocating is smaller than a page
+ */
+ base = kmalloc(len, GFP_KERNEL|__GFP_COMP);
+ if (!base)
+ goto enomem;
+
+ vma->vm_start = (unsigned long) base;
+ vma->vm_end = vma->vm_start + len;
+ vma->vm_flags |= VM_MAPPED_COPY;
+
+#ifdef WARN_ON_SLACK
+ if (len + WARN_ON_SLACK <= kobjsize(result))
+ printk("Allocation of %lu bytes from process %d has %lu bytes of slack\n",
+ len, current->pid, kobjsize(result) - len);
+#endif
+
+ if (vma->vm_file) {
+ /* read the contents of a file into the copy */
+ mm_segment_t old_fs;
+ loff_t fpos;
+
+ fpos = vma->vm_pgoff;
+ fpos <<= PAGE_SHIFT;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = vma->vm_file->f_op->read(vma->vm_file, base, len, &fpos);
+ set_fs(old_fs);
+
+ if (ret < 0)
+ goto error_free;
+
+ /* clear the last little bit */
+ if (ret < len)
+ memset(base + ret, 0, len - ret);
+
+ } else {
+ /* if it's an anonymous mapping, then just clear it */
+ memset(base, 0, len);
+ }
+
+ return 0;
+
+error_free:
+ kfree(base);
+ vma->vm_start = 0;
+ return ret;
+
+enomem:
+ printk("Allocation of length %lu from process %d failed\n",
+ len, current->pid);
+ show_free_areas();
+ return -ENOMEM;
+}
+
+/*
+ * 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 long capabilities, vm_flags;
+ void *result;
+ int ret;
+
+ /* decide whether we should attempt the mapping, and if so what sort of
+ * mapping */
+ ret = validate_mmap_request(file, addr, len, prot, flags, pgoff,
+ &capabilities);
+ if (ret < 0)