Skip to content

Commit de44585

Browse files
Vineeth Pillaichantra
authored andcommitted
rcu: Shrinker for lazy rcu
The shrinker is used to speed up the free'ing of memory potentially held by RCU lazy callbacks. RCU kernel module test cases show this to be effective. Test is introduced in a later patch. Signed-off-by: Vineeth Pillai <[email protected]> Signed-off-by: Joel Fernandes (Google) <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 4163fda commit de44585

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

kernel/rcu/tree_nocb.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,55 @@ int rcu_nocb_cpu_offload(int cpu)
13121312
}
13131313
EXPORT_SYMBOL_GPL(rcu_nocb_cpu_offload);
13141314

1315+
static unsigned long
1316+
lazy_rcu_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
1317+
{
1318+
int cpu;
1319+
unsigned long count = 0;
1320+
1321+
/* Snapshot count of all CPUs */
1322+
for_each_possible_cpu(cpu) {
1323+
struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
1324+
1325+
count += READ_ONCE(rdp->lazy_len);
1326+
}
1327+
1328+
return count ? count : SHRINK_EMPTY;
1329+
}
1330+
1331+
static unsigned long
1332+
lazy_rcu_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
1333+
{
1334+
int cpu;
1335+
unsigned long flags;
1336+
unsigned long count = 0;
1337+
1338+
/* Snapshot count of all CPUs */
1339+
for_each_possible_cpu(cpu) {
1340+
struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
1341+
int _count = READ_ONCE(rdp->lazy_len);
1342+
1343+
if (_count == 0)
1344+
continue;
1345+
rcu_nocb_lock_irqsave(rdp, flags);
1346+
WRITE_ONCE(rdp->lazy_len, 0);
1347+
rcu_nocb_unlock_irqrestore(rdp, flags);
1348+
wake_nocb_gp(rdp, false);
1349+
sc->nr_to_scan -= _count;
1350+
count += _count;
1351+
if (sc->nr_to_scan <= 0)
1352+
break;
1353+
}
1354+
return count ? count : SHRINK_STOP;
1355+
}
1356+
1357+
static struct shrinker lazy_rcu_shrinker = {
1358+
.count_objects = lazy_rcu_shrink_count,
1359+
.scan_objects = lazy_rcu_shrink_scan,
1360+
.batch = 0,
1361+
.seeks = DEFAULT_SEEKS,
1362+
};
1363+
13151364
void __init rcu_init_nohz(void)
13161365
{
13171366
int cpu;
@@ -1342,6 +1391,9 @@ void __init rcu_init_nohz(void)
13421391
if (!rcu_state.nocb_is_setup)
13431392
return;
13441393

1394+
if (register_shrinker(&lazy_rcu_shrinker, "rcu-lazy"))
1395+
pr_err("Failed to register lazy_rcu shrinker!\n");
1396+
13451397
if (!cpumask_subset(rcu_nocb_mask, cpu_possible_mask)) {
13461398
pr_info("\tNote: kernel parameter 'rcu_nocbs=', 'nohz_full', or 'isolcpus=' contains nonexistent CPUs.\n");
13471399
cpumask_and(rcu_nocb_mask, cpu_possible_mask,

0 commit comments

Comments
 (0)