/* * Generic process-grouping system. * * Based originally on the cpuset system, extracted by Paul Menage * Copyright (C) 2006 Google, Inc * * Notifications support * Copyright (C) 2009 Nokia Corporation * Author: Kirill A. Shutemov * * Copyright notices from the original cpuset code: * -------------------------------------------------- * Copyright (C) 2003 BULL SA. * Copyright (C) 2004-2006 Silicon Graphics, Inc. * * Portions derived from Patrick Mochel's sysfs code. * sysfs is Copyright (c) 2001-3 Patrick Mochel * * 2003-10-10 Written by Simon Derr. * 2003-10-22 Updates by Stephen Hemminger. * 2004 May-July Rework by Paul Jackson. * --------------------------------------------------- * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the Linux * distribution for more details. */ #include <linux/cgroup.h>#include <linux/ctype.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/mm.h>#include <linux/mutex.h>#include <linux/mount.h>#include <linux/pagemap.h>#include <linux/proc_fs.h>#include <linux/rcupdate.h>#include <linux/sched.h>#include <linux/backing-dev.h>#include <linux/seq_file.h>#include <linux/slab.h>#include <linux/magic.h>#include <linux/spinlock.h>#include <linux/string.h>#include <linux/sort.h>#include <linux/kmod.h>#include <linux/module.h>#include <linux/delayacct.h>#include <linux/cgroupstats.h>#include <linux/hash.h>#include <linux/namei.h>#include <linux/pid_namespace.h>#include <linux/idr.h>#include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */#include <linux/eventfd.h>#include <linux/poll.h> #include <asm/atomic.h> static DEFINE_MUTEX(cgroup_mutex); /* * Generate an array of cgroup subsystem pointers. At boot time, this is * populated up to CGROUP_BUILTIN_SUBSYS_COUNT, and modular subsystems are * registered after that. The mutable section of this array is protected by * cgroup_mutex. */#define SUBSYS(_x) &_x ## _subsys,static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = {#include <linux/cgroup_subsys.h>}; #define MAX_CGROUP_ROOT_NAMELEN 64 /* * A cgroupfs_root represents the root of a cgroup hierarchy, * and may be associated with a superblock to form an active * hierarchy */struct cgroupfs_root { struct super_block *sb; /* * The bitmask of subsystems intended to be attached to this * hierarchy */ unsigned long subsys_bits; /* Unique id for this hierarchy. */ int hierarchy_id; /* The bitmask of subsystems currently attached to this hierarchy */ unsigned long actual_subsys_bits; /* A list running through the attached subsystems */ struct list_head subsys_list; /* The root cgroup for this hierarchy */ struct cgroup top_cgroup; /* Tracks how many cgroups are currently defined in hierarchy.*/ int number_of_cgroups; /* A list running through the active hierarchies */ struct list_head root_list; /* Hierarchy-specific flags */ unsigned long flags; /* The path to use for release notifications. */ char release_agent_path[PATH_MAX]; /* The name for this hierarchy - may be empty */ char name[MAX_CGROUP_ROOT_NAMELEN];}; /* * The "rootnode" hierarchy is the "dummy hierarchy", reserved for the * subsystems that are otherwise unattached - it never has more than a * single cgroup, and all tasks are part of that cgroup. */static struct cgroupfs_root rootnode; /* * CSS ID -- ID per subsys's Cgroup Subsys State(CSS). used only when * cgroup_subsys->use_id != 0. */#define CSS_ID_MAX (65535)struct css_id { /* * The css to which this ID points. This pointer is set to valid value * after cgroup is populated. If cgroup is removed, this will be NULL. * This pointer is expected to be RCU-safe because destroy() * is called after synchronize_rcu(). But for safe use, css_is_removed() * css_tryget() should be used for avoiding race. */ struct cgroup_subsys_state __rcu *css; /* * ID of this css. */ unsigned short id; /* * Depth in hierarchy which this ID belongs to. */ unsigned short depth; /* * ID is freed by RCU. (and lookup routine is RCU safe.) */ struct rcu_head rcu_head; /* * Hierarchy of CSS ID belongs to. */ unsigned short stack[0]; /* Array of Length (depth+1) */}; /* * cgroup_event represents events which userspace want to recieve. */struct cgroup_event { /* * Cgroup which the event belongs to. */ struct cgroup *cgrp; /* * Control file which the event associated. */ struct cftype *cft; /* * eventfd to signal userspace about the event. */ struct eventfd_ctx *eventfd; /* * Each of these stored in a list by the cgroup. */ struct list_head list; /* * All fields below needed to unregister event when * userspace closes eventfd. */ poll_table pt; wait_queue_head_t *wqh; wait_queue_t wait; struct work_struct remove;}; /* The list of hierarchy roots */ static LIST_HEAD(roots);static int root_count; static DEFINE_IDA(hierarchy_ida);static int next_hierarchy_id;static DEFINE_SPINLOCK(hierarchy_id_lock); /* dummytop is a shorthand for the dummy hierarchy's top cgroup */#define dummytop (&rootnode.top_cgroup) /* This flag indicates whether tasks in the fork and exit paths should * check for fork/exit handlers to call. This avoids us having to do * extra work in the fork/exit path if none of the subsystems need to * be called. */static int need_forkexit_callback __read_mostly; #ifdef CONFIG_PROVE_LOCKINGint cgroup_lock_is_held(void){ return lockdep_is_held(&cgroup_mutex);}#else /* #ifdef CONFIG_PROVE_LOCKING */int cgroup_lock_is_held(void){ return mutex_is_locked(&cgroup_mutex);}#endif /* #else #ifdef CONFIG_PROVE_LOCKING */ EXPORT_SYMBOL_GPL(cgroup_lock_is_held); /* convenient tests for these bits */inline int cgroup_is_removed(const struct cgroup *cgrp){ return test_bit(CGRP_REMOVED, &cgrp->flags);} /* bits in struct cgroupfs_root flags field */enum { ROOT_NOPREFIX, /* mounted subsystems have no named prefix */}; static int cgroup_is_releasable(const struct cgroup *cgrp){ const int bits = (1 << CGRP_RELEASABLE) | (1 << CGRP_NOTIFY_ON_RELEASE); return (cgrp->flags & bits) == bits;} static int notify_on_release(const struct cgroup *cgrp){ return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);} static int clone_children(const struct cgroup *cgrp){ return test_bit(CGRP_CLONE_CHILDREN, &cgrp->flags);} /* * for_each_subsys() allows you to iterate on each subsystem attached to * an active hierarchy */#define for_each_subsys(_root, _ss) \list_for_each_entry(_ss, &_root->subsys_list, sibling) /* for_each_active_root() allows you to iterate across the active hierarchies */#define for_each_active_root(_root) \list_for_each_entry(_root, &roots, root_list) /* the list of cgroups eligible for automatic release. Protected by * release_list_lock */static LIST_HEAD(release_list);static DEFINE_SPINLOCK(release_list_lock);static void cgroup_release_agent(struct work_struct *work);static DECLARE_WORK(release_agent_work, cgroup_release_agent);static void check_for_release(struct cgroup *cgrp); /* Link structure for associating css_set objects with cgroups */struct cg_cgroup_link { /* * List running through cg_cgroup_links associated with a * cgroup, anchored on cgroup->css_sets */ struct list_head cgrp_link_list; struct cgroup *cgrp; /* * List running through cg_cgroup_links pointing at a * single css_set object, anchored on css_set->cg_links */ struct list_head cg_link_list; struct css_set *cg;}; /* The default css_set - used by init and its children prior to any * hierarchies being mounted. It contains a pointer to the root state * for each subsystem. Also used to anchor the list of css_sets. Not * reference-counted, to improve performance when child cgroups * haven't been created. */ static struct css_set init_css_set;static struct cg_cgroup_link init_css_set_link; static int cgroup_init_idr(struct cgroup_subsys *ss, struct cgroup_subsys_state *css); /* css_set_lock protects the list of css_set objects, and the * chain of tasks off each css_set. Nests outside task->alloc_lock * due to cgroup_iter_start() */static DEFINE_RWLOCK(css_set_lock);static int css_set_count; /* * hash table for cgroup groups. This improves the performance to find * an existing css_set. This hash doesn't (currently) take into * account cgroups in empty hierarchies. */#define CSS_SET_HASH_BITS 7#define CSS_SET_TABLE_SIZE (1 << CSS_SET_HASH_BITS)static struct hlist_head css_set_table[CSS_SET_TABLE_SIZE]; static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[]){ int i; int index; unsigned long tmp = 0UL; for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) tmp += (unsigned long)css[i]; tmp = (tmp >> 16) ^ tmp; index = hash_long(tmp, CSS_SET_HASH_BITS); return &css_set_table[index];} static void free_css_set_rcu(struct rcu_head *obj){ struct css_set *cg = container_of(obj, struct css_set, rcu_head); kfree(cg);} /* We don't maintain the lists running through each css_set to its * task until after the first call to cgroup_iter_start(). This * reduces the fork()/exit() overhead for people who have cgroups * compiled into their kernel but not actually in use */static int use_task_css_set_links __read_mostly; static void __put_css_set(struct css_set *cg, int taskexit){ struct cg_cgroup_link *link; struct cg_cgroup_link *saved_link; /* * Ensure that the refcount doesn't hit zero while any readers * can see it. Similar to atomic_dec_and_lock(), but for an * rwlock */ if (atomic_add_unless(&cg->refcount, -1, 1)) return; write_lock(&css_set_lock); if (!atomic_dec_and_test(&cg->refcount)) { write_unlock(&css_set_lock); return; } /* This css_set is dead. unlink it and release cgroup refcounts */ hlist_del(&cg->hlist); css_set_count--; list_for_each_entry_safe(link, saved_link, &cg->cg_links, cg_link_list) { struct cgroup *cgrp = link->cgrp; list_del(&link->cg_link_list); list_del(&link->cgrp_link_list); if (atomic_dec_and_test(&cgrp->count) && notify_on_release(cgrp)) { if (taskexit) set_bit(CGRP_RELEASABLE, &cgrp->flags); check_for_release(cgrp); } kfree(link); } write_unlock(&css_set_lock); call_rcu(&cg->rcu_head, free_css_set_rcu);} /* * refcounted get/put for css_set objects */static inline void get_css_set(struct css_set *cg){ atomic_inc(&cg->refcount);} static inline void put_css_set(struct css_set *cg){ __put_css_set(cg, 0);} static inline void put_css_set_taskexit(struct css_set *cg){ __put_css_set(cg, 1);} /* * compare_css_sets - helper function for find_existing_css_set(). * @cg: candidate css_set being tested * @old_cg: existing css_set for a task * @new_cgrp: cgroup that's being entered by the task * @template: desired set of css pointers in css_set (pre-calculated) * * Returns true if "cg" matches "old_cg" except for the hierarchy * which "new_cgrp" belongs to, for which it should match "new_cgrp". */static bool compare_css_sets(struct css_set *cg, struct css_set *old_cg, struct cgroup *new_cgrp, struct cgroup_subsys_state *template[]){ struct list_head *l1, *l2; if (memcmp(template, cg->subsys, sizeof(cg->subsys))) { /* Not all subsystems matched */ return false; } /* * Compare cgroup pointers in order to distinguish between * different cgroups in heirarchies with no subsystems. We * could get by with just this check alone (and skip the * memcmp above) but on most setups the memcmp check will * avoid the need for this more expensive check on almost all * candidates. */ l1 = &cg->cg_links; l2 = &old_cg->cg_links; while (1) { struct cg_cgroup_link *cgl1, *cgl2; struct cgroup *cg1, *cg2; l1 = l1->next; l2 = l2->next; /* See if we reached the end - both lists are equal length. */ if (l1 == &cg->cg_links) { BUG_ON(l2 != &old_cg->cg_links); break; } else { BUG_ON(l2 == &old_cg->cg_links); } /* Locate the cgroups associated with these links. */ cgl1 = list_entry(l1, struct cg_cgroup_link, cg_link_list); cgl2 = list_entry(l2, struct cg_cgroup_link, cg_link_list); cg1 = cgl1->cgrp; cg2 = cgl2->cgrp; /* Hierarchies should be linked in the same order. */ BUG_ON(cg1->root != cg2->root); /* * If this hierarchy is the hierarchy of the cgroup * that's changing, then we need to check that this * css_set points to the new cgroup; if it's any other * hierarchy, then this css_set should point to the * same cgroup as the old css_set. */ if (cg1->root == new_cgrp->root) { if (cg1 != new_cgrp) return false; } else { if (cg1 != cg2) return false; } } return true;} /* * find_existing_css_set() is a helper for * find_css_set(), and checks to see whether an existing * css_set is suitable. * * oldcg: the cgroup group that we're using before the cgroup * transition * * cgrp: the cgroup that we're moving into * * template: location in which to build the desired set of subsystem * state objects for the new cgroup group */static struct css_set *find_existing_css_set( struct css_set *oldcg, struct cgroup *cgrp, struct cgroup_subsys_state *template[]){ int i; struct cgroupfs_root *root = cgrp->root; struct hlist_head *hhead; struct hlist_node *node; struct css_set *cg; /* * Build the set of subsystem state objects that we want to see in the * new css_set. while subsystems can change globally, the entries here * won't change, so no need for locking. */ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {Lines 1–500 of 4966. Load more
/* * Generic process-grouping system. * * Based originally on the cpuset system, extracted by Paul Menage * Copyright (C) 2006 Google, Inc * * Notifications support * Copyright (C) 2009 Nokia Corporation * Author: Kirill A. Shutemov * * Copyright notices from the original cpuset code: * -------------------------------------------------- * Copyright (C) 2003 BULL SA. * Copyright (C) 2004-2006 Silicon Graphics, Inc. * * Portions derived from Patrick Mochel's sysfs code. * sysfs is Copyright (c) 2001-3 Patrick Mochel * * 2003-10-10 Written by Simon Derr. * 2003-10-22 Updates by Stephen Hemminger. * 2004 May-July Rework by Paul Jackson. * --------------------------------------------------- * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the Linux * distribution for more details. */ #include <linux/cgroup.h> #include <linux/ctype.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/mm.h> #include <linux/mutex.h> #include <linux/mount.h> #include <linux/pagemap.h> #include <linux/proc_fs.h> #include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/backing-dev.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/magic.h> #include <linux/spinlock.h> #include <linux/string.h> #include <linux/sort.h> #include <linux/kmod.h> #include <linux/module.h> #include <linux/delayacct.h> #include <linux/cgroupstats.h> #include <linux/hash.h> #include <linux/namei.h> #include <linux/pid_namespace.h> #include <linux/idr.h> #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */ #include <linux/eventfd.h> #include <linux/poll.h> #include <asm/atomic.h> static DEFINE_MUTEX(cgroup_mutex); /* * Generate an array of cgroup subsystem pointers. At boot time, this is * populated up to CGROUP_BUILTIN_SUBSYS_COUNT, and modular subsystems are * registered after that. The mutable section of this array is protected by * cgroup_mutex. */ #define SUBSYS(_x) &_x ## _subsys, static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = { #include <linux/cgroup_subsys.h> }; #define MAX_CGROUP_ROOT_NAMELEN 64 /* * A cgroupfs_root represents the root of a cgroup hierarchy, * and may be associated with a superblock to form an active * hierarchy */ struct cgroupfs_root { struct super_block *sb; /* * The bitmask of subsystems intended to be attached to this * hierarchy */ unsigned long subsys_bits; /* Unique id for this hierarchy. */ int hierarchy_id; /* The bitmask of subsystems currently attached to this hierarchy */ unsigned long actual_subsys_bits; /* A list running through the attached subsystems */ struct list_head subsys_list; /* The root cgroup for this hierarchy */ struct cgroup top_cgroup; /* Tracks how many cgroups are currently defined in hierarchy.*/ int number_of_cgroups; /* A list running through the active hierarchies */ struct list_head root_list; /* Hierarchy-specific flags */ unsigned long flags; /* The path to use for release notifications. */ char release_agent_path[PATH_MAX]; /* The name for this hierarchy - may be empty */ char name[MAX_CGROUP_ROOT_NAMELEN]; }; /* * The "rootnode" hierarchy is the "dummy hierarchy", reserved for the * subsystems that are otherwise unattached - it never has more than a * single cgroup, and all tasks are part of that cgroup. */ static struct cgroupfs_root rootnode; /* * CSS ID -- ID per subsys's Cgroup Subsys State(CSS). used only when * cgroup_subsys->use_id != 0. */ #define CSS_ID_MAX (65535) struct css_id { /* * The css to which this ID points. This pointer is set to valid value * after cgroup is populated. If cgroup is removed, this will be NULL. * This pointer is expected to be RCU-safe because destroy() * is called after synchronize_rcu(). But for safe use, css_is_removed() * css_tryget() should be used for avoiding race. */ struct cgroup_subsys_state __rcu *css; /* * ID of this css. */ unsigned short id; /* * Depth in hierarchy which this ID belongs to. */ unsigned short depth; /* * ID is freed by RCU. (and lookup routine is RCU safe.) */ struct rcu_head rcu_head; /* * Hierarchy of CSS ID belongs to. */ unsigned short stack[0]; /* Array of Length (depth+1) */ }; /* * cgroup_event represents events which userspace want to recieve. */ struct cgroup_event { /* * Cgroup which the event belongs to. */ struct cgroup *cgrp; /* * Control file which the event associated. */ struct cftype *cft; /* * eventfd to signal userspace about the event. */ struct eventfd_ctx *eventfd; /* * Each of these stored in a list by the cgroup. */ struct list_head list; /* * All fields below needed to unregister event when * userspace closes eventfd. */ poll_table pt; wait_queue_head_t *wqh; wait_queue_t wait; struct work_struct remove; }; /* The list of hierarchy roots */ static LIST_HEAD(roots); static int root_count; static DEFINE_IDA(hierarchy_ida); static int next_hierarchy_id; static DEFINE_SPINLOCK(hierarchy_id_lock); /* dummytop is a shorthand for the dummy hierarchy's top cgroup */ #define dummytop (&rootnode.top_cgroup) /* This flag indicates whether tasks in the fork and exit paths should * check for fork/exit handlers to call. This avoids us having to do * extra work in the fork/exit path if none of the subsystems need to * be called. */ static int need_forkexit_callback __read_mostly; #ifdef CONFIG_PROVE_LOCKING int cgroup_lock_is_held(void) { return lockdep_is_held(&cgroup_mutex); } #else /* #ifdef CONFIG_PROVE_LOCKING */ int cgroup_lock_is_held(void) { return mutex_is_locked(&cgroup_mutex); } #endif /* #else #ifdef CONFIG_PROVE_LOCKING */ EXPORT_SYMBOL_GPL(cgroup_lock_is_held); /* convenient tests for these bits */ inline int cgroup_is_removed(const struct cgroup *cgrp) { return test_bit(CGRP_REMOVED, &cgrp->flags); } /* bits in struct cgroupfs_root flags field */ enum { ROOT_NOPREFIX, /* mounted subsystems have no named prefix */ }; static int cgroup_is_releasable(const struct cgroup *cgrp) { const int bits = (1 << CGRP_RELEASABLE) | (1 << CGRP_NOTIFY_ON_RELEASE); return (cgrp->flags & bits) == bits; } static int notify_on_release(const struct cgroup *cgrp) { return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); } static int clone_children(const struct cgroup *cgrp) { return test_bit(CGRP_CLONE_CHILDREN, &cgrp->flags); } /* * for_each_subsys() allows you to iterate on each subsystem attached to * an active hierarchy */ #define for_each_subsys(_root, _ss) \ list_for_each_entry(_ss, &_root->subsys_list, sibling) /* for_each_active_root() allows you to iterate across the active hierarchies */ #define for_each_active_root(_root) \ list_for_each_entry(_root, &roots, root_list) /* the list of cgroups eligible for automatic release. Protected by * release_list_lock */ static LIST_HEAD(release_list); static DEFINE_SPINLOCK(release_list_lock); static void cgroup_release_agent(struct work_struct *work); static DECLARE_WORK(release_agent_work, cgroup_release_agent); static void check_for_release(struct cgroup *cgrp); /* Link structure for associating css_set objects with cgroups */ struct cg_cgroup_link { /* * List running through cg_cgroup_links associated with a * cgroup, anchored on cgroup->css_sets */ struct list_head cgrp_link_list; struct cgroup *cgrp; /* * List running through cg_cgroup_links pointing at a * single css_set object, anchored on css_set->cg_links */ struct list_head cg_link_list; struct css_set *cg; }; /* The default css_set - used by init and its children prior to any * hierarchies being mounted. It contains a pointer to the root state * for each subsystem. Also used to anchor the list of css_sets. Not * reference-counted, to improve performance when child cgroups * haven't been created. */ static struct css_set init_css_set; static struct cg_cgroup_link init_css_set_link; static int cgroup_init_idr(struct cgroup_subsys *ss, struct cgroup_subsys_state *css); /* css_set_lock protects the list of css_set objects, and the * chain of tasks off each css_set. Nests outside task->alloc_lock * due to cgroup_iter_start() */ static DEFINE_RWLOCK(css_set_lock); static int css_set_count; /* * hash table for cgroup groups. This improves the performance to find * an existing css_set. This hash doesn't (currently) take into * account cgroups in empty hierarchies. */ #define CSS_SET_HASH_BITS 7 #define CSS_SET_TABLE_SIZE (1 << CSS_SET_HASH_BITS) static struct hlist_head css_set_table[CSS_SET_TABLE_SIZE]; static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[]) { int i; int index; unsigned long tmp = 0UL; for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) tmp += (unsigned long)css[i]; tmp = (tmp >> 16) ^ tmp; index = hash_long(tmp, CSS_SET_HASH_BITS); return &css_set_table[index]; } static void free_css_set_rcu(struct rcu_head *obj) { struct css_set *cg = container_of(obj, struct css_set, rcu_head); kfree(cg); } /* We don't maintain the lists running through each css_set to its * task until after the first call to cgroup_iter_start(). This * reduces the fork()/exit() overhead for people who have cgroups * compiled into their kernel but not actually in use */ static int use_task_css_set_links __read_mostly; static void __put_css_set(struct css_set *cg, int taskexit) { struct cg_cgroup_link *link; struct cg_cgroup_link *saved_link; /* * Ensure that the refcount doesn't hit zero while any readers * can see it. Similar to atomic_dec_and_lock(), but for an * rwlock */ if (atomic_add_unless(&cg->refcount, -1, 1)) return; write_lock(&css_set_lock); if (!atomic_dec_and_test(&cg->refcount)) { write_unlock(&css_set_lock); return; } /* This css_set is dead. unlink it and release cgroup refcounts */ hlist_del(&cg->hlist); css_set_count--; list_for_each_entry_safe(link, saved_link, &cg->cg_links, cg_link_list) { struct cgroup *cgrp = link->cgrp; list_del(&link->cg_link_list); list_del(&link->cgrp_link_list); if (atomic_dec_and_test(&cgrp->count) && notify_on_release(cgrp)) { if (taskexit) set_bit(CGRP_RELEASABLE, &cgrp->flags); check_for_release(cgrp); } kfree(link); } write_unlock(&css_set_lock); call_rcu(&cg->rcu_head, free_css_set_rcu); } /* * refcounted get/put for css_set objects */ static inline void get_css_set(struct css_set *cg) { atomic_inc(&cg->refcount); } static inline void put_css_set(struct css_set *cg) { __put_css_set(cg, 0); } static inline void put_css_set_taskexit(struct css_set *cg) { __put_css_set(cg, 1); } /* * compare_css_sets - helper function for find_existing_css_set(). * @cg: candidate css_set being tested * @old_cg: existing css_set for a task * @new_cgrp: cgroup that's being entered by the task * @template: desired set of css pointers in css_set (pre-calculated) * * Returns true if "cg" matches "old_cg" except for the hierarchy * which "new_cgrp" belongs to, for which it should match "new_cgrp". */ static bool compare_css_sets(struct css_set *cg, struct css_set *old_cg, struct cgroup *new_cgrp, struct cgroup_subsys_state *template[]) { struct list_head *l1, *l2; if (memcmp(template, cg->subsys, sizeof(cg->subsys))) { /* Not all subsystems matched */ return false; } /* * Compare cgroup pointers in order to distinguish between * different cgroups in heirarchies with no subsystems. We * could get by with just this check alone (and skip the * memcmp above) but on most setups the memcmp check will * avoid the need for this more expensive check on almost all * candidates. */ l1 = &cg->cg_links; l2 = &old_cg->cg_links; while (1) { struct cg_cgroup_link *cgl1, *cgl2; struct cgroup *cg1, *cg2; l1 = l1->next; l2 = l2->next; /* See if we reached the end - both lists are equal length. */ if (l1 == &cg->cg_links) { BUG_ON(l2 != &old_cg->cg_links); break; } else { BUG_ON(l2 == &old_cg->cg_links); } /* Locate the cgroups associated with these links. */ cgl1 = list_entry(l1, struct cg_cgroup_link, cg_link_list); cgl2 = list_entry(l2, struct cg_cgroup_link, cg_link_list); cg1 = cgl1->cgrp; cg2 = cgl2->cgrp; /* Hierarchies should be linked in the same order. */ BUG_ON(cg1->root != cg2->root); /* * If this hierarchy is the hierarchy of the cgroup * that's changing, then we need to check that this * css_set points to the new cgroup; if it's any other * hierarchy, then this css_set should point to the * same cgroup as the old css_set. */ if (cg1->root == new_cgrp->root) { if (cg1 != new_cgrp) return false; } else { if (cg1 != cg2) return false; } } return true; } /* * find_existing_css_set() is a helper for * find_css_set(), and checks to see whether an existing * css_set is suitable. * * oldcg: the cgroup group that we're using before the cgroup * transition * * cgrp: the cgroup that we're moving into * * template: location in which to build the desired set of subsystem * state objects for the new cgroup group */ static struct css_set *find_existing_css_set( struct css_set *oldcg, struct cgroup *cgrp, struct cgroup_subsys_state *template[]) { int i; struct cgroupfs_root *root = cgrp->root; struct hlist_head *hhead; struct hlist_node *node; struct css_set *cg; /* * Build the set of subsystem state objects that we want to see in the * new css_set. while subsystems can change globally, the entries here * won't change, so no need for locking. */ for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {