2006-10-11 13:32:15

by Adam Litke

[permalink] [raw]
Subject: [RFC] hugetlb: Move hugetlb_get_unmapped_area

I am trying to do some hugetlb interface cleanups which include
separation of the hugetlb utility functions (mostly in mm/hugetlb.c)
from the hugetlbfs interface to huge pages (fs/hugetlbfs/inode.c).

This patch simply moves hugetlb_get_unmapped_area() (which I'll argue is
more of a utility function than an interface) to mm/hugetlb.c.

Signed-off-by: Adam Litke <[email protected]>
---
fs/hugetlbfs/inode.c | 58 ------------------------------------------------
include/linux/hugetlb.h | 3 ++
mm/hugetlb.c | 54 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 57 insertions(+), 58 deletions(-)
diff -upN reference/fs/hugetlbfs/inode.c current/fs/hugetlbfs/inode.c
--- reference/fs/hugetlbfs/inode.c
+++ current/fs/hugetlbfs/inode.c
@@ -100,64 +100,6 @@ out:
}

/*
- * Called under down_write(mmap_sem).
- */
-
-#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags);
-#else
-static unsigned long
-hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
-{
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
- unsigned long start_addr;
-
- if (len & ~HPAGE_MASK)
- return -EINVAL;
- if (len > TASK_SIZE)
- return -ENOMEM;
-
- if (addr) {
- addr = ALIGN(addr, HPAGE_SIZE);
- vma = find_vma(mm, addr);
- if (TASK_SIZE - len >= addr &&
- (!vma || addr + len <= vma->vm_start))
- return addr;
- }
-
- start_addr = mm->free_area_cache;
-
- if (len <= mm->cached_hole_size)
- start_addr = TASK_UNMAPPED_BASE;
-
-full_search:
- addr = ALIGN(start_addr, HPAGE_SIZE);
-
- for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
- /* At this point: (!vma || addr < vma->vm_end). */
- if (TASK_SIZE - len < addr) {
- /*
- * Start a new search - just in case we missed
- * some holes.
- */
- if (start_addr != TASK_UNMAPPED_BASE) {
- start_addr = TASK_UNMAPPED_BASE;
- goto full_search;
- }
- return -ENOMEM;
- }
-
- if (!vma || addr + len <= vma->vm_start)
- return addr;
- addr = ALIGN(vma->vm_end, HPAGE_SIZE);
- }
-}
-#endif
-
-/*
* Read a page. Again trivial. If it didn't already exist
* in the page cache, it is zero-filled.
*/
diff -upN reference/include/linux/hugetlb.h current/include/linux/hugetlb.h
--- reference/include/linux/hugetlb.h
+++ current/include/linux/hugetlb.h
@@ -87,6 +87,9 @@ pte_t huge_ptep_get_and_clear(struct mm_
void hugetlb_prefault_arch_hook(struct mm_struct *mm);
#endif

+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags);
+
#else /* !CONFIG_HUGETLB_PAGE */

static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
diff -upN reference/mm/hugetlb.c current/mm/hugetlb.c
--- reference/mm/hugetlb.c
+++ current/mm/hugetlb.c
@@ -796,3 +796,57 @@ void hugetlb_unreserve_pages(struct inod
long chg = region_truncate(&inode->i_mapping->private_list, offset);
hugetlb_acct_memory(freed - chg);
}
+
+/*
+ * Called under down_write(mmap_sem).
+ */
+
+#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ unsigned long start_addr;
+
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ if (len > TASK_SIZE)
+ return -ENOMEM;
+
+ if (addr) {
+ addr = ALIGN(addr, HPAGE_SIZE);
+ vma = find_vma(mm, addr);
+ if (TASK_SIZE - len >= addr &&
+ (!vma || addr + len <= vma->vm_start))
+ return addr;
+ }
+
+ start_addr = mm->free_area_cache;
+
+ if (len <= mm->cached_hole_size)
+ start_addr = TASK_UNMAPPED_BASE;
+
+full_search:
+ addr = ALIGN(start_addr, HPAGE_SIZE);
+
+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (TASK_SIZE - len < addr) {
+ /*
+ * Start a new search - just in case we missed
+ * some holes.
+ */
+ if (start_addr != TASK_UNMAPPED_BASE) {
+ start_addr = TASK_UNMAPPED_BASE;
+ goto full_search;
+ }
+ return -ENOMEM;
+ }
+
+ if (!vma || addr + len <= vma->vm_start)
+ return addr;
+ addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+ }
+}
+#endif

--
Adam Litke - (agl at us.ibm.com)
IBM Linux Technology Center


2006-10-11 15:43:58

by Chen, Kenneth W

[permalink] [raw]
Subject: RE: [RFC] hugetlb: Move hugetlb_get_unmapped_area

Adam Litke wrote on Wednesday, October 11, 2006 6:32 AM
> I am trying to do some hugetlb interface cleanups which include
> separation of the hugetlb utility functions (mostly in mm/hugetlb.c)
> from the hugetlbfs interface to huge pages (fs/hugetlbfs/inode.c).
>
> This patch simply moves hugetlb_get_unmapped_area() (which I'll argue is
> more of a utility function than an interface) to mm/hugetlb.c.

To me it doesn't look like a clean up. get_unmapped_area() is one of
file_operations method and it make sense with the current arrangement
that it stays together with .mmap method, which both live in
fs/hugetlbfs/inode.c.

- Ken