[PATCH] RCU documentation: self-limiting updates and call_rcu()

An update to the RCU documentation calling out the
self-limiting-update-rate advantages of synchronize_rcu(), and describing
how to use call_rcu() in a way that results in self-limiting updates.
Self-limiting updates are important to avoiding RCU-induced OOM in face of
denial-of-service attacks.

Signed-off-by: Paul E. McKenney <paulmck@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Paul E. McKenney 2006-06-25 05:48:44 -07:00 committed by Linus Torvalds
parent 76d42bd969
commit 165d6c78ee
2 changed files with 52 additions and 4 deletions

View File

@ -144,9 +144,47 @@ over a rather long period of time, but improvements are always welcome!
whether the increased speed is worth it. whether the increased speed is worth it.
8. Although synchronize_rcu() is a bit slower than is call_rcu(), 8. Although synchronize_rcu() is a bit slower than is call_rcu(),
it usually results in simpler code. So, unless update performance it usually results in simpler code. So, unless update
is important or the updaters cannot block, synchronize_rcu() performance is critically important or the updaters cannot block,
should be used in preference to call_rcu(). synchronize_rcu() should be used in preference to call_rcu().
An especially important property of the synchronize_rcu()
primitive is that it automatically self-limits: if grace periods
are delayed for whatever reason, then the synchronize_rcu()
primitive will correspondingly delay updates. In contrast,
code using call_rcu() should explicitly limit update rate in
cases where grace periods are delayed, as failing to do so can
result in excessive realtime latencies or even OOM conditions.
Ways of gaining this self-limiting property when using call_rcu()
include:
a. Keeping a count of the number of data-structure elements
used by the RCU-protected data structure, including those
waiting for a grace period to elapse. Enforce a limit
on this number, stalling updates as needed to allow
previously deferred frees to complete.
Alternatively, limit only the number awaiting deferred
free rather than the total number of elements.
b. Limiting update rate. For example, if updates occur only
once per hour, then no explicit rate limiting is required,
unless your system is already badly broken. The dcache
subsystem takes this approach -- updates are guarded
by a global lock, limiting their rate.
c. Trusted update -- if updates can only be done manually by
superuser or some other trusted user, then it might not
be necessary to automatically limit them. The theory
here is that superuser already has lots of ways to crash
the machine.
d. Use call_rcu_bh() rather than call_rcu(), in order to take
advantage of call_rcu_bh()'s faster grace periods.
e. Periodically invoke synchronize_rcu(), permitting a limited
number of updates per grace period.
9. All RCU list-traversal primitives, which include 9. All RCU list-traversal primitives, which include
list_for_each_rcu(), list_for_each_entry_rcu(), list_for_each_rcu(), list_for_each_entry_rcu(),

View File

@ -184,7 +184,17 @@ synchronize_rcu()
blocking, it registers a function and argument which are invoked blocking, it registers a function and argument which are invoked
after all ongoing RCU read-side critical sections have completed. after all ongoing RCU read-side critical sections have completed.
This callback variant is particularly useful in situations where This callback variant is particularly useful in situations where
it is illegal to block. it is illegal to block or where update-side performance is
critically important.
However, the call_rcu() API should not be used lightly, as use
of the synchronize_rcu() API generally results in simpler code.
In addition, the synchronize_rcu() API has the nice property
of automatically limiting update rate should grace periods
be delayed. This property results in system resilience in face
of denial-of-service attacks. Code using call_rcu() should limit
update rate in order to gain this same sort of resilience. See
checklist.txt for some approaches to limiting the update rate.
rcu_assign_pointer() rcu_assign_pointer()