Skip to content

Commit 907860e

Browse files
kiryltorvalds
authored andcommitted
cgroups: make cftype.unregister_event() void-returning
Since we are unable to handle an error returned by cftype.unregister_event() properly, let's make the callback void-returning. mem_cgroup_unregister_event() has been rewritten to be a "never fail" function. On mem_cgroup_usage_register_event() we save old buffer for thresholds array and reuse it in mem_cgroup_usage_unregister_event() to avoid allocation. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Phil Carmody <ext-phil.2.carmody@nokia.com> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Cc: Paul Menage <menage@google.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent ac39cf8 commit 907860e

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed

include/linux/cgroup.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ struct cftype {
397397
* This callback must be implemented, if you want provide
398398
* notification functionality.
399399
*/
400-
int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft,
400+
void (*unregister_event)(struct cgroup *cgrp, struct cftype *cft,
401401
struct eventfd_ctx *eventfd);
402402
};
403403

kernel/cgroup.c

-1
Original file line numberDiff line numberDiff line change
@@ -2994,7 +2994,6 @@ static void cgroup_event_remove(struct work_struct *work)
29942994
remove);
29952995
struct cgroup *cgrp = event->cgrp;
29962996

2997-
/* TODO: check return code */
29982997
event->cft->unregister_event(cgrp, event->cft, event->eventfd);
29992998

30002999
eventfd_ctx_put(event->eventfd);

mm/memcontrol.c

+41-24
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,19 @@ struct mem_cgroup {
226226
/* thresholds for memory usage. RCU-protected */
227227
struct mem_cgroup_threshold_ary *thresholds;
228228

229+
/*
230+
* Preallocated buffer to be used in mem_cgroup_unregister_event()
231+
* to make it "never fail".
232+
* It must be able to store at least thresholds->size - 1 entries.
233+
*/
234+
struct mem_cgroup_threshold_ary *__thresholds;
235+
229236
/* thresholds for mem+swap usage. RCU-protected */
230237
struct mem_cgroup_threshold_ary *memsw_thresholds;
231238

239+
/* the same as __thresholds, but for memsw_thresholds */
240+
struct mem_cgroup_threshold_ary *__memsw_thresholds;
241+
232242
/* For oom notifier event fd */
233243
struct list_head oom_notify;
234244

@@ -3604,25 +3614,35 @@ static int mem_cgroup_usage_register_event(struct cgroup *cgrp,
36043614
else
36053615
rcu_assign_pointer(memcg->memsw_thresholds, thresholds_new);
36063616

3607-
/* To be sure that nobody uses thresholds before freeing it */
3617+
/* To be sure that nobody uses thresholds */
36083618
synchronize_rcu();
36093619

3610-
kfree(thresholds);
3620+
/*
3621+
* Free old preallocated buffer and use thresholds as new
3622+
* preallocated buffer.
3623+
*/
3624+
if (type == _MEM) {
3625+
kfree(memcg->__thresholds);
3626+
memcg->__thresholds = thresholds;
3627+
} else {
3628+
kfree(memcg->__memsw_thresholds);
3629+
memcg->__memsw_thresholds = thresholds;
3630+
}
36113631
unlock:
36123632
mutex_unlock(&memcg->thresholds_lock);
36133633

36143634
return ret;
36153635
}
36163636

3617-
static int mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
3637+
static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
36183638
struct cftype *cft, struct eventfd_ctx *eventfd)
36193639
{
36203640
struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
36213641
struct mem_cgroup_threshold_ary *thresholds, *thresholds_new;
36223642
int type = MEMFILE_TYPE(cft->private);
36233643
u64 usage;
36243644
int size = 0;
3625-
int i, j, ret = 0;
3645+
int i, j;
36263646

36273647
mutex_lock(&memcg->thresholds_lock);
36283648
if (type == _MEM)
@@ -3649,20 +3669,19 @@ static int mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
36493669
size++;
36503670
}
36513671

3672+
/* Use preallocated buffer for new array of thresholds */
3673+
if (type == _MEM)
3674+
thresholds_new = memcg->__thresholds;
3675+
else
3676+
thresholds_new = memcg->__memsw_thresholds;
3677+
36523678
/* Set thresholds array to NULL if we don't have thresholds */
36533679
if (!size) {
3680+
kfree(thresholds_new);
36543681
thresholds_new = NULL;
3655-
goto assign;
3682+
goto swap_buffers;
36563683
}
36573684

3658-
/* Allocate memory for new array of thresholds */
3659-
thresholds_new = kmalloc(sizeof(*thresholds_new) +
3660-
size * sizeof(struct mem_cgroup_threshold),
3661-
GFP_KERNEL);
3662-
if (!thresholds_new) {
3663-
ret = -ENOMEM;
3664-
goto unlock;
3665-
}
36663685
thresholds_new->size = size;
36673686

36683687
/* Copy thresholds and find current threshold */
@@ -3683,20 +3702,20 @@ static int mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
36833702
j++;
36843703
}
36853704

3686-
assign:
3687-
if (type == _MEM)
3705+
swap_buffers:
3706+
/* Swap thresholds array and preallocated buffer */
3707+
if (type == _MEM) {
3708+
memcg->__thresholds = thresholds;
36883709
rcu_assign_pointer(memcg->thresholds, thresholds_new);
3689-
else
3710+
} else {
3711+
memcg->__memsw_thresholds = thresholds;
36903712
rcu_assign_pointer(memcg->memsw_thresholds, thresholds_new);
3713+
}
36913714

3692-
/* To be sure that nobody uses thresholds before freeing it */
3715+
/* To be sure that nobody uses thresholds */
36933716
synchronize_rcu();
36943717

3695-
kfree(thresholds);
3696-
unlock:
36973718
mutex_unlock(&memcg->thresholds_lock);
3698-
3699-
return ret;
37003719
}
37013720

37023721
static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
@@ -3724,7 +3743,7 @@ static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
37243743
return 0;
37253744
}
37263745

3727-
static int mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
3746+
static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
37283747
struct cftype *cft, struct eventfd_ctx *eventfd)
37293748
{
37303749
struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
@@ -3743,8 +3762,6 @@ static int mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
37433762
}
37443763

37453764
mutex_unlock(&memcg_oom_mutex);
3746-
3747-
return 0;
37483765
}
37493766

37503767
static int mem_cgroup_oom_control_read(struct cgroup *cgrp,

0 commit comments

Comments
 (0)