diff options
author | Michel Lespinasse <walken@google.com> | 2012-12-11 19:02:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 20:22:25 -0500 |
commit | 0865935598bb112a02f40017e8aaa6bce8577f23 (patch) | |
tree | 93460e1539ba63dc3aea857e1aaf2b9fa9429ce5 /fs/hugetlbfs | |
parent | 7d025059650f1c41a427173789ac14b74212b361 (diff) |
mm: use vm_unmapped_area() in hugetlbfs
Update the hugetlb_get_unmapped_area function to make use of
vm_unmapped_area() instead of implementing a brute force search.
Signed-off-by: Michel Lespinasse <walken@google.com>
Reviewed-by: Rik van Riel <riel@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hugetlbfs')
-rw-r--r-- | fs/hugetlbfs/inode.c | 42 |
1 files changed, 8 insertions, 34 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 21b8a4875237..47e6e2f21e21 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -151,8 +151,8 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
151 | { | 151 | { |
152 | struct mm_struct *mm = current->mm; | 152 | struct mm_struct *mm = current->mm; |
153 | struct vm_area_struct *vma; | 153 | struct vm_area_struct *vma; |
154 | unsigned long start_addr; | ||
155 | struct hstate *h = hstate_file(file); | 154 | struct hstate *h = hstate_file(file); |
155 | struct vm_unmapped_area_info info; | ||
156 | 156 | ||
157 | if (len & ~huge_page_mask(h)) | 157 | if (len & ~huge_page_mask(h)) |
158 | return -EINVAL; | 158 | return -EINVAL; |
@@ -173,39 +173,13 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
173 | return addr; | 173 | return addr; |
174 | } | 174 | } |
175 | 175 | ||
176 | if (len > mm->cached_hole_size) | 176 | info.flags = 0; |
177 | start_addr = mm->free_area_cache; | 177 | info.length = len; |
178 | else { | 178 | info.low_limit = TASK_UNMAPPED_BASE; |
179 | start_addr = TASK_UNMAPPED_BASE; | 179 | info.high_limit = TASK_SIZE; |
180 | mm->cached_hole_size = 0; | 180 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); |
181 | } | 181 | info.align_offset = 0; |
182 | 182 | return vm_unmapped_area(&info); | |
183 | full_search: | ||
184 | addr = ALIGN(start_addr, huge_page_size(h)); | ||
185 | |||
186 | for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { | ||
187 | /* At this point: (!vma || addr < vma->vm_end). */ | ||
188 | if (TASK_SIZE - len < addr) { | ||
189 | /* | ||
190 | * Start a new search - just in case we missed | ||
191 | * some holes. | ||
192 | */ | ||
193 | if (start_addr != TASK_UNMAPPED_BASE) { | ||
194 | start_addr = TASK_UNMAPPED_BASE; | ||
195 | mm->cached_hole_size = 0; | ||
196 | goto full_search; | ||
197 | } | ||
198 | return -ENOMEM; | ||
199 | } | ||
200 | |||
201 | if (!vma || addr + len <= vma->vm_start) { | ||
202 | mm->free_area_cache = addr + len; | ||
203 | return addr; | ||
204 | } | ||
205 | if (addr + mm->cached_hole_size < vma->vm_start) | ||
206 | mm->cached_hole_size = vma->vm_start - addr; | ||
207 | addr = ALIGN(vma->vm_end, huge_page_size(h)); | ||
208 | } | ||
209 | } | 183 | } |
210 | #endif | 184 | #endif |
211 | 185 | ||