@@ -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+ }
36113631unlock :
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
37023721static 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
37503767static int mem_cgroup_oom_control_read (struct cgroup * cgrp ,
0 commit comments