1 .. SPDX-License-Identifier: GPL-2.0 2 3 ================= 4 Lockdep-RCU Splat 5 ================= 6 7 Lockdep-RCU was added to the Linux kernel in e 8 (http://lwn.net/Articles/371986/). This facil 9 misuses of the RCU API, most notably using one 10 family to access an RCU-protected pointer with 11 When such misuse is detected, an lockdep-RCU s 12 13 The usual cause of a lockdep-RCU splat is some 14 RCU-protected data structure without either (1 15 RCU read-side critical section or (2) holding 16 This problem can therefore be serious: it migh 17 overwriting or worse. There can of course be 18 being the real world and all that. 19 20 So let's look at an example RCU lockdep splat 21 has long since been fixed:: 22 23 ============================= 24 WARNING: suspicious RCU usage 25 ----------------------------- 26 block/cfq-iosched.c:2776 suspicious rcu_de 27 28 other info that might help us debug this:: 29 30 rcu_scheduler_active = 1, debug_locks = 0 31 3 locks held by scsi_scan_6/1552: 32 #0: (&shost->scan_mutex){+.+.}, at: [<fff 33 scsi_scan_host_selected+0x5a/0x150 34 #1: (&eq->sysfs_lock){+.+.}, at: [<ffffff 35 elevator_exit+0x22/0x60 36 #2: (&(&q->__queue_lock)->rlock){-.-.}, a 37 cfq_exit_queue+0x43/0x190 38 39 stack backtrace: 40 Pid: 1552, comm: scsi_scan_6 Not tainted 3 41 Call Trace: 42 [<ffffffff810abb9b>] lockdep_rcu_dereferen 43 [<ffffffff812b6139>] __cfq_exit_single_io_ 44 [<ffffffff812b626c>] cfq_exit_queue+0x7c/0 45 [<ffffffff812a5046>] elevator_exit+0x36/0x 46 [<ffffffff812a802a>] blk_cleanup_queue+0x4 47 [<ffffffff8145cc09>] scsi_free_queue+0x9/0 48 [<ffffffff81460944>] __scsi_remove_device+ 49 [<ffffffff8145dca3>] scsi_probe_and_add_lu 50 [<ffffffff817da069>] ? error_exit+0x29/0xb 51 [<ffffffff817d98ed>] ? _raw_spin_unlock_ir 52 [<ffffffff8145e722>] __scsi_scan_target+0x 53 [<ffffffff812c690d>] ? trace_hardirqs_off_ 54 [<ffffffff817da069>] ? error_exit+0x29/0xb 55 [<ffffffff812bcc60>] ? kobject_del+0x40/0x 56 [<ffffffff8145ed16>] scsi_scan_channel+0x8 57 [<ffffffff8145f0b0>] scsi_scan_host_select 58 [<ffffffff8145f149>] do_scsi_scan_host+0x8 59 [<ffffffff8145f170>] do_scan_async+0x20/0x 60 [<ffffffff8145f150>] ? do_scsi_scan_host+0 61 [<ffffffff810975b6>] kthread+0xa6/0xb0 62 [<ffffffff817db154>] kernel_thread_helper+ 63 [<ffffffff81066430>] ? finish_task_switch+ 64 [<ffffffff817d9c04>] ? retint_restore_args 65 [<ffffffff81097510>] ? __kthread_init_work 66 [<ffffffff817db150>] ? gs_change+0xb/0xb 67 68 Line 2776 of block/cfq-iosched.c in v3.0-rc5 i 69 70 if (rcu_dereference(ioc->ioc_data) == 71 72 This form says that it must be in a plain vani 73 section, but the "other info" list above shows 74 case. Instead, we hold three locks, one of wh 75 And maybe that lock really does protect this r 76 is to inform RCU, perhaps by changing __cfq_ex 77 take the struct request_queue "q" from cfq_exi 78 which would permit us to invoke rcu_dereferenc 79 80 if (rcu_dereference_protected(ioc->ioc 81 lockdep_ 82 83 With this change, there would be no lockdep-RC 84 code was invoked either from within an RCU rea 85 or with the ->queue_lock held. In particular, 86 the above lockdep-RCU splat because ->queue_lo 87 list above). 88 89 On the other hand, perhaps we really do need a 90 section. In this case, the critical section m 91 return value from rcu_dereference(), or at lea 92 reference count incremented or some such. One 93 add rcu_read_lock() and rcu_read_unlock() as f 94 95 rcu_read_lock(); 96 if (rcu_dereference(ioc->ioc_data) == 97 spin_lock(&ioc->lock); 98 rcu_assign_pointer(ioc->ioc_da 99 spin_unlock(&ioc->lock); 100 } 101 rcu_read_unlock(); 102 103 With this change, the rcu_dereference() is alw 104 read-side critical section, which again would 105 above lockdep-RCU splat. 106 107 But in this particular case, we don't actually 108 returned from rcu_dereference(). Instead, tha 109 to the cic pointer, which means that the rcu_d 110 by rcu_access_pointer() as follows:: 111 112 if (rcu_access_pointer(ioc->ioc_data) 113 114 Because it is legal to invoke rcu_access_point 115 this change would also suppress the above lock
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.