diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 171 |
1 files changed, 99 insertions, 72 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 565ff775fcda..c5d1fee42360 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -8107,6 +8107,23 @@ struct s_data { | |||
8107 | struct root_domain *rd; | 8107 | struct root_domain *rd; |
8108 | }; | 8108 | }; |
8109 | 8109 | ||
8110 | enum s_alloc { | ||
8111 | sa_sched_groups = 0, | ||
8112 | sa_rootdomain, | ||
8113 | sa_tmpmask, | ||
8114 | sa_send_covered, | ||
8115 | sa_this_core_map, | ||
8116 | sa_this_sibling_map, | ||
8117 | sa_nodemask, | ||
8118 | sa_sched_group_nodes, | ||
8119 | #ifdef CONFIG_NUMA | ||
8120 | sa_notcovered, | ||
8121 | sa_covered, | ||
8122 | sa_domainspan, | ||
8123 | #endif | ||
8124 | sa_none, | ||
8125 | }; | ||
8126 | |||
8110 | /* | 8127 | /* |
8111 | * SMT sched-domains: | 8128 | * SMT sched-domains: |
8112 | */ | 8129 | */ |
@@ -8394,6 +8411,77 @@ static void set_domain_attribute(struct sched_domain *sd, | |||
8394 | } | 8411 | } |
8395 | } | 8412 | } |
8396 | 8413 | ||
8414 | static void __free_domain_allocs(struct s_data *d, enum s_alloc what, | ||
8415 | const struct cpumask *cpu_map) | ||
8416 | { | ||
8417 | switch (what) { | ||
8418 | case sa_sched_groups: | ||
8419 | free_sched_groups(cpu_map, d->tmpmask); /* fall through */ | ||
8420 | d->sched_group_nodes = NULL; | ||
8421 | case sa_rootdomain: | ||
8422 | free_rootdomain(d->rd); /* fall through */ | ||
8423 | case sa_tmpmask: | ||
8424 | free_cpumask_var(d->tmpmask); /* fall through */ | ||
8425 | case sa_send_covered: | ||
8426 | free_cpumask_var(d->send_covered); /* fall through */ | ||
8427 | case sa_this_core_map: | ||
8428 | free_cpumask_var(d->this_core_map); /* fall through */ | ||
8429 | case sa_this_sibling_map: | ||
8430 | free_cpumask_var(d->this_sibling_map); /* fall through */ | ||
8431 | case sa_nodemask: | ||
8432 | free_cpumask_var(d->nodemask); /* fall through */ | ||
8433 | case sa_sched_group_nodes: | ||
8434 | #ifdef CONFIG_NUMA | ||
8435 | kfree(d->sched_group_nodes); /* fall through */ | ||
8436 | case sa_notcovered: | ||
8437 | free_cpumask_var(d->notcovered); /* fall through */ | ||
8438 | case sa_covered: | ||
8439 | free_cpumask_var(d->covered); /* fall through */ | ||
8440 | case sa_domainspan: | ||
8441 | free_cpumask_var(d->domainspan); /* fall through */ | ||
8442 | #endif | ||
8443 | case sa_none: | ||
8444 | break; | ||
8445 | } | ||
8446 | } | ||
8447 | |||
8448 | static enum s_alloc __visit_domain_allocation_hell(struct s_data *d, | ||
8449 | const struct cpumask *cpu_map) | ||
8450 | { | ||
8451 | #ifdef CONFIG_NUMA | ||
8452 | if (!alloc_cpumask_var(&d->domainspan, GFP_KERNEL)) | ||
8453 | return sa_none; | ||
8454 | if (!alloc_cpumask_var(&d->covered, GFP_KERNEL)) | ||
8455 | return sa_domainspan; | ||
8456 | if (!alloc_cpumask_var(&d->notcovered, GFP_KERNEL)) | ||
8457 | return sa_covered; | ||
8458 | /* Allocate the per-node list of sched groups */ | ||
8459 | d->sched_group_nodes = kcalloc(nr_node_ids, | ||
8460 | sizeof(struct sched_group *), GFP_KERNEL); | ||
8461 | if (!d->sched_group_nodes) { | ||
8462 | printk(KERN_WARNING "Can not alloc sched group node list\n"); | ||
8463 | return sa_notcovered; | ||
8464 | } | ||
8465 | sched_group_nodes_bycpu[cpumask_first(cpu_map)] = d->sched_group_nodes; | ||
8466 | #endif | ||
8467 | if (!alloc_cpumask_var(&d->nodemask, GFP_KERNEL)) | ||
8468 | return sa_sched_group_nodes; | ||
8469 | if (!alloc_cpumask_var(&d->this_sibling_map, GFP_KERNEL)) | ||
8470 | return sa_nodemask; | ||
8471 | if (!alloc_cpumask_var(&d->this_core_map, GFP_KERNEL)) | ||
8472 | return sa_this_sibling_map; | ||
8473 | if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL)) | ||
8474 | return sa_this_core_map; | ||
8475 | if (!alloc_cpumask_var(&d->tmpmask, GFP_KERNEL)) | ||
8476 | return sa_send_covered; | ||
8477 | d->rd = alloc_rootdomain(); | ||
8478 | if (!d->rd) { | ||
8479 | printk(KERN_WARNING "Cannot alloc root domain\n"); | ||
8480 | return sa_tmpmask; | ||
8481 | } | ||
8482 | return sa_rootdomain; | ||
8483 | } | ||
8484 | |||
8397 | /* | 8485 | /* |
8398 | * Build sched domains for a given set of cpus and attach the sched domains | 8486 | * Build sched domains for a given set of cpus and attach the sched domains |
8399 | * to the individual cpus | 8487 | * to the individual cpus |
@@ -8401,50 +8489,17 @@ static void set_domain_attribute(struct sched_domain *sd, | |||
8401 | static int __build_sched_domains(const struct cpumask *cpu_map, | 8489 | static int __build_sched_domains(const struct cpumask *cpu_map, |
8402 | struct sched_domain_attr *attr) | 8490 | struct sched_domain_attr *attr) |
8403 | { | 8491 | { |
8492 | enum s_alloc alloc_state = sa_none; | ||
8404 | struct s_data d; | 8493 | struct s_data d; |
8405 | int i, err = -ENOMEM; | 8494 | int i; |
8406 | #ifdef CONFIG_NUMA | 8495 | #ifdef CONFIG_NUMA |
8407 | d.sd_allnodes = 0; | 8496 | d.sd_allnodes = 0; |
8408 | if (!alloc_cpumask_var(&d.domainspan, GFP_KERNEL)) | ||
8409 | goto out; | ||
8410 | if (!alloc_cpumask_var(&d.covered, GFP_KERNEL)) | ||
8411 | goto free_domainspan; | ||
8412 | if (!alloc_cpumask_var(&d.notcovered, GFP_KERNEL)) | ||
8413 | goto free_covered; | ||
8414 | #endif | ||
8415 | |||
8416 | if (!alloc_cpumask_var(&d.nodemask, GFP_KERNEL)) | ||
8417 | goto free_notcovered; | ||
8418 | if (!alloc_cpumask_var(&d.this_sibling_map, GFP_KERNEL)) | ||
8419 | goto free_nodemask; | ||
8420 | if (!alloc_cpumask_var(&d.this_core_map, GFP_KERNEL)) | ||
8421 | goto free_this_sibling_map; | ||
8422 | if (!alloc_cpumask_var(&d.send_covered, GFP_KERNEL)) | ||
8423 | goto free_this_core_map; | ||
8424 | if (!alloc_cpumask_var(&d.tmpmask, GFP_KERNEL)) | ||
8425 | goto free_send_covered; | ||
8426 | |||
8427 | #ifdef CONFIG_NUMA | ||
8428 | /* | ||
8429 | * Allocate the per-node list of sched groups | ||
8430 | */ | ||
8431 | d.sched_group_nodes = kcalloc(nr_node_ids, sizeof(struct sched_group *), | ||
8432 | GFP_KERNEL); | ||
8433 | if (!d.sched_group_nodes) { | ||
8434 | printk(KERN_WARNING "Can not alloc sched group node list\n"); | ||
8435 | goto free_tmpmask; | ||
8436 | } | ||
8437 | #endif | 8497 | #endif |
8438 | 8498 | ||
8439 | d.rd = alloc_rootdomain(); | 8499 | alloc_state = __visit_domain_allocation_hell(&d, cpu_map); |
8440 | if (!d.rd) { | 8500 | if (alloc_state != sa_rootdomain) |
8441 | printk(KERN_WARNING "Cannot alloc root domain\n"); | 8501 | goto error; |
8442 | goto free_sched_groups; | 8502 | alloc_state = sa_sched_groups; |
8443 | } | ||
8444 | |||
8445 | #ifdef CONFIG_NUMA | ||
8446 | sched_group_nodes_bycpu[cpumask_first(cpu_map)] = d.sched_group_nodes; | ||
8447 | #endif | ||
8448 | 8503 | ||
8449 | /* | 8504 | /* |
8450 | * Set up domains for cpus specified by the cpu_map. | 8505 | * Set up domains for cpus specified by the cpu_map. |
@@ -8675,41 +8730,13 @@ static int __build_sched_domains(const struct cpumask *cpu_map, | |||
8675 | cpu_attach_domain(sd, d.rd, i); | 8730 | cpu_attach_domain(sd, d.rd, i); |
8676 | } | 8731 | } |
8677 | 8732 | ||
8678 | err = 0; | 8733 | d.sched_group_nodes = NULL; /* don't free this we still need it */ |
8679 | 8734 | __free_domain_allocs(&d, sa_tmpmask, cpu_map); | |
8680 | free_tmpmask: | 8735 | return 0; |
8681 | free_cpumask_var(d.tmpmask); | ||
8682 | free_send_covered: | ||
8683 | free_cpumask_var(d.send_covered); | ||
8684 | free_this_core_map: | ||
8685 | free_cpumask_var(d.this_core_map); | ||
8686 | free_this_sibling_map: | ||
8687 | free_cpumask_var(d.this_sibling_map); | ||
8688 | free_nodemask: | ||
8689 | free_cpumask_var(d.nodemask); | ||
8690 | free_notcovered: | ||
8691 | #ifdef CONFIG_NUMA | ||
8692 | free_cpumask_var(d.notcovered); | ||
8693 | free_covered: | ||
8694 | free_cpumask_var(d.covered); | ||
8695 | free_domainspan: | ||
8696 | free_cpumask_var(d.domainspan); | ||
8697 | out: | ||
8698 | #endif | ||
8699 | return err; | ||
8700 | |||
8701 | free_sched_groups: | ||
8702 | #ifdef CONFIG_NUMA | ||
8703 | kfree(d.sched_group_nodes); | ||
8704 | #endif | ||
8705 | goto free_tmpmask; | ||
8706 | 8736 | ||
8707 | #ifdef CONFIG_NUMA | ||
8708 | error: | 8737 | error: |
8709 | free_sched_groups(cpu_map, d.tmpmask); | 8738 | __free_domain_allocs(&d, alloc_state, cpu_map); |
8710 | free_rootdomain(d.rd); | 8739 | return -ENOMEM; |
8711 | goto free_tmpmask; | ||
8712 | #endif | ||
8713 | } | 8740 | } |
8714 | 8741 | ||
8715 | static int build_sched_domains(const struct cpumask *cpu_map) | 8742 | static int build_sched_domains(const struct cpumask *cpu_map) |