summaryrefslogtreecommitdiff
path: root/net/rose/rose_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rose/rose_route.c')
-rw-r--r--net/rose/rose_route.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index b72bf8a08d48..a1e9b05ef6f5 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -93,11 +93,11 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
rose_neigh->ax25 = NULL;
rose_neigh->dev = dev;
rose_neigh->count = 0;
- rose_neigh->use = 0;
rose_neigh->dce_mode = 0;
rose_neigh->loopback = 0;
rose_neigh->number = rose_neigh_no++;
rose_neigh->restarted = 0;
+ refcount_set(&rose_neigh->use, 1);
skb_queue_head_init(&rose_neigh->queue);
@@ -178,6 +178,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
}
}
rose_neigh->count++;
+ rose_neigh_hold(rose_neigh);
goto out;
}
@@ -187,6 +188,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
rose_node->neighbour[rose_node->count] = rose_neigh;
rose_node->count++;
rose_neigh->count++;
+ rose_neigh_hold(rose_neigh);
}
out:
@@ -234,20 +236,12 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
if ((s = rose_neigh_list) == rose_neigh) {
rose_neigh_list = rose_neigh->next;
- if (rose_neigh->ax25)
- ax25_cb_put(rose_neigh->ax25);
- kfree(rose_neigh->digipeat);
- kfree(rose_neigh);
return;
}
while (s != NULL && s->next != NULL) {
if (s->next == rose_neigh) {
s->next = rose_neigh->next;
- if (rose_neigh->ax25)
- ax25_cb_put(rose_neigh->ax25);
- kfree(rose_neigh->digipeat);
- kfree(rose_neigh);
return;
}
@@ -263,10 +257,10 @@ static void rose_remove_route(struct rose_route *rose_route)
struct rose_route *s;
if (rose_route->neigh1 != NULL)
- rose_route->neigh1->use--;
+ rose_neigh_put(rose_route->neigh1);
if (rose_route->neigh2 != NULL)
- rose_route->neigh2->use--;
+ rose_neigh_put(rose_route->neigh2);
if ((s = rose_route_list) == rose_route) {
rose_route_list = rose_route->next;
@@ -330,9 +324,12 @@ static int rose_del_node(struct rose_route_struct *rose_route,
for (i = 0; i < rose_node->count; i++) {
if (rose_node->neighbour[i] == rose_neigh) {
rose_neigh->count--;
+ rose_neigh_put(rose_neigh);
- if (rose_neigh->count == 0 && rose_neigh->use == 0)
+ if (rose_neigh->count == 0) {
rose_remove_neigh(rose_neigh);
+ rose_neigh_put(rose_neigh);
+ }
rose_node->count--;
@@ -381,11 +378,11 @@ void rose_add_loopback_neigh(void)
sn->ax25 = NULL;
sn->dev = NULL;
sn->count = 0;
- sn->use = 0;
sn->dce_mode = 1;
sn->loopback = 1;
sn->number = rose_neigh_no++;
sn->restarted = 1;
+ refcount_set(&sn->use, 1);
skb_queue_head_init(&sn->queue);
@@ -436,6 +433,7 @@ int rose_add_loopback_node(const rose_address *address)
rose_node_list = rose_node;
rose_loopback_neigh->count++;
+ rose_neigh_hold(rose_loopback_neigh);
out:
spin_unlock_bh(&rose_node_list_lock);
@@ -467,6 +465,7 @@ void rose_del_loopback_node(const rose_address *address)
rose_remove_node(rose_node);
rose_loopback_neigh->count--;
+ rose_neigh_put(rose_loopback_neigh);
out:
spin_unlock_bh(&rose_node_list_lock);
@@ -506,6 +505,7 @@ void rose_rt_device_down(struct net_device *dev)
memmove(&t->neighbour[i], &t->neighbour[i + 1],
sizeof(t->neighbour[0]) *
(t->count - i));
+ rose_neigh_put(s);
}
if (t->count <= 0)
@@ -513,6 +513,7 @@ void rose_rt_device_down(struct net_device *dev)
}
rose_remove_neigh(s);
+ rose_neigh_put(s);
}
spin_unlock_bh(&rose_neigh_list_lock);
spin_unlock_bh(&rose_node_list_lock);
@@ -548,6 +549,7 @@ static int rose_clear_routes(void)
{
struct rose_neigh *s, *rose_neigh;
struct rose_node *t, *rose_node;
+ int i;
spin_lock_bh(&rose_node_list_lock);
spin_lock_bh(&rose_neigh_list_lock);
@@ -558,17 +560,21 @@ static int rose_clear_routes(void)
while (rose_node != NULL) {
t = rose_node;
rose_node = rose_node->next;
- if (!t->loopback)
+
+ if (!t->loopback) {
+ for (i = 0; i < t->count; i++)
+ rose_neigh_put(t->neighbour[i]);
rose_remove_node(t);
+ }
}
while (rose_neigh != NULL) {
s = rose_neigh;
rose_neigh = rose_neigh->next;
- if (s->use == 0 && !s->loopback) {
- s->count = 0;
+ if (!s->loopback) {
rose_remove_neigh(s);
+ rose_neigh_put(s);
}
}
@@ -684,6 +690,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
for (i = 0; i < node->count; i++) {
if (node->neighbour[i]->restarted) {
res = node->neighbour[i];
+ rose_neigh_hold(node->neighbour[i]);
goto out;
}
}
@@ -695,6 +702,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
for (i = 0; i < node->count; i++) {
if (!rose_ftimer_running(node->neighbour[i])) {
res = node->neighbour[i];
+ rose_neigh_hold(node->neighbour[i]);
goto out;
}
failed = 1;
@@ -784,13 +792,13 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh)
}
if (rose_route->neigh1 == rose_neigh) {
- rose_route->neigh1->use--;
+ rose_neigh_put(rose_route->neigh1);
rose_route->neigh1 = NULL;
rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0);
}
if (rose_route->neigh2 == rose_neigh) {
- rose_route->neigh2->use--;
+ rose_neigh_put(rose_route->neigh2);
rose_route->neigh2 = NULL;
rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0);
}
@@ -919,7 +927,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
rose_clear_queues(sk);
rose->cause = ROSE_NETWORK_CONGESTION;
rose->diagnostic = 0;
- rose->neighbour->use--;
+ rose_neigh_put(rose->neighbour);
rose->neighbour = NULL;
rose->lci = 0;
rose->state = ROSE_STATE_0;
@@ -1044,12 +1052,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
if ((new_lci = rose_new_lci(new_neigh)) == 0) {
rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71);
- goto out;
+ goto put_neigh;
}
if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) {
rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120);
- goto out;
+ goto put_neigh;
}
rose_route->lci1 = lci;
@@ -1062,8 +1070,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
rose_route->lci2 = new_lci;
rose_route->neigh2 = new_neigh;
- rose_route->neigh1->use++;
- rose_route->neigh2->use++;
+ rose_neigh_hold(rose_route->neigh1);
+ rose_neigh_hold(rose_route->neigh2);
rose_route->next = rose_route_list;
rose_route_list = rose_route;
@@ -1075,6 +1083,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
rose_transmit_link(skb, rose_route->neigh2);
res = 1;
+put_neigh:
+ rose_neigh_put(new_neigh);
out:
spin_unlock_bh(&rose_route_list_lock);
spin_unlock_bh(&rose_neigh_list_lock);
@@ -1190,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
(rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign),
rose_neigh->dev ? rose_neigh->dev->name : "???",
rose_neigh->count,
- rose_neigh->use,
+ refcount_read(&rose_neigh->use) - rose_neigh->count - 1,
(rose_neigh->dce_mode) ? "DCE" : "DTE",
(rose_neigh->restarted) ? "yes" : "no",
ax25_display_timer(&rose_neigh->t0timer) / HZ,
@@ -1295,18 +1305,22 @@ void __exit rose_rt_free(void)
struct rose_neigh *s, *rose_neigh = rose_neigh_list;
struct rose_node *t, *rose_node = rose_node_list;
struct rose_route *u, *rose_route = rose_route_list;
+ int i;
while (rose_neigh != NULL) {
s = rose_neigh;
rose_neigh = rose_neigh->next;
rose_remove_neigh(s);
+ rose_neigh_put(s);
}
while (rose_node != NULL) {
t = rose_node;
rose_node = rose_node->next;
+ for (i = 0; i < t->count; i++)
+ rose_neigh_put(t->neighbour[i]);
rose_remove_node(t);
}