Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / Documentation / RCU / whatisRCU.txt
index 5ed85af..318df44 100644 (file)
@@ -184,7 +184,17 @@ synchronize_rcu()
        blocking, it registers a function and argument which are invoked
        after all ongoing RCU read-side critical sections have completed.
        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()
 
@@ -360,7 +370,7 @@ uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt.
                struct foo *new_fp;
                struct foo *old_fp;
 
-               new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+               new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL);
                spin_lock(&foo_mutex);
                old_fp = gbl_foo;
                *new_fp = *old_fp;
@@ -461,7 +471,7 @@ The foo_update_a() function might then be written as follows:
                struct foo *new_fp;
                struct foo *old_fp;
 
-               new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+               new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL);
                spin_lock(&foo_mutex);
                old_fp = gbl_foo;
                *new_fp = *old_fp;
@@ -605,7 +615,7 @@ are the same as those shown in the preceding section, so they are omitted.
        {
                int cpu;
 
-               for_each_cpu(cpu)
+               for_each_possible_cpu(cpu)
                        run_on(cpu);
        }
 
@@ -677,8 +687,9 @@ diff shows how closely related RCU and reader-writer locking can be.
        +       spin_lock(&listmutex);
                list_for_each_entry(p, head, lp) {
                        if (p->key == key) {
-                               list_del(&p->list);
+       -                       list_del(&p->list);
        -                       write_unlock(&listmutex);
+       +                       list_del_rcu(&p->list);
        +                       spin_unlock(&listmutex);
        +                       synchronize_rcu();
                                kfree(p);
@@ -726,7 +737,7 @@ Or, for those who prefer a side-by-side listing:
  5   write_lock(&listmutex);            5   spin_lock(&listmutex);
  6   list_for_each_entry(p, head, lp) { 6   list_for_each_entry(p, head, lp) {
  7     if (p->key == key) {             7     if (p->key == key) {
- 8       list_del(&p->list);            8       list_del(&p->list);
+ 8       list_del(&p->list);            8       list_del_rcu(&p->list);
  9       write_unlock(&listmutex);      9       spin_unlock(&listmutex);
                                        10       synchronize_rcu();
 10       kfree(p);                     11       kfree(p);
@@ -790,7 +801,6 @@ RCU pointer update:
 
 RCU grace period:
 
-       synchronize_kernel (deprecated)
        synchronize_net
        synchronize_sched
        synchronize_rcu