@@ -226,9 +226,19 @@ struct mem_cgroup {
226
226
/* thresholds for memory usage. RCU-protected */
227
227
struct mem_cgroup_threshold_ary * thresholds ;
228
228
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
+
229
236
/* thresholds for mem+swap usage. RCU-protected */
230
237
struct mem_cgroup_threshold_ary * memsw_thresholds ;
231
238
239
+ /* the same as __thresholds, but for memsw_thresholds */
240
+ struct mem_cgroup_threshold_ary * __memsw_thresholds ;
241
+
232
242
/* For oom notifier event fd */
233
243
struct list_head oom_notify ;
234
244
@@ -3604,25 +3614,35 @@ static int mem_cgroup_usage_register_event(struct cgroup *cgrp,
3604
3614
else
3605
3615
rcu_assign_pointer (memcg -> memsw_thresholds , thresholds_new );
3606
3616
3607
- /* To be sure that nobody uses thresholds before freeing it */
3617
+ /* To be sure that nobody uses thresholds */
3608
3618
synchronize_rcu ();
3609
3619
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
+ }
3611
3631
unlock :
3612
3632
mutex_unlock (& memcg -> thresholds_lock );
3613
3633
3614
3634
return ret ;
3615
3635
}
3616
3636
3617
- static int mem_cgroup_usage_unregister_event (struct cgroup * cgrp ,
3637
+ static void mem_cgroup_usage_unregister_event (struct cgroup * cgrp ,
3618
3638
struct cftype * cft , struct eventfd_ctx * eventfd )
3619
3639
{
3620
3640
struct mem_cgroup * memcg = mem_cgroup_from_cont (cgrp );
3621
3641
struct mem_cgroup_threshold_ary * thresholds , * thresholds_new ;
3622
3642
int type = MEMFILE_TYPE (cft -> private );
3623
3643
u64 usage ;
3624
3644
int size = 0 ;
3625
- int i , j , ret = 0 ;
3645
+ int i , j ;
3626
3646
3627
3647
mutex_lock (& memcg -> thresholds_lock );
3628
3648
if (type == _MEM )
@@ -3649,20 +3669,19 @@ static int mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
3649
3669
size ++ ;
3650
3670
}
3651
3671
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
+
3652
3678
/* Set thresholds array to NULL if we don't have thresholds */
3653
3679
if (!size ) {
3680
+ kfree (thresholds_new );
3654
3681
thresholds_new = NULL ;
3655
- goto assign ;
3682
+ goto swap_buffers ;
3656
3683
}
3657
3684
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
- }
3666
3685
thresholds_new -> size = size ;
3667
3686
3668
3687
/* Copy thresholds and find current threshold */
@@ -3683,20 +3702,20 @@ static int mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
3683
3702
j ++ ;
3684
3703
}
3685
3704
3686
- assign :
3687
- if (type == _MEM )
3705
+ swap_buffers :
3706
+ /* Swap thresholds array and preallocated buffer */
3707
+ if (type == _MEM ) {
3708
+ memcg -> __thresholds = thresholds ;
3688
3709
rcu_assign_pointer (memcg -> thresholds , thresholds_new );
3689
- else
3710
+ } else {
3711
+ memcg -> __memsw_thresholds = thresholds ;
3690
3712
rcu_assign_pointer (memcg -> memsw_thresholds , thresholds_new );
3713
+ }
3691
3714
3692
- /* To be sure that nobody uses thresholds before freeing it */
3715
+ /* To be sure that nobody uses thresholds */
3693
3716
synchronize_rcu ();
3694
3717
3695
- kfree (thresholds );
3696
- unlock :
3697
3718
mutex_unlock (& memcg -> thresholds_lock );
3698
-
3699
- return ret ;
3700
3719
}
3701
3720
3702
3721
static int mem_cgroup_oom_register_event (struct cgroup * cgrp ,
@@ -3724,7 +3743,7 @@ static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
3724
3743
return 0 ;
3725
3744
}
3726
3745
3727
- static int mem_cgroup_oom_unregister_event (struct cgroup * cgrp ,
3746
+ static void mem_cgroup_oom_unregister_event (struct cgroup * cgrp ,
3728
3747
struct cftype * cft , struct eventfd_ctx * eventfd )
3729
3748
{
3730
3749
struct mem_cgroup * mem = mem_cgroup_from_cont (cgrp );
@@ -3743,8 +3762,6 @@ static int mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
3743
3762
}
3744
3763
3745
3764
mutex_unlock (& memcg_oom_mutex );
3746
-
3747
- return 0 ;
3748
3765
}
3749
3766
3750
3767
static int mem_cgroup_oom_control_read (struct cgroup * cgrp ,
0 commit comments