Under extreme memory used up situations, percpu allocation might fail. We hit it when system goes to suspend-to-ram, causing a kworker panic: EIP: [<c124411a>] build_sched_domains+0x23a/0xad0 Kernel panic - not syncing: Fatal exception Pid: 3026, comm: kworker/u:3 3.0.8-137473-gf42fbef #1 Call Trace: [<c18cc4f2>] panic+0x66/0x16c [...] [<c1244c37>] partition_sched_domains+0x287/0x4b0 [<c12a77be>] cpuset_update_active_cpus+0x1fe/0x210 [<c123712d>] cpuset_cpu_inactive+0x1d/0x30 [...] With this fix applied build_sched_domains() will return -ENOMEM and the suspend attempt fails.
Unified · Split
| @@ -6405,16 +6405,26 @@ static void __sdt_free(const struct cpumask *cpu_map) · 6404 unmodified lines | |||
| 6405 | struct sd_data *sdd = &tl->data; | 6405 | struct sd_data *sdd = &tl->data; |
| 6406 | 6406 | ||
| 6407 | for_each_cpu(j, cpu_map) { | 6407 | for_each_cpu(j, cpu_map) { |
| 6408 | struct sched_domain *sd = *per_cpu_ptr(sdd->sd, j); | 6408 | struct sched_domain *sd; |
| 6409 | if (sd && (sd->flags & SD_OVERLAP)) | 6409 | |
| 6410 | free_sched_groups(sd->groups, 0); | 6410 | if (sdd->sd) { |
| 6411 | kfree(*per_cpu_ptr(sdd->sd, j)); | 6411 | sd = *per_cpu_ptr(sdd->sd, j); |
| 6412 | kfree(*per_cpu_ptr(sdd->sg, j)); | 6412 | if (sd && (sd->flags & SD_OVERLAP)) |
| 6413 | kfree(*per_cpu_ptr(sdd->sgp, j)); | 6413 | free_sched_groups(sd->groups, 0); |
| 6414 | kfree(*per_cpu_ptr(sdd->sd, j)); | ||
| 6415 | } | ||
| 6416 | |||
| 6417 | if (sdd->sg) | ||
| 6418 | kfree(*per_cpu_ptr(sdd->sg, j)); | ||
| 6419 | if (sdd->sgp) | ||
| 6420 | kfree(*per_cpu_ptr(sdd->sgp, j)); | ||
| 6414 | } | 6421 | } |
| 6415 | free_percpu(sdd->sd); | 6422 | free_percpu(sdd->sd); |
| 6423 | sdd->sd = NULL; | ||
| 6416 | free_percpu(sdd->sg); | 6424 | free_percpu(sdd->sg); |
| 6425 | sdd->sg = NULL; | ||
| 6417 | free_percpu(sdd->sgp); | 6426 | free_percpu(sdd->sgp); |
| 6427 | sdd->sgp = NULL; | ||
| 6418 | } | 6428 | } |
| 6419 | } | 6429 | } |
| 6420 | 6430 | ||