summaryrefslogtreecommitdiff
path: root/net/mptcp/pm_kernel.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mptcp/pm_kernel.c')
-rw-r--r--net/mptcp/pm_kernel.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
index 57570a44e418..b26675054b0d 100644
--- a/net/mptcp/pm_kernel.c
+++ b/net/mptcp/pm_kernel.c
@@ -1294,16 +1294,26 @@ static void __reset_counters(struct pm_nl_pernet *pernet)
int mptcp_pm_nl_flush_addrs_doit(struct sk_buff *skb, struct genl_info *info)
{
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
- LIST_HEAD(free_list);
+ struct list_head free_list;
spin_lock_bh(&pernet->lock);
- list_splice_init(&pernet->endp_list, &free_list);
+ free_list = pernet->endp_list;
+ INIT_LIST_HEAD_RCU(&pernet->endp_list);
__reset_counters(pernet);
pernet->next_id = 1;
bitmap_zero(pernet->id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
spin_unlock_bh(&pernet->lock);
- mptcp_nl_flush_addrs_list(sock_net(skb->sk), &free_list);
+
+ if (free_list.next == &pernet->endp_list)
+ return 0;
+
synchronize_rcu();
+
+ /* Adjust the pointers to free_list instead of pernet->endp_list */
+ free_list.prev->next = &free_list;
+ free_list.next->prev = &free_list;
+
+ mptcp_nl_flush_addrs_list(sock_net(skb->sk), &free_list);
__flush_addrs(&free_list);
return 0;
}