diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 42 |
1 files changed, 34 insertions, 8 deletions
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)) { |