diff options
| -rw-r--r-- | mm/percpu.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/mm/percpu.c b/mm/percpu.c index 83617ca3ba52..4a048abad043 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
| @@ -1043,7 +1043,9 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void) | |||
| 1043 | */ | 1043 | */ |
| 1044 | static void *pcpu_alloc(size_t size, size_t align, bool reserved) | 1044 | static void *pcpu_alloc(size_t size, size_t align, bool reserved) |
| 1045 | { | 1045 | { |
| 1046 | static int warn_limit = 10; | ||
| 1046 | struct pcpu_chunk *chunk; | 1047 | struct pcpu_chunk *chunk; |
| 1048 | const char *err; | ||
| 1047 | int slot, off; | 1049 | int slot, off; |
| 1048 | 1050 | ||
| 1049 | if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) { | 1051 | if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) { |
| @@ -1059,11 +1061,14 @@ static void *pcpu_alloc(size_t size, size_t align, bool reserved) | |||
| 1059 | if (reserved && pcpu_reserved_chunk) { | 1061 | if (reserved && pcpu_reserved_chunk) { |
| 1060 | chunk = pcpu_reserved_chunk; | 1062 | chunk = pcpu_reserved_chunk; |
| 1061 | if (size > chunk->contig_hint || | 1063 | if (size > chunk->contig_hint || |
| 1062 | pcpu_extend_area_map(chunk) < 0) | 1064 | pcpu_extend_area_map(chunk) < 0) { |
| 1065 | err = "failed to extend area map of reserved chunk"; | ||
| 1063 | goto fail_unlock; | 1066 | goto fail_unlock; |
| 1067 | } | ||
| 1064 | off = pcpu_alloc_area(chunk, size, align); | 1068 | off = pcpu_alloc_area(chunk, size, align); |
| 1065 | if (off >= 0) | 1069 | if (off >= 0) |
| 1066 | goto area_found; | 1070 | goto area_found; |
| 1071 | err = "alloc from reserved chunk failed"; | ||
| 1067 | goto fail_unlock; | 1072 | goto fail_unlock; |
| 1068 | } | 1073 | } |
| 1069 | 1074 | ||
| @@ -1080,6 +1085,7 @@ restart: | |||
| 1080 | case 1: | 1085 | case 1: |
| 1081 | goto restart; /* pcpu_lock dropped, restart */ | 1086 | goto restart; /* pcpu_lock dropped, restart */ |
| 1082 | default: | 1087 | default: |
| 1088 | err = "failed to extend area map"; | ||
| 1083 | goto fail_unlock; | 1089 | goto fail_unlock; |
| 1084 | } | 1090 | } |
| 1085 | 1091 | ||
| @@ -1093,8 +1099,10 @@ restart: | |||
| 1093 | spin_unlock_irq(&pcpu_lock); | 1099 | spin_unlock_irq(&pcpu_lock); |
| 1094 | 1100 | ||
| 1095 | chunk = alloc_pcpu_chunk(); | 1101 | chunk = alloc_pcpu_chunk(); |
| 1096 | if (!chunk) | 1102 | if (!chunk) { |
| 1103 | err = "failed to allocate new chunk"; | ||
| 1097 | goto fail_unlock_mutex; | 1104 | goto fail_unlock_mutex; |
| 1105 | } | ||
| 1098 | 1106 | ||
| 1099 | spin_lock_irq(&pcpu_lock); | 1107 | spin_lock_irq(&pcpu_lock); |
| 1100 | pcpu_chunk_relocate(chunk, -1); | 1108 | pcpu_chunk_relocate(chunk, -1); |
| @@ -1107,6 +1115,7 @@ area_found: | |||
| 1107 | if (pcpu_populate_chunk(chunk, off, size)) { | 1115 | if (pcpu_populate_chunk(chunk, off, size)) { |
| 1108 | spin_lock_irq(&pcpu_lock); | 1116 | spin_lock_irq(&pcpu_lock); |
| 1109 | pcpu_free_area(chunk, off); | 1117 | pcpu_free_area(chunk, off); |
| 1118 | err = "failed to populate"; | ||
| 1110 | goto fail_unlock; | 1119 | goto fail_unlock; |
| 1111 | } | 1120 | } |
| 1112 | 1121 | ||
| @@ -1119,6 +1128,13 @@ fail_unlock: | |||
| 1119 | spin_unlock_irq(&pcpu_lock); | 1128 | spin_unlock_irq(&pcpu_lock); |
| 1120 | fail_unlock_mutex: | 1129 | fail_unlock_mutex: |
| 1121 | mutex_unlock(&pcpu_alloc_mutex); | 1130 | mutex_unlock(&pcpu_alloc_mutex); |
| 1131 | if (warn_limit) { | ||
| 1132 | pr_warning("PERCPU: allocation failed, size=%zu align=%zu, " | ||
| 1133 | "%s\n", size, align, err); | ||
| 1134 | dump_stack(); | ||
| 1135 | if (!--warn_limit) | ||
| 1136 | pr_info("PERCPU: limit reached, disable warning\n"); | ||
| 1137 | } | ||
| 1122 | return NULL; | 1138 | return NULL; |
| 1123 | } | 1139 | } |
| 1124 | 1140 | ||
