aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChas Williams <chas@cmf.nrl.navy.mil>2006-09-29 20:16:48 -0400
committerDavid S. Miller <davem@davemloft.net>2006-09-29 20:16:48 -0400
commit33a9c2d4b758279c5077fc15d221b385a574ae0b (patch)
treeadcaad67bd057b2d8200bae2219710c920c586f5
parent987e46bdf314c55e060570ff46723d770e461f0e (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.c42
-rw-r--r--net/atm/lec_arpc.h1
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));
108static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); 108static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
109 109
110/* must be done under lec_arp_lock */
111static inline void lec_arp_hold(struct lec_arp_table *entry)
112{
113 atomic_inc(&entry->usage);
114}
115
116static 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
110static struct lane2_ops lane2_ops = { 123static 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/*