diff options
Diffstat (limited to 'mm/vmalloc.c')
| -rw-r--r-- | mm/vmalloc.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 75f49d312e8c..520a75980269 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
| @@ -323,6 +323,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size, | |||
| 323 | unsigned long addr; | 323 | unsigned long addr; |
| 324 | int purged = 0; | 324 | int purged = 0; |
| 325 | 325 | ||
| 326 | BUG_ON(!size); | ||
| 326 | BUG_ON(size & ~PAGE_MASK); | 327 | BUG_ON(size & ~PAGE_MASK); |
| 327 | 328 | ||
| 328 | va = kmalloc_node(sizeof(struct vmap_area), | 329 | va = kmalloc_node(sizeof(struct vmap_area), |
| @@ -334,6 +335,9 @@ retry: | |||
| 334 | addr = ALIGN(vstart, align); | 335 | addr = ALIGN(vstart, align); |
| 335 | 336 | ||
| 336 | spin_lock(&vmap_area_lock); | 337 | spin_lock(&vmap_area_lock); |
| 338 | if (addr + size - 1 < addr) | ||
| 339 | goto overflow; | ||
| 340 | |||
| 337 | /* XXX: could have a last_hole cache */ | 341 | /* XXX: could have a last_hole cache */ |
| 338 | n = vmap_area_root.rb_node; | 342 | n = vmap_area_root.rb_node; |
| 339 | if (n) { | 343 | if (n) { |
| @@ -365,6 +369,8 @@ retry: | |||
| 365 | 369 | ||
| 366 | while (addr + size > first->va_start && addr + size <= vend) { | 370 | while (addr + size > first->va_start && addr + size <= vend) { |
| 367 | addr = ALIGN(first->va_end + PAGE_SIZE, align); | 371 | addr = ALIGN(first->va_end + PAGE_SIZE, align); |
| 372 | if (addr + size - 1 < addr) | ||
| 373 | goto overflow; | ||
| 368 | 374 | ||
| 369 | n = rb_next(&first->rb_node); | 375 | n = rb_next(&first->rb_node); |
| 370 | if (n) | 376 | if (n) |
| @@ -375,6 +381,7 @@ retry: | |||
| 375 | } | 381 | } |
| 376 | found: | 382 | found: |
| 377 | if (addr + size > vend) { | 383 | if (addr + size > vend) { |
| 384 | overflow: | ||
| 378 | spin_unlock(&vmap_area_lock); | 385 | spin_unlock(&vmap_area_lock); |
| 379 | if (!purged) { | 386 | if (!purged) { |
| 380 | purge_vmap_area_lazy(); | 387 | purge_vmap_area_lazy(); |
| @@ -498,6 +505,7 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end, | |||
| 498 | static DEFINE_SPINLOCK(purge_lock); | 505 | static DEFINE_SPINLOCK(purge_lock); |
| 499 | LIST_HEAD(valist); | 506 | LIST_HEAD(valist); |
| 500 | struct vmap_area *va; | 507 | struct vmap_area *va; |
| 508 | struct vmap_area *n_va; | ||
| 501 | int nr = 0; | 509 | int nr = 0; |
| 502 | 510 | ||
| 503 | /* | 511 | /* |
| @@ -537,7 +545,7 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end, | |||
| 537 | 545 | ||
| 538 | if (nr) { | 546 | if (nr) { |
| 539 | spin_lock(&vmap_area_lock); | 547 | spin_lock(&vmap_area_lock); |
| 540 | list_for_each_entry(va, &valist, purge_list) | 548 | list_for_each_entry_safe(va, n_va, &valist, purge_list) |
| 541 | __free_vmap_area(va); | 549 | __free_vmap_area(va); |
| 542 | spin_unlock(&vmap_area_lock); | 550 | spin_unlock(&vmap_area_lock); |
| 543 | } | 551 | } |
| @@ -1012,6 +1020,8 @@ void __init vmalloc_init(void) | |||
| 1012 | void unmap_kernel_range(unsigned long addr, unsigned long size) | 1020 | void unmap_kernel_range(unsigned long addr, unsigned long size) |
| 1013 | { | 1021 | { |
| 1014 | unsigned long end = addr + size; | 1022 | unsigned long end = addr + size; |
| 1023 | |||
| 1024 | flush_cache_vunmap(addr, end); | ||
| 1015 | vunmap_page_range(addr, end); | 1025 | vunmap_page_range(addr, end); |
| 1016 | flush_tlb_kernel_range(addr, end); | 1026 | flush_tlb_kernel_range(addr, end); |
| 1017 | } | 1027 | } |
| @@ -1106,6 +1116,14 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, | |||
| 1106 | } | 1116 | } |
| 1107 | EXPORT_SYMBOL_GPL(__get_vm_area); | 1117 | EXPORT_SYMBOL_GPL(__get_vm_area); |
| 1108 | 1118 | ||
| 1119 | struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags, | ||
| 1120 | unsigned long start, unsigned long end, | ||
| 1121 | void *caller) | ||
| 1122 | { | ||
| 1123 | return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL, | ||
| 1124 | caller); | ||
| 1125 | } | ||
| 1126 | |||
| 1109 | /** | 1127 | /** |
| 1110 | * get_vm_area - reserve a contiguous kernel virtual area | 1128 | * get_vm_area - reserve a contiguous kernel virtual area |
| 1111 | * @size: size of the area | 1129 | * @size: size of the area |
