aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-10-20 10:06:09 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-20 10:06:09 -0400
commit902f90735b693550eb51a3989895f3148b8229d8 (patch)
treefaddc60f0b27ed6d2a26f20c2c09f365dc4a2d7d /mm
parent07b8fede6da76ae6a0f547716c44b801a116bb4a (diff)
parent93918e9afc76717176e9e114e79cdbb602a45ae8 (diff)
Merge branch 'master'
Diffstat (limited to 'mm')
-rw-r--r--mm/bootmem.c31
-rw-r--r--mm/hugetlb.c35
-rw-r--r--mm/memory.c14
3 files changed, 54 insertions, 26 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c
index c1330cc19783..a58699b6579e 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -154,10 +154,10 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
154 */ 154 */
155static void * __init 155static void * __init
156__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, 156__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
157 unsigned long align, unsigned long goal) 157 unsigned long align, unsigned long goal, unsigned long limit)
158{ 158{
159 unsigned long offset, remaining_size, areasize, preferred; 159 unsigned long offset, remaining_size, areasize, preferred;
160 unsigned long i, start = 0, incr, eidx; 160 unsigned long i, start = 0, incr, eidx, end_pfn = bdata->node_low_pfn;
161 void *ret; 161 void *ret;
162 162
163 if(!size) { 163 if(!size) {
@@ -166,7 +166,14 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
166 } 166 }
167 BUG_ON(align & (align-1)); 167 BUG_ON(align & (align-1));
168 168
169 eidx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT); 169 if (limit && bdata->node_boot_start >= limit)
170 return NULL;
171
172 limit >>=PAGE_SHIFT;
173 if (limit && end_pfn > limit)
174 end_pfn = limit;
175
176 eidx = end_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
170 offset = 0; 177 offset = 0;
171 if (align && 178 if (align &&
172 (bdata->node_boot_start & (align - 1UL)) != 0) 179 (bdata->node_boot_start & (align - 1UL)) != 0)
@@ -178,11 +185,12 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
178 * first, then we try to allocate lower pages. 185 * first, then we try to allocate lower pages.
179 */ 186 */
180 if (goal && (goal >= bdata->node_boot_start) && 187 if (goal && (goal >= bdata->node_boot_start) &&
181 ((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) { 188 ((goal >> PAGE_SHIFT) < end_pfn)) {
182 preferred = goal - bdata->node_boot_start; 189 preferred = goal - bdata->node_boot_start;
183 190
184 if (bdata->last_success >= preferred) 191 if (bdata->last_success >= preferred)
185 preferred = bdata->last_success; 192 if (!limit || (limit && limit > bdata->last_success))
193 preferred = bdata->last_success;
186 } else 194 } else
187 preferred = 0; 195 preferred = 0;
188 196
@@ -382,14 +390,15 @@ unsigned long __init free_all_bootmem (void)
382 return(free_all_bootmem_core(NODE_DATA(0))); 390 return(free_all_bootmem_core(NODE_DATA(0)));
383} 391}
384 392
385void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal) 393void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal,
394 unsigned long limit)
386{ 395{
387 pg_data_t *pgdat = pgdat_list; 396 pg_data_t *pgdat = pgdat_list;
388 void *ptr; 397 void *ptr;
389 398
390 for_each_pgdat(pgdat) 399 for_each_pgdat(pgdat)
391 if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, 400 if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
392 align, goal))) 401 align, goal, limit)))
393 return(ptr); 402 return(ptr);
394 403
395 /* 404 /*
@@ -400,14 +409,16 @@ void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned
400 return NULL; 409 return NULL;
401} 410}
402 411
403void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal) 412
413void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align,
414 unsigned long goal, unsigned long limit)
404{ 415{
405 void *ptr; 416 void *ptr;
406 417
407 ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal); 418 ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, limit);
408 if (ptr) 419 if (ptr)
409 return (ptr); 420 return (ptr);
410 421
411 return __alloc_bootmem(size, align, goal); 422 return __alloc_bootmem_limit(size, align, goal, limit);
412} 423}
413 424
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 901ac523a1c3..a1b30d45459e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -274,21 +274,22 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
274{ 274{
275 pte_t *src_pte, *dst_pte, entry; 275 pte_t *src_pte, *dst_pte, entry;
276 struct page *ptepage; 276 struct page *ptepage;
277 unsigned long addr = vma->vm_start; 277 unsigned long addr;
278 unsigned long end = vma->vm_end;
279 278
280 while (addr < end) { 279 for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
281 dst_pte = huge_pte_alloc(dst, addr); 280 dst_pte = huge_pte_alloc(dst, addr);
282 if (!dst_pte) 281 if (!dst_pte)
283 goto nomem; 282 goto nomem;
283 spin_lock(&src->page_table_lock);
284 src_pte = huge_pte_offset(src, addr); 284 src_pte = huge_pte_offset(src, addr);
285 BUG_ON(!src_pte || pte_none(*src_pte)); /* prefaulted */ 285 if (src_pte && !pte_none(*src_pte)) {
286 entry = *src_pte; 286 entry = *src_pte;
287 ptepage = pte_page(entry); 287 ptepage = pte_page(entry);
288 get_page(ptepage); 288 get_page(ptepage);
289 add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE); 289 add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
290 set_huge_pte_at(dst, addr, dst_pte, entry); 290 set_huge_pte_at(dst, addr, dst_pte, entry);
291 addr += HPAGE_SIZE; 291 }
292 spin_unlock(&src->page_table_lock);
292 } 293 }
293 return 0; 294 return 0;
294 295
@@ -323,8 +324,8 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
323 324
324 page = pte_page(pte); 325 page = pte_page(pte);
325 put_page(page); 326 put_page(page);
327 add_mm_counter(mm, rss, - (HPAGE_SIZE / PAGE_SIZE));
326 } 328 }
327 add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
328 flush_tlb_range(vma, start, end); 329 flush_tlb_range(vma, start, end);
329} 330}
330 331
@@ -403,6 +404,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
403 BUG_ON(!is_vm_hugetlb_page(vma)); 404 BUG_ON(!is_vm_hugetlb_page(vma));
404 405
405 vpfn = vaddr/PAGE_SIZE; 406 vpfn = vaddr/PAGE_SIZE;
407 spin_lock(&mm->page_table_lock);
406 while (vaddr < vma->vm_end && remainder) { 408 while (vaddr < vma->vm_end && remainder) {
407 409
408 if (pages) { 410 if (pages) {
@@ -415,8 +417,13 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
415 * indexing below to work. */ 417 * indexing below to work. */
416 pte = huge_pte_offset(mm, vaddr & HPAGE_MASK); 418 pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
417 419
418 /* hugetlb should be locked, and hence, prefaulted */ 420 /* the hugetlb file might have been truncated */
419 WARN_ON(!pte || pte_none(*pte)); 421 if (!pte || pte_none(*pte)) {
422 remainder = 0;
423 if (!i)
424 i = -EFAULT;
425 break;
426 }
420 427
421 page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; 428 page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
422 429
@@ -434,7 +441,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
434 --remainder; 441 --remainder;
435 ++i; 442 ++i;
436 } 443 }
437 444 spin_unlock(&mm->page_table_lock);
438 *length = remainder; 445 *length = remainder;
439 *position = vaddr; 446 *position = vaddr;
440 447
diff --git a/mm/memory.c b/mm/memory.c
index ae8161f1f459..8c88b973abc5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2045,8 +2045,18 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
2045 2045
2046 inc_page_state(pgfault); 2046 inc_page_state(pgfault);
2047 2047
2048 if (is_vm_hugetlb_page(vma)) 2048 if (unlikely(is_vm_hugetlb_page(vma))) {
2049 return VM_FAULT_SIGBUS; /* mapping truncation does this. */ 2049 if (valid_hugetlb_file_off(vma, address))
2050 /* We get here only if there was a stale(zero) TLB entry
2051 * (because of HW prefetching).
2052 * Low-level arch code (if needed) should have already
2053 * purged the stale entry as part of this fault handling.
2054 * Here we just return.
2055 */
2056 return VM_FAULT_MINOR;
2057 else
2058 return VM_FAULT_SIGBUS; /* mapping truncation does this. */
2059 }
2050 2060
2051 /* 2061 /*
2052 * We need the page table lock to synchronize with kswapd 2062 * We need the page table lock to synchronize with kswapd