aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cpuset.c89
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 */
609static 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
598static int update_cpumask(struct cpuset *cs, char *buf) 650static 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
616static int update_nodemask(struct cpuset *cs, char *buf) 672static 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
669static int attach_task(struct cpuset *cs, char *buf) 730static 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);