@@ -210,21 +210,8 @@ static inline int shrinker_defer_size(int nr_items)
210
210
static struct shrinker_info * shrinker_info_protected (struct mem_cgroup * memcg ,
211
211
int nid )
212
212
{
213
- return srcu_dereference_check (memcg -> nodeinfo [nid ]-> shrinker_info ,
214
- & shrinker_srcu ,
215
- lockdep_is_held (& shrinker_rwsem ));
216
- }
217
-
218
- static struct shrinker_info * shrinker_info_srcu (struct mem_cgroup * memcg ,
219
- int nid )
220
- {
221
- return srcu_dereference (memcg -> nodeinfo [nid ]-> shrinker_info ,
222
- & shrinker_srcu );
223
- }
224
-
225
- static void free_shrinker_info_rcu (struct rcu_head * head )
226
- {
227
- kvfree (container_of (head , struct shrinker_info , rcu ));
213
+ return rcu_dereference_protected (memcg -> nodeinfo [nid ]-> shrinker_info ,
214
+ lockdep_is_held (& shrinker_rwsem ));
228
215
}
229
216
230
217
static int expand_one_shrinker_info (struct mem_cgroup * memcg ,
@@ -265,7 +252,7 @@ static int expand_one_shrinker_info(struct mem_cgroup *memcg,
265
252
defer_size - old_defer_size );
266
253
267
254
rcu_assign_pointer (pn -> shrinker_info , new );
268
- call_srcu ( & shrinker_srcu , & old -> rcu , free_shrinker_info_rcu );
255
+ kvfree_rcu ( old , rcu );
269
256
}
270
257
271
258
return 0 ;
@@ -351,16 +338,15 @@ void set_shrinker_bit(struct mem_cgroup *memcg, int nid, int shrinker_id)
351
338
{
352
339
if (shrinker_id >= 0 && memcg && !mem_cgroup_is_root (memcg )) {
353
340
struct shrinker_info * info ;
354
- int srcu_idx ;
355
341
356
- srcu_idx = srcu_read_lock ( & shrinker_srcu );
357
- info = shrinker_info_srcu (memcg , nid );
342
+ rcu_read_lock ( );
343
+ info = rcu_dereference (memcg -> nodeinfo [ nid ] -> shrinker_info );
358
344
if (!WARN_ON_ONCE (shrinker_id >= info -> map_nr_max )) {
359
345
/* Pairs with smp mb in shrink_slab() */
360
346
smp_mb__before_atomic ();
361
347
set_bit (shrinker_id , info -> map );
362
348
}
363
- srcu_read_unlock ( & shrinker_srcu , srcu_idx );
349
+ rcu_read_unlock ( );
364
350
}
365
351
}
366
352
@@ -374,6 +360,7 @@ static int prealloc_memcg_shrinker(struct shrinker *shrinker)
374
360
return - ENOSYS ;
375
361
376
362
down_write (& shrinker_rwsem );
363
+ /* This may call shrinker, so it must use down_read_trylock() */
377
364
id = idr_alloc (& shrinker_idr , shrinker , 0 , 0 , GFP_KERNEL );
378
365
if (id < 0 )
379
366
goto unlock ;
@@ -407,7 +394,7 @@ static long xchg_nr_deferred_memcg(int nid, struct shrinker *shrinker,
407
394
{
408
395
struct shrinker_info * info ;
409
396
410
- info = shrinker_info_srcu (memcg , nid );
397
+ info = shrinker_info_protected (memcg , nid );
411
398
return atomic_long_xchg (& info -> nr_deferred [shrinker -> id ], 0 );
412
399
}
413
400
@@ -416,7 +403,7 @@ static long add_nr_deferred_memcg(long nr, int nid, struct shrinker *shrinker,
416
403
{
417
404
struct shrinker_info * info ;
418
405
419
- info = shrinker_info_srcu (memcg , nid );
406
+ info = shrinker_info_protected (memcg , nid );
420
407
return atomic_long_add_return (nr , & info -> nr_deferred [shrinker -> id ]);
421
408
}
422
409
@@ -947,14 +934,15 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
947
934
{
948
935
struct shrinker_info * info ;
949
936
unsigned long ret , freed = 0 ;
950
- int srcu_idx ;
951
937
int i ;
952
938
953
939
if (!mem_cgroup_online (memcg ))
954
940
return 0 ;
955
941
956
- srcu_idx = srcu_read_lock (& shrinker_srcu );
957
- info = shrinker_info_srcu (memcg , nid );
942
+ if (!down_read_trylock (& shrinker_rwsem ))
943
+ return 0 ;
944
+
945
+ info = shrinker_info_protected (memcg , nid );
958
946
if (unlikely (!info ))
959
947
goto unlock ;
960
948
@@ -1004,9 +992,14 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid,
1004
992
set_shrinker_bit (memcg , nid , i );
1005
993
}
1006
994
freed += ret ;
995
+
996
+ if (rwsem_is_contended (& shrinker_rwsem )) {
997
+ freed = freed ? : 1 ;
998
+ break ;
999
+ }
1007
1000
}
1008
1001
unlock :
1009
- srcu_read_unlock ( & shrinker_srcu , srcu_idx );
1002
+ up_read ( & shrinker_rwsem );
1010
1003
return freed ;
1011
1004
}
1012
1005
#else /* CONFIG_MEMCG */
0 commit comments