Commit 3a62a477 authored by Ralf Bächle's avatar Ralf Bächle

Protect ax25_dev_list with it's own spinlock replacing the previous

cli / sti mess.
parent ba8f7fa4
......@@ -226,6 +226,7 @@ extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
/* ax25_dev.c */
extern ax25_dev *ax25_dev_list;
extern spinlock_t ax25_dev_lock;
extern ax25_dev *ax25_dev_ax25dev(struct net_device *);
extern ax25_dev *ax25_addr_ax25dev(ax25_address *);
extern void ax25_dev_device_up(struct net_device *);
......
......@@ -9,7 +9,7 @@ af_ax25.c:ax25_connect:
return sock_error(sk); /* Always set at this point */
}
Do the spinlocks ax25_list_lock, ax25_uid_lock, ax25_route_lock and
protocol_list_lock really have to be interrupt safe?
Do the spinlocks ax25_list_lock, ax25_uid_lock, ax25_route_lock,
protocol_list_lock and ax25_dev_lock really have to be interrupt safe?
What locking will be needed for linkfail_list and listen_list?
......@@ -27,6 +27,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
......@@ -41,27 +42,37 @@
#include <linux/init.h>
ax25_dev *ax25_dev_list;
spinlock_t ax25_dev_lock;
ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
{
ax25_dev *ax25_dev;
ax25_dev *ax25_dev, *res = NULL;
unsigned long flags;
spin_lock_irqsave(&ax25_dev_lock, flags);
for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
if (ax25_dev->dev == dev)
return ax25_dev;
if (ax25_dev->dev == dev) {
res = ax25_dev;
break;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
return NULL;
return res;
}
ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
{
ax25_dev *ax25_dev;
ax25_dev *ax25_dev, *res = NULL;
unsigned long flags;
spin_lock_irqsave(&ax25_dev_lock, flags);
for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0)
return ax25_dev;
if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
res = ax25_dev;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
return NULL;
return res;
}
/*
......@@ -100,10 +111,10 @@ void ax25_dev_device_up(struct net_device *dev)
ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL;
ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
save_flags(flags); cli();
spin_lock_irqsave(&ax25_dev_lock, flags);
ax25_dev->next = ax25_dev_list;
ax25_dev_list = ax25_dev;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
ax25_register_sysctl();
}
......@@ -118,7 +129,7 @@ void ax25_dev_device_down(struct net_device *dev)
ax25_unregister_sysctl();
save_flags(flags); cli();
spin_lock_irqsave(&ax25_dev_lock, flags);
#ifdef CONFIG_AX25_DAMA_SLAVE
ax25_ds_del_timer(ax25_dev);
......@@ -133,7 +144,7 @@ void ax25_dev_device_down(struct net_device *dev)
if ((s = ax25_dev_list) == ax25_dev) {
ax25_dev_list = s->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
kfree(ax25_dev);
ax25_register_sysctl();
return;
......@@ -142,7 +153,7 @@ void ax25_dev_device_down(struct net_device *dev)
while (s != NULL && s->next != NULL) {
if (s->next == ax25_dev) {
s->next = ax25_dev->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
kfree(ax25_dev);
ax25_register_sysctl();
return;
......@@ -150,8 +161,8 @@ void ax25_dev_device_down(struct net_device *dev)
s = s->next;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
restore_flags(flags);
ax25_register_sysctl();
}
......@@ -202,12 +213,17 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
*/
void __exit ax25_dev_free(void)
{
ax25_dev *s, *ax25_dev = ax25_dev_list;
ax25_dev *s, *ax25_dev;
unsigned long flags;
spin_lock_irqsave(&ax25_dev_lock, flags);
ax25_dev = ax25_dev_list;
while (ax25_dev != NULL) {
s = ax25_dev;
ax25_dev = ax25_dev->next;
kfree(s);
}
ax25_dev_list = NULL;
spin_unlock_irqrestore(&ax25_dev_lock, flags);
}
......@@ -8,6 +8,7 @@
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
static int min_ipdefmode[] = {0}, max_ipdefmode[] = {1};
......@@ -102,9 +103,11 @@ static const ctl_table ax25_param_table[] = {
void ax25_register_sysctl(void)
{
unsigned long flags;
ax25_dev *ax25_dev;
int n, k;
spin_lock_irqsave(&ax25_dev_lock, flags);
for (ax25_table_size = sizeof(ctl_table), ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
ax25_table_size += sizeof(ctl_table);
......@@ -119,6 +122,7 @@ void ax25_register_sysctl(void)
while (n--)
kfree(ax25_table[n].child);
kfree(ax25_table);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
return;
}
memcpy(child, ax25_param_table, sizeof(ax25_param_table));
......@@ -144,6 +148,7 @@ void ax25_register_sysctl(void)
n++;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
ax25_dir_table[0].child = ax25_table;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment