Commit 6244be2f authored by Ralf Bächle's avatar Ralf Bächle

Convert ax25_route_list by a rw_lock, no longer an interrup-save

spinlock.
Reformat switch statements.
parent be0eacc3
......@@ -732,7 +732,8 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
break;
case SO_BINDTODEVICE:
if (optlen > IFNAMSIZ) optlen=IFNAMSIZ;
if (optlen > IFNAMSIZ)
optlen=IFNAMSIZ;
if (copy_from_user(devname, optval, optlen)) {
res = -EFAULT;
break;
......@@ -885,6 +886,7 @@ int ax25_create(struct socket *sock, int protocol)
if (protocol == 0 || protocol == PF_AX25)
protocol = AX25_P_TEXT;
break;
case SOCK_SEQPACKET:
switch (protocol) {
case 0:
......@@ -917,6 +919,7 @@ int ax25_create(struct socket *sock, int protocol)
break;
}
break;
case SOCK_RAW:
break;
default:
......@@ -1325,8 +1328,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
#ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE:
ax25->modulus = AX25_MODULUS;
ax25->window =
ax25->ax25_dev->values[AX25_VALUES_WINDOW];
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
if (ax25->ax25_dev->dama.slave)
ax25_ds_establish_data_link(ax25);
else
......
......@@ -95,11 +95,13 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
break;
case AX25_DM:
if (pf) ax25_disconnect(ax25, ECONNREFUSED);
if (pf)
ax25_disconnect(ax25, ECONNREFUSED);
break;
default:
if (pf) ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
if (pf)
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
break;
}
......
......@@ -182,7 +182,6 @@ void ax25_ds_idletimer_expiry(ax25_cb *ax25)
void ax25_ds_t1_timeout(ax25_cb *ax25)
{
switch (ax25->state) {
case AX25_STATE_1:
if (ax25->n2count == ax25->n2) {
if (ax25->modulus == AX25_MODULUS) {
......
......@@ -41,7 +41,7 @@ static struct protocol_struct {
unsigned int pid;
int (*func)(struct sk_buff *, ax25_cb *);
} *protocol_list;
static spinlock_t protocol_list_lock = SPIN_LOCK_UNLOCKED;
static rwlock_t protocol_list_lock = RW_LOCK_UNLOCKED;
static struct linkfail_struct {
struct linkfail_struct *next;
......@@ -59,7 +59,6 @@ static spinlock_t listen_lock = SPIN_LOCK_UNLOCKED;
int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_cb *))
{
struct protocol_struct *protocol;
unsigned long flags;
if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
return 0;
......@@ -73,10 +72,10 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
protocol->pid = pid;
protocol->func = func;
spin_lock_irqsave(&protocol_list_lock, flags);
write_lock(&protocol_list_lock);
protocol->next = protocol_list;
protocol_list = protocol;
spin_unlock_irqrestore(&protocol_list_lock, flags);
write_unlock(&protocol_list_lock);
return 1;
}
......@@ -84,18 +83,17 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
void ax25_protocol_release(unsigned int pid)
{
struct protocol_struct *s, *protocol;
unsigned long flags;
spin_lock_irqsave(&protocol_list_lock, flags);
write_lock(&protocol_list_lock);
protocol = protocol_list;
if (protocol == NULL) {
spin_unlock_irqrestore(&protocol_list_lock, flags);
write_unlock(&protocol_list_lock);
return;
}
if (protocol->pid == pid) {
protocol_list = protocol->next;
spin_unlock_irqrestore(&protocol_list_lock, flags);
write_unlock(&protocol_list_lock);
kfree(protocol);
return;
}
......@@ -104,14 +102,14 @@ void ax25_protocol_release(unsigned int pid)
if (protocol->next->pid == pid) {
s = protocol->next;
protocol->next = protocol->next->next;
spin_unlock_irqrestore(&protocol_list_lock, flags);
write_unlock(&protocol_list_lock);
kfree(s);
return;
}
protocol = protocol->next;
}
spin_unlock_irqrestore(&protocol_list_lock, flags);
write_unlock(&protocol_list_lock);
}
int ax25_linkfail_register(void (*func)(ax25_cb *, int))
......@@ -220,15 +218,14 @@ int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
{
int (*res)(struct sk_buff *, ax25_cb *) = NULL;
struct protocol_struct *protocol;
unsigned long flags;
spin_lock_irqsave(&protocol_list_lock, flags);
read_lock(&protocol_list_lock);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid) {
res = protocol->func;
break;
}
spin_unlock_irqrestore(&protocol_list_lock, flags);
read_unlock(&protocol_list_lock);
return res;
}
......@@ -261,16 +258,15 @@ void ax25_link_failed(ax25_cb *ax25, int reason)
int ax25_protocol_is_registered(unsigned int pid)
{
struct protocol_struct *protocol;
unsigned long flags;
int res = 0;
spin_lock_irqsave(&protocol_list_lock, flags);
read_lock(&protocol_list_lock);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid) {
res = 1;
break;
}
spin_unlock_irqrestore(&protocol_list_lock, flags);
read_unlock(&protocol_list_lock);
return res;
}
......@@ -66,7 +66,7 @@
#include <linux/init.h>
static ax25_route *ax25_route_list;
static spinlock_t ax25_route_lock = SPIN_LOCK_UNLOCKED;
static rwlock_t ax25_route_lock = RW_LOCK_UNLOCKED;
static ax25_route *ax25_find_route(ax25_address *, struct net_device *);
......@@ -89,9 +89,8 @@ static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
void ax25_rt_device_down(struct net_device *dev)
{
ax25_route *s, *t, *ax25_rt;
unsigned long flags;
spin_lock_irqsave(&ax25_route_lock, flags);
write_lock(&ax25_route_lock);
ax25_rt = ax25_route_list;
while (ax25_rt != NULL) {
s = ax25_rt;
......@@ -116,12 +115,11 @@ void ax25_rt_device_down(struct net_device *dev)
}
}
}
spin_unlock_irqrestore(&ax25_route_lock, flags);
write_unlock(&ax25_route_lock);
}
int ax25_rt_ioctl(unsigned int cmd, void *arg)
{
unsigned long flags;
ax25_route *s, *t, *ax25_rt;
struct ax25_routes_struct route;
struct ax25_route_opt_struct rt_option;
......@@ -136,6 +134,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
return -EINVAL;
if (route.digi_count > AX25_MAX_DIGIS)
return -EINVAL;
write_lock(ax25_route_lock);
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) {
if (ax25_rt->digipeat != NULL) {
......@@ -143,8 +142,10 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
ax25_rt->digipeat = NULL;
}
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock);
return -ENOMEM;
}
ax25_rt->digipeat->lastrepeat = -1;
ax25_rt->digipeat->ndigi = route.digi_count;
for (i = 0; i < route.digi_count; i++) {
......@@ -155,14 +156,17 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
return 0;
}
}
if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL)
if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock);
return -ENOMEM;
}
ax25_rt->callsign = route.dest_addr;
ax25_rt->dev = ax25_dev->dev;
ax25_rt->digipeat = NULL;
ax25_rt->ip_mode = ' ';
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock);
kfree(ax25_rt);
return -ENOMEM;
}
......@@ -173,10 +177,9 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
}
spin_lock_irqsave(&ax25_route_lock, flags);
ax25_rt->next = ax25_route_list;
ax25_route_list = ax25_rt;
spin_unlock_irqrestore(&ax25_route_lock, flags);
write_unlock(ax25_route_lock);
break;
......@@ -215,6 +218,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
return -EFAULT;
if ((ax25_dev = ax25_addr_ax25dev(&rt_option.port_addr)) == NULL)
return -EINVAL;
write_lock(ax25_route_lock);
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25_rt->dev == ax25_dev->dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) {
switch (rt_option.cmd) {
......@@ -234,6 +238,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
}
}
}
write_unlock(ax25_route_lock);
break;
default:
......@@ -246,14 +251,13 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
{
ax25_route *ax25_rt;
unsigned long flags;
int len = 0;
off_t pos = 0;
off_t begin = 0;
char *callsign;
int i;
spin_lock_irqsave(&ax25_route_lock, flags);
read_lock(&ax25_route_lock);
len += sprintf(buffer, "callsign dev mode digipeaters\n");
......@@ -294,7 +298,7 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length)
break;
}
spin_unlock_irqrestore(&ax25_route_lock, flags);
read_unlock(&ax25_route_lock);
*start = buffer + (offset - begin);
len -= (offset - begin);
......@@ -314,6 +318,7 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev)
ax25_route *ax25_def_rt = NULL;
ax25_route *ax25_rt;
read_lock(&ax25_route_lock);
/*
* Bind to the physical interface we heard them on, or the default
* route if none is found;
......@@ -331,6 +336,7 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev)
ax25_def_rt = ax25_rt;
}
}
read_unlock(&ax25_route_lock);
if (ax25_spe_rt != NULL)
return ax25_spe_rt;
......@@ -448,6 +454,7 @@ void __exit ax25_rt_free(void)
{
ax25_route *s, *ax25_rt = ax25_route_list;
write_unlock(&ax25_route_lock);
while (ax25_rt != NULL) {
s = ax25_rt;
ax25_rt = ax25_rt->next;
......@@ -457,4 +464,5 @@ void __exit ax25_rt_free(void)
kfree(s);
}
write_unlock(&ax25_route_lock);
}
......@@ -142,7 +142,8 @@ static int ax25_std_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
case AX25_DM:
case AX25_UA:
if (pf) ax25_disconnect(ax25, 0);
if (pf)
ax25_disconnect(ax25, 0);
break;
case AX25_I:
......@@ -397,7 +398,8 @@ static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
}
ax25_frames_acked(ax25, nr);
if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
if (pf) ax25_std_enquiry_response(ax25);
if (pf)
ax25_std_enquiry_response(ax25);
break;
}
if (ns == ax25->vr) {
......
......@@ -47,7 +47,6 @@
void ax25_std_heartbeat_expiry(ax25_cb *ax25)
{
switch (ax25->state) {
case AX25_STATE_0:
/* Magic here: If we listen() and a new link dies before it
is accepted() it isn't 'dead' so doesn't get removed. */
......
......@@ -48,7 +48,7 @@
*/
static ax25_uid_assoc *ax25_uid_list;
static spinlock_t ax25_uid_lock = SPIN_LOCK_UNLOCKED;
static rwlock_t ax25_uid_lock = RW_LOCK_UNLOCKED;
int ax25_uid_policy = 0;
......@@ -56,16 +56,15 @@ ax25_address *ax25_findbyuid(uid_t uid)
{
ax25_uid_assoc *ax25_uid;
ax25_address *res = NULL;
unsigned long flags;
spin_lock_irqsave(&ax25_uid_lock, flags);
read_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25_uid->uid == uid) {
res = &ax25_uid->call;
break;
}
}
spin_lock_irqsave(&ax25_uid_lock, flags);
read_unlock(&ax25_uid_lock);
return NULL;
}
......@@ -73,20 +72,19 @@ ax25_address *ax25_findbyuid(uid_t uid)
int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
{
ax25_uid_assoc *s, *ax25_uid;
unsigned long flags;
unsigned long res;
switch (cmd) {
case SIOCAX25GETUID:
res = -ENOENT;
spin_lock_irqsave(&ax25_uid_lock, flags);
read_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
res = ax25_uid->uid;
break;
}
}
spin_lock_irqsave(&ax25_uid_lock, flags);
read_unlock(&ax25_uid_lock);
return res;
......@@ -103,10 +101,10 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
ax25_uid->uid = sax->sax25_uid;
ax25_uid->call = sax->sax25_call;
spin_lock_irqsave(&ax25_uid_lock, flags);
write_lock(&ax25_uid_lock);
ax25_uid->next = ax25_uid_list;
ax25_uid_list = ax25_uid;
spin_unlock_irqrestore(&ax25_uid_lock, flags);
write_unlock(&ax25_uid_lock);
return 0;
......@@ -114,32 +112,32 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&ax25_uid_lock, flags);
write_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
break;
}
}
if (ax25_uid == NULL) {
spin_unlock_irqrestore(&ax25_uid_lock, flags);
write_unlock(&ax25_uid_lock);
return -ENOENT;
}
if ((s = ax25_uid_list) == ax25_uid) {
ax25_uid_list = s->next;
spin_unlock_irqrestore(&ax25_uid_lock, flags);
write_unlock(&ax25_uid_lock);
kfree(ax25_uid);
return 0;
}
while (s != NULL && s->next != NULL) {
if (s->next == ax25_uid) {
s->next = ax25_uid->next;
spin_unlock_irqrestore(&ax25_uid_lock, flags);
write_unlock(&ax25_uid_lock);
kfree(ax25_uid);
return 0;
}
s = s->next;
}
spin_unlock_irqrestore(&ax25_uid_lock, flags);
write_unlock(&ax25_uid_lock);
return -ENOENT;
......@@ -152,13 +150,12 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
{
unsigned long flags;
ax25_uid_assoc *pt;
int len = 0;
off_t pos = 0;
off_t begin = 0;
spin_lock_irqsave(&ax25_uid_lock, flags);
read_lock(&ax25_uid_lock);
len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy);
for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
......@@ -174,7 +171,7 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length)
break;
}
spin_unlock_irqrestore(&ax25_uid_lock, flags);
read_unlock(&ax25_uid_lock);
*start = buffer + (offset - begin);
len -= offset - begin;
......@@ -191,9 +188,8 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
void __exit ax25_uid_free(void)
{
ax25_uid_assoc *s, *ax25_uid;
unsigned long flags;
spin_lock_irqsave(&ax25_uid_lock, flags);
write_lock(&ax25_uid_lock);
ax25_uid = ax25_uid_list;
while (ax25_uid != NULL) {
s = ax25_uid;
......@@ -202,5 +198,5 @@ void __exit ax25_uid_free(void)
kfree(s);
}
ax25_uid_list = NULL;
spin_unlock_irqrestore(&ax25_uid_lock, flags);
write_unlock(&ax25_uid_lock);
}
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