@@ -1740,6 +1740,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
17401740 struct cgroup * dcgrp = & dst_root -> cgrp ;
17411741 struct cgroup_subsys * ss ;
17421742 int ssid , i , ret ;
1743+ u16 dfl_disable_ss_mask = 0 ;
17431744
17441745 lockdep_assert_held (& cgroup_mutex );
17451746
@@ -1756,8 +1757,28 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
17561757 /* can't move between two non-dummy roots either */
17571758 if (ss -> root != & cgrp_dfl_root && dst_root != & cgrp_dfl_root )
17581759 return - EBUSY ;
1760+
1761+ /*
1762+ * Collect ssid's that need to be disabled from default
1763+ * hierarchy.
1764+ */
1765+ if (ss -> root == & cgrp_dfl_root )
1766+ dfl_disable_ss_mask |= 1 << ssid ;
1767+
17591768 } while_each_subsys_mask ();
17601769
1770+ if (dfl_disable_ss_mask ) {
1771+ struct cgroup * scgrp = & cgrp_dfl_root .cgrp ;
1772+
1773+ /*
1774+ * Controllers from default hierarchy that need to be rebound
1775+ * are all disabled together in one go.
1776+ */
1777+ cgrp_dfl_root .subsys_mask &= ~dfl_disable_ss_mask ;
1778+ WARN_ON (cgroup_apply_control (scgrp ));
1779+ cgroup_finalize_control (scgrp , 0 );
1780+ }
1781+
17611782 do_each_subsys_mask (ss , ssid , ss_mask ) {
17621783 struct cgroup_root * src_root = ss -> root ;
17631784 struct cgroup * scgrp = & src_root -> cgrp ;
@@ -1766,10 +1787,12 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
17661787
17671788 WARN_ON (!css || cgroup_css (dcgrp , ss ));
17681789
1769- /* disable from the source */
1770- src_root -> subsys_mask &= ~(1 << ssid );
1771- WARN_ON (cgroup_apply_control (scgrp ));
1772- cgroup_finalize_control (scgrp , 0 );
1790+ if (src_root != & cgrp_dfl_root ) {
1791+ /* disable from the source */
1792+ src_root -> subsys_mask &= ~(1 << ssid );
1793+ WARN_ON (cgroup_apply_control (scgrp ));
1794+ cgroup_finalize_control (scgrp , 0 );
1795+ }
17731796
17741797 /* rebind */
17751798 RCU_INIT_POINTER (scgrp -> subsys [ssid ], NULL );
@@ -5911,17 +5934,20 @@ struct cgroup *cgroup_get_from_id(u64 id)
59115934 struct kernfs_node * kn ;
59125935 struct cgroup * cgrp = NULL ;
59135936
5914- mutex_lock (& cgroup_mutex );
59155937 kn = kernfs_find_and_get_node_by_id (cgrp_dfl_root .kf_root , id );
59165938 if (!kn )
5917- goto out_unlock ;
5939+ goto out ;
59185940
5919- cgrp = kn -> priv ;
5920- if (cgroup_is_dead (cgrp ) || !cgroup_tryget (cgrp ))
5941+ rcu_read_lock ();
5942+
5943+ cgrp = rcu_dereference (* (void __rcu __force * * )& kn -> priv );
5944+ if (cgrp && !cgroup_tryget (cgrp ))
59215945 cgrp = NULL ;
5946+
5947+ rcu_read_unlock ();
5948+
59225949 kernfs_put (kn );
5923- out_unlock :
5924- mutex_unlock (& cgroup_mutex );
5950+ out :
59255951 return cgrp ;
59265952}
59275953EXPORT_SYMBOL_GPL (cgroup_get_from_id );
@@ -6474,30 +6500,34 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss)
64746500 *
64756501 * Find the cgroup at @path on the default hierarchy, increment its
64766502 * reference count and return it. Returns pointer to the found cgroup on
6477- * success, ERR_PTR(-ENOENT) if @path doesn't exist and ERR_PTR(-ENOTDIR)
6478- * if @path points to a non-directory.
6503+ * success, ERR_PTR(-ENOENT) if @path doesn't exist or if the cgroup has already
6504+ * been released and ERR_PTR(-ENOTDIR) if @path points to a non-directory.
64796505 */
64806506struct cgroup * cgroup_get_from_path (const char * path )
64816507{
64826508 struct kernfs_node * kn ;
6483- struct cgroup * cgrp ;
6484-
6485- mutex_lock (& cgroup_mutex );
6509+ struct cgroup * cgrp = ERR_PTR (- ENOENT );
64866510
64876511 kn = kernfs_walk_and_get (cgrp_dfl_root .cgrp .kn , path );
6488- if (kn ) {
6489- if (kernfs_type (kn ) == KERNFS_DIR ) {
6490- cgrp = kn -> priv ;
6491- cgroup_get_live (cgrp );
6492- } else {
6493- cgrp = ERR_PTR (- ENOTDIR );
6494- }
6495- kernfs_put (kn );
6496- } else {
6497- cgrp = ERR_PTR (- ENOENT );
6512+ if (!kn )
6513+ goto out ;
6514+
6515+ if (kernfs_type (kn ) != KERNFS_DIR ) {
6516+ cgrp = ERR_PTR (- ENOTDIR );
6517+ goto out_kernfs ;
64986518 }
64996519
6500- mutex_unlock (& cgroup_mutex );
6520+ rcu_read_lock ();
6521+
6522+ cgrp = rcu_dereference (* (void __rcu __force * * )& kn -> priv );
6523+ if (!cgrp || !cgroup_tryget (cgrp ))
6524+ cgrp = ERR_PTR (- ENOENT );
6525+
6526+ rcu_read_unlock ();
6527+
6528+ out_kernfs :
6529+ kernfs_put (kn );
6530+ out :
65016531 return cgrp ;
65026532}
65036533EXPORT_SYMBOL_GPL (cgroup_get_from_path );
@@ -6625,44 +6655,6 @@ void cgroup_sk_free(struct sock_cgroup_data *skcd)
66256655
66266656#endif /* CONFIG_SOCK_CGROUP_DATA */
66276657
6628- #ifdef CONFIG_CGROUP_BPF
6629- int cgroup_bpf_attach (struct cgroup * cgrp ,
6630- struct bpf_prog * prog , struct bpf_prog * replace_prog ,
6631- struct bpf_cgroup_link * link ,
6632- enum bpf_attach_type type ,
6633- u32 flags )
6634- {
6635- int ret ;
6636-
6637- mutex_lock (& cgroup_mutex );
6638- ret = __cgroup_bpf_attach (cgrp , prog , replace_prog , link , type , flags );
6639- mutex_unlock (& cgroup_mutex );
6640- return ret ;
6641- }
6642-
6643- int cgroup_bpf_detach (struct cgroup * cgrp , struct bpf_prog * prog ,
6644- enum bpf_attach_type type )
6645- {
6646- int ret ;
6647-
6648- mutex_lock (& cgroup_mutex );
6649- ret = __cgroup_bpf_detach (cgrp , prog , NULL , type );
6650- mutex_unlock (& cgroup_mutex );
6651- return ret ;
6652- }
6653-
6654- int cgroup_bpf_query (struct cgroup * cgrp , const union bpf_attr * attr ,
6655- union bpf_attr __user * uattr )
6656- {
6657- int ret ;
6658-
6659- mutex_lock (& cgroup_mutex );
6660- ret = __cgroup_bpf_query (cgrp , attr , uattr );
6661- mutex_unlock (& cgroup_mutex );
6662- return ret ;
6663- }
6664- #endif /* CONFIG_CGROUP_BPF */
6665-
66666658#ifdef CONFIG_SYSFS
66676659static ssize_t show_delegatable_files (struct cftype * files , char * buf ,
66686660 ssize_t size , const char * prefix )
0 commit comments