Skip to content

Commit

Permalink
Revert "cgroup/cpuset: remove circular dependency deadlock"
Browse files Browse the repository at this point in the history
This reverts commit aa24163.

This and the following commit led to another circular locking scenario
and the scenario which is fixed by this commit no longer exists after
e8b3f8d ("workqueue/hotplug: simplify workqueue_offline_cpu()")
which removes work item flushing from hotplug path.

Revert it for now.

Signed-off-by: Tejun Heo <tj@kernel.org>
  • Loading branch information
Tejun Heo committed Dec 4, 2017
1 parent 11db855 commit bdfbbda
Showing 1 changed file with 23 additions and 30 deletions.
53 changes: 23 additions & 30 deletions kernel/cgroup/cpuset.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,18 +812,6 @@ static int generate_sched_domains(cpumask_var_t **domains,
return ndoms;
}

static void cpuset_sched_change_begin(void)
{
cpus_read_lock();
mutex_lock(&cpuset_mutex);
}

static void cpuset_sched_change_end(void)
{
mutex_unlock(&cpuset_mutex);
cpus_read_unlock();
}

/*
* Rebuild scheduler domains.
*
Expand All @@ -833,40 +821,44 @@ static void cpuset_sched_change_end(void)
* 'cpus' is removed, then call this routine to rebuild the
* scheduler's dynamic sched domains.
*
* Call with cpuset_mutex held. Takes get_online_cpus().
*/
static void rebuild_sched_domains_cpuslocked(void)
static void rebuild_sched_domains_locked(void)
{
struct sched_domain_attr *attr;
cpumask_var_t *doms;
int ndoms;

lockdep_assert_held(&cpuset_mutex);
get_online_cpus();

/*
* We have raced with CPU hotplug. Don't do anything to avoid
* passing doms with offlined cpu to partition_sched_domains().
* Anyways, hotplug work item will rebuild sched domains.
*/
if (!cpumask_equal(top_cpuset.effective_cpus, cpu_active_mask))
return;
goto out;

/* Generate domain masks and attrs */
ndoms = generate_sched_domains(&doms, &attr);

/* Have scheduler rebuild the domains */
partition_sched_domains(ndoms, doms, attr);
out:
put_online_cpus();
}
#else /* !CONFIG_SMP */
static void rebuild_sched_domains_cpuslocked(void)
static void rebuild_sched_domains_locked(void)
{
}
#endif /* CONFIG_SMP */

void rebuild_sched_domains(void)
{
cpuset_sched_change_begin();
rebuild_sched_domains_cpuslocked();
cpuset_sched_change_end();
mutex_lock(&cpuset_mutex);
rebuild_sched_domains_locked();
mutex_unlock(&cpuset_mutex);
}

/**
Expand Down Expand Up @@ -952,7 +944,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct cpumask *new_cpus)
rcu_read_unlock();

if (need_rebuild_sched_domains)
rebuild_sched_domains_cpuslocked();
rebuild_sched_domains_locked();
}

/**
Expand Down Expand Up @@ -1284,7 +1276,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
cs->relax_domain_level = val;
if (!cpumask_empty(cs->cpus_allowed) &&
is_sched_load_balance(cs))
rebuild_sched_domains_cpuslocked();
rebuild_sched_domains_locked();
}

return 0;
Expand Down Expand Up @@ -1317,6 +1309,7 @@ static void update_tasks_flags(struct cpuset *cs)
*
* Call with cpuset_mutex held.
*/

static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
int turning_on)
{
Expand Down Expand Up @@ -1349,7 +1342,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
spin_unlock_irq(&callback_lock);

if (!cpumask_empty(trialcs->cpus_allowed) && balance_flag_changed)
rebuild_sched_domains_cpuslocked();
rebuild_sched_domains_locked();

if (spread_flag_changed)
update_tasks_flags(cs);
Expand Down Expand Up @@ -1617,7 +1610,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft,
cpuset_filetype_t type = cft->private;
int retval = 0;

cpuset_sched_change_begin();
mutex_lock(&cpuset_mutex);
if (!is_cpuset_online(cs)) {
retval = -ENODEV;
goto out_unlock;
Expand Down Expand Up @@ -1653,7 +1646,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft,
break;
}
out_unlock:
cpuset_sched_change_end();
mutex_unlock(&cpuset_mutex);
return retval;
}

Expand All @@ -1664,7 +1657,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft,
cpuset_filetype_t type = cft->private;
int retval = -ENODEV;

cpuset_sched_change_begin();
mutex_lock(&cpuset_mutex);
if (!is_cpuset_online(cs))
goto out_unlock;

Expand All @@ -1677,7 +1670,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft,
break;
}
out_unlock:
cpuset_sched_change_end();
mutex_unlock(&cpuset_mutex);
return retval;
}

Expand Down Expand Up @@ -1716,7 +1709,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
kernfs_break_active_protection(of->kn);
flush_work(&cpuset_hotplug_work);

cpuset_sched_change_begin();
mutex_lock(&cpuset_mutex);
if (!is_cpuset_online(cs))
goto out_unlock;

Expand All @@ -1740,7 +1733,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,

free_trial_cpuset(trialcs);
out_unlock:
cpuset_sched_change_end();
mutex_unlock(&cpuset_mutex);
kernfs_unbreak_active_protection(of->kn);
css_put(&cs->css);
flush_workqueue(cpuset_migrate_mm_wq);
Expand Down Expand Up @@ -2041,22 +2034,22 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
/*
* If the cpuset being removed has its flag 'sched_load_balance'
* enabled, then simulate turning sched_load_balance off, which
* will call rebuild_sched_domains_cpuslocked().
* will call rebuild_sched_domains_locked().
*/

static void cpuset_css_offline(struct cgroup_subsys_state *css)
{
struct cpuset *cs = css_cs(css);

cpuset_sched_change_begin();
mutex_lock(&cpuset_mutex);

if (is_sched_load_balance(cs))
update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);

cpuset_dec();
clear_bit(CS_ONLINE, &cs->flags);

cpuset_sched_change_end();
mutex_unlock(&cpuset_mutex);
}

static void cpuset_css_free(struct cgroup_subsys_state *css)
Expand Down

0 comments on commit bdfbbda

Please sign in to comment.