@@ -1806,17 +1806,28 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
18061806 *
18071807 * Compute add/delete mask to/from effective_cpus
18081808 *
1809- * addmask = effective_xcpus & ~newmask & parent->effective_xcpus
1810- * delmask = newmask & ~cs->effective_xcpus
1811- * & parent->effective_xcpus
1809+ * For valid partition:
1810+ * addmask = exclusive_cpus & ~newmask
1811+ * & parent->effective_xcpus
1812+ * delmask = newmask & ~exclusive_cpus
1813+ * & parent->effective_xcpus
1814+ *
1815+ * For invalid partition:
1816+ * delmask = newmask & parent->effective_xcpus
18121817 */
1813- cpumask_andnot (tmp -> addmask , xcpus , newmask );
1814- adding = cpumask_and (tmp -> addmask , tmp -> addmask ,
1815- parent -> effective_xcpus );
1818+ if (is_prs_invalid (old_prs )) {
1819+ adding = false;
1820+ deleting = cpumask_and (tmp -> delmask ,
1821+ newmask , parent -> effective_xcpus );
1822+ } else {
1823+ cpumask_andnot (tmp -> addmask , xcpus , newmask );
1824+ adding = cpumask_and (tmp -> addmask , tmp -> addmask ,
1825+ parent -> effective_xcpus );
18161826
1817- cpumask_andnot (tmp -> delmask , newmask , xcpus );
1818- deleting = cpumask_and (tmp -> delmask , tmp -> delmask ,
1819- parent -> effective_xcpus );
1827+ cpumask_andnot (tmp -> delmask , newmask , xcpus );
1828+ deleting = cpumask_and (tmp -> delmask , tmp -> delmask ,
1829+ parent -> effective_xcpus );
1830+ }
18201831 /*
18211832 * Make partition invalid if parent's effective_cpus could
18221833 * become empty and there are tasks in the parent.
@@ -1910,9 +1921,11 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
19101921
19111922 /*
19121923 * Transitioning between invalid to valid or vice versa may require
1913- * changing CS_CPU_EXCLUSIVE.
1924+ * changing CS_CPU_EXCLUSIVE. In the case of partcmd_update,
1925+ * validate_change() has already been successfully called and
1926+ * CPU lists in cs haven't been updated yet. So defer it to later.
19141927 */
1915- if (old_prs != new_prs ) {
1928+ if (( old_prs != new_prs ) && ( cmd != partcmd_update )) {
19161929 int err = update_partition_exclusive (cs , new_prs );
19171930
19181931 if (err )
@@ -1960,6 +1973,9 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
19601973
19611974 spin_unlock_irq (& callback_lock );
19621975
1976+ if ((old_prs != new_prs ) && (cmd == partcmd_update ))
1977+ update_partition_exclusive (cs , new_prs );
1978+
19631979 if (adding || deleting ) {
19641980 update_tasks_cpumask (parent , tmp -> addmask );
19651981 update_sibling_cpumasks (parent , cs , tmp );
@@ -2356,8 +2372,9 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
23562372 if (alloc_cpumasks (NULL , & tmp ))
23572373 return - ENOMEM ;
23582374
2359- if (is_partition_valid (cs )) {
2360- if (cpumask_empty (trialcs -> effective_xcpus )) {
2375+ if (old_prs ) {
2376+ if (is_partition_valid (cs ) &&
2377+ cpumask_empty (trialcs -> effective_xcpus )) {
23612378 invalidate = true;
23622379 cs -> prs_err = PERR_INVCPUS ;
23632380 } else if (prstate_housekeeping_conflict (old_prs , trialcs -> effective_xcpus )) {
@@ -2391,32 +2408,41 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
23912408 */
23922409 invalidate = true;
23932410 rcu_read_lock ();
2394- cpuset_for_each_child (cp , css , parent )
2411+ cpuset_for_each_child (cp , css , parent ) {
2412+ struct cpumask * xcpus = fetch_xcpus (trialcs );
2413+
23952414 if (is_partition_valid (cp ) &&
2396- cpumask_intersects (trialcs -> effective_xcpus , cp -> effective_xcpus )) {
2415+ cpumask_intersects (xcpus , cp -> effective_xcpus )) {
23972416 rcu_read_unlock ();
23982417 update_parent_effective_cpumask (cp , partcmd_invalidate , NULL , & tmp );
23992418 rcu_read_lock ();
24002419 }
2420+ }
24012421 rcu_read_unlock ();
24022422 retval = 0 ;
24032423 }
24042424
24052425 if (retval < 0 )
24062426 goto out_free ;
24072427
2408- if (is_partition_valid (cs )) {
2428+ if (is_partition_valid (cs ) ||
2429+ (is_partition_invalid (cs ) && !invalidate )) {
2430+ struct cpumask * xcpus = trialcs -> effective_xcpus ;
2431+
2432+ if (cpumask_empty (xcpus ) && is_partition_invalid (cs ))
2433+ xcpus = trialcs -> cpus_allowed ;
2434+
24092435 /*
24102436 * Call remote_cpus_update() to handle valid remote partition
24112437 */
24122438 if (is_remote_partition (cs ))
2413- remote_cpus_update (cs , trialcs -> effective_xcpus , & tmp );
2439+ remote_cpus_update (cs , xcpus , & tmp );
24142440 else if (invalidate )
24152441 update_parent_effective_cpumask (cs , partcmd_invalidate ,
24162442 NULL , & tmp );
24172443 else
24182444 update_parent_effective_cpumask (cs , partcmd_update ,
2419- trialcs -> effective_xcpus , & tmp );
2445+ xcpus , & tmp );
24202446 } else if (!cpumask_empty (cs -> exclusive_cpus )) {
24212447 /*
24222448 * Use trialcs->effective_cpus as a temp cpumask
@@ -2493,7 +2519,7 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
24932519 if (retval )
24942520 return retval ;
24952521
2496- if (is_partition_valid ( cs ) ) {
2522+ if (old_prs ) {
24972523 if (cpumask_empty (trialcs -> effective_xcpus )) {
24982524 invalidate = true;
24992525 cs -> prs_err = PERR_INVCPUS ;
@@ -2927,19 +2953,10 @@ static int update_prstate(struct cpuset *cs, int new_prs)
29272953 return 0 ;
29282954
29292955 /*
2930- * For a previously invalid partition root with valid partition root
2931- * parent, treat it as if it is a "member". Otherwise, reject it as
2932- * remote partition cannot currently self-recover from an invalid
2933- * state.
2956+ * Treat a previously invalid partition root as if it is a "member".
29342957 */
2935- if (new_prs && is_prs_invalid (old_prs )) {
2936- if (is_partition_valid (parent )) {
2937- old_prs = PRS_MEMBER ;
2938- } else {
2939- cs -> partition_root_state = - new_prs ;
2940- return 0 ;
2941- }
2942- }
2958+ if (new_prs && is_prs_invalid (old_prs ))
2959+ old_prs = PRS_MEMBER ;
29432960
29442961 if (alloc_cpumasks (NULL , & tmpmask ))
29452962 return - ENOMEM ;
0 commit comments