diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-11-02 14:26:28 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-11-03 14:01:01 +0100 |
commit | c8b111bad16160aec5cf944bcf6fb1da47d601db (patch) | |
tree | 815b8ac6c458b7f2ee856378c6cf3f3a62fe0d68 /src/peer.c | |
parent | tools: abstract pkg-config to PKG_CONFIG (diff) | |
download | wireguard-monolithic-historical-c8b111bad16160aec5cf944bcf6fb1da47d601db.tar.xz wireguard-monolithic-historical-c8b111bad16160aec5cf944bcf6fb1da47d601db.zip |
timers: take reference like a lookup table
Diffstat (limited to 'src/peer.c')
-rw-r--r-- | src/peer.c | 23 |
1 files changed, 15 insertions, 8 deletions
@@ -49,15 +49,26 @@ struct wireguard_peer *peer_get(struct wireguard_peer *peer) return peer; } +struct wireguard_peer *peer_rcu_get(struct wireguard_peer *peer) +{ + rcu_read_lock(); + peer = peer_get(peer); + rcu_read_unlock(); + return peer; +} + +/* We have a separate "remove" function to get rid of the final reference because + * peer_list, clearing handshakes, and flushing all require mutexes which requires + * sleeping, which must only be done from certain contexts. */ void peer_remove(struct wireguard_peer *peer) { if (unlikely(!peer)) return; lockdep_assert_held(&peer->device->device_update_lock); - - list_del(&peer->peer_list); noise_handshake_clear(&peer->handshake); noise_keypairs_clear(&peer->keypairs); + list_del(&peer->peer_list); + timers_uninit_peer(peer); routing_table_remove_by_peer(&peer->device->peer_routing_table, peer); pubkey_hashtable_remove(&peer->device->peer_hashtable, peer); if (peer->device->workqueue) @@ -70,12 +81,10 @@ static void rcu_release(struct rcu_head *rcu) { struct wireguard_peer *peer = container_of(rcu, struct wireguard_peer, rcu); pr_debug("Peer %Lu (%pISpfsc) destroyed\n", peer->internal_id, &peer->endpoint_addr); - timers_uninit_peer(peer); skb_queue_purge(&peer->tx_packet_queue); if (peer->endpoint_dst) dst_release(peer->endpoint_dst); - memzero_explicit(peer, sizeof(struct wireguard_peer)); - kfree(peer); + kzfree(peer); } static void kref_release(struct kref *refcount) @@ -98,9 +107,7 @@ int peer_for_each_unlocked(struct wireguard_device *wg, int (*fn)(struct wiregua lockdep_assert_held(&wg->device_update_lock); list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) { - rcu_read_lock(); - peer = peer_get(peer); - rcu_read_unlock(); + peer = peer_rcu_get(peer); if (unlikely(!peer)) continue; ret = fn(peer, data); |