aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-11-22 18:20:43 -0500
committerTejun Heo <tj@kernel.org>2013-11-22 18:20:43 -0500
commitfba94807837850e211f8975e1970e23e7804ff4d (patch)
treec26b1b43027424574532e3fa74ed4656e445334a /mm/memcontrol.c
parentb5557c4c3b1a38074d7001b87c2482eda3a0834a (diff)
cgroup, memcg: move cgroup->event_list[_lock] and event callbacks into memcg
cgroup_event is being moved from cgroup core to memcg and the implementation is already moved by the previous patch. This patch moves the data fields and callbacks. * cgroup->event_list[_lock] are moved to mem_cgroup. * cftype->[un]register_event() are moved to cgroup_event. This makes it impossible for individual cftype definitions to specify their event callbacks. This is worked around by simply hard-coding filename to event callback mapping in cgroup_write_event_control(). This is awkward and inflexible, which is actually desirable given that we don't want to grow more usages of this feature. * eventfd_ctx declaration is removed from cgroup.h, which makes vmpressure.h miss eventfd_ctx declaration. Include eventfd.h from vmpressure.h. v2: Use file name from dentry instead of cftype. This will allow removing all cftype handling in the function. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Acked-by: Michal Hocko <mhocko@suse.cz> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Balbir Singh <bsingharora@gmail.com>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c87
1 files changed, 60 insertions, 27 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d00368110b08..2fcacb18404b 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -249,6 +249,22 @@ struct cgroup_event {
249 */ 249 */
250 struct list_head list; 250 struct list_head list;
251 /* 251 /*
252 * register_event() callback will be used to add new userspace
253 * waiter for changes related to this event. Use eventfd_signal()
254 * on eventfd to send notification to userspace.
255 */
256 int (*register_event)(struct cgroup_subsys_state *css,
257 struct cftype *cft, struct eventfd_ctx *eventfd,
258 const char *args);
259 /*
260 * unregister_event() callback will be called when userspace closes
261 * the eventfd or on cgroup removing. This callback must be set,
262 * if you want provide notification functionality.
263 */
264 void (*unregister_event)(struct cgroup_subsys_state *css,
265 struct cftype *cft,
266 struct eventfd_ctx *eventfd);
267 /*
252 * All fields below needed to unregister event when 268 * All fields below needed to unregister event when
253 * userspace closes eventfd. 269 * userspace closes eventfd.
254 */ 270 */
@@ -362,6 +378,10 @@ struct mem_cgroup {
362 atomic_t numainfo_updating; 378 atomic_t numainfo_updating;
363#endif 379#endif
364 380
381 /* List of events which userspace want to receive */
382 struct list_head event_list;
383 spinlock_t event_list_lock;
384
365 struct mem_cgroup_per_node *nodeinfo[0]; 385 struct mem_cgroup_per_node *nodeinfo[0];
366 /* WARNING: nodeinfo must be the last member here */ 386 /* WARNING: nodeinfo must be the last member here */
367}; 387};
@@ -5992,7 +6012,7 @@ static void cgroup_event_remove(struct work_struct *work)
5992 6012
5993 remove_wait_queue(event->wqh, &event->wait); 6013 remove_wait_queue(event->wqh, &event->wait);
5994 6014
5995 event->cft->unregister_event(css, event->cft, event->eventfd); 6015 event->unregister_event(css, event->cft, event->eventfd);
5996 6016
5997 /* Notify userspace the event is going away. */ 6017 /* Notify userspace the event is going away. */
5998 eventfd_signal(event->eventfd, 1); 6018 eventfd_signal(event->eventfd, 1);
@@ -6012,7 +6032,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
6012{ 6032{
6013 struct cgroup_event *event = container_of(wait, 6033 struct cgroup_event *event = container_of(wait,
6014 struct cgroup_event, wait); 6034 struct cgroup_event, wait);
6015 struct cgroup *cgrp = event->css->cgroup; 6035 struct mem_cgroup *memcg = mem_cgroup_from_css(event->css);
6016 unsigned long flags = (unsigned long)key; 6036 unsigned long flags = (unsigned long)key;
6017 6037
6018 if (flags & POLLHUP) { 6038 if (flags & POLLHUP) {
@@ -6025,7 +6045,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
6025 * side will require wqh->lock via remove_wait_queue(), 6045 * side will require wqh->lock via remove_wait_queue(),
6026 * which we hold. 6046 * which we hold.
6027 */ 6047 */
6028 spin_lock(&cgrp->event_list_lock); 6048 spin_lock(&memcg->event_list_lock);
6029 if (!list_empty(&event->list)) { 6049 if (!list_empty(&event->list)) {
6030 list_del_init(&event->list); 6050 list_del_init(&event->list);
6031 /* 6051 /*
@@ -6034,7 +6054,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
6034 */ 6054 */
6035 schedule_work(&event->remove); 6055 schedule_work(&event->remove);
6036 } 6056 }
6037 spin_unlock(&cgrp->event_list_lock); 6057 spin_unlock(&memcg->event_list_lock);
6038 } 6058 }
6039 6059
6040 return 0; 6060 return 0;
@@ -6059,12 +6079,13 @@ static void cgroup_event_ptable_queue_proc(struct file *file,
6059static int cgroup_write_event_control(struct cgroup_subsys_state *css, 6079static int cgroup_write_event_control(struct cgroup_subsys_state *css,
6060 struct cftype *cft, const char *buffer) 6080 struct cftype *cft, const char *buffer)
6061{ 6081{
6062 struct cgroup *cgrp = css->cgroup; 6082 struct mem_cgroup *memcg = mem_cgroup_from_css(css);
6063 struct cgroup_event *event; 6083 struct cgroup_event *event;
6064 struct cgroup_subsys_state *cfile_css; 6084 struct cgroup_subsys_state *cfile_css;
6065 unsigned int efd, cfd; 6085 unsigned int efd, cfd;
6066 struct fd efile; 6086 struct fd efile;
6067 struct fd cfile; 6087 struct fd cfile;
6088 const char *name;
6068 char *endp; 6089 char *endp;
6069 int ret; 6090 int ret;
6070 6091
@@ -6119,6 +6140,31 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
6119 } 6140 }
6120 6141
6121 /* 6142 /*
6143 * Determine the event callbacks and set them in @event. This used
6144 * to be done via struct cftype but cgroup core no longer knows
6145 * about these events. The following is crude but the whole thing
6146 * is for compatibility anyway.
6147 */
6148 name = cfile.file->f_dentry->d_name.name;
6149
6150 if (!strcmp(name, "memory.usage_in_bytes")) {
6151 event->register_event = mem_cgroup_usage_register_event;
6152 event->unregister_event = mem_cgroup_usage_unregister_event;
6153 } else if (!strcmp(name, "memory.oom_control")) {
6154 event->register_event = mem_cgroup_oom_register_event;
6155 event->unregister_event = mem_cgroup_oom_unregister_event;
6156 } else if (!strcmp(name, "memory.pressure_level")) {
6157 event->register_event = vmpressure_register_event;
6158 event->unregister_event = vmpressure_unregister_event;
6159 } else if (!strcmp(name, "memory.memsw.usage_in_bytes")) {
6160 event->register_event = mem_cgroup_usage_register_event;
6161 event->unregister_event = mem_cgroup_usage_unregister_event;
6162 } else {
6163 ret = -EINVAL;
6164 goto out_put_cfile;
6165 }
6166
6167 /*
6122 * Verify @cfile should belong to @css. Also, remaining events are 6168 * Verify @cfile should belong to @css. Also, remaining events are
6123 * automatically removed on cgroup destruction but the removal is 6169 * automatically removed on cgroup destruction but the removal is
6124 * asynchronous, so take an extra ref on @css. 6170 * asynchronous, so take an extra ref on @css.
@@ -6135,21 +6181,15 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
6135 if (ret) 6181 if (ret)
6136 goto out_put_cfile; 6182 goto out_put_cfile;
6137 6183
6138 if (!event->cft->register_event || !event->cft->unregister_event) { 6184 ret = event->register_event(css, event->cft, event->eventfd, buffer);
6139 ret = -EINVAL;
6140 goto out_put_css;
6141 }
6142
6143 ret = event->cft->register_event(css, event->cft,
6144 event->eventfd, buffer);
6145 if (ret) 6185 if (ret)
6146 goto out_put_css; 6186 goto out_put_css;
6147 6187
6148 efile.file->f_op->poll(efile.file, &event->pt); 6188 efile.file->f_op->poll(efile.file, &event->pt);
6149 6189
6150 spin_lock(&cgrp->event_list_lock); 6190 spin_lock(&memcg->event_list_lock);
6151 list_add(&event->list, &cgrp->event_list); 6191 list_add(&event->list, &memcg->event_list);
6152 spin_unlock(&cgrp->event_list_lock); 6192 spin_unlock(&memcg->event_list_lock);
6153 6193
6154 fdput(cfile); 6194 fdput(cfile);
6155 fdput(efile); 6195 fdput(efile);
@@ -6175,8 +6215,6 @@ static struct cftype mem_cgroup_files[] = {
6175 .name = "usage_in_bytes", 6215 .name = "usage_in_bytes",
6176 .private = MEMFILE_PRIVATE(_MEM, RES_USAGE), 6216 .private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
6177 .read = mem_cgroup_read, 6217 .read = mem_cgroup_read,
6178 .register_event = mem_cgroup_usage_register_event,
6179 .unregister_event = mem_cgroup_usage_unregister_event,
6180 }, 6218 },
6181 { 6219 {
6182 .name = "max_usage_in_bytes", 6220 .name = "max_usage_in_bytes",
@@ -6236,14 +6274,10 @@ static struct cftype mem_cgroup_files[] = {
6236 .name = "oom_control", 6274 .name = "oom_control",
6237 .read_map = mem_cgroup_oom_control_read, 6275 .read_map = mem_cgroup_oom_control_read,
6238 .write_u64 = mem_cgroup_oom_control_write, 6276 .write_u64 = mem_cgroup_oom_control_write,
6239 .register_event = mem_cgroup_oom_register_event,
6240 .unregister_event = mem_cgroup_oom_unregister_event,
6241 .private = MEMFILE_PRIVATE(_OOM_TYPE, OOM_CONTROL), 6277 .private = MEMFILE_PRIVATE(_OOM_TYPE, OOM_CONTROL),
6242 }, 6278 },
6243 { 6279 {
6244 .name = "pressure_level", 6280 .name = "pressure_level",
6245 .register_event = vmpressure_register_event,
6246 .unregister_event = vmpressure_unregister_event,
6247 }, 6281 },
6248#ifdef CONFIG_NUMA 6282#ifdef CONFIG_NUMA
6249 { 6283 {
@@ -6291,8 +6325,6 @@ static struct cftype memsw_cgroup_files[] = {
6291 .name = "memsw.usage_in_bytes", 6325 .name = "memsw.usage_in_bytes",
6292 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE), 6326 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
6293 .read = mem_cgroup_read, 6327 .read = mem_cgroup_read,
6294 .register_event = mem_cgroup_usage_register_event,
6295 .unregister_event = mem_cgroup_usage_unregister_event,
6296 }, 6328 },
6297 { 6329 {
6298 .name = "memsw.max_usage_in_bytes", 6330 .name = "memsw.max_usage_in_bytes",
@@ -6483,6 +6515,8 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
6483 mutex_init(&memcg->thresholds_lock); 6515 mutex_init(&memcg->thresholds_lock);
6484 spin_lock_init(&memcg->move_lock); 6516 spin_lock_init(&memcg->move_lock);
6485 vmpressure_init(&memcg->vmpressure); 6517 vmpressure_init(&memcg->vmpressure);
6518 INIT_LIST_HEAD(&memcg->event_list);
6519 spin_lock_init(&memcg->event_list_lock);
6486 6520
6487 return &memcg->css; 6521 return &memcg->css;
6488 6522
@@ -6555,7 +6589,6 @@ static void mem_cgroup_invalidate_reclaim_iterators(struct mem_cgroup *memcg)
6555static void mem_cgroup_css_offline(struct cgroup_subsys_state *css) 6589static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
6556{ 6590{
6557 struct mem_cgroup *memcg = mem_cgroup_from_css(css); 6591 struct mem_cgroup *memcg = mem_cgroup_from_css(css);
6558 struct cgroup *cgrp = css->cgroup;
6559 struct cgroup_event *event, *tmp; 6592 struct cgroup_event *event, *tmp;
6560 6593
6561 /* 6594 /*
@@ -6563,12 +6596,12 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
6563 * Notify userspace about cgroup removing only after rmdir of cgroup 6596 * Notify userspace about cgroup removing only after rmdir of cgroup
6564 * directory to avoid race between userspace and kernelspace. 6597 * directory to avoid race between userspace and kernelspace.
6565 */ 6598 */
6566 spin_lock(&cgrp->event_list_lock); 6599 spin_lock(&memcg->event_list_lock);
6567 list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) { 6600 list_for_each_entry_safe(event, tmp, &memcg->event_list, list) {
6568 list_del_init(&event->list); 6601 list_del_init(&event->list);
6569 schedule_work(&event->remove); 6602 schedule_work(&event->remove);
6570 } 6603 }
6571 spin_unlock(&cgrp->event_list_lock); 6604 spin_unlock(&memcg->event_list_lock);
6572 6605
6573 kmem_cgroup_css_offline(memcg); 6606 kmem_cgroup_css_offline(memcg);
6574 6607