@@ -4082,6 +4082,24 @@ static void mem_cgroup_id_get(struct mem_cgroup *memcg)
4082
4082
atomic_inc (& memcg -> id .ref );
4083
4083
}
4084
4084
4085
+ static struct mem_cgroup * mem_cgroup_id_get_online (struct mem_cgroup * memcg )
4086
+ {
4087
+ while (!atomic_inc_not_zero (& memcg -> id .ref )) {
4088
+ /*
4089
+ * The root cgroup cannot be destroyed, so it's refcount must
4090
+ * always be >= 1.
4091
+ */
4092
+ if (WARN_ON_ONCE (memcg == root_mem_cgroup )) {
4093
+ VM_BUG_ON (1 );
4094
+ break ;
4095
+ }
4096
+ memcg = parent_mem_cgroup (memcg );
4097
+ if (!memcg )
4098
+ memcg = root_mem_cgroup ;
4099
+ }
4100
+ return memcg ;
4101
+ }
4102
+
4085
4103
static void mem_cgroup_id_put (struct mem_cgroup * memcg )
4086
4104
{
4087
4105
if (atomic_dec_and_test (& memcg -> id .ref )) {
@@ -5800,7 +5818,7 @@ subsys_initcall(mem_cgroup_init);
5800
5818
*/
5801
5819
void mem_cgroup_swapout (struct page * page , swp_entry_t entry )
5802
5820
{
5803
- struct mem_cgroup * memcg ;
5821
+ struct mem_cgroup * memcg , * swap_memcg ;
5804
5822
unsigned short oldid ;
5805
5823
5806
5824
VM_BUG_ON_PAGE (PageLRU (page ), page );
@@ -5815,16 +5833,27 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
5815
5833
if (!memcg )
5816
5834
return ;
5817
5835
5818
- mem_cgroup_id_get (memcg );
5819
- oldid = swap_cgroup_record (entry , mem_cgroup_id (memcg ));
5836
+ /*
5837
+ * In case the memcg owning these pages has been offlined and doesn't
5838
+ * have an ID allocated to it anymore, charge the closest online
5839
+ * ancestor for the swap instead and transfer the memory+swap charge.
5840
+ */
5841
+ swap_memcg = mem_cgroup_id_get_online (memcg );
5842
+ oldid = swap_cgroup_record (entry , mem_cgroup_id (swap_memcg ));
5820
5843
VM_BUG_ON_PAGE (oldid , page );
5821
- mem_cgroup_swap_statistics (memcg , true);
5844
+ mem_cgroup_swap_statistics (swap_memcg , true);
5822
5845
5823
5846
page -> mem_cgroup = NULL ;
5824
5847
5825
5848
if (!mem_cgroup_is_root (memcg ))
5826
5849
page_counter_uncharge (& memcg -> memory , 1 );
5827
5850
5851
+ if (memcg != swap_memcg ) {
5852
+ if (!mem_cgroup_is_root (swap_memcg ))
5853
+ page_counter_charge (& swap_memcg -> memsw , 1 );
5854
+ page_counter_uncharge (& memcg -> memsw , 1 );
5855
+ }
5856
+
5828
5857
/*
5829
5858
* Interrupts should be disabled here because the caller holds the
5830
5859
* mapping->tree_lock lock which is taken with interrupts-off. It is
@@ -5863,11 +5892,14 @@ int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry)
5863
5892
if (!memcg )
5864
5893
return 0 ;
5865
5894
5895
+ memcg = mem_cgroup_id_get_online (memcg );
5896
+
5866
5897
if (!mem_cgroup_is_root (memcg ) &&
5867
- !page_counter_try_charge (& memcg -> swap , 1 , & counter ))
5898
+ !page_counter_try_charge (& memcg -> swap , 1 , & counter )) {
5899
+ mem_cgroup_id_put (memcg );
5868
5900
return - ENOMEM ;
5901
+ }
5869
5902
5870
- mem_cgroup_id_get (memcg );
5871
5903
oldid = swap_cgroup_record (entry , mem_cgroup_id (memcg ));
5872
5904
VM_BUG_ON_PAGE (oldid , page );
5873
5905
mem_cgroup_swap_statistics (memcg , true);
0 commit comments