aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/mm/hugetlbpage.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/mm/hugetlbpage.c')
-rw-r--r--arch/i386/mm/hugetlbpage.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 5aa06001a4bd..3b099f32b948 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -140,7 +140,12 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
140 struct vm_area_struct *vma; 140 struct vm_area_struct *vma;
141 unsigned long start_addr; 141 unsigned long start_addr;
142 142
143 start_addr = mm->free_area_cache; 143 if (len > mm->cached_hole_size) {
144 start_addr = mm->free_area_cache;
145 } else {
146 start_addr = TASK_UNMAPPED_BASE;
147 mm->cached_hole_size = 0;
148 }
144 149
145full_search: 150full_search:
146 addr = ALIGN(start_addr, HPAGE_SIZE); 151 addr = ALIGN(start_addr, HPAGE_SIZE);
@@ -154,6 +159,7 @@ full_search:
154 */ 159 */
155 if (start_addr != TASK_UNMAPPED_BASE) { 160 if (start_addr != TASK_UNMAPPED_BASE) {
156 start_addr = TASK_UNMAPPED_BASE; 161 start_addr = TASK_UNMAPPED_BASE;
162 mm->cached_hole_size = 0;
157 goto full_search; 163 goto full_search;
158 } 164 }
159 return -ENOMEM; 165 return -ENOMEM;
@@ -162,6 +168,8 @@ full_search:
162 mm->free_area_cache = addr + len; 168 mm->free_area_cache = addr + len;
163 return addr; 169 return addr;
164 } 170 }
171 if (addr + mm->cached_hole_size < vma->vm_start)
172 mm->cached_hole_size = vma->vm_start - addr;
165 addr = ALIGN(vma->vm_end, HPAGE_SIZE); 173 addr = ALIGN(vma->vm_end, HPAGE_SIZE);
166 } 174 }
167} 175}
@@ -173,12 +181,17 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
173 struct mm_struct *mm = current->mm; 181 struct mm_struct *mm = current->mm;
174 struct vm_area_struct *vma, *prev_vma; 182 struct vm_area_struct *vma, *prev_vma;
175 unsigned long base = mm->mmap_base, addr = addr0; 183 unsigned long base = mm->mmap_base, addr = addr0;
184 unsigned long largest_hole = mm->cached_hole_size;
176 int first_time = 1; 185 int first_time = 1;
177 186
178 /* don't allow allocations above current base */ 187 /* don't allow allocations above current base */
179 if (mm->free_area_cache > base) 188 if (mm->free_area_cache > base)
180 mm->free_area_cache = base; 189 mm->free_area_cache = base;
181 190
191 if (len <= largest_hole) {
192 largest_hole = 0;
193 mm->free_area_cache = base;
194 }
182try_again: 195try_again:
183 /* make sure it can fit in the remaining address space */ 196 /* make sure it can fit in the remaining address space */
184 if (mm->free_area_cache < len) 197 if (mm->free_area_cache < len)
@@ -199,13 +212,21 @@ try_again:
199 * vma->vm_start, use it: 212 * vma->vm_start, use it:
200 */ 213 */
201 if (addr + len <= vma->vm_start && 214 if (addr + len <= vma->vm_start &&
202 (!prev_vma || (addr >= prev_vma->vm_end))) 215 (!prev_vma || (addr >= prev_vma->vm_end))) {
203 /* remember the address as a hint for next time */ 216 /* remember the address as a hint for next time */
204 return (mm->free_area_cache = addr); 217 mm->cached_hole_size = largest_hole;
205 else 218 return (mm->free_area_cache = addr);
219 } else {
206 /* pull free_area_cache down to the first hole */ 220 /* pull free_area_cache down to the first hole */
207 if (mm->free_area_cache == vma->vm_end) 221 if (mm->free_area_cache == vma->vm_end) {
208 mm->free_area_cache = vma->vm_start; 222 mm->free_area_cache = vma->vm_start;
223 mm->cached_hole_size = largest_hole;
224 }
225 }
226
227 /* remember the largest hole we saw so far */
228 if (addr + largest_hole < vma->vm_start)
229 largest_hole = vma->vm_start - addr;
209 230
210 /* try just below the current vma->vm_start */ 231 /* try just below the current vma->vm_start */
211 addr = (vma->vm_start - len) & HPAGE_MASK; 232 addr = (vma->vm_start - len) & HPAGE_MASK;
@@ -218,6 +239,7 @@ fail:
218 */ 239 */
219 if (first_time) { 240 if (first_time) {
220 mm->free_area_cache = base; 241 mm->free_area_cache = base;
242 largest_hole = 0;
221 first_time = 0; 243 first_time = 0;
222 goto try_again; 244 goto try_again;
223 } 245 }
@@ -228,6 +250,7 @@ fail:
228 * allocations. 250 * allocations.
229 */ 251 */
230 mm->free_area_cache = TASK_UNMAPPED_BASE; 252 mm->free_area_cache = TASK_UNMAPPED_BASE;
253 mm->cached_hole_size = ~0UL;
231 addr = hugetlb_get_unmapped_area_bottomup(file, addr0, 254 addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
232 len, pgoff, flags); 255 len, pgoff, flags);
233 256
@@ -235,6 +258,7 @@ fail:
235 * Restore the topdown base: 258 * Restore the topdown base:
236 */ 259 */
237 mm->free_area_cache = base; 260 mm->free_area_cache = base;
261 mm->cached_hole_size = ~0UL;
238 262
239 return addr; 263 return addr;
240} 264}