diff options
-rw-r--r-- | include/linux/cgroup-defs.h | 4 | ||||
-rw-r--r-- | include/linux/cgroup.h | 14 | ||||
-rw-r--r-- | kernel/cgroup.c | 42 |
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 | */ |
91 | struct cgroup_file { | 91 | struct 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); | |||
88 | int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); | 88 | int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); |
89 | int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); | 89 | int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); |
90 | int cgroup_rm_cftypes(struct cftype *cfts); | 90 | int cgroup_rm_cftypes(struct cftype *cfts); |
91 | void cgroup_file_notify(struct cgroup_file *cfile); | ||
91 | 92 | ||
92 | char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen); | 93 | char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen); |
93 | int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry); | 94 | int 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 | */ | ||
525 | static 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 | ||
534 | struct cgroup_subsys_state; | 522 | struct 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); | |||
98 | static DEFINE_SPINLOCK(cgroup_idr_lock); | 98 | static 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 | */ | ||
104 | static 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 | */ | ||
3576 | void 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)) { |