diff options
author | Chas Williams <chas@cmf.nrl.navy.mil> | 2006-09-29 20:16:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-09-29 20:16:48 -0400 |
commit | 33a9c2d4b758279c5077fc15d221b385a574ae0b (patch) | |
tree | adcaad67bd057b2d8200bae2219710c920c586f5 | |
parent | 987e46bdf314c55e060570ff46723d770e461f0e (diff) |
[ATM]: [lec] add reference counting to lec_arp entries
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/atm/lec.c | 42 | ||||
-rw-r--r-- | net/atm/lec_arpc.h | 1 |
2 files changed, 29 insertions, 14 deletions
diff --git a/net/atm/lec.c b/net/atm/lec.c index 29acfb0e6d04..c5d1f9e9a647 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -107,6 +107,19 @@ static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, | |||
107 | struct sk_buff *skb)); | 107 | struct sk_buff *skb)); |
108 | static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); | 108 | static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); |
109 | 109 | ||
110 | /* must be done under lec_arp_lock */ | ||
111 | static inline void lec_arp_hold(struct lec_arp_table *entry) | ||
112 | { | ||
113 | atomic_inc(&entry->usage); | ||
114 | } | ||
115 | |||
116 | static inline void lec_arp_put(struct lec_arp_table *entry) | ||
117 | { | ||
118 | if (atomic_dec_and_test(&entry->usage)) | ||
119 | kfree(entry); | ||
120 | } | ||
121 | |||
122 | |||
110 | static struct lane2_ops lane2_ops = { | 123 | static struct lane2_ops lane2_ops = { |
111 | lane2_resolve, /* resolve, spec 3.1.3 */ | 124 | lane2_resolve, /* resolve, spec 3.1.3 */ |
112 | lane2_associate_req, /* associate_req, spec 3.1.4 */ | 125 | lane2_associate_req, /* associate_req, spec 3.1.4 */ |
@@ -795,7 +808,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
795 | entry = lec_arp_find(priv, src); | 808 | entry = lec_arp_find(priv, src); |
796 | if (entry && entry->vcc != vcc) { | 809 | if (entry && entry->vcc != vcc) { |
797 | lec_arp_remove(priv, entry); | 810 | lec_arp_remove(priv, entry); |
798 | kfree(entry); | 811 | lec_arp_put(entry); |
799 | } | 812 | } |
800 | } | 813 | } |
801 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 814 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
@@ -1726,7 +1739,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
1726 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { | 1739 | for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { |
1727 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { | 1740 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
1728 | lec_arp_remove(priv, entry); | 1741 | lec_arp_remove(priv, entry); |
1729 | kfree(entry); | 1742 | lec_arp_put(entry); |
1730 | } | 1743 | } |
1731 | INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); | 1744 | INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); |
1732 | } | 1745 | } |
@@ -1735,7 +1748,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
1735 | del_timer_sync(&entry->timer); | 1748 | del_timer_sync(&entry->timer); |
1736 | lec_arp_clear_vccs(entry); | 1749 | lec_arp_clear_vccs(entry); |
1737 | hlist_del(&entry->next); | 1750 | hlist_del(&entry->next); |
1738 | kfree(entry); | 1751 | lec_arp_put(entry); |
1739 | } | 1752 | } |
1740 | INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); | 1753 | INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); |
1741 | 1754 | ||
@@ -1743,7 +1756,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
1743 | del_timer_sync(&entry->timer); | 1756 | del_timer_sync(&entry->timer); |
1744 | lec_arp_clear_vccs(entry); | 1757 | lec_arp_clear_vccs(entry); |
1745 | hlist_del(&entry->next); | 1758 | hlist_del(&entry->next); |
1746 | kfree(entry); | 1759 | lec_arp_put(entry); |
1747 | } | 1760 | } |
1748 | INIT_HLIST_HEAD(&priv->lec_no_forward); | 1761 | INIT_HLIST_HEAD(&priv->lec_no_forward); |
1749 | 1762 | ||
@@ -1751,7 +1764,7 @@ static void lec_arp_destroy(struct lec_priv *priv) | |||
1751 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 1764 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
1752 | lec_arp_clear_vccs(entry); | 1765 | lec_arp_clear_vccs(entry); |
1753 | hlist_del(&entry->next); | 1766 | hlist_del(&entry->next); |
1754 | kfree(entry); | 1767 | lec_arp_put(entry); |
1755 | } | 1768 | } |
1756 | INIT_HLIST_HEAD(&priv->mcast_fwds); | 1769 | INIT_HLIST_HEAD(&priv->mcast_fwds); |
1757 | priv->mcast_vcc = NULL; | 1770 | priv->mcast_vcc = NULL; |
@@ -1799,6 +1812,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv, | |||
1799 | to_return->last_used = jiffies; | 1812 | to_return->last_used = jiffies; |
1800 | to_return->priv = priv; | 1813 | to_return->priv = priv; |
1801 | skb_queue_head_init(&to_return->tx_wait); | 1814 | skb_queue_head_init(&to_return->tx_wait); |
1815 | atomic_set(&to_return->usage, 1); | ||
1802 | return to_return; | 1816 | return to_return; |
1803 | } | 1817 | } |
1804 | 1818 | ||
@@ -1843,7 +1857,7 @@ static void lec_arp_expire_vcc(unsigned long data) | |||
1843 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 1857 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
1844 | 1858 | ||
1845 | lec_arp_clear_vccs(to_remove); | 1859 | lec_arp_clear_vccs(to_remove); |
1846 | kfree(to_remove); | 1860 | lec_arp_put(to_remove); |
1847 | } | 1861 | } |
1848 | 1862 | ||
1849 | /* | 1863 | /* |
@@ -1891,7 +1905,7 @@ static void lec_arp_check_expire(void *data) | |||
1891 | /* Remove entry */ | 1905 | /* Remove entry */ |
1892 | DPRINTK("LEC:Entry timed out\n"); | 1906 | DPRINTK("LEC:Entry timed out\n"); |
1893 | lec_arp_remove(priv, entry); | 1907 | lec_arp_remove(priv, entry); |
1894 | kfree(entry); | 1908 | lec_arp_put(entry); |
1895 | } else { | 1909 | } else { |
1896 | /* Something else */ | 1910 | /* Something else */ |
1897 | if ((entry->status == ESI_VC_PENDING || | 1911 | if ((entry->status == ESI_VC_PENDING || |
@@ -2045,7 +2059,7 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, | |||
2045 | && (permanent || | 2059 | && (permanent || |
2046 | !(entry->flags & LEC_PERMANENT_FLAG))) { | 2060 | !(entry->flags & LEC_PERMANENT_FLAG))) { |
2047 | lec_arp_remove(priv, entry); | 2061 | lec_arp_remove(priv, entry); |
2048 | kfree(entry); | 2062 | lec_arp_put(entry); |
2049 | } | 2063 | } |
2050 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | 2064 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); |
2051 | return 0; | 2065 | return 0; |
@@ -2094,7 +2108,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, | |||
2094 | tmp->old_push = entry->old_push; | 2108 | tmp->old_push = entry->old_push; |
2095 | tmp->last_used = jiffies; | 2109 | tmp->last_used = jiffies; |
2096 | del_timer(&entry->timer); | 2110 | del_timer(&entry->timer); |
2097 | kfree(entry); | 2111 | lec_arp_put(entry); |
2098 | entry = tmp; | 2112 | entry = tmp; |
2099 | } else { | 2113 | } else { |
2100 | entry->status = ESI_FORWARD_DIRECT; | 2114 | entry->status = ESI_FORWARD_DIRECT; |
@@ -2414,7 +2428,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
2414 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { | 2428 | hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { |
2415 | if (vcc == entry->vcc) { | 2429 | if (vcc == entry->vcc) { |
2416 | lec_arp_remove(priv, entry); | 2430 | lec_arp_remove(priv, entry); |
2417 | kfree(entry); | 2431 | lec_arp_put(entry); |
2418 | if (priv->mcast_vcc == vcc) { | 2432 | if (priv->mcast_vcc == vcc) { |
2419 | priv->mcast_vcc = NULL; | 2433 | priv->mcast_vcc = NULL; |
2420 | } | 2434 | } |
@@ -2427,7 +2441,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
2427 | lec_arp_clear_vccs(entry); | 2441 | lec_arp_clear_vccs(entry); |
2428 | del_timer(&entry->timer); | 2442 | del_timer(&entry->timer); |
2429 | hlist_del(&entry->next); | 2443 | hlist_del(&entry->next); |
2430 | kfree(entry); | 2444 | lec_arp_put(entry); |
2431 | } | 2445 | } |
2432 | } | 2446 | } |
2433 | 2447 | ||
@@ -2436,7 +2450,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
2436 | lec_arp_clear_vccs(entry); | 2450 | lec_arp_clear_vccs(entry); |
2437 | del_timer(&entry->timer); | 2451 | del_timer(&entry->timer); |
2438 | hlist_del(&entry->next); | 2452 | hlist_del(&entry->next); |
2439 | kfree(entry); | 2453 | lec_arp_put(entry); |
2440 | } | 2454 | } |
2441 | } | 2455 | } |
2442 | 2456 | ||
@@ -2445,7 +2459,7 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) | |||
2445 | lec_arp_clear_vccs(entry); | 2459 | lec_arp_clear_vccs(entry); |
2446 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ | 2460 | /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ |
2447 | hlist_del(&entry->next); | 2461 | hlist_del(&entry->next); |
2448 | kfree(entry); | 2462 | lec_arp_put(entry); |
2449 | } | 2463 | } |
2450 | } | 2464 | } |
2451 | 2465 | ||
@@ -2481,7 +2495,7 @@ lec_arp_check_empties(struct lec_priv *priv, | |||
2481 | /* We might have got an entry */ | 2495 | /* We might have got an entry */ |
2482 | if ((tmp = lec_arp_find(priv, src))) { | 2496 | if ((tmp = lec_arp_find(priv, src))) { |
2483 | lec_arp_remove(priv, tmp); | 2497 | lec_arp_remove(priv, tmp); |
2484 | kfree(tmp); | 2498 | lec_arp_put(tmp); |
2485 | } | 2499 | } |
2486 | hlist_del(&entry->next); | 2500 | hlist_del(&entry->next); |
2487 | lec_arp_add(priv, entry); | 2501 | lec_arp_add(priv, entry); |
diff --git a/net/atm/lec_arpc.h b/net/atm/lec_arpc.h index 125df36d33b8..ec67435a40a6 100644 --- a/net/atm/lec_arpc.h +++ b/net/atm/lec_arpc.h | |||
@@ -47,6 +47,7 @@ struct lec_arp_table { | |||
47 | * the length of the tlvs array | 47 | * the length of the tlvs array |
48 | */ | 48 | */ |
49 | struct sk_buff_head tx_wait; /* wait queue for outgoing packets */ | 49 | struct sk_buff_head tx_wait; /* wait queue for outgoing packets */ |
50 | atomic_t usage; /* usage count */ | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | /* | 53 | /* |