diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 7d5d1c927d9d..21bba7722350 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2690,17 +2690,20 @@ out: | |||
2690 | return error; | 2690 | return error; |
2691 | } | 2691 | } |
2692 | 2692 | ||
2693 | static int cgroup_add_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, | 2693 | static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, |
2694 | const struct cftype cfts[]) | 2694 | const struct cftype cfts[], bool is_add) |
2695 | { | 2695 | { |
2696 | const struct cftype *cft; | 2696 | const struct cftype *cft; |
2697 | int err, ret = 0; | 2697 | int err, ret = 0; |
2698 | 2698 | ||
2699 | for (cft = cfts; cft->name[0] != '\0'; cft++) { | 2699 | for (cft = cfts; cft->name[0] != '\0'; cft++) { |
2700 | err = cgroup_add_file(cgrp, subsys, cft); | 2700 | if (is_add) |
2701 | err = cgroup_add_file(cgrp, subsys, cft); | ||
2702 | else | ||
2703 | err = cgroup_rm_file(cgrp, cft); | ||
2701 | if (err) { | 2704 | if (err) { |
2702 | pr_warning("cgroup_add_files: failed to create %s, err=%d\n", | 2705 | pr_warning("cgroup_addrm_files: failed to %s %s, err=%d\n", |
2703 | cft->name, err); | 2706 | is_add ? "add" : "remove", cft->name, err); |
2704 | ret = err; | 2707 | ret = err; |
2705 | } | 2708 | } |
2706 | } | 2709 | } |
@@ -2724,7 +2727,7 @@ static void cgroup_cfts_prepare(void) | |||
2724 | } | 2727 | } |
2725 | 2728 | ||
2726 | static void cgroup_cfts_commit(struct cgroup_subsys *ss, | 2729 | static void cgroup_cfts_commit(struct cgroup_subsys *ss, |
2727 | const struct cftype *cfts) | 2730 | const struct cftype *cfts, bool is_add) |
2728 | __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex) | 2731 | __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex) |
2729 | { | 2732 | { |
2730 | LIST_HEAD(pending); | 2733 | LIST_HEAD(pending); |
@@ -2750,7 +2753,7 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss, | |||
2750 | mutex_lock(&inode->i_mutex); | 2753 | mutex_lock(&inode->i_mutex); |
2751 | mutex_lock(&cgroup_mutex); | 2754 | mutex_lock(&cgroup_mutex); |
2752 | if (!cgroup_is_removed(cgrp)) | 2755 | if (!cgroup_is_removed(cgrp)) |
2753 | cgroup_add_files(cgrp, ss, cfts); | 2756 | cgroup_addrm_files(cgrp, ss, cfts, is_add); |
2754 | mutex_unlock(&cgroup_mutex); | 2757 | mutex_unlock(&cgroup_mutex); |
2755 | mutex_unlock(&inode->i_mutex); | 2758 | mutex_unlock(&inode->i_mutex); |
2756 | 2759 | ||
@@ -2786,13 +2789,44 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts) | |||
2786 | cgroup_cfts_prepare(); | 2789 | cgroup_cfts_prepare(); |
2787 | set->cfts = cfts; | 2790 | set->cfts = cfts; |
2788 | list_add_tail(&set->node, &ss->cftsets); | 2791 | list_add_tail(&set->node, &ss->cftsets); |
2789 | cgroup_cfts_commit(ss, cfts); | 2792 | cgroup_cfts_commit(ss, cfts, true); |
2790 | 2793 | ||
2791 | return 0; | 2794 | return 0; |
2792 | } | 2795 | } |
2793 | EXPORT_SYMBOL_GPL(cgroup_add_cftypes); | 2796 | EXPORT_SYMBOL_GPL(cgroup_add_cftypes); |
2794 | 2797 | ||
2795 | /** | 2798 | /** |
2799 | * cgroup_rm_cftypes - remove an array of cftypes from a subsystem | ||
2800 | * @ss: target cgroup subsystem | ||
2801 | * @cfts: zero-length name terminated array of cftypes | ||
2802 | * | ||
2803 | * Unregister @cfts from @ss. Files described by @cfts are removed from | ||
2804 | * all existing cgroups to which @ss is attached and all future cgroups | ||
2805 | * won't have them either. This function can be called anytime whether @ss | ||
2806 | * is attached or not. | ||
2807 | * | ||
2808 | * Returns 0 on successful unregistration, -ENOENT if @cfts is not | ||
2809 | * registered with @ss. | ||
2810 | */ | ||
2811 | int cgroup_rm_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts) | ||
2812 | { | ||
2813 | struct cftype_set *set; | ||
2814 | |||
2815 | cgroup_cfts_prepare(); | ||
2816 | |||
2817 | list_for_each_entry(set, &ss->cftsets, node) { | ||
2818 | if (set->cfts == cfts) { | ||
2819 | list_del_init(&set->node); | ||
2820 | cgroup_cfts_commit(ss, cfts, false); | ||
2821 | return 0; | ||
2822 | } | ||
2823 | } | ||
2824 | |||
2825 | cgroup_cfts_commit(ss, NULL, false); | ||
2826 | return -ENOENT; | ||
2827 | } | ||
2828 | |||
2829 | /** | ||
2796 | * cgroup_task_count - count the number of tasks in a cgroup. | 2830 | * cgroup_task_count - count the number of tasks in a cgroup. |
2797 | * @cgrp: the cgroup in question | 2831 | * @cgrp: the cgroup in question |
2798 | * | 2832 | * |
@@ -3784,7 +3818,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp) | |||
3784 | int err; | 3818 | int err; |
3785 | struct cgroup_subsys *ss; | 3819 | struct cgroup_subsys *ss; |
3786 | 3820 | ||
3787 | err = cgroup_add_files(cgrp, NULL, files); | 3821 | err = cgroup_addrm_files(cgrp, NULL, files, true); |
3788 | if (err < 0) | 3822 | if (err < 0) |
3789 | return err; | 3823 | return err; |
3790 | 3824 | ||
@@ -3796,7 +3830,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp) | |||
3796 | return err; | 3830 | return err; |
3797 | 3831 | ||
3798 | list_for_each_entry(set, &ss->cftsets, node) | 3832 | list_for_each_entry(set, &ss->cftsets, node) |
3799 | cgroup_add_files(cgrp, ss, set->cfts); | 3833 | cgroup_addrm_files(cgrp, ss, set->cfts, true); |
3800 | } | 3834 | } |
3801 | 3835 | ||
3802 | /* This cgroup is ready now */ | 3836 | /* This cgroup is ready now */ |