Loading include/linux/cgroup.h +1 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,7 @@ struct cgroup { /* For RCU-protected deletion */ struct rcu_head rcu_head; struct work_struct free_work; /* List of events which userspace want to receive */ struct list_head event_list; Loading kernel/cgroup.c +43 −29 Original line number Diff line number Diff line Loading @@ -852,20 +852,10 @@ static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb) return inode; } static void cgroup_diput(struct dentry *dentry, struct inode *inode) static void cgroup_free_fn(struct work_struct *work) { /* is dentry a directory ? if so, kfree() associated cgroup */ if (S_ISDIR(inode->i_mode)) { struct cgroup *cgrp = dentry->d_fsdata; struct cgroup *cgrp = container_of(work, struct cgroup, free_work); struct cgroup_subsys *ss; BUG_ON(!(cgroup_is_removed(cgrp))); /* It's possible for external users to be holding css * reference counts on a cgroup; css_put() needs to * be able to access the cgroup after decrementing * the reference count in order to know if it needs to * queue the cgroup to be handled by the release * agent */ synchronize_rcu(); mutex_lock(&cgroup_mutex); /* Loading Loading @@ -893,6 +883,29 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id); kfree(cgrp); } static void cgroup_free_rcu(struct rcu_head *head) { struct cgroup *cgrp = container_of(head, struct cgroup, rcu_head); schedule_work(&cgrp->free_work); } static void cgroup_diput(struct dentry *dentry, struct inode *inode) { /* is dentry a directory ? if so, kfree() associated cgroup */ if (S_ISDIR(inode->i_mode)) { struct cgroup *cgrp = dentry->d_fsdata; BUG_ON(!(cgroup_is_removed(cgrp))); /* It's possible for external users to be holding css * reference counts on a cgroup; css_put() needs to * be able to access the cgroup after decrementing * the reference count in order to know if it needs to * queue the cgroup to be handled by the release * agent */ call_rcu(&cgrp->rcu_head, cgroup_free_rcu); } else { struct cfent *cfe = __d_cfe(dentry); struct cgroup *cgrp = dentry->d_parent->d_fsdata; Loading Loading @@ -1391,6 +1404,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) INIT_LIST_HEAD(&cgrp->allcg_node); INIT_LIST_HEAD(&cgrp->release_list); INIT_LIST_HEAD(&cgrp->pidlists); INIT_WORK(&cgrp->free_work, cgroup_free_fn); mutex_init(&cgrp->pidlist_mutex); INIT_LIST_HEAD(&cgrp->event_list); spin_lock_init(&cgrp->event_list_lock); Loading Loading
include/linux/cgroup.h +1 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,7 @@ struct cgroup { /* For RCU-protected deletion */ struct rcu_head rcu_head; struct work_struct free_work; /* List of events which userspace want to receive */ struct list_head event_list; Loading
kernel/cgroup.c +43 −29 Original line number Diff line number Diff line Loading @@ -852,20 +852,10 @@ static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb) return inode; } static void cgroup_diput(struct dentry *dentry, struct inode *inode) static void cgroup_free_fn(struct work_struct *work) { /* is dentry a directory ? if so, kfree() associated cgroup */ if (S_ISDIR(inode->i_mode)) { struct cgroup *cgrp = dentry->d_fsdata; struct cgroup *cgrp = container_of(work, struct cgroup, free_work); struct cgroup_subsys *ss; BUG_ON(!(cgroup_is_removed(cgrp))); /* It's possible for external users to be holding css * reference counts on a cgroup; css_put() needs to * be able to access the cgroup after decrementing * the reference count in order to know if it needs to * queue the cgroup to be handled by the release * agent */ synchronize_rcu(); mutex_lock(&cgroup_mutex); /* Loading Loading @@ -893,6 +883,29 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id); kfree(cgrp); } static void cgroup_free_rcu(struct rcu_head *head) { struct cgroup *cgrp = container_of(head, struct cgroup, rcu_head); schedule_work(&cgrp->free_work); } static void cgroup_diput(struct dentry *dentry, struct inode *inode) { /* is dentry a directory ? if so, kfree() associated cgroup */ if (S_ISDIR(inode->i_mode)) { struct cgroup *cgrp = dentry->d_fsdata; BUG_ON(!(cgroup_is_removed(cgrp))); /* It's possible for external users to be holding css * reference counts on a cgroup; css_put() needs to * be able to access the cgroup after decrementing * the reference count in order to know if it needs to * queue the cgroup to be handled by the release * agent */ call_rcu(&cgrp->rcu_head, cgroup_free_rcu); } else { struct cfent *cfe = __d_cfe(dentry); struct cgroup *cgrp = dentry->d_parent->d_fsdata; Loading Loading @@ -1391,6 +1404,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) INIT_LIST_HEAD(&cgrp->allcg_node); INIT_LIST_HEAD(&cgrp->release_list); INIT_LIST_HEAD(&cgrp->pidlists); INIT_WORK(&cgrp->free_work, cgroup_free_fn); mutex_init(&cgrp->pidlist_mutex); INIT_LIST_HEAD(&cgrp->event_list); spin_lock_init(&cgrp->event_list_lock); Loading