diff options
Diffstat (limited to 'kernel/cpuset.c')
| -rw-r--r-- | kernel/cpuset.c | 89 |
1 files changed, 76 insertions, 13 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 79dd929f4084..984c0bf3807f 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -595,10 +595,62 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) | |||
| 595 | return 0; | 595 | return 0; |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | /* | ||
| 599 | * For a given cpuset cur, partition the system as follows | ||
| 600 | * a. All cpus in the parent cpuset's cpus_allowed that are not part of any | ||
| 601 | * exclusive child cpusets | ||
| 602 | * b. All cpus in the current cpuset's cpus_allowed that are not part of any | ||
| 603 | * exclusive child cpusets | ||
| 604 | * Build these two partitions by calling partition_sched_domains | ||
| 605 | * | ||
| 606 | * Call with cpuset_sem held. May nest a call to the | ||
| 607 | * lock_cpu_hotplug()/unlock_cpu_hotplug() pair. | ||
| 608 | */ | ||
| 609 | static void update_cpu_domains(struct cpuset *cur) | ||
| 610 | { | ||
| 611 | struct cpuset *c, *par = cur->parent; | ||
| 612 | cpumask_t pspan, cspan; | ||
| 613 | |||
| 614 | if (par == NULL || cpus_empty(cur->cpus_allowed)) | ||
| 615 | return; | ||
| 616 | |||
| 617 | /* | ||
| 618 | * Get all cpus from parent's cpus_allowed not part of exclusive | ||
| 619 | * children | ||
| 620 | */ | ||
| 621 | pspan = par->cpus_allowed; | ||
| 622 | list_for_each_entry(c, &par->children, sibling) { | ||
| 623 | if (is_cpu_exclusive(c)) | ||
| 624 | cpus_andnot(pspan, pspan, c->cpus_allowed); | ||
| 625 | } | ||
| 626 | if (is_removed(cur) || !is_cpu_exclusive(cur)) { | ||
| 627 | cpus_or(pspan, pspan, cur->cpus_allowed); | ||
| 628 | if (cpus_equal(pspan, cur->cpus_allowed)) | ||
| 629 | return; | ||
| 630 | cspan = CPU_MASK_NONE; | ||
| 631 | } else { | ||
| 632 | if (cpus_empty(pspan)) | ||
| 633 | return; | ||
| 634 | cspan = cur->cpus_allowed; | ||
| 635 | /* | ||
| 636 | * Get all cpus from current cpuset's cpus_allowed not part | ||
| 637 | * of exclusive children | ||
| 638 | */ | ||
| 639 | list_for_each_entry(c, &cur->children, sibling) { | ||
| 640 | if (is_cpu_exclusive(c)) | ||
| 641 | cpus_andnot(cspan, cspan, c->cpus_allowed); | ||
| 642 | } | ||
| 643 | } | ||
| 644 | |||
| 645 | lock_cpu_hotplug(); | ||
| 646 | partition_sched_domains(&pspan, &cspan); | ||
| 647 | unlock_cpu_hotplug(); | ||
| 648 | } | ||
| 649 | |||
| 598 | static int update_cpumask(struct cpuset *cs, char *buf) | 650 | static int update_cpumask(struct cpuset *cs, char *buf) |
| 599 | { | 651 | { |
| 600 | struct cpuset trialcs; | 652 | struct cpuset trialcs; |
| 601 | int retval; | 653 | int retval, cpus_unchanged; |
| 602 | 654 | ||
| 603 | trialcs = *cs; | 655 | trialcs = *cs; |
| 604 | retval = cpulist_parse(buf, trialcs.cpus_allowed); | 656 | retval = cpulist_parse(buf, trialcs.cpus_allowed); |
| @@ -608,9 +660,13 @@ static int update_cpumask(struct cpuset *cs, char *buf) | |||
| 608 | if (cpus_empty(trialcs.cpus_allowed)) | 660 | if (cpus_empty(trialcs.cpus_allowed)) |
| 609 | return -ENOSPC; | 661 | return -ENOSPC; |
| 610 | retval = validate_change(cs, &trialcs); | 662 | retval = validate_change(cs, &trialcs); |
| 611 | if (retval == 0) | 663 | if (retval < 0) |
| 612 | cs->cpus_allowed = trialcs.cpus_allowed; | 664 | return retval; |
| 613 | return retval; | 665 | cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed); |
| 666 | cs->cpus_allowed = trialcs.cpus_allowed; | ||
| 667 | if (is_cpu_exclusive(cs) && !cpus_unchanged) | ||
| 668 | update_cpu_domains(cs); | ||
| 669 | return 0; | ||
| 614 | } | 670 | } |
| 615 | 671 | ||
| 616 | static int update_nodemask(struct cpuset *cs, char *buf) | 672 | static int update_nodemask(struct cpuset *cs, char *buf) |
| @@ -646,7 +702,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) | |||
| 646 | { | 702 | { |
| 647 | int turning_on; | 703 | int turning_on; |
| 648 | struct cpuset trialcs; | 704 | struct cpuset trialcs; |
| 649 | int err; | 705 | int err, cpu_exclusive_changed; |
| 650 | 706 | ||
| 651 | turning_on = (simple_strtoul(buf, NULL, 10) != 0); | 707 | turning_on = (simple_strtoul(buf, NULL, 10) != 0); |
| 652 | 708 | ||
| @@ -657,13 +713,18 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) | |||
| 657 | clear_bit(bit, &trialcs.flags); | 713 | clear_bit(bit, &trialcs.flags); |
| 658 | 714 | ||
| 659 | err = validate_change(cs, &trialcs); | 715 | err = validate_change(cs, &trialcs); |
| 660 | if (err == 0) { | 716 | if (err < 0) |
| 661 | if (turning_on) | 717 | return err; |
| 662 | set_bit(bit, &cs->flags); | 718 | cpu_exclusive_changed = |
| 663 | else | 719 | (is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs)); |
| 664 | clear_bit(bit, &cs->flags); | 720 | if (turning_on) |
| 665 | } | 721 | set_bit(bit, &cs->flags); |
| 666 | return err; | 722 | else |
| 723 | clear_bit(bit, &cs->flags); | ||
| 724 | |||
| 725 | if (cpu_exclusive_changed) | ||
| 726 | update_cpu_domains(cs); | ||
| 727 | return 0; | ||
| 667 | } | 728 | } |
| 668 | 729 | ||
| 669 | static int attach_task(struct cpuset *cs, char *buf) | 730 | static int attach_task(struct cpuset *cs, char *buf) |
| @@ -1309,12 +1370,14 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
| 1309 | up(&cpuset_sem); | 1370 | up(&cpuset_sem); |
| 1310 | return -EBUSY; | 1371 | return -EBUSY; |
| 1311 | } | 1372 | } |
| 1312 | spin_lock(&cs->dentry->d_lock); | ||
| 1313 | parent = cs->parent; | 1373 | parent = cs->parent; |
| 1314 | set_bit(CS_REMOVED, &cs->flags); | 1374 | set_bit(CS_REMOVED, &cs->flags); |
| 1375 | if (is_cpu_exclusive(cs)) | ||
| 1376 | update_cpu_domains(cs); | ||
| 1315 | list_del(&cs->sibling); /* delete my sibling from parent->children */ | 1377 | list_del(&cs->sibling); /* delete my sibling from parent->children */ |
| 1316 | if (list_empty(&parent->children)) | 1378 | if (list_empty(&parent->children)) |
| 1317 | check_for_release(parent); | 1379 | check_for_release(parent); |
| 1380 | spin_lock(&cs->dentry->d_lock); | ||
| 1318 | d = dget(cs->dentry); | 1381 | d = dget(cs->dentry); |
| 1319 | cs->dentry = NULL; | 1382 | cs->dentry = NULL; |
| 1320 | spin_unlock(&d->d_lock); | 1383 | spin_unlock(&d->d_lock); |
