aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-11-22 18:32:25 -0500
committerTejun Heo <tj@kernel.org>2013-11-22 18:32:25 -0500
commitedab95103d3a1eb5e3faf977eae4ad0b5bf5669c (patch)
tree812c111f94b0ae31bf88b49e7c37a7f5ba353eef /kernel/cgroup.c
parente5fca243abae1445afbfceebda5f08462ef869d3 (diff)
parentb36824c75c7855585d6476eef2b234f6e0e68872 (diff)
cgroup: Merge branch 'memcg_event' into for-3.14
Merge v3.12 based patch series to move cgroup_event implementation to memcg into for-3.14. The following two commits cause a conflict in kernel/cgroup.c 2ff2a7d03bbe4 ("cgroup: kill css_id") 79bd9814e5ec9 ("cgroup, memcg: move cgroup_event implementation to memcg") Each patch removes a struct definition from kernel/cgroup.c. As the two are adjacent, they cause a context conflict. Easily resolved by removing both structs. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c259
1 files changed, 0 insertions, 259 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index a7b98ee35ef7..be42967f4f1a 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -56,11 +56,8 @@
56#include <linux/pid_namespace.h> 56#include <linux/pid_namespace.h>
57#include <linux/idr.h> 57#include <linux/idr.h>
58#include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */ 58#include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
59#include <linux/eventfd.h>
60#include <linux/poll.h>
61#include <linux/flex_array.h> /* used in cgroup_attach_task */ 59#include <linux/flex_array.h> /* used in cgroup_attach_task */
62#include <linux/kthread.h> 60#include <linux/kthread.h>
63#include <linux/file.h>
64 61
65#include <linux/atomic.h> 62#include <linux/atomic.h>
66 63
@@ -132,36 +129,6 @@ struct cfent {
132 struct simple_xattrs xattrs; 129 struct simple_xattrs xattrs;
133}; 130};
134 131
135/*
136 * cgroup_event represents events which userspace want to receive.
137 */
138struct cgroup_event {
139 /*
140 * css which the event belongs to.
141 */
142 struct cgroup_subsys_state *css;
143 /*
144 * Control file which the event associated.
145 */
146 struct cftype *cft;
147 /*
148 * eventfd to signal userspace about the event.
149 */
150 struct eventfd_ctx *eventfd;
151 /*
152 * Each of these stored in a list by the cgroup.
153 */
154 struct list_head list;
155 /*
156 * All fields below needed to unregister event when
157 * userspace closes eventfd.
158 */
159 poll_table pt;
160 wait_queue_head_t *wqh;
161 wait_queue_t wait;
162 struct work_struct remove;
163};
164
165/* The list of hierarchy roots */ 132/* The list of hierarchy roots */
166 133
167static LIST_HEAD(cgroup_roots); 134static LIST_HEAD(cgroup_roots);
@@ -1351,8 +1318,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
1351 INIT_LIST_HEAD(&cgrp->pidlists); 1318 INIT_LIST_HEAD(&cgrp->pidlists);
1352 mutex_init(&cgrp->pidlist_mutex); 1319 mutex_init(&cgrp->pidlist_mutex);
1353 cgrp->dummy_css.cgroup = cgrp; 1320 cgrp->dummy_css.cgroup = cgrp;
1354 INIT_LIST_HEAD(&cgrp->event_list);
1355 spin_lock_init(&cgrp->event_list_lock);
1356 simple_xattrs_init(&cgrp->xattrs); 1321 simple_xattrs_init(&cgrp->xattrs);
1357} 1322}
1358 1323
@@ -2626,16 +2591,6 @@ static const struct inode_operations cgroup_dir_inode_operations = {
2626 .removexattr = cgroup_removexattr, 2591 .removexattr = cgroup_removexattr,
2627}; 2592};
2628 2593
2629/*
2630 * Check if a file is a control file
2631 */
2632static inline struct cftype *__file_cft(struct file *file)
2633{
2634 if (file_inode(file)->i_fop != &cgroup_file_operations)
2635 return ERR_PTR(-EINVAL);
2636 return __d_cft(file->f_dentry);
2637}
2638
2639static int cgroup_create_file(struct dentry *dentry, umode_t mode, 2594static int cgroup_create_file(struct dentry *dentry, umode_t mode,
2640 struct super_block *sb) 2595 struct super_block *sb)
2641{ 2596{
@@ -3915,202 +3870,6 @@ static void cgroup_dput(struct cgroup *cgrp)
3915 deactivate_super(sb); 3870 deactivate_super(sb);
3916} 3871}
3917 3872
3918/*
3919 * Unregister event and free resources.
3920 *
3921 * Gets called from workqueue.
3922 */
3923static void cgroup_event_remove(struct work_struct *work)
3924{
3925 struct cgroup_event *event = container_of(work, struct cgroup_event,
3926 remove);
3927 struct cgroup_subsys_state *css = event->css;
3928
3929 remove_wait_queue(event->wqh, &event->wait);
3930
3931 event->cft->unregister_event(css, event->cft, event->eventfd);
3932
3933 /* Notify userspace the event is going away. */
3934 eventfd_signal(event->eventfd, 1);
3935
3936 eventfd_ctx_put(event->eventfd);
3937 kfree(event);
3938 css_put(css);
3939}
3940
3941/*
3942 * Gets called on POLLHUP on eventfd when user closes it.
3943 *
3944 * Called with wqh->lock held and interrupts disabled.
3945 */
3946static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
3947 int sync, void *key)
3948{
3949 struct cgroup_event *event = container_of(wait,
3950 struct cgroup_event, wait);
3951 struct cgroup *cgrp = event->css->cgroup;
3952 unsigned long flags = (unsigned long)key;
3953
3954 if (flags & POLLHUP) {
3955 /*
3956 * If the event has been detached at cgroup removal, we
3957 * can simply return knowing the other side will cleanup
3958 * for us.
3959 *
3960 * We can't race against event freeing since the other
3961 * side will require wqh->lock via remove_wait_queue(),
3962 * which we hold.
3963 */
3964 spin_lock(&cgrp->event_list_lock);
3965 if (!list_empty(&event->list)) {
3966 list_del_init(&event->list);
3967 /*
3968 * We are in atomic context, but cgroup_event_remove()
3969 * may sleep, so we have to call it in workqueue.
3970 */
3971 schedule_work(&event->remove);
3972 }
3973 spin_unlock(&cgrp->event_list_lock);
3974 }
3975
3976 return 0;
3977}
3978
3979static void cgroup_event_ptable_queue_proc(struct file *file,
3980 wait_queue_head_t *wqh, poll_table *pt)
3981{
3982 struct cgroup_event *event = container_of(pt,
3983 struct cgroup_event, pt);
3984
3985 event->wqh = wqh;
3986 add_wait_queue(wqh, &event->wait);
3987}
3988
3989/*
3990 * Parse input and register new cgroup event handler.
3991 *
3992 * Input must be in format '<event_fd> <control_fd> <args>'.
3993 * Interpretation of args is defined by control file implementation.
3994 */
3995static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css,
3996 struct cftype *cft, const char *buffer)
3997{
3998 struct cgroup *cgrp = dummy_css->cgroup;
3999 struct cgroup_event *event;
4000 struct cgroup_subsys_state *cfile_css;
4001 unsigned int efd, cfd;
4002 struct fd efile;
4003 struct fd cfile;
4004 char *endp;
4005 int ret;
4006
4007 efd = simple_strtoul(buffer, &endp, 10);
4008 if (*endp != ' ')
4009 return -EINVAL;
4010 buffer = endp + 1;
4011
4012 cfd = simple_strtoul(buffer, &endp, 10);
4013 if ((*endp != ' ') && (*endp != '\0'))
4014 return -EINVAL;
4015 buffer = endp + 1;
4016
4017 event = kzalloc(sizeof(*event), GFP_KERNEL);
4018 if (!event)
4019 return -ENOMEM;
4020
4021 INIT_LIST_HEAD(&event->list);
4022 init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc);
4023 init_waitqueue_func_entry(&event->wait, cgroup_event_wake);
4024 INIT_WORK(&event->remove, cgroup_event_remove);
4025
4026 efile = fdget(efd);
4027 if (!efile.file) {
4028 ret = -EBADF;
4029 goto out_kfree;
4030 }
4031
4032 event->eventfd = eventfd_ctx_fileget(efile.file);
4033 if (IS_ERR(event->eventfd)) {
4034 ret = PTR_ERR(event->eventfd);
4035 goto out_put_efile;
4036 }
4037
4038 cfile = fdget(cfd);
4039 if (!cfile.file) {
4040 ret = -EBADF;
4041 goto out_put_eventfd;
4042 }
4043
4044 /* the process need read permission on control file */
4045 /* AV: shouldn't we check that it's been opened for read instead? */
4046 ret = inode_permission(file_inode(cfile.file), MAY_READ);
4047 if (ret < 0)
4048 goto out_put_cfile;
4049
4050 event->cft = __file_cft(cfile.file);
4051 if (IS_ERR(event->cft)) {
4052 ret = PTR_ERR(event->cft);
4053 goto out_put_cfile;
4054 }
4055
4056 if (!event->cft->ss) {
4057 ret = -EBADF;
4058 goto out_put_cfile;
4059 }
4060
4061 /*
4062 * Determine the css of @cfile, verify it belongs to the same
4063 * cgroup as cgroup.event_control, and associate @event with it.
4064 * Remaining events are automatically removed on cgroup destruction
4065 * but the removal is asynchronous, so take an extra ref.
4066 */
4067 rcu_read_lock();
4068
4069 ret = -EINVAL;
4070 event->css = cgroup_css(cgrp, event->cft->ss);
4071 cfile_css = css_from_dir(cfile.file->f_dentry->d_parent, event->cft->ss);
4072 if (event->css && event->css == cfile_css && css_tryget(event->css))
4073 ret = 0;
4074
4075 rcu_read_unlock();
4076 if (ret)
4077 goto out_put_cfile;
4078
4079 if (!event->cft->register_event || !event->cft->unregister_event) {
4080 ret = -EINVAL;
4081 goto out_put_css;
4082 }
4083
4084 ret = event->cft->register_event(event->css, event->cft,
4085 event->eventfd, buffer);
4086 if (ret)
4087 goto out_put_css;
4088
4089 efile.file->f_op->poll(efile.file, &event->pt);
4090
4091 spin_lock(&cgrp->event_list_lock);
4092 list_add(&event->list, &cgrp->event_list);
4093 spin_unlock(&cgrp->event_list_lock);
4094
4095 fdput(cfile);
4096 fdput(efile);
4097
4098 return 0;
4099
4100out_put_css:
4101 css_put(event->css);
4102out_put_cfile:
4103 fdput(cfile);
4104out_put_eventfd:
4105 eventfd_ctx_put(event->eventfd);
4106out_put_efile:
4107 fdput(efile);
4108out_kfree:
4109 kfree(event);
4110
4111 return ret;
4112}
4113
4114static u64 cgroup_clone_children_read(struct cgroup_subsys_state *css, 3873static u64 cgroup_clone_children_read(struct cgroup_subsys_state *css,
4115 struct cftype *cft) 3874 struct cftype *cft)
4116{ 3875{
@@ -4136,11 +3895,6 @@ static struct cftype cgroup_base_files[] = {
4136 .mode = S_IRUGO | S_IWUSR, 3895 .mode = S_IRUGO | S_IWUSR,
4137 }, 3896 },
4138 { 3897 {
4139 .name = "cgroup.event_control",
4140 .write_string = cgroup_write_event_control,
4141 .mode = S_IWUGO,
4142 },
4143 {
4144 .name = "cgroup.clone_children", 3898 .name = "cgroup.clone_children",
4145 .flags = CFTYPE_INSANE, 3899 .flags = CFTYPE_INSANE,
4146 .read_u64 = cgroup_clone_children_read, 3900 .read_u64 = cgroup_clone_children_read,
@@ -4610,7 +4364,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4610 __releases(&cgroup_mutex) __acquires(&cgroup_mutex) 4364 __releases(&cgroup_mutex) __acquires(&cgroup_mutex)
4611{ 4365{
4612 struct dentry *d = cgrp->dentry; 4366 struct dentry *d = cgrp->dentry;
4613 struct cgroup_event *event, *tmp;
4614 struct cgroup_subsys *ss; 4367 struct cgroup_subsys *ss;
4615 struct cgroup *child; 4368 struct cgroup *child;
4616 bool empty; 4369 bool empty;
@@ -4685,18 +4438,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4685 dget(d); 4438 dget(d);
4686 cgroup_d_remove_dir(d); 4439 cgroup_d_remove_dir(d);
4687 4440
4688 /*
4689 * Unregister events and notify userspace.
4690 * Notify userspace about cgroup removing only after rmdir of cgroup
4691 * directory to avoid race between userspace and kernelspace.
4692 */
4693 spin_lock(&cgrp->event_list_lock);
4694 list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
4695 list_del_init(&event->list);
4696 schedule_work(&event->remove);
4697 }
4698 spin_unlock(&cgrp->event_list_lock);
4699
4700 return 0; 4441 return 0;
4701}; 4442};
4702 4443