diff options
| -rw-r--r-- | mm/percpu.c | 161 |
1 files changed, 124 insertions, 37 deletions
diff --git a/mm/percpu.c b/mm/percpu.c index 4c8a419119da..bfe6a3afaf45 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | #include <linux/pfn.h> | 62 | #include <linux/pfn.h> |
| 63 | #include <linux/rbtree.h> | 63 | #include <linux/rbtree.h> |
| 64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
| 65 | #include <linux/spinlock.h> | ||
| 65 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
| 66 | #include <linux/workqueue.h> | 67 | #include <linux/workqueue.h> |
| 67 | 68 | ||
| @@ -101,20 +102,28 @@ static struct pcpu_chunk *pcpu_reserved_chunk; | |||
| 101 | static int pcpu_reserved_chunk_limit; | 102 | static int pcpu_reserved_chunk_limit; |
| 102 | 103 | ||
| 103 | /* | 104 | /* |
| 104 | * One mutex to rule them all. | 105 | * Synchronization rules. |
| 105 | * | 106 | * |
| 106 | * The following mutex is grabbed in the outermost public alloc/free | 107 | * There are two locks - pcpu_alloc_mutex and pcpu_lock. The former |
| 107 | * interface functions and released only when the operation is | 108 | * protects allocation/reclaim paths, chunks and chunk->page arrays. |
| 108 | * complete. As such, every function in this file other than the | 109 | * The latter is a spinlock and protects the index data structures - |
| 109 | * outermost functions are called under pcpu_mutex. | 110 | * chunk slots, rbtree, chunks and area maps in chunks. |
| 110 | * | 111 | * |
| 111 | * It can easily be switched to use spinlock such that only the area | 112 | * During allocation, pcpu_alloc_mutex is kept locked all the time and |
| 112 | * allocation and page population commit are protected with it doing | 113 | * pcpu_lock is grabbed and released as necessary. All actual memory |
| 113 | * actual [de]allocation without holding any lock. However, given | 114 | * allocations are done using GFP_KERNEL with pcpu_lock released. |
| 114 | * what this allocator does, I think it's better to let them run | 115 | * |
| 115 | * sequentially. | 116 | * Free path accesses and alters only the index data structures, so it |
| 117 | * can be safely called from atomic context. When memory needs to be | ||
| 118 | * returned to the system, free path schedules reclaim_work which | ||
| 119 | * grabs both pcpu_alloc_mutex and pcpu_lock, unlinks chunks to be | ||
| 120 | * reclaimed, release both locks and frees the chunks. Note that it's | ||
| 121 | * necessary to grab both locks to remove a chunk from circulation as | ||
| 122 | * allocation path might be referencing the chunk with only | ||
| 123 | * pcpu_alloc_mutex locked. | ||
| 116 | */ | 124 | */ |
| 117 | static DEFINE_MUTEX(pcpu_mutex); | 125 | static DEFINE_MUTEX(pcpu_alloc_mutex); /* protects whole alloc and reclaim */ |
| 126 | static DEFINE_SPINLOCK(pcpu_lock); /* protects index data structures */ | ||
| 118 | 127 | ||
| 119 | static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */ | 128 | static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */ |
| 120 | static struct rb_root pcpu_addr_root = RB_ROOT; /* chunks by address */ | 129 | static struct rb_root pcpu_addr_root = RB_ROOT; /* chunks by address */ |
| @@ -176,6 +185,9 @@ static bool pcpu_chunk_page_occupied(struct pcpu_chunk *chunk, | |||
| 176 | * kzalloc() is used; otherwise, vmalloc() is used. The returned | 185 | * kzalloc() is used; otherwise, vmalloc() is used. The returned |
| 177 | * memory is always zeroed. | 186 | * memory is always zeroed. |
| 178 | * | 187 | * |
| 188 | * CONTEXT: | ||
| 189 | * Does GFP_KERNEL allocation. | ||
| 190 | * | ||
| 179 | * RETURNS: | 191 | * RETURNS: |
| 180 | * Pointer to the allocated area on success, NULL on failure. | 192 | * Pointer to the allocated area on success, NULL on failure. |
| 181 | */ | 193 | */ |
| @@ -215,6 +227,9 @@ static void pcpu_mem_free(void *ptr, size_t size) | |||
| 215 | * New slot according to the changed state is determined and @chunk is | 227 | * New slot according to the changed state is determined and @chunk is |
| 216 | * moved to the slot. Note that the reserved chunk is never put on | 228 | * moved to the slot. Note that the reserved chunk is never put on |
| 217 | * chunk slots. | 229 | * chunk slots. |
| 230 | * | ||
| 231 | * CONTEXT: | ||
| 232 | * pcpu_lock. | ||
| 218 | */ | 233 | */ |
| 219 | static void pcpu_chunk_relocate(struct pcpu_chunk *chunk, int oslot) | 234 | static void pcpu_chunk_relocate(struct pcpu_chunk *chunk, int oslot) |
| 220 | { | 235 | { |
| @@ -260,6 +275,9 @@ static struct rb_node **pcpu_chunk_rb_search(void *addr, | |||
| 260 | * searchs for the chunk with the highest start address which isn't | 275 | * searchs for the chunk with the highest start address which isn't |
| 261 | * beyond @addr. | 276 | * beyond @addr. |
| 262 | * | 277 | * |
| 278 | * CONTEXT: | ||
| 279 | * pcpu_lock. | ||
| 280 | * | ||
| 263 | * RETURNS: | 281 | * RETURNS: |
| 264 | * The address of the found chunk. | 282 | * The address of the found chunk. |
| 265 | */ | 283 | */ |
| @@ -300,6 +318,9 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr) | |||
| 300 | * @new: chunk to insert | 318 | * @new: chunk to insert |
| 301 | * | 319 | * |
| 302 | * Insert @new into address rb tree. | 320 | * Insert @new into address rb tree. |
| 321 | * | ||
| 322 | * CONTEXT: | ||
| 323 | * pcpu_lock. | ||
| 303 | */ | 324 | */ |
| 304 | static void pcpu_chunk_addr_insert(struct pcpu_chunk *new) | 325 | static void pcpu_chunk_addr_insert(struct pcpu_chunk *new) |
| 305 | { | 326 | { |
| @@ -319,6 +340,10 @@ static void pcpu_chunk_addr_insert(struct pcpu_chunk *new) | |||
| 319 | * A single allocation can split an area into three areas, so this | 340 | * A single allocation can split an area into three areas, so this |
| 320 | * function makes sure that @chunk->map has at least two extra slots. | 341 | * function makes sure that @chunk->map has at least two extra slots. |
| 321 | * | 342 | * |
| 343 | * CONTEXT: | ||
| 344 | * pcpu_alloc_mutex, pcpu_lock. pcpu_lock is released and reacquired | ||
| 345 | * if area map is extended. | ||
| 346 | * | ||
| 322 | * RETURNS: | 347 | * RETURNS: |
| 323 | * 0 if noop, 1 if successfully extended, -errno on failure. | 348 | * 0 if noop, 1 if successfully extended, -errno on failure. |
| 324 | */ | 349 | */ |
| @@ -332,13 +357,25 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk) | |||
| 332 | if (chunk->map_alloc >= chunk->map_used + 2) | 357 | if (chunk->map_alloc >= chunk->map_used + 2) |
| 333 | return 0; | 358 | return 0; |
| 334 | 359 | ||
| 360 | spin_unlock_irq(&pcpu_lock); | ||
| 361 | |||
| 335 | new_alloc = PCPU_DFL_MAP_ALLOC; | 362 | new_alloc = PCPU_DFL_MAP_ALLOC; |
| 336 | while (new_alloc < chunk->map_used + 2) | 363 | while (new_alloc < chunk->map_used + 2) |
| 337 | new_alloc *= 2; | 364 | new_alloc *= 2; |
| 338 | 365 | ||
| 339 | new = pcpu_mem_alloc(new_alloc * sizeof(new[0])); | 366 | new = pcpu_mem_alloc(new_alloc * sizeof(new[0])); |
| 340 | if (!new) | 367 | if (!new) { |
| 368 | spin_lock_irq(&pcpu_lock); | ||
| 341 | return -ENOMEM; | 369 | return -ENOMEM; |
| 370 | } | ||
| 371 | |||
| 372 | /* | ||
| 373 | * Acquire pcpu_lock and switch to new area map. Only free | ||
| 374 | * could have happened inbetween, so map_used couldn't have | ||
| 375 | * grown. | ||
| 376 | */ | ||
| 377 | spin_lock_irq(&pcpu_lock); | ||
| 378 | BUG_ON(new_alloc < chunk->map_used + 2); | ||
| 342 | 379 | ||
| 343 | size = chunk->map_alloc * sizeof(chunk->map[0]); | 380 | size = chunk->map_alloc * sizeof(chunk->map[0]); |
| 344 | memcpy(new, chunk->map, size); | 381 | memcpy(new, chunk->map, size); |
| @@ -371,6 +408,9 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk) | |||
| 371 | * is inserted after the target block. | 408 | * is inserted after the target block. |
| 372 | * | 409 | * |
| 373 | * @chunk->map must have enough free slots to accomodate the split. | 410 | * @chunk->map must have enough free slots to accomodate the split. |
| 411 | * | ||
| 412 | * CONTEXT: | ||
| 413 | * pcpu_lock. | ||
| 374 | */ | 414 | */ |
| 375 | static void pcpu_split_block(struct pcpu_chunk *chunk, int i, | 415 | static void pcpu_split_block(struct pcpu_chunk *chunk, int i, |
| 376 | int head, int tail) | 416 | int head, int tail) |
| @@ -406,6 +446,9 @@ static void pcpu_split_block(struct pcpu_chunk *chunk, int i, | |||
| 406 | * | 446 | * |
| 407 | * @chunk->map must have at least two free slots. | 447 | * @chunk->map must have at least two free slots. |
| 408 | * | 448 | * |
| 449 | * CONTEXT: | ||
| 450 | * pcpu_lock. | ||
| 451 | * | ||
| 409 | * RETURNS: | 452 | * RETURNS: |
| 410 | * Allocated offset in @chunk on success, -1 if no matching area is | 453 | * Allocated offset in @chunk on success, -1 if no matching area is |
| 411 | * found. | 454 | * found. |
| @@ -495,6 +538,9 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align) | |||
| 495 | * Free area starting from @freeme to @chunk. Note that this function | 538 | * Free area starting from @freeme to @chunk. Note that this function |
| 496 | * only modifies the allocation map. It doesn't depopulate or unmap | 539 | * only modifies the allocation map. It doesn't depopulate or unmap |
| 497 | * the area. | 540 | * the area. |
| 541 | * | ||
| 542 | * CONTEXT: | ||
| 543 | * pcpu_lock. | ||
| 498 | */ | 544 | */ |
| 499 | static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme) | 545 | static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme) |
| 500 | { | 546 | { |
| @@ -580,6 +626,9 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | |||
| 580 | * For each cpu, depopulate and unmap pages [@page_start,@page_end) | 626 | * For each cpu, depopulate and unmap pages [@page_start,@page_end) |
| 581 | * from @chunk. If @flush is true, vcache is flushed before unmapping | 627 | * from @chunk. If @flush is true, vcache is flushed before unmapping |
| 582 | * and tlb after. | 628 | * and tlb after. |
| 629 | * | ||
| 630 | * CONTEXT: | ||
| 631 | * pcpu_alloc_mutex. | ||
| 583 | */ | 632 | */ |
| 584 | static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size, | 633 | static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size, |
| 585 | bool flush) | 634 | bool flush) |
| @@ -658,6 +707,9 @@ static int pcpu_map(struct pcpu_chunk *chunk, int page_start, int page_end) | |||
| 658 | * | 707 | * |
| 659 | * For each cpu, populate and map pages [@page_start,@page_end) into | 708 | * For each cpu, populate and map pages [@page_start,@page_end) into |
| 660 | * @chunk. The area is cleared on return. | 709 | * @chunk. The area is cleared on return. |
| 710 | * | ||
| 711 | * CONTEXT: | ||
| 712 | * pcpu_alloc_mutex, does GFP_KERNEL allocation. | ||
| 661 | */ | 713 | */ |
| 662 | static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) | 714 | static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) |
| 663 | { | 715 | { |
| @@ -748,15 +800,16 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void) | |||
| 748 | * @align: alignment of area (max PAGE_SIZE) | 800 | * @align: alignment of area (max PAGE_SIZE) |
| 749 | * @reserved: allocate from the reserved chunk if available | 801 | * @reserved: allocate from the reserved chunk if available |
| 750 | * | 802 | * |
| 751 | * Allocate percpu area of @size bytes aligned at @align. Might | 803 | * Allocate percpu area of @size bytes aligned at @align. |
| 752 | * sleep. Might trigger writeouts. | 804 | * |
| 805 | * CONTEXT: | ||
| 806 | * Does GFP_KERNEL allocation. | ||
| 753 | * | 807 | * |
| 754 | * RETURNS: | 808 | * RETURNS: |
| 755 | * Percpu pointer to the allocated area on success, NULL on failure. | 809 | * Percpu pointer to the allocated area on success, NULL on failure. |
| 756 | */ | 810 | */ |
| 757 | static void *pcpu_alloc(size_t size, size_t align, bool reserved) | 811 | static void *pcpu_alloc(size_t size, size_t align, bool reserved) |
| 758 | { | 812 | { |
| 759 | void *ptr = NULL; | ||
| 760 | struct pcpu_chunk *chunk; | 813 | struct pcpu_chunk *chunk; |
| 761 | int slot, off; | 814 | int slot, off; |
| 762 | 815 | ||
| @@ -766,27 +819,37 @@ static void *pcpu_alloc(size_t size, size_t align, bool reserved) | |||
| 766 | return NULL; | 819 | return NULL; |
| 767 | } | 820 | } |
| 768 | 821 | ||
| 769 | mutex_lock(&pcpu_mutex); | 822 | mutex_lock(&pcpu_alloc_mutex); |
| 823 | spin_lock_irq(&pcpu_lock); | ||
| 770 | 824 | ||
| 771 | /* serve reserved allocations from the reserved chunk if available */ | 825 | /* serve reserved allocations from the reserved chunk if available */ |
| 772 | if (reserved && pcpu_reserved_chunk) { | 826 | if (reserved && pcpu_reserved_chunk) { |
| 773 | chunk = pcpu_reserved_chunk; | 827 | chunk = pcpu_reserved_chunk; |
| 774 | if (size > chunk->contig_hint || | 828 | if (size > chunk->contig_hint || |
| 775 | pcpu_extend_area_map(chunk) < 0) | 829 | pcpu_extend_area_map(chunk) < 0) |
| 776 | goto out_unlock; | 830 | goto fail_unlock; |
| 777 | off = pcpu_alloc_area(chunk, size, align); | 831 | off = pcpu_alloc_area(chunk, size, align); |
| 778 | if (off >= 0) | 832 | if (off >= 0) |
| 779 | goto area_found; | 833 | goto area_found; |
| 780 | goto out_unlock; | 834 | goto fail_unlock; |
| 781 | } | 835 | } |
| 782 | 836 | ||
| 837 | restart: | ||
| 783 | /* search through normal chunks */ | 838 | /* search through normal chunks */ |
| 784 | for (slot = pcpu_size_to_slot(size); slot < pcpu_nr_slots; slot++) { | 839 | for (slot = pcpu_size_to_slot(size); slot < pcpu_nr_slots; slot++) { |
| 785 | list_for_each_entry(chunk, &pcpu_slot[slot], list) { | 840 | list_for_each_entry(chunk, &pcpu_slot[slot], list) { |
| 786 | if (size > chunk->contig_hint) | 841 | if (size > chunk->contig_hint) |
| 787 | continue; | 842 | continue; |
| 788 | if (pcpu_extend_area_map(chunk) < 0) | 843 | |
| 789 | goto out_unlock; | 844 | switch (pcpu_extend_area_map(chunk)) { |
| 845 | case 0: | ||
| 846 | break; | ||
| 847 | case 1: | ||
| 848 | goto restart; /* pcpu_lock dropped, restart */ | ||
| 849 | default: | ||
| 850 | goto fail_unlock; | ||
| 851 | } | ||
| 852 | |||
| 790 | off = pcpu_alloc_area(chunk, size, align); | 853 | off = pcpu_alloc_area(chunk, size, align); |
| 791 | if (off >= 0) | 854 | if (off >= 0) |
| 792 | goto area_found; | 855 | goto area_found; |
| @@ -794,27 +857,36 @@ static void *pcpu_alloc(size_t size, size_t align, bool reserved) | |||
| 794 | } | 857 | } |
| 795 | 858 | ||
| 796 | /* hmmm... no space left, create a new chunk */ | 859 | /* hmmm... no space left, create a new chunk */ |
| 860 | spin_unlock_irq(&pcpu_lock); | ||
| 861 | |||
| 797 | chunk = alloc_pcpu_chunk(); | 862 | chunk = alloc_pcpu_chunk(); |
| 798 | if (!chunk) | 863 | if (!chunk) |
| 799 | goto out_unlock; | 864 | goto fail_unlock_mutex; |
| 865 | |||
| 866 | spin_lock_irq(&pcpu_lock); | ||
| 800 | pcpu_chunk_relocate(chunk, -1); | 867 | pcpu_chunk_relocate(chunk, -1); |
| 801 | pcpu_chunk_addr_insert(chunk); | 868 | pcpu_chunk_addr_insert(chunk); |
| 802 | 869 | goto restart; | |
| 803 | off = pcpu_alloc_area(chunk, size, align); | ||
| 804 | if (off < 0) | ||
| 805 | goto out_unlock; | ||
| 806 | 870 | ||
| 807 | area_found: | 871 | area_found: |
| 872 | spin_unlock_irq(&pcpu_lock); | ||
| 873 | |||
| 808 | /* populate, map and clear the area */ | 874 | /* populate, map and clear the area */ |
| 809 | if (pcpu_populate_chunk(chunk, off, size)) { | 875 | if (pcpu_populate_chunk(chunk, off, size)) { |
| 876 | spin_lock_irq(&pcpu_lock); | ||
| 810 | pcpu_free_area(chunk, off); | 877 | pcpu_free_area(chunk, off); |
| 811 | goto out_unlock; | 878 | goto fail_unlock; |
| 812 | } | 879 | } |
| 813 | 880 | ||
| 814 | ptr = __addr_to_pcpu_ptr(chunk->vm->addr + off); | 881 | mutex_unlock(&pcpu_alloc_mutex); |
| 815 | out_unlock: | 882 | |
| 816 | mutex_unlock(&pcpu_mutex); | 883 | return __addr_to_pcpu_ptr(chunk->vm->addr + off); |
| 817 | return ptr; | 884 | |
| 885 | fail_unlock: | ||
| 886 | spin_unlock_irq(&pcpu_lock); | ||
| 887 | fail_unlock_mutex: | ||
| 888 | mutex_unlock(&pcpu_alloc_mutex); | ||
| 889 | return NULL; | ||
| 818 | } | 890 | } |
| 819 | 891 | ||
| 820 | /** | 892 | /** |
| @@ -825,6 +897,9 @@ out_unlock: | |||
| 825 | * Allocate percpu area of @size bytes aligned at @align. Might | 897 | * Allocate percpu area of @size bytes aligned at @align. Might |
| 826 | * sleep. Might trigger writeouts. | 898 | * sleep. Might trigger writeouts. |
| 827 | * | 899 | * |
| 900 | * CONTEXT: | ||
| 901 | * Does GFP_KERNEL allocation. | ||
| 902 | * | ||
| 828 | * RETURNS: | 903 | * RETURNS: |
| 829 | * Percpu pointer to the allocated area on success, NULL on failure. | 904 | * Percpu pointer to the allocated area on success, NULL on failure. |
| 830 | */ | 905 | */ |
| @@ -843,6 +918,9 @@ EXPORT_SYMBOL_GPL(__alloc_percpu); | |||
| 843 | * percpu area if arch has set it up; otherwise, allocation is served | 918 | * percpu area if arch has set it up; otherwise, allocation is served |
| 844 | * from the same dynamic area. Might sleep. Might trigger writeouts. | 919 | * from the same dynamic area. Might sleep. Might trigger writeouts. |
| 845 | * | 920 | * |
| 921 | * CONTEXT: | ||
| 922 | * Does GFP_KERNEL allocation. | ||
| 923 | * | ||
| 846 | * RETURNS: | 924 | * RETURNS: |
| 847 | * Percpu pointer to the allocated area on success, NULL on failure. | 925 | * Percpu pointer to the allocated area on success, NULL on failure. |
| 848 | */ | 926 | */ |
| @@ -856,6 +934,9 @@ void *__alloc_reserved_percpu(size_t size, size_t align) | |||
| 856 | * @work: unused | 934 | * @work: unused |
| 857 | * | 935 | * |
| 858 | * Reclaim all fully free chunks except for the first one. | 936 | * Reclaim all fully free chunks except for the first one. |
| 937 | * | ||
| 938 | * CONTEXT: | ||
| 939 | * workqueue context. | ||
| 859 | */ | 940 | */ |
| 860 | static void pcpu_reclaim(struct work_struct *work) | 941 | static void pcpu_reclaim(struct work_struct *work) |
| 861 | { | 942 | { |
| @@ -863,7 +944,8 @@ static void pcpu_reclaim(struct work_struct *work) | |||
| 863 | struct list_head *head = &pcpu_slot[pcpu_nr_slots - 1]; | 944 | struct list_head *head = &pcpu_slot[pcpu_nr_slots - 1]; |
| 864 | struct pcpu_chunk *chunk, *next; | 945 | struct pcpu_chunk *chunk, *next; |
| 865 | 946 | ||
| 866 | mutex_lock(&pcpu_mutex); | 947 | mutex_lock(&pcpu_alloc_mutex); |
| 948 | spin_lock_irq(&pcpu_lock); | ||
| 867 | 949 | ||
| 868 | list_for_each_entry_safe(chunk, next, head, list) { | 950 | list_for_each_entry_safe(chunk, next, head, list) { |
| 869 | WARN_ON(chunk->immutable); | 951 | WARN_ON(chunk->immutable); |
| @@ -876,7 +958,8 @@ static void pcpu_reclaim(struct work_struct *work) | |||
| 876 | list_move(&chunk->list, &todo); | 958 | list_move(&chunk->list, &todo); |
| 877 | } | 959 | } |
| 878 | 960 | ||
| 879 | mutex_unlock(&pcpu_mutex); | 961 | spin_unlock_irq(&pcpu_lock); |
| 962 | mutex_unlock(&pcpu_alloc_mutex); | ||
| 880 | 963 | ||
| 881 | list_for_each_entry_safe(chunk, next, &todo, list) { | 964 | list_for_each_entry_safe(chunk, next, &todo, list) { |
| 882 | pcpu_depopulate_chunk(chunk, 0, pcpu_unit_size, false); | 965 | pcpu_depopulate_chunk(chunk, 0, pcpu_unit_size, false); |
| @@ -888,18 +971,22 @@ static void pcpu_reclaim(struct work_struct *work) | |||
| 888 | * free_percpu - free percpu area | 971 | * free_percpu - free percpu area |
| 889 | * @ptr: pointer to area to free | 972 | * @ptr: pointer to area to free |
| 890 | * | 973 | * |
| 891 | * Free percpu area @ptr. Might sleep. | 974 | * Free percpu area @ptr. |
| 975 | * | ||
| 976 | * CONTEXT: | ||
| 977 | * Can be called from atomic context. | ||
| 892 | */ | 978 | */ |
| 893 | void free_percpu(void *ptr) | 979 | void free_percpu(void *ptr) |
| 894 | { | 980 | { |
| 895 | void *addr = __pcpu_ptr_to_addr(ptr); | 981 | void *addr = __pcpu_ptr_to_addr(ptr); |
| 896 | struct pcpu_chunk *chunk; | 982 | struct pcpu_chunk *chunk; |
| 983 | unsigned long flags; | ||
| 897 | int off; | 984 | int off; |
| 898 | 985 | ||
| 899 | if (!ptr) | 986 | if (!ptr) |
| 900 | return; | 987 | return; |
| 901 | 988 | ||
| 902 | mutex_lock(&pcpu_mutex); | 989 | spin_lock_irqsave(&pcpu_lock, flags); |
| 903 | 990 | ||
| 904 | chunk = pcpu_chunk_addr_search(addr); | 991 | chunk = pcpu_chunk_addr_search(addr); |
| 905 | off = addr - chunk->vm->addr; | 992 | off = addr - chunk->vm->addr; |
| @@ -917,7 +1004,7 @@ void free_percpu(void *ptr) | |||
| 917 | } | 1004 | } |
| 918 | } | 1005 | } |
| 919 | 1006 | ||
| 920 | mutex_unlock(&pcpu_mutex); | 1007 | spin_unlock_irqrestore(&pcpu_lock, flags); |
| 921 | } | 1008 | } |
| 922 | EXPORT_SYMBOL_GPL(free_percpu); | 1009 | EXPORT_SYMBOL_GPL(free_percpu); |
| 923 | 1010 | ||
