1// 2// Look for missing lock releases before returning from an error path. 3// 4// Target: DragonFly 5// Copyright: 2012 - LIP6/INRIA 6// License: Licensed under ISC. See LICENSE or http://www.isc.org/software/license 7// Author: Julia Lawall <Julia.Lawall@lip6.fr> 8// (original code, adapted for DragonFly by swildner) 9// URL: http://coccinelle.lip6.fr/ 10// URL: http://coccinellery.org/ 11// 12// Applies to kernel code. 13// 14// NOTES 15// ----- 16// * The results of running this patch have to be carefully reviewed. 17// Some functions legally return with the lock held, even if the 18// below pattern matches. Some other functions begin with the lock 19// held, only to release and then reacquire it again. 20// 21// * Consider using -timeout because it might run a long time 22// (indefinitely?) on some files. 23// 24 25// ACPI_SERIAL_BEGIN(...) / ACPI_SERIAL_END(...) 26// 27@rcu_ACPI_SERIAL_BEGIN exists@ 28position p1; 29expression E; 30@@ 31 32ACPI_SERIAL_BEGIN@p1(E); 33... 34ACPI_SERIAL_END(E); 35 36@exists@ 37position rcu_ACPI_SERIAL_BEGIN.p1; 38expression E; 39@@ 40 41*ACPI_SERIAL_BEGIN@p1(E); 42... when != ACPI_SERIAL_END(E); 43?*return ...; 44 45// crit_enter() / crit_exit() 46// 47@rcu_crit_enter exists@ 48position p1; 49@@ 50 51crit_enter@p1(); 52... 53crit_exit(); 54 55@exists@ 56position rcu_crit_enter.p1; 57@@ 58 59*crit_enter@p1(); 60... when != crit_exit(); 61?*return ...; 62 63// get_mplock() / rel_mplock() 64// 65@rcu_get_mplock exists@ 66position p1; 67@@ 68 69get_mplock@p1(); 70... 71rel_mplock(); 72 73@exists@ 74position rcu_get_mplock.p1; 75@@ 76 77*get_mplock@p1(); 78... when != rel_mplock(); 79?*return ...; 80 81// lockmgr(..., {LK_EXCLUSIVE,LK_SHARED}) / lockmgr(..., LK_RELEASE) 82// 83@rcu_lockmgr exists@ 84position p1; 85expression E; 86@@ 87 88lockmgr@p1(E,\(LK_SHARED\|LK_EXCLUSIVE\)); 89... 90lockmgr(E,LK_RELEASE); 91 92@exists@ 93position rcu_lockmgr.p1; 94expression E; 95@@ 96 97*lockmgr@p1(E,\(LK_SHARED\|LK_EXCLUSIVE\)); 98... when != lockmgr(E,LK_RELEASE); 99?*return ...; 100 101// lwkt_gettoken(...) / lwkt_reltoken(...) 102// 103@rcu_lwkt_gettoken exists@ 104position p1; 105expression E; 106@@ 107 108lwkt_gettoken@p1(E); 109... 110lwkt_reltoken(E); 111 112@exists@ 113position rcu_lwkt_gettoken.p1; 114expression E; 115@@ 116 117*lwkt_gettoken@p1(E); 118... when != lwkt_reltoken(E); 119?*return ...; 120 121// lwkt_serialize_enter(...) / lwkt_serialize_exit(...) 122// 123@rcu_lwkt_serialize_enter exists@ 124position p1; 125expression E; 126@@ 127 128lwkt_serialize_enter@p1(E); 129... 130lwkt_serialize_exit(E); 131 132@exists@ 133position rcu_lwkt_serialize_enter.p1; 134expression E; 135@@ 136 137*lwkt_serialize_enter@p1(E); 138... when != lwkt_serialize_exit(E); 139?*return ...; 140 141// nlookup_init(...) / nlookup_done(...) 142// 143@rcu_nlookup_init exists@ 144position p1; 145expression E; 146@@ 147 148nlookup_init@p1(E,...); 149... 150nlookup_done(E); 151 152@exists@ 153position rcu_nlookup_init.p1; 154expression E; 155@@ 156 157*nlookup_init@p1(E,...); 158... when != nlookup_done(E); 159?*return ...; 160 161// spin_lock(...) / spin_unlock(...) 162// 163@rcu_spin_lock exists@ 164position p1; 165expression E; 166@@ 167 168spin_lock@p1(E); 169... 170spin_unlock(E); 171 172@exists@ 173position rcu_spin_lock.p1; 174expression E; 175@@ 176 177*spin_lock@p1(E); 178... when != spin_unlock(E); 179?*return ...; 180 181// vm_object_hold(...) / vm_object_drop(...) 182// 183@rcu_vm_object_hold exists@ 184position p1; 185expression E; 186@@ 187 188vm_object_hold@p1(E); 189... 190vm_object_drop(E); 191 192@exists@ 193position rcu_vm_object_hold.p1; 194expression E; 195@@ 196 197*vm_object_hold@p1(E); 198... when != vm_object_drop(E); 199?*return ...; 200 201// vn_lock(...) / vn_unlock(...) 202// 203@rcu_vn_lock exists@ 204position p1; 205expression E; 206@@ 207 208( 209vn_lock@p1(E,...); 210| 211vget@p1(E); 212) 213... 214( 215vn_unlock(E); 216| 217vput(E); 218) 219 220@exists@ 221position rcu_vn_lock.p1; 222expression E; 223@@ 224 225( 226*vn_lock@p1(E,...); 227| 228*vget@p1(E); 229) 230... when != \(vn_unlock\|vput\)(E); 231?*return ...; 232 233// wlan_serialize_enter() / wlan_serialize_exit() 234// 235@rcu_wlan_serialize_enter exists@ 236position p1; 237@@ 238 239wlan_serialize_enter@p1(); 240... 241wlan_serialize_exit(); 242 243@exists@ 244position rcu_wlan_serialize_enter.p1; 245@@ 246 247*wlan_serialize_enter@p1(); 248... when != wlan_serialize_exit(); 249?*return ...; 250