|
@@ -2304,6 +2304,13 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * RCU callback function to leak a callback.
|
|
|
+ */
|
|
|
+static void rcu_leak_callback(struct rcu_head *rhp)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Helper function for call_rcu() and friends. The cpu argument will
|
|
|
* normally be -1, indicating "currently running CPU". It may specify
|
|
@@ -2318,7 +2325,12 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
|
|
|
struct rcu_data *rdp;
|
|
|
|
|
|
WARN_ON_ONCE((unsigned long)head & 0x3); /* Misaligned rcu_head! */
|
|
|
- debug_rcu_head_queue(head);
|
|
|
+ if (debug_rcu_head_queue(head)) {
|
|
|
+ /* Probable double call_rcu(), so leak the callback. */
|
|
|
+ ACCESS_ONCE(head->func) = rcu_leak_callback;
|
|
|
+ WARN_ONCE(1, "__call_rcu(): Leaked duplicate callback\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
head->func = func;
|
|
|
head->next = NULL;
|
|
|
|