0001
0002 #include <linux/cgroup.h>
0003 #include <linux/sched.h>
0004 #include <linux/sched/task.h>
0005 #include <linux/sched/signal.h>
0006
0007 #include "cgroup-internal.h"
0008
0009 #include <trace/events/cgroup.h>
0010
0011
0012
0013
0014 static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
0015 {
0016 int desc = 1;
0017
0018
0019
0020
0021
0022
0023
0024 while ((cgrp = cgroup_parent(cgrp))) {
0025 if (frozen) {
0026 cgrp->freezer.nr_frozen_descendants += desc;
0027 if (!test_bit(CGRP_FROZEN, &cgrp->flags) &&
0028 test_bit(CGRP_FREEZE, &cgrp->flags) &&
0029 cgrp->freezer.nr_frozen_descendants ==
0030 cgrp->nr_descendants) {
0031 set_bit(CGRP_FROZEN, &cgrp->flags);
0032 cgroup_file_notify(&cgrp->events_file);
0033 TRACE_CGROUP_PATH(notify_frozen, cgrp, 1);
0034 desc++;
0035 }
0036 } else {
0037 cgrp->freezer.nr_frozen_descendants -= desc;
0038 if (test_bit(CGRP_FROZEN, &cgrp->flags)) {
0039 clear_bit(CGRP_FROZEN, &cgrp->flags);
0040 cgroup_file_notify(&cgrp->events_file);
0041 TRACE_CGROUP_PATH(notify_frozen, cgrp, 0);
0042 desc++;
0043 }
0044 }
0045 }
0046 }
0047
0048
0049
0050
0051
0052 void cgroup_update_frozen(struct cgroup *cgrp)
0053 {
0054 bool frozen;
0055
0056 lockdep_assert_held(&css_set_lock);
0057
0058
0059
0060
0061
0062
0063 frozen = test_bit(CGRP_FREEZE, &cgrp->flags) &&
0064 cgrp->freezer.nr_frozen_tasks == __cgroup_task_count(cgrp);
0065
0066 if (frozen) {
0067
0068 if (test_bit(CGRP_FROZEN, &cgrp->flags))
0069 return;
0070
0071 set_bit(CGRP_FROZEN, &cgrp->flags);
0072 } else {
0073
0074 if (!test_bit(CGRP_FROZEN, &cgrp->flags))
0075 return;
0076
0077 clear_bit(CGRP_FROZEN, &cgrp->flags);
0078 }
0079 cgroup_file_notify(&cgrp->events_file);
0080 TRACE_CGROUP_PATH(notify_frozen, cgrp, frozen);
0081
0082
0083 cgroup_propagate_frozen(cgrp, frozen);
0084 }
0085
0086
0087
0088
0089 static void cgroup_inc_frozen_cnt(struct cgroup *cgrp)
0090 {
0091 cgrp->freezer.nr_frozen_tasks++;
0092 }
0093
0094
0095
0096
0097 static void cgroup_dec_frozen_cnt(struct cgroup *cgrp)
0098 {
0099 cgrp->freezer.nr_frozen_tasks--;
0100 WARN_ON_ONCE(cgrp->freezer.nr_frozen_tasks < 0);
0101 }
0102
0103
0104
0105
0106
0107 void cgroup_enter_frozen(void)
0108 {
0109 struct cgroup *cgrp;
0110
0111 if (current->frozen)
0112 return;
0113
0114 spin_lock_irq(&css_set_lock);
0115 current->frozen = true;
0116 cgrp = task_dfl_cgroup(current);
0117 cgroup_inc_frozen_cnt(cgrp);
0118 cgroup_update_frozen(cgrp);
0119 spin_unlock_irq(&css_set_lock);
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 void cgroup_leave_frozen(bool always_leave)
0132 {
0133 struct cgroup *cgrp;
0134
0135 spin_lock_irq(&css_set_lock);
0136 cgrp = task_dfl_cgroup(current);
0137 if (always_leave || !test_bit(CGRP_FREEZE, &cgrp->flags)) {
0138 cgroup_dec_frozen_cnt(cgrp);
0139 cgroup_update_frozen(cgrp);
0140 WARN_ON_ONCE(!current->frozen);
0141 current->frozen = false;
0142 } else if (!(current->jobctl & JOBCTL_TRAP_FREEZE)) {
0143 spin_lock(¤t->sighand->siglock);
0144 current->jobctl |= JOBCTL_TRAP_FREEZE;
0145 set_thread_flag(TIF_SIGPENDING);
0146 spin_unlock(¤t->sighand->siglock);
0147 }
0148 spin_unlock_irq(&css_set_lock);
0149 }
0150
0151
0152
0153
0154
0155 static void cgroup_freeze_task(struct task_struct *task, bool freeze)
0156 {
0157 unsigned long flags;
0158
0159
0160 if (!lock_task_sighand(task, &flags))
0161 return;
0162
0163 if (freeze) {
0164 task->jobctl |= JOBCTL_TRAP_FREEZE;
0165 signal_wake_up(task, false);
0166 } else {
0167 task->jobctl &= ~JOBCTL_TRAP_FREEZE;
0168 wake_up_process(task);
0169 }
0170
0171 unlock_task_sighand(task, &flags);
0172 }
0173
0174
0175
0176
0177 static void cgroup_do_freeze(struct cgroup *cgrp, bool freeze)
0178 {
0179 struct css_task_iter it;
0180 struct task_struct *task;
0181
0182 lockdep_assert_held(&cgroup_mutex);
0183
0184 spin_lock_irq(&css_set_lock);
0185 if (freeze)
0186 set_bit(CGRP_FREEZE, &cgrp->flags);
0187 else
0188 clear_bit(CGRP_FREEZE, &cgrp->flags);
0189 spin_unlock_irq(&css_set_lock);
0190
0191 if (freeze)
0192 TRACE_CGROUP_PATH(freeze, cgrp);
0193 else
0194 TRACE_CGROUP_PATH(unfreeze, cgrp);
0195
0196 css_task_iter_start(&cgrp->self, 0, &it);
0197 while ((task = css_task_iter_next(&it))) {
0198
0199
0200
0201
0202 if (task->flags & PF_KTHREAD)
0203 continue;
0204 cgroup_freeze_task(task, freeze);
0205 }
0206 css_task_iter_end(&it);
0207
0208
0209
0210
0211
0212 spin_lock_irq(&css_set_lock);
0213 if (cgrp->nr_descendants == cgrp->freezer.nr_frozen_descendants)
0214 cgroup_update_frozen(cgrp);
0215 spin_unlock_irq(&css_set_lock);
0216 }
0217
0218
0219
0220
0221
0222 void cgroup_freezer_migrate_task(struct task_struct *task,
0223 struct cgroup *src, struct cgroup *dst)
0224 {
0225 lockdep_assert_held(&css_set_lock);
0226
0227
0228
0229
0230 if (task->flags & PF_KTHREAD)
0231 return;
0232
0233
0234
0235
0236
0237 if (!test_bit(CGRP_FREEZE, &src->flags) &&
0238 !test_bit(CGRP_FREEZE, &dst->flags) &&
0239 !task->frozen)
0240 return;
0241
0242
0243
0244
0245
0246
0247 if (task->frozen) {
0248 cgroup_inc_frozen_cnt(dst);
0249 cgroup_dec_frozen_cnt(src);
0250 }
0251 cgroup_update_frozen(dst);
0252 cgroup_update_frozen(src);
0253
0254
0255
0256
0257 cgroup_freeze_task(task, test_bit(CGRP_FREEZE, &dst->flags));
0258 }
0259
0260 void cgroup_freeze(struct cgroup *cgrp, bool freeze)
0261 {
0262 struct cgroup_subsys_state *css;
0263 struct cgroup *dsct;
0264 bool applied = false;
0265
0266 lockdep_assert_held(&cgroup_mutex);
0267
0268
0269
0270
0271 if (cgrp->freezer.freeze == freeze)
0272 return;
0273
0274 cgrp->freezer.freeze = freeze;
0275
0276
0277
0278
0279 css_for_each_descendant_pre(css, &cgrp->self) {
0280 dsct = css->cgroup;
0281
0282 if (cgroup_is_dead(dsct))
0283 continue;
0284
0285 if (freeze) {
0286 dsct->freezer.e_freeze++;
0287
0288
0289
0290 if (dsct->freezer.e_freeze > 1)
0291 continue;
0292 } else {
0293 dsct->freezer.e_freeze--;
0294
0295
0296
0297 if (dsct->freezer.e_freeze > 0)
0298 continue;
0299
0300 WARN_ON_ONCE(dsct->freezer.e_freeze < 0);
0301 }
0302
0303
0304
0305
0306 cgroup_do_freeze(dsct, freeze);
0307 applied = true;
0308 }
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318 if (!applied) {
0319 TRACE_CGROUP_PATH(notify_frozen, cgrp,
0320 test_bit(CGRP_FROZEN, &cgrp->flags));
0321 cgroup_file_notify(&cgrp->events_file);
0322 }
0323 }