@@ -2453,6 +2453,20 @@ static int fmeter_getrate(struct fmeter *fmp)
24532453
24542454static struct cpuset * cpuset_attach_old_cs ;
24552455
2456+ /*
2457+ * Check to see if a cpuset can accept a new task
2458+ * For v1, cpus_allowed and mems_allowed can't be empty.
2459+ * For v2, effective_cpus can't be empty.
2460+ * Note that in v1, effective_cpus = cpus_allowed.
2461+ */
2462+ static int cpuset_can_attach_check (struct cpuset * cs )
2463+ {
2464+ if (cpumask_empty (cs -> effective_cpus ) ||
2465+ (!is_in_v2_mode () && nodes_empty (cs -> mems_allowed )))
2466+ return - ENOSPC ;
2467+ return 0 ;
2468+ }
2469+
24562470/* Called by cgroups to determine if a cpuset is usable; cpuset_rwsem held */
24572471static int cpuset_can_attach (struct cgroup_taskset * tset )
24582472{
@@ -2467,16 +2481,9 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
24672481
24682482 percpu_down_write (& cpuset_rwsem );
24692483
2470- /* allow moving tasks into an empty cpuset if on default hierarchy */
2471- ret = - ENOSPC ;
2472- if (!is_in_v2_mode () &&
2473- (cpumask_empty (cs -> cpus_allowed ) || nodes_empty (cs -> mems_allowed )))
2474- goto out_unlock ;
2475-
2476- /*
2477- * Task cannot be moved to a cpuset with empty effective cpus.
2478- */
2479- if (cpumask_empty (cs -> effective_cpus ))
2484+ /* Check to see if task is allowed in the cpuset */
2485+ ret = cpuset_can_attach_check (cs );
2486+ if (ret )
24802487 goto out_unlock ;
24812488
24822489 cgroup_taskset_for_each (task , css , tset ) {
@@ -2493,7 +2500,6 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
24932500 * changes which zero cpus/mems_allowed.
24942501 */
24952502 cs -> attach_in_progress ++ ;
2496- ret = 0 ;
24972503out_unlock :
24982504 percpu_up_write (& cpuset_rwsem );
24992505 return ret ;
@@ -3264,6 +3270,68 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
32643270 percpu_up_write (& cpuset_rwsem );
32653271}
32663272
3273+ /*
3274+ * In case the child is cloned into a cpuset different from its parent,
3275+ * additional checks are done to see if the move is allowed.
3276+ */
3277+ static int cpuset_can_fork (struct task_struct * task , struct css_set * cset )
3278+ {
3279+ struct cpuset * cs = css_cs (cset -> subsys [cpuset_cgrp_id ]);
3280+ bool same_cs ;
3281+ int ret ;
3282+
3283+ rcu_read_lock ();
3284+ same_cs = (cs == task_cs (current ));
3285+ rcu_read_unlock ();
3286+
3287+ if (same_cs )
3288+ return 0 ;
3289+
3290+ lockdep_assert_held (& cgroup_mutex );
3291+ percpu_down_write (& cpuset_rwsem );
3292+
3293+ /* Check to see if task is allowed in the cpuset */
3294+ ret = cpuset_can_attach_check (cs );
3295+ if (ret )
3296+ goto out_unlock ;
3297+
3298+ ret = task_can_attach (task , cs -> effective_cpus );
3299+ if (ret )
3300+ goto out_unlock ;
3301+
3302+ ret = security_task_setscheduler (task );
3303+ if (ret )
3304+ goto out_unlock ;
3305+
3306+ /*
3307+ * Mark attach is in progress. This makes validate_change() fail
3308+ * changes which zero cpus/mems_allowed.
3309+ */
3310+ cs -> attach_in_progress ++ ;
3311+ out_unlock :
3312+ percpu_up_write (& cpuset_rwsem );
3313+ return ret ;
3314+ }
3315+
3316+ static void cpuset_cancel_fork (struct task_struct * task , struct css_set * cset )
3317+ {
3318+ struct cpuset * cs = css_cs (cset -> subsys [cpuset_cgrp_id ]);
3319+ bool same_cs ;
3320+
3321+ rcu_read_lock ();
3322+ same_cs = (cs == task_cs (current ));
3323+ rcu_read_unlock ();
3324+
3325+ if (same_cs )
3326+ return ;
3327+
3328+ percpu_down_write (& cpuset_rwsem );
3329+ cs -> attach_in_progress -- ;
3330+ if (!cs -> attach_in_progress )
3331+ wake_up (& cpuset_attach_wq );
3332+ percpu_up_write (& cpuset_rwsem );
3333+ }
3334+
32673335/*
32683336 * Make sure the new task conform to the current state of its parent,
32693337 * which could have been changed by cpuset just after it inherits the
@@ -3292,6 +3360,11 @@ static void cpuset_fork(struct task_struct *task)
32923360 percpu_down_write (& cpuset_rwsem );
32933361 guarantee_online_mems (cs , & cpuset_attach_nodemask_to );
32943362 cpuset_attach_task (cs , task );
3363+
3364+ cs -> attach_in_progress -- ;
3365+ if (!cs -> attach_in_progress )
3366+ wake_up (& cpuset_attach_wq );
3367+
32953368 percpu_up_write (& cpuset_rwsem );
32963369}
32973370
@@ -3305,6 +3378,8 @@ struct cgroup_subsys cpuset_cgrp_subsys = {
33053378 .attach = cpuset_attach ,
33063379 .post_attach = cpuset_post_attach ,
33073380 .bind = cpuset_bind ,
3381+ .can_fork = cpuset_can_fork ,
3382+ .cancel_fork = cpuset_cancel_fork ,
33083383 .fork = cpuset_fork ,
33093384 .legacy_cftypes = legacy_files ,
33103385 .dfl_cftypes = dfl_files ,
0 commit comments