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