diff options
Diffstat (limited to 'kernel/cgroup_freezer.c')
| -rw-r--r-- | kernel/cgroup_freezer.c | 63 | 
1 files changed, 28 insertions, 35 deletions
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index 213c0351dad..fcb93fca782 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c @@ -48,19 +48,17 @@ static inline struct freezer *task_freezer(struct task_struct *task)  			    struct freezer, css);  } -static inline int __cgroup_freezing_or_frozen(struct task_struct *task) +bool cgroup_freezing(struct task_struct *task)  { -	enum freezer_state state = task_freezer(task)->state; -	return (state == CGROUP_FREEZING) || (state == CGROUP_FROZEN); -} +	enum freezer_state state; +	bool ret; -int cgroup_freezing_or_frozen(struct task_struct *task) -{ -	int result; -	task_lock(task); -	result = __cgroup_freezing_or_frozen(task); -	task_unlock(task); -	return result; +	rcu_read_lock(); +	state = task_freezer(task)->state; +	ret = state == CGROUP_FREEZING || state == CGROUP_FROZEN; +	rcu_read_unlock(); + +	return ret;  }  /* @@ -102,9 +100,6 @@ struct cgroup_subsys freezer_subsys;   * freezer_can_attach():   * cgroup_mutex (held by caller of can_attach)   * - * cgroup_freezing_or_frozen(): - * task->alloc_lock (to get task's cgroup) - *   * freezer_fork() (preserving fork() performance means can't take cgroup_mutex):   * freezer->lock   *  sighand->siglock (if the cgroup is freezing) @@ -130,7 +125,7 @@ struct cgroup_subsys freezer_subsys;   *   write_lock css_set_lock (cgroup iterator start)   *    task->alloc_lock   *   read_lock css_set_lock (cgroup iterator start) - *    task->alloc_lock (inside thaw_process(), prevents race with refrigerator()) + *    task->alloc_lock (inside __thaw_task(), prevents race with refrigerator())   *     sighand->siglock   */  static struct cgroup_subsys_state *freezer_create(struct cgroup_subsys *ss, @@ -150,7 +145,11 @@ static struct cgroup_subsys_state *freezer_create(struct cgroup_subsys *ss,  static void freezer_destroy(struct cgroup_subsys *ss,  			    struct cgroup *cgroup)  { -	kfree(cgroup_freezer(cgroup)); +	struct freezer *freezer = cgroup_freezer(cgroup); + +	if (freezer->state != CGROUP_THAWED) +		atomic_dec(&system_freezing_cnt); +	kfree(freezer);  }  /* task is frozen or will freeze immediately when next it gets woken */ @@ -184,13 +183,7 @@ static int freezer_can_attach(struct cgroup_subsys *ss,  static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk)  { -	rcu_read_lock(); -	if (__cgroup_freezing_or_frozen(tsk)) { -		rcu_read_unlock(); -		return -EBUSY; -	} -	rcu_read_unlock(); -	return 0; +	return cgroup_freezing(tsk) ? -EBUSY : 0;  }  static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task) @@ -220,7 +213,7 @@ static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task)  	/* Locking avoids race with FREEZING -> THAWED transitions. */  	if (freezer->state == CGROUP_FREEZING) -		freeze_task(task, true); +		freeze_task(task);  	spin_unlock_irq(&freezer->lock);  } @@ -238,7 +231,7 @@ static void update_if_frozen(struct cgroup *cgroup,  	cgroup_iter_start(cgroup, &it);  	while ((task = cgroup_iter_next(cgroup, &it))) {  		ntotal++; -		if (is_task_frozen_enough(task)) +		if (freezing(task) && is_task_frozen_enough(task))  			nfrozen++;  	} @@ -286,10 +279,9 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)  	struct task_struct *task;  	unsigned int num_cant_freeze_now = 0; -	freezer->state = CGROUP_FREEZING;  	cgroup_iter_start(cgroup, &it);  	while ((task = cgroup_iter_next(cgroup, &it))) { -		if (!freeze_task(task, true)) +		if (!freeze_task(task))  			continue;  		if (is_task_frozen_enough(task))  			continue; @@ -307,12 +299,9 @@ static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)  	struct task_struct *task;  	cgroup_iter_start(cgroup, &it); -	while ((task = cgroup_iter_next(cgroup, &it))) { -		thaw_process(task); -	} +	while ((task = cgroup_iter_next(cgroup, &it))) +		__thaw_task(task);  	cgroup_iter_end(cgroup, &it); - -	freezer->state = CGROUP_THAWED;  }  static int freezer_change_state(struct cgroup *cgroup, @@ -326,20 +315,24 @@ static int freezer_change_state(struct cgroup *cgroup,  	spin_lock_irq(&freezer->lock);  	update_if_frozen(cgroup, freezer); -	if (goal_state == freezer->state) -		goto out;  	switch (goal_state) {  	case CGROUP_THAWED: +		if (freezer->state != CGROUP_THAWED) +			atomic_dec(&system_freezing_cnt); +		freezer->state = CGROUP_THAWED;  		unfreeze_cgroup(cgroup, freezer);  		break;  	case CGROUP_FROZEN: +		if (freezer->state == CGROUP_THAWED) +			atomic_inc(&system_freezing_cnt); +		freezer->state = CGROUP_FREEZING;  		retval = try_to_freeze_cgroup(cgroup, freezer);  		break;  	default:  		BUG();  	} -out: +  	spin_unlock_irq(&freezer->lock);  	return retval;  |