Branch data Line data Source code
1 : : //SPDX-License-Identifier: GPL-2.0 2 : : #include <linux/cgroup.h> 3 : : #include <linux/sched.h> 4 : : #include <linux/sched/task.h> 5 : : #include <linux/sched/signal.h> 6 : : 7 : : #include "cgroup-internal.h" 8 : : 9 : : #include <trace/events/cgroup.h> 10 : : 11 : : /* 12 : : * Propagate the cgroup frozen state upwards by the cgroup tree. 13 : : */ 14 : 0 : static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen) 15 : : { 16 : : int desc = 1; 17 : : 18 : : /* 19 : : * If the new state is frozen, some freezing ancestor cgroups may change 20 : : * their state too, depending on if all their descendants are frozen. 21 : : * 22 : : * Otherwise, all ancestor cgroups are forced into the non-frozen state. 23 : : */ 24 : 0 : while ((cgrp = cgroup_parent(cgrp))) { 25 : 0 : if (frozen) { 26 : 0 : cgrp->freezer.nr_frozen_descendants += desc; 27 : 0 : if (!test_bit(CGRP_FROZEN, &cgrp->flags) && 28 : 0 : test_bit(CGRP_FREEZE, &cgrp->flags) && 29 : : cgrp->freezer.nr_frozen_descendants == 30 : 0 : cgrp->nr_descendants) { 31 : 0 : set_bit(CGRP_FROZEN, &cgrp->flags); 32 : 0 : cgroup_file_notify(&cgrp->events_file); 33 : 0 : TRACE_CGROUP_PATH(notify_frozen, cgrp, 1); 34 : 0 : desc++; 35 : : } 36 : : } else { 37 : 0 : cgrp->freezer.nr_frozen_descendants -= desc; 38 : 0 : if (test_bit(CGRP_FROZEN, &cgrp->flags)) { 39 : 0 : clear_bit(CGRP_FROZEN, &cgrp->flags); 40 : 0 : cgroup_file_notify(&cgrp->events_file); 41 : 0 : TRACE_CGROUP_PATH(notify_frozen, cgrp, 0); 42 : 0 : desc++; 43 : : } 44 : : } 45 : : } 46 : 0 : } 47 : : 48 : : /* 49 : : * Revisit the cgroup frozen state. 50 : : * Checks if the cgroup is really frozen and perform all state transitions. 51 : : */ 52 : 3 : void cgroup_update_frozen(struct cgroup *cgrp) 53 : : { 54 : : bool frozen; 55 : : 56 : : lockdep_assert_held(&css_set_lock); 57 : : 58 : : /* 59 : : * If the cgroup has to be frozen (CGRP_FREEZE bit set), 60 : : * and all tasks are frozen and/or stopped, let's consider 61 : : * the cgroup frozen. Otherwise it's not frozen. 62 : : */ 63 : 3 : frozen = test_bit(CGRP_FREEZE, &cgrp->flags) && 64 : 0 : cgrp->freezer.nr_frozen_tasks == __cgroup_task_count(cgrp); 65 : : 66 : 3 : if (frozen) { 67 : : /* Already there? */ 68 : 0 : if (test_bit(CGRP_FROZEN, &cgrp->flags)) 69 : : return; 70 : : 71 : 0 : set_bit(CGRP_FROZEN, &cgrp->flags); 72 : : } else { 73 : : /* Already there? */ 74 : 3 : if (!test_bit(CGRP_FROZEN, &cgrp->flags)) 75 : : return; 76 : : 77 : 0 : clear_bit(CGRP_FROZEN, &cgrp->flags); 78 : : } 79 : 0 : cgroup_file_notify(&cgrp->events_file); 80 : 0 : TRACE_CGROUP_PATH(notify_frozen, cgrp, frozen); 81 : : 82 : : /* Update the state of ancestor cgroups. */ 83 : 0 : cgroup_propagate_frozen(cgrp, frozen); 84 : : } 85 : : 86 : : /* 87 : : * Increment cgroup's nr_frozen_tasks. 88 : : */ 89 : : static void cgroup_inc_frozen_cnt(struct cgroup *cgrp) 90 : : { 91 : 3 : cgrp->freezer.nr_frozen_tasks++; 92 : : } 93 : : 94 : : /* 95 : : * Decrement cgroup's nr_frozen_tasks. 96 : : */ 97 : 3 : static void cgroup_dec_frozen_cnt(struct cgroup *cgrp) 98 : : { 99 : 3 : cgrp->freezer.nr_frozen_tasks--; 100 : 3 : WARN_ON_ONCE(cgrp->freezer.nr_frozen_tasks < 0); 101 : 3 : } 102 : : 103 : : /* 104 : : * Enter frozen/stopped state, if not yet there. Update cgroup's counters, 105 : : * and revisit the state of the cgroup, if necessary. 106 : : */ 107 : 3 : void cgroup_enter_frozen(void) 108 : : { 109 : : struct cgroup *cgrp; 110 : : 111 : 3 : if (current->frozen) 112 : 3 : return; 113 : : 114 : : spin_lock_irq(&css_set_lock); 115 : 3 : current->frozen = true; 116 : 3 : cgrp = task_dfl_cgroup(current); 117 : : cgroup_inc_frozen_cnt(cgrp); 118 : 3 : cgroup_update_frozen(cgrp); 119 : : spin_unlock_irq(&css_set_lock); 120 : : } 121 : : 122 : : /* 123 : : * Conditionally leave frozen/stopped state. Update cgroup's counters, 124 : : * and revisit the state of the cgroup, if necessary. 125 : : * 126 : : * If always_leave is not set, and the cgroup is freezing, 127 : : * we're racing with the cgroup freezing. In this case, we don't 128 : : * drop the frozen counter to avoid a transient switch to 129 : : * the unfrozen state. 130 : : */ 131 : 3 : void cgroup_leave_frozen(bool always_leave) 132 : : { 133 : : struct cgroup *cgrp; 134 : : 135 : : spin_lock_irq(&css_set_lock); 136 : 3 : cgrp = task_dfl_cgroup(current); 137 : 3 : if (always_leave || !test_bit(CGRP_FREEZE, &cgrp->flags)) { 138 : 3 : cgroup_dec_frozen_cnt(cgrp); 139 : 3 : cgroup_update_frozen(cgrp); 140 : 3 : WARN_ON_ONCE(!current->frozen); 141 : 3 : current->frozen = false; 142 : 0 : } else if (!(current->jobctl & JOBCTL_TRAP_FREEZE)) { 143 : 0 : spin_lock(¤t->sighand->siglock); 144 : 0 : current->jobctl |= JOBCTL_TRAP_FREEZE; 145 : : set_thread_flag(TIF_SIGPENDING); 146 : 0 : spin_unlock(¤t->sighand->siglock); 147 : : } 148 : : spin_unlock_irq(&css_set_lock); 149 : 3 : } 150 : : 151 : : /* 152 : : * Freeze or unfreeze the task by setting or clearing the JOBCTL_TRAP_FREEZE 153 : : * jobctl bit. 154 : : */ 155 : 0 : static void cgroup_freeze_task(struct task_struct *task, bool freeze) 156 : : { 157 : : unsigned long flags; 158 : : 159 : : /* If the task is about to die, don't bother with freezing it. */ 160 : 0 : if (!lock_task_sighand(task, &flags)) 161 : 0 : return; 162 : : 163 : 0 : if (freeze) { 164 : 0 : task->jobctl |= JOBCTL_TRAP_FREEZE; 165 : : signal_wake_up(task, false); 166 : : } else { 167 : 0 : task->jobctl &= ~JOBCTL_TRAP_FREEZE; 168 : 0 : wake_up_process(task); 169 : : } 170 : : 171 : : unlock_task_sighand(task, &flags); 172 : : } 173 : : 174 : : /* 175 : : * Freeze or unfreeze all tasks in the given cgroup. 176 : : */ 177 : 0 : static void cgroup_do_freeze(struct cgroup *cgrp, bool freeze) 178 : : { 179 : : struct css_task_iter it; 180 : : struct task_struct *task; 181 : : 182 : : lockdep_assert_held(&cgroup_mutex); 183 : : 184 : : spin_lock_irq(&css_set_lock); 185 : 0 : if (freeze) 186 : 0 : set_bit(CGRP_FREEZE, &cgrp->flags); 187 : : else 188 : 0 : clear_bit(CGRP_FREEZE, &cgrp->flags); 189 : : spin_unlock_irq(&css_set_lock); 190 : : 191 : 0 : if (freeze) 192 : 0 : TRACE_CGROUP_PATH(freeze, cgrp); 193 : : else 194 : 0 : TRACE_CGROUP_PATH(unfreeze, cgrp); 195 : : 196 : 0 : css_task_iter_start(&cgrp->self, 0, &it); 197 : 0 : while ((task = css_task_iter_next(&it))) { 198 : : /* 199 : : * Ignore kernel threads here. Freezing cgroups containing 200 : : * kthreads isn't supported. 201 : : */ 202 : 0 : if (task->flags & PF_KTHREAD) 203 : 0 : continue; 204 : 0 : cgroup_freeze_task(task, freeze); 205 : : } 206 : 0 : css_task_iter_end(&it); 207 : : 208 : : /* 209 : : * Cgroup state should be revisited here to cover empty leaf cgroups 210 : : * and cgroups which descendants are already in the desired state. 211 : : */ 212 : : spin_lock_irq(&css_set_lock); 213 : 0 : if (cgrp->nr_descendants == cgrp->freezer.nr_frozen_descendants) 214 : 0 : cgroup_update_frozen(cgrp); 215 : : spin_unlock_irq(&css_set_lock); 216 : 0 : } 217 : : 218 : : /* 219 : : * Adjust the task state (freeze or unfreeze) and revisit the state of 220 : : * source and destination cgroups. 221 : : */ 222 : 3 : void cgroup_freezer_migrate_task(struct task_struct *task, 223 : : struct cgroup *src, struct cgroup *dst) 224 : : { 225 : : lockdep_assert_held(&css_set_lock); 226 : : 227 : : /* 228 : : * Kernel threads are not supposed to be frozen at all. 229 : : */ 230 : 3 : if (task->flags & PF_KTHREAD) 231 : : return; 232 : : 233 : : /* 234 : : * It's not necessary to do changes if both of the src and dst cgroups 235 : : * are not freezing and task is not frozen. 236 : : */ 237 : 3 : if (!test_bit(CGRP_FREEZE, &src->flags) && 238 : 3 : !test_bit(CGRP_FREEZE, &dst->flags) && 239 : 3 : !task->frozen) 240 : : return; 241 : : 242 : : /* 243 : : * Adjust counters of freezing and frozen tasks. 244 : : * Note, that if the task is frozen, but the destination cgroup is not 245 : : * frozen, we bump both counters to keep them balanced. 246 : : */ 247 : 0 : if (task->frozen) { 248 : : cgroup_inc_frozen_cnt(dst); 249 : 0 : cgroup_dec_frozen_cnt(src); 250 : : } 251 : 0 : cgroup_update_frozen(dst); 252 : 0 : cgroup_update_frozen(src); 253 : : 254 : : /* 255 : : * Force the task to the desired state. 256 : : */ 257 : 0 : cgroup_freeze_task(task, test_bit(CGRP_FREEZE, &dst->flags)); 258 : : } 259 : : 260 : 0 : void cgroup_freeze(struct cgroup *cgrp, bool freeze) 261 : : { 262 : : struct cgroup_subsys_state *css; 263 : : struct cgroup *dsct; 264 : : bool applied = false; 265 : : 266 : : lockdep_assert_held(&cgroup_mutex); 267 : : 268 : : /* 269 : : * Nothing changed? Just exit. 270 : : */ 271 : 0 : if (cgrp->freezer.freeze == freeze) 272 : 0 : return; 273 : : 274 : 0 : cgrp->freezer.freeze = freeze; 275 : : 276 : : /* 277 : : * Propagate changes downwards the cgroup tree. 278 : : */ 279 : 0 : css_for_each_descendant_pre(css, &cgrp->self) { 280 : 0 : dsct = css->cgroup; 281 : : 282 : 0 : if (cgroup_is_dead(dsct)) 283 : 0 : continue; 284 : : 285 : 0 : if (freeze) { 286 : 0 : dsct->freezer.e_freeze++; 287 : : /* 288 : : * Already frozen because of ancestor's settings? 289 : : */ 290 : 0 : if (dsct->freezer.e_freeze > 1) 291 : 0 : continue; 292 : : } else { 293 : 0 : dsct->freezer.e_freeze--; 294 : : /* 295 : : * Still frozen because of ancestor's settings? 296 : : */ 297 : 0 : if (dsct->freezer.e_freeze > 0) 298 : 0 : continue; 299 : : 300 : 0 : WARN_ON_ONCE(dsct->freezer.e_freeze < 0); 301 : : } 302 : : 303 : : /* 304 : : * Do change actual state: freeze or unfreeze. 305 : : */ 306 : 0 : cgroup_do_freeze(dsct, freeze); 307 : : applied = true; 308 : : } 309 : : 310 : : /* 311 : : * Even if the actual state hasn't changed, let's notify a user. 312 : : * The state can be enforced by an ancestor cgroup: the cgroup 313 : : * can already be in the desired state or it can be locked in the 314 : : * opposite state, so that the transition will never happen. 315 : : * In both cases it's better to notify a user, that there is 316 : : * nothing to wait for. 317 : : */ 318 : 0 : if (!applied) { 319 : 0 : TRACE_CGROUP_PATH(notify_frozen, cgrp, 320 : : test_bit(CGRP_FROZEN, &cgrp->flags)); 321 : 0 : cgroup_file_notify(&cgrp->events_file); 322 : : } 323 : : }