Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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  * Propagate the cgroup frozen state upwards by the cgroup tree.
0013  */
0014 static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
0015 {
0016     int desc = 1;
0017 
0018     /*
0019      * If the new state is frozen, some freezing ancestor cgroups may change
0020      * their state too, depending on if all their descendants are frozen.
0021      *
0022      * Otherwise, all ancestor cgroups are forced into the non-frozen state.
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  * Revisit the cgroup frozen state.
0050  * Checks if the cgroup is really frozen and perform all state transitions.
0051  */
0052 void cgroup_update_frozen(struct cgroup *cgrp)
0053 {
0054     bool frozen;
0055 
0056     lockdep_assert_held(&css_set_lock);
0057 
0058     /*
0059      * If the cgroup has to be frozen (CGRP_FREEZE bit set),
0060      * and all tasks are frozen and/or stopped, let's consider
0061      * the cgroup frozen. Otherwise it's not frozen.
0062      */
0063     frozen = test_bit(CGRP_FREEZE, &cgrp->flags) &&
0064         cgrp->freezer.nr_frozen_tasks == __cgroup_task_count(cgrp);
0065 
0066     if (frozen) {
0067         /* Already there? */
0068         if (test_bit(CGRP_FROZEN, &cgrp->flags))
0069             return;
0070 
0071         set_bit(CGRP_FROZEN, &cgrp->flags);
0072     } else {
0073         /* Already there? */
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     /* Update the state of ancestor cgroups. */
0083     cgroup_propagate_frozen(cgrp, frozen);
0084 }
0085 
0086 /*
0087  * Increment cgroup's nr_frozen_tasks.
0088  */
0089 static void cgroup_inc_frozen_cnt(struct cgroup *cgrp)
0090 {
0091     cgrp->freezer.nr_frozen_tasks++;
0092 }
0093 
0094 /*
0095  * Decrement cgroup's nr_frozen_tasks.
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  * Enter frozen/stopped state, if not yet there. Update cgroup's counters,
0105  * and revisit the state of the cgroup, if necessary.
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  * Conditionally leave frozen/stopped state. Update cgroup's counters,
0124  * and revisit the state of the cgroup, if necessary.
0125  *
0126  * If always_leave is not set, and the cgroup is freezing,
0127  * we're racing with the cgroup freezing. In this case, we don't
0128  * drop the frozen counter to avoid a transient switch to
0129  * the unfrozen state.
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(&current->sighand->siglock);
0144         current->jobctl |= JOBCTL_TRAP_FREEZE;
0145         set_thread_flag(TIF_SIGPENDING);
0146         spin_unlock(&current->sighand->siglock);
0147     }
0148     spin_unlock_irq(&css_set_lock);
0149 }
0150 
0151 /*
0152  * Freeze or unfreeze the task by setting or clearing the JOBCTL_TRAP_FREEZE
0153  * jobctl bit.
0154  */
0155 static void cgroup_freeze_task(struct task_struct *task, bool freeze)
0156 {
0157     unsigned long flags;
0158 
0159     /* If the task is about to die, don't bother with freezing it. */
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  * Freeze or unfreeze all tasks in the given cgroup.
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          * Ignore kernel threads here. Freezing cgroups containing
0200          * kthreads isn't supported.
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      * Cgroup state should be revisited here to cover empty leaf cgroups
0210      * and cgroups which descendants are already in the desired state.
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  * Adjust the task state (freeze or unfreeze) and revisit the state of
0220  * source and destination cgroups.
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      * Kernel threads are not supposed to be frozen at all.
0229      */
0230     if (task->flags & PF_KTHREAD)
0231         return;
0232 
0233     /*
0234      * It's not necessary to do changes if both of the src and dst cgroups
0235      * are not freezing and task is not frozen.
0236      */
0237     if (!test_bit(CGRP_FREEZE, &src->flags) &&
0238         !test_bit(CGRP_FREEZE, &dst->flags) &&
0239         !task->frozen)
0240         return;
0241 
0242     /*
0243      * Adjust counters of freezing and frozen tasks.
0244      * Note, that if the task is frozen, but the destination cgroup is not
0245      * frozen, we bump both counters to keep them balanced.
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      * Force the task to the desired state.
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      * Nothing changed? Just exit.
0270      */
0271     if (cgrp->freezer.freeze == freeze)
0272         return;
0273 
0274     cgrp->freezer.freeze = freeze;
0275 
0276     /*
0277      * Propagate changes downwards the cgroup tree.
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              * Already frozen because of ancestor's settings?
0289              */
0290             if (dsct->freezer.e_freeze > 1)
0291                 continue;
0292         } else {
0293             dsct->freezer.e_freeze--;
0294             /*
0295              * Still frozen because of ancestor's settings?
0296              */
0297             if (dsct->freezer.e_freeze > 0)
0298                 continue;
0299 
0300             WARN_ON_ONCE(dsct->freezer.e_freeze < 0);
0301         }
0302 
0303         /*
0304          * Do change actual state: freeze or unfreeze.
0305          */
0306         cgroup_do_freeze(dsct, freeze);
0307         applied = true;
0308     }
0309 
0310     /*
0311      * Even if the actual state hasn't changed, let's notify a user.
0312      * The state can be enforced by an ancestor cgroup: the cgroup
0313      * can already be in the desired state or it can be locked in the
0314      * opposite state, so that the transition will never happen.
0315      * In both cases it's better to notify a user, that there is
0316      * nothing to wait for.
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 }