static void pppoe_flush_dev(struct net_device *dev) { int hash; BUG_ON(dev == NULL); read_lock_bh(&pppoe_hash_lock); for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) { struct pppox_sock *po = item_hash_table[hash]; while (po != NULL) { if (po->pppoe_dev == dev) { struct sock *sk = sk_pppox(po); sock_hold(sk); po->pppoe_dev = NULL; /* We hold a reference to SK, now drop the * hash table lock so that we may attempt * to lock the socket (which can sleep). */ read_unlock_bh(&pppoe_hash_lock); lock_sock(sk); if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { pppox_unbind_sock(sk); dev_put(dev); sk->sk_state = PPPOX_ZOMBIE; sk->sk_state_change(sk); } release_sock(sk); sock_put(sk); read_lock_bh(&pppoe_hash_lock); /* Now restart from the beginning of this * hash chain. We always NULL out pppoe_dev * so we are guaranteed to make forward * progress. */ po = item_hash_table[hash]; continue; } po = po->next; } } read_unlock_bh(&pppoe_hash_lock); }
/********************************************************************** * * Set/get/delete/rehash items * **********************************************************************/ static inline struct pppox_sock *get_item(unsigned long sid, unsigned char *addr) { struct pppox_sock *po; read_lock_bh(&pppoe_hash_lock); po = __get_item(sid, addr); if (po) sock_hold(sk_pppox(po)); read_unlock_bh(&pppoe_hash_lock); return po; }
static inline struct pppox_sock *dzc_get_item(struct pppoe_net *pn, __be16 sid, unsigned char *addr, int ifindex) { struct pppox_sock *po; read_lock_bh(&pn->hash_lock); po = __get_item(pn, sid, addr, ifindex); if (po) sock_hold(sk_pppox(po)); read_unlock_bh(&pn->hash_lock); return po; }
static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr) { struct pppox_sock *sock; struct pptp_opt *opt; rcu_read_lock(); sock = rcu_dereference(callid_sock[call_id]); if (sock) { opt = &sock->proto.pptp; if (opt->dst_addr.sin_addr.s_addr != s_addr) sock = NULL; else sock_hold(sk_pppox(sock)); } rcu_read_unlock(); return sock; }
static void pppoe_dzc_flush_dev(struct net_device *dev) { struct pppoe_net *pn; int i; pn = dzc_pppoe_pernet(dev_net(dev)); write_lock_bh(&pn->hash_lock); for (i = 0; i < (1 << 4); i++) { struct pppox_sock *po = pn->hash_table[i]; struct sock *sk; while (po) { while (po && po->pppoe_dev != dev) { po = po->next; } if (!po) break; sk = sk_pppox(po); sock_hold(sk); write_unlock_bh(&pn->hash_lock); lock_sock(sk); if (po->pppoe_dev == dev && sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { pppox_unbind_sock(sk); sk->sk_state = PPPOX_ZOMBIE; sk->sk_state_change(sk); po->pppoe_dev = NULL; dev_put(dev); } release_sock(sk); sock_put(sk); BUG_ON(dzc_pppoe_pernet(dev_net(dev)) == NULL); write_lock_bh(&pn->hash_lock); po = pn->hash_table[i]; } } write_unlock_bh(&pn->hash_lock); }