@@ -248,6 +248,22 @@ struct cgroup_event {
248
248
* Each of these stored in a list by the cgroup.
249
249
*/
250
250
struct list_head list ;
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 );
251
267
/*
252
268
* All fields below needed to unregister event when
253
269
* userspace closes eventfd.
@@ -362,6 +378,10 @@ struct mem_cgroup {
362
378
atomic_t numainfo_updating ;
363
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
385
struct mem_cgroup_per_node * nodeinfo [0 ];
366
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
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
6017
/* Notify userspace the event is going away. */
5998
6018
eventfd_signal (event -> eventfd , 1 );
@@ -6012,7 +6032,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
6012
6032
{
6013
6033
struct cgroup_event * event = container_of (wait ,
6014
6034
struct cgroup_event , wait );
6015
- struct cgroup * cgrp = event -> css -> cgroup ;
6035
+ struct mem_cgroup * memcg = mem_cgroup_from_css ( event -> css ) ;
6016
6036
unsigned long flags = (unsigned long )key ;
6017
6037
6018
6038
if (flags & POLLHUP ) {
@@ -6025,7 +6045,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
6025
6045
* side will require wqh->lock via remove_wait_queue(),
6026
6046
* which we hold.
6027
6047
*/
6028
- spin_lock (& cgrp -> event_list_lock );
6048
+ spin_lock (& memcg -> event_list_lock );
6029
6049
if (!list_empty (& event -> list )) {
6030
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
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
6060
return 0 ;
@@ -6059,12 +6079,13 @@ static void cgroup_event_ptable_queue_proc(struct file *file,
6059
6079
static int cgroup_write_event_control (struct cgroup_subsys_state * css ,
6060
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
6083
struct cgroup_event * event ;
6064
6084
struct cgroup_subsys_state * cfile_css ;
6065
6085
unsigned int efd , cfd ;
6066
6086
struct fd efile ;
6067
6087
struct fd cfile ;
6088
+ const char * name ;
6068
6089
char * endp ;
6069
6090
int ret ;
6070
6091
@@ -6118,6 +6139,31 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
6118
6139
goto out_put_cfile ;
6119
6140
}
6120
6141
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
+
6121
6167
/*
6122
6168
* Verify @cfile should belong to @css. Also, remaining events are
6123
6169
* automatically removed on cgroup destruction but the removal is
@@ -6135,21 +6181,15 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
6135
6181
if (ret )
6136
6182
goto out_put_cfile ;
6137
6183
6138
- if (!event -> cft -> register_event || !event -> cft -> unregister_event ) {
6139
- ret = - EINVAL ;
6140
- goto out_put_css ;
6141
- }
6142
-
6143
- ret = event -> cft -> register_event (css , event -> cft ,
6144
- event -> eventfd , buffer );
6184
+ ret = event -> register_event (css , event -> cft , event -> eventfd , buffer );
6145
6185
if (ret )
6146
6186
goto out_put_css ;
6147
6187
6148
6188
efile .file -> f_op -> poll (efile .file , & event -> pt );
6149
6189
6150
- spin_lock (& cgrp -> event_list_lock );
6151
- list_add (& event -> list , & cgrp -> event_list );
6152
- spin_unlock (& cgrp -> event_list_lock );
6190
+ spin_lock (& memcg -> event_list_lock );
6191
+ list_add (& event -> list , & memcg -> event_list );
6192
+ spin_unlock (& memcg -> event_list_lock );
6153
6193
6154
6194
fdput (cfile );
6155
6195
fdput (efile );
@@ -6175,8 +6215,6 @@ static struct cftype mem_cgroup_files[] = {
6175
6215
.name = "usage_in_bytes" ,
6176
6216
.private = MEMFILE_PRIVATE (_MEM , RES_USAGE ),
6177
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
6220
.name = "max_usage_in_bytes" ,
@@ -6236,14 +6274,10 @@ static struct cftype mem_cgroup_files[] = {
6236
6274
.name = "oom_control" ,
6237
6275
.read_map = mem_cgroup_oom_control_read ,
6238
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
6277
.private = MEMFILE_PRIVATE (_OOM_TYPE , OOM_CONTROL ),
6242
6278
},
6243
6279
{
6244
6280
.name = "pressure_level" ,
6245
- .register_event = vmpressure_register_event ,
6246
- .unregister_event = vmpressure_unregister_event ,
6247
6281
},
6248
6282
#ifdef CONFIG_NUMA
6249
6283
{
@@ -6291,8 +6325,6 @@ static struct cftype memsw_cgroup_files[] = {
6291
6325
.name = "memsw.usage_in_bytes" ,
6292
6326
.private = MEMFILE_PRIVATE (_MEMSWAP , RES_USAGE ),
6293
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
6330
.name = "memsw.max_usage_in_bytes" ,
@@ -6483,6 +6515,8 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
6483
6515
mutex_init (& memcg -> thresholds_lock );
6484
6516
spin_lock_init (& memcg -> move_lock );
6485
6517
vmpressure_init (& memcg -> vmpressure );
6518
+ INIT_LIST_HEAD (& memcg -> event_list );
6519
+ spin_lock_init (& memcg -> event_list_lock );
6486
6520
6487
6521
return & memcg -> css ;
6488
6522
@@ -6555,20 +6589,19 @@ static void mem_cgroup_invalidate_reclaim_iterators(struct mem_cgroup *memcg)
6555
6589
static void mem_cgroup_css_offline (struct cgroup_subsys_state * css )
6556
6590
{
6557
6591
struct mem_cgroup * memcg = mem_cgroup_from_css (css );
6558
- struct cgroup * cgrp = css -> cgroup ;
6559
6592
struct cgroup_event * event , * tmp ;
6560
6593
6561
6594
/*
6562
6595
* Unregister events and notify userspace.
6563
6596
* Notify userspace about cgroup removing only after rmdir of cgroup
6564
6597
* directory to avoid race between userspace and kernelspace.
6565
6598
*/
6566
- spin_lock (& cgrp -> event_list_lock );
6567
- list_for_each_entry_safe (event , tmp , & cgrp -> event_list , list ) {
6599
+ spin_lock (& memcg -> event_list_lock );
6600
+ list_for_each_entry_safe (event , tmp , & memcg -> event_list , list ) {
6568
6601
list_del_init (& event -> list );
6569
6602
schedule_work (& event -> remove );
6570
6603
}
6571
- spin_unlock (& cgrp -> event_list_lock );
6604
+ spin_unlock (& memcg -> event_list_lock );
6572
6605
6573
6606
kmem_cgroup_css_offline (memcg );
6574
6607
0 commit comments