Commit f2badb0c950ed308be9b321203b9c8d341690cd4

Authored by Tejun Heo
1 parent 635b75fc18

percpu: make allocation failures more verbose

Warn and dump stack when percpu allocation fails.  percpu allocator is
still young and unchecked NULL percpu pointer usage can result in
random memory corruption when combined with the pointer shifting in
access macros.  Allocation failures should be rare and the warning
message will be disabled after certain times.

Signed-off-by: Tejun Heo <tj@kernel.org>

Showing 1 changed file with 18 additions and 2 deletions Side-by-side Diff

... ... @@ -1043,7 +1043,9 @@
1043 1043 */
1044 1044 static void *pcpu_alloc(size_t size, size_t align, bool reserved)
1045 1045 {
  1046 + static int warn_limit = 10;
1046 1047 struct pcpu_chunk *chunk;
  1048 + const char *err;
1047 1049 int slot, off;
1048 1050  
1049 1051 if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) {
1050 1052  
1051 1053  
... ... @@ -1059,11 +1061,14 @@
1059 1061 if (reserved && pcpu_reserved_chunk) {
1060 1062 chunk = pcpu_reserved_chunk;
1061 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 1066 goto fail_unlock;
  1067 + }
1064 1068 off = pcpu_alloc_area(chunk, size, align);
1065 1069 if (off >= 0)
1066 1070 goto area_found;
  1071 + err = "alloc from reserved chunk failed";
1067 1072 goto fail_unlock;
1068 1073 }
1069 1074  
... ... @@ -1080,6 +1085,7 @@
1080 1085 case 1:
1081 1086 goto restart; /* pcpu_lock dropped, restart */
1082 1087 default:
  1088 + err = "failed to extend area map";
1083 1089 goto fail_unlock;
1084 1090 }
1085 1091  
1086 1092  
... ... @@ -1093,8 +1099,10 @@
1093 1099 spin_unlock_irq(&pcpu_lock);
1094 1100  
1095 1101 chunk = alloc_pcpu_chunk();
1096   - if (!chunk)
  1102 + if (!chunk) {
  1103 + err = "failed to allocate new chunk";
1097 1104 goto fail_unlock_mutex;
  1105 + }
1098 1106  
1099 1107 spin_lock_irq(&pcpu_lock);
1100 1108 pcpu_chunk_relocate(chunk, -1);
... ... @@ -1107,6 +1115,7 @@
1107 1115 if (pcpu_populate_chunk(chunk, off, size)) {
1108 1116 spin_lock_irq(&pcpu_lock);
1109 1117 pcpu_free_area(chunk, off);
  1118 + err = "failed to populate";
1110 1119 goto fail_unlock;
1111 1120 }
1112 1121  
... ... @@ -1119,6 +1128,13 @@
1119 1128 spin_unlock_irq(&pcpu_lock);
1120 1129 fail_unlock_mutex:
1121 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 1138 return NULL;
1123 1139 }
1124 1140