aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup-defs.h4
-rw-r--r--include/linux/cgroup.h14
-rw-r--r--kernel/cgroup.c42
3 files changed, 35 insertions, 25 deletions
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 60d44b26276d..869fd4a3d28e 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -90,7 +90,6 @@ enum {
90 */ 90 */
91struct cgroup_file { 91struct cgroup_file {
92 /* do not access any fields from outside cgroup core */ 92 /* do not access any fields from outside cgroup core */
93 struct list_head node; /* anchored at css->files */
94 struct kernfs_node *kn; 93 struct kernfs_node *kn;
95}; 94};
96 95
@@ -134,9 +133,6 @@ struct cgroup_subsys_state {
134 */ 133 */
135 u64 serial_nr; 134 u64 serial_nr;
136 135
137 /* all cgroup_files associated with this css */
138 struct list_head files;
139
140 /* percpu_ref killing and RCU release */ 136 /* percpu_ref killing and RCU release */
141 struct rcu_head rcu_head; 137 struct rcu_head rcu_head;
142 struct work_struct destroy_work; 138 struct work_struct destroy_work;
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 22e3754f89c5..f64083030ad5 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -88,6 +88,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
88int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); 88int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
89int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); 89int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
90int cgroup_rm_cftypes(struct cftype *cfts); 90int cgroup_rm_cftypes(struct cftype *cfts);
91void cgroup_file_notify(struct cgroup_file *cfile);
91 92
92char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen); 93char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
93int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry); 94int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry);
@@ -516,19 +517,6 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
516 pr_cont_kernfs_path(cgrp->kn); 517 pr_cont_kernfs_path(cgrp->kn);
517} 518}
518 519
519/**
520 * cgroup_file_notify - generate a file modified event for a cgroup_file
521 * @cfile: target cgroup_file
522 *
523 * @cfile must have been obtained by setting cftype->file_offset.
524 */
525static inline void cgroup_file_notify(struct cgroup_file *cfile)
526{
527 /* might not have been created due to one of the CFTYPE selector flags */
528 if (cfile->kn)
529 kernfs_notify(cfile->kn);
530}
531
532#else /* !CONFIG_CGROUPS */ 520#else /* !CONFIG_CGROUPS */
533 521
534struct cgroup_subsys_state; 522struct cgroup_subsys_state;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f1603c153890..b316debadeb3 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -98,6 +98,12 @@ static DEFINE_SPINLOCK(css_set_lock);
98static DEFINE_SPINLOCK(cgroup_idr_lock); 98static DEFINE_SPINLOCK(cgroup_idr_lock);
99 99
100/* 100/*
101 * Protects cgroup_file->kn for !self csses. It synchronizes notifications
102 * against file removal/re-creation across css hiding.
103 */
104static DEFINE_SPINLOCK(cgroup_file_kn_lock);
105
106/*
101 * Protects cgroup_subsys->release_agent_path. Modifying it also requires 107 * Protects cgroup_subsys->release_agent_path. Modifying it also requires
102 * cgroup_mutex. Reading requires either cgroup_mutex or this spinlock. 108 * cgroup_mutex. Reading requires either cgroup_mutex or this spinlock.
103 */ 109 */
@@ -1393,6 +1399,16 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
1393 char name[CGROUP_FILE_NAME_MAX]; 1399 char name[CGROUP_FILE_NAME_MAX];
1394 1400
1395 lockdep_assert_held(&cgroup_mutex); 1401 lockdep_assert_held(&cgroup_mutex);
1402
1403 if (cft->file_offset) {
1404 struct cgroup_subsys_state *css = cgroup_css(cgrp, cft->ss);
1405 struct cgroup_file *cfile = (void *)css + cft->file_offset;
1406
1407 spin_lock_irq(&cgroup_file_kn_lock);
1408 cfile->kn = NULL;
1409 spin_unlock_irq(&cgroup_file_kn_lock);
1410 }
1411
1396 kernfs_remove_by_name(cgrp->kn, cgroup_file_name(cgrp, cft, name)); 1412 kernfs_remove_by_name(cgrp->kn, cgroup_file_name(cgrp, cft, name));
1397} 1413}
1398 1414
@@ -1856,7 +1872,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
1856 1872
1857 INIT_LIST_HEAD(&cgrp->self.sibling); 1873 INIT_LIST_HEAD(&cgrp->self.sibling);
1858 INIT_LIST_HEAD(&cgrp->self.children); 1874 INIT_LIST_HEAD(&cgrp->self.children);
1859 INIT_LIST_HEAD(&cgrp->self.files);
1860 INIT_LIST_HEAD(&cgrp->cset_links); 1875 INIT_LIST_HEAD(&cgrp->cset_links);
1861 INIT_LIST_HEAD(&cgrp->pidlists); 1876 INIT_LIST_HEAD(&cgrp->pidlists);
1862 mutex_init(&cgrp->pidlist_mutex); 1877 mutex_init(&cgrp->pidlist_mutex);
@@ -3313,9 +3328,9 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
3313 if (cft->file_offset) { 3328 if (cft->file_offset) {
3314 struct cgroup_file *cfile = (void *)css + cft->file_offset; 3329 struct cgroup_file *cfile = (void *)css + cft->file_offset;
3315 3330
3316 kernfs_get(kn); 3331 spin_lock_irq(&cgroup_file_kn_lock);
3317 cfile->kn = kn; 3332 cfile->kn = kn;
3318 list_add(&cfile->node, &css->files); 3333 spin_unlock_irq(&cgroup_file_kn_lock);
3319 } 3334 }
3320 3335
3321 return 0; 3336 return 0;
@@ -3553,6 +3568,22 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
3553} 3568}
3554 3569
3555/** 3570/**
3571 * cgroup_file_notify - generate a file modified event for a cgroup_file
3572 * @cfile: target cgroup_file
3573 *
3574 * @cfile must have been obtained by setting cftype->file_offset.
3575 */
3576void cgroup_file_notify(struct cgroup_file *cfile)
3577{
3578 unsigned long flags;
3579
3580 spin_lock_irqsave(&cgroup_file_kn_lock, flags);
3581 if (cfile->kn)
3582 kernfs_notify(cfile->kn);
3583 spin_unlock_irqrestore(&cgroup_file_kn_lock, flags);
3584}
3585
3586/**
3556 * cgroup_task_count - count the number of tasks in a cgroup. 3587 * cgroup_task_count - count the number of tasks in a cgroup.
3557 * @cgrp: the cgroup in question 3588 * @cgrp: the cgroup in question
3558 * 3589 *
@@ -4613,13 +4644,9 @@ static void css_free_work_fn(struct work_struct *work)
4613 container_of(work, struct cgroup_subsys_state, destroy_work); 4644 container_of(work, struct cgroup_subsys_state, destroy_work);
4614 struct cgroup_subsys *ss = css->ss; 4645 struct cgroup_subsys *ss = css->ss;
4615 struct cgroup *cgrp = css->cgroup; 4646 struct cgroup *cgrp = css->cgroup;
4616 struct cgroup_file *cfile;
4617 4647
4618 percpu_ref_exit(&css->refcnt); 4648 percpu_ref_exit(&css->refcnt);
4619 4649
4620 list_for_each_entry(cfile, &css->files, node)
4621 kernfs_put(cfile->kn);
4622
4623 if (ss) { 4650 if (ss) {
4624 /* css free path */ 4651 /* css free path */
4625 int id = css->id; 4652 int id = css->id;
@@ -4724,7 +4751,6 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
4724 css->ss = ss; 4751 css->ss = ss;
4725 INIT_LIST_HEAD(&css->sibling); 4752 INIT_LIST_HEAD(&css->sibling);
4726 INIT_LIST_HEAD(&css->children); 4753 INIT_LIST_HEAD(&css->children);
4727 INIT_LIST_HEAD(&css->files);
4728 css->serial_nr = css_serial_nr_next++; 4754 css->serial_nr = css_serial_nr_next++;
4729 4755
4730 if (cgroup_parent(cgrp)) { 4756 if (cgroup_parent(cgrp)) {