aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVineeth Pillai <vineeth@bitbyteword.org>2022-10-16 16:22:56 +0000
committerTreehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com>2024-04-30 19:06:12 +0000
commit107b3bf6c040388ef4aa396ff220511cb9c3eed6 (patch)
tree1ec494ac82c0944bd6994598f4332cc2b6a02775
parentcca23ea66214d1be9c380a869f9888fdf2defdd2 (diff)
downloadhikey-linaro-107b3bf6c040388ef4aa396ff220511cb9c3eed6.tar.gz
BACKPORT: 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. [Joel: register_shrinker() argument list change.] Bug: 258241771 Bug: 222463781 Test: CQ Change-Id: I6a73a9dae79ff35feca37abe2663e55a0f46dda8 Signed-off-by: Vineeth Pillai <vineeth@bitbyteword.org> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org> (cherry picked from commit c945b4da7a448a9a56becc5a8745d942b2b83d3c) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/4318046 Tested-by: Joel Fernandes <joelaf@google.com> Reviewed-by: Vineeth Pillai <vineethrp@google.com> Commit-Queue: Joel Fernandes <joelaf@google.com> (cherry picked from commit 2cf50ca2e7c3bc08f5182fc517a89a65e8dca7e3) [Cherry picked from chromeos-5.15 tree. Minor tweaks to commit message to match Android style] Signed-off-by: Qais Yousef <qyousef@google.com>
-rw-r--r--kernel/rcu/tree_nocb.h52
1 files changed, 52 insertions, 0 deletions
diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
index 2c30f32df7d1..a4daed924191 100644
--- a/kernel/rcu/tree_nocb.h
+++ b/kernel/rcu/tree_nocb.h
@@ -1215,6 +1215,55 @@ int rcu_nocb_cpu_offload(int cpu)
}
EXPORT_SYMBOL_GPL(rcu_nocb_cpu_offload);
+static unsigned long
+lazy_rcu_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
+{
+ int cpu;
+ unsigned long count = 0;
+
+ /* Snapshot count of all CPUs */
+ for_each_possible_cpu(cpu) {
+ struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
+
+ count += READ_ONCE(rdp->lazy_len);
+ }
+
+ return count ? count : SHRINK_EMPTY;
+}
+
+static unsigned long
+lazy_rcu_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
+{
+ int cpu;
+ unsigned long flags;
+ unsigned long count = 0;
+
+ /* Snapshot count of all CPUs */
+ for_each_possible_cpu(cpu) {
+ struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
+ int _count = READ_ONCE(rdp->lazy_len);
+
+ if (_count == 0)
+ continue;
+ rcu_nocb_lock_irqsave(rdp, flags);
+ WRITE_ONCE(rdp->lazy_len, 0);
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ wake_nocb_gp(rdp, false);
+ sc->nr_to_scan -= _count;
+ count += _count;
+ if (sc->nr_to_scan <= 0)
+ break;
+ }
+ return count ? count : SHRINK_STOP;
+}
+
+static struct shrinker lazy_rcu_shrinker = {
+ .count_objects = lazy_rcu_shrink_count,
+ .scan_objects = lazy_rcu_shrink_scan,
+ .batch = 0,
+ .seeks = DEFAULT_SEEKS,
+};
+
void __init rcu_init_nohz(void)
{
int cpu;
@@ -1240,6 +1289,9 @@ void __init rcu_init_nohz(void)
cpumask_or(rcu_nocb_mask, rcu_nocb_mask, tick_nohz_full_mask);
#endif /* #if defined(CONFIG_NO_HZ_FULL) */
+ if (register_shrinker(&lazy_rcu_shrinker))
+ pr_err("Failed to register lazy_rcu shrinker!\n");
+
if (!cpumask_subset(rcu_nocb_mask, cpu_possible_mask)) {
pr_info("\tNote: kernel parameter 'rcu_nocbs=', 'nohz_full', or 'isolcpus=' contains nonexistent CPUs.\n");
cpumask_and(rcu_nocb_mask, cpu_possible_mask,