|
@@ -48,7 +48,7 @@
|
|
|
|
|
|
static const struct proto_ops econet_ops;
|
|
static const struct proto_ops econet_ops;
|
|
static struct hlist_head econet_sklist;
|
|
static struct hlist_head econet_sklist;
|
|
-static DEFINE_RWLOCK(econet_lock);
|
|
|
|
|
|
+static DEFINE_SPINLOCK(econet_lock);
|
|
static DEFINE_MUTEX(econet_mutex);
|
|
static DEFINE_MUTEX(econet_mutex);
|
|
|
|
|
|
/* Since there are only 256 possible network numbers (or fewer, depends
|
|
/* Since there are only 256 possible network numbers (or fewer, depends
|
|
@@ -98,16 +98,16 @@ struct ec_cb
|
|
|
|
|
|
static void econet_remove_socket(struct hlist_head *list, struct sock *sk)
|
|
static void econet_remove_socket(struct hlist_head *list, struct sock *sk)
|
|
{
|
|
{
|
|
- write_lock_bh(&econet_lock);
|
|
|
|
|
|
+ spin_lock_bh(&econet_lock);
|
|
sk_del_node_init(sk);
|
|
sk_del_node_init(sk);
|
|
- write_unlock_bh(&econet_lock);
|
|
|
|
|
|
+ spin_unlock_bh(&econet_lock);
|
|
}
|
|
}
|
|
|
|
|
|
static void econet_insert_socket(struct hlist_head *list, struct sock *sk)
|
|
static void econet_insert_socket(struct hlist_head *list, struct sock *sk)
|
|
{
|
|
{
|
|
- write_lock_bh(&econet_lock);
|
|
|
|
|
|
+ spin_lock_bh(&econet_lock);
|
|
sk_add_node(sk, list);
|
|
sk_add_node(sk, list);
|
|
- write_unlock_bh(&econet_lock);
|
|
|
|
|
|
+ spin_unlock_bh(&econet_lock);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -782,15 +782,19 @@ static struct sock *ec_listening_socket(unsigned char port, unsigned char
|
|
struct sock *sk;
|
|
struct sock *sk;
|
|
struct hlist_node *node;
|
|
struct hlist_node *node;
|
|
|
|
|
|
|
|
+ spin_lock(&econet_lock);
|
|
sk_for_each(sk, node, &econet_sklist) {
|
|
sk_for_each(sk, node, &econet_sklist) {
|
|
struct econet_sock *opt = ec_sk(sk);
|
|
struct econet_sock *opt = ec_sk(sk);
|
|
if ((opt->port == port || opt->port == 0) &&
|
|
if ((opt->port == port || opt->port == 0) &&
|
|
(opt->station == station || opt->station == 0) &&
|
|
(opt->station == station || opt->station == 0) &&
|
|
- (opt->net == net || opt->net == 0))
|
|
|
|
|
|
+ (opt->net == net || opt->net == 0)) {
|
|
|
|
+ sock_hold(sk);
|
|
goto found;
|
|
goto found;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
sk = NULL;
|
|
sk = NULL;
|
|
found:
|
|
found:
|
|
|
|
+ spin_unlock(&econet_lock);
|
|
return sk;
|
|
return sk;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -852,7 +856,7 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
|
|
{
|
|
{
|
|
struct iphdr *ip = ip_hdr(skb);
|
|
struct iphdr *ip = ip_hdr(skb);
|
|
unsigned char stn = ntohl(ip->saddr) & 0xff;
|
|
unsigned char stn = ntohl(ip->saddr) & 0xff;
|
|
- struct sock *sk;
|
|
|
|
|
|
+ struct sock *sk = NULL;
|
|
struct sk_buff *newskb;
|
|
struct sk_buff *newskb;
|
|
struct ec_device *edev = skb->dev->ec_ptr;
|
|
struct ec_device *edev = skb->dev->ec_ptr;
|
|
|
|
|
|
@@ -882,10 +886,13 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
|
|
}
|
|
}
|
|
|
|
|
|
aun_send_response(ip->saddr, ah->handle, 3, 0);
|
|
aun_send_response(ip->saddr, ah->handle, 3, 0);
|
|
|
|
+ sock_put(sk);
|
|
return;
|
|
return;
|
|
|
|
|
|
bad:
|
|
bad:
|
|
aun_send_response(ip->saddr, ah->handle, 4, 0);
|
|
aun_send_response(ip->saddr, ah->handle, 4, 0);
|
|
|
|
+ if (sk)
|
|
|
|
+ sock_put(sk);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1050,7 +1057,7 @@ release:
|
|
static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
|
|
static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
|
|
{
|
|
{
|
|
struct ec_framehdr *hdr;
|
|
struct ec_framehdr *hdr;
|
|
- struct sock *sk;
|
|
|
|
|
|
+ struct sock *sk = NULL;
|
|
struct ec_device *edev = dev->ec_ptr;
|
|
struct ec_device *edev = dev->ec_ptr;
|
|
|
|
|
|
if (!net_eq(dev_net(dev), &init_net))
|
|
if (!net_eq(dev_net(dev), &init_net))
|
|
@@ -1085,10 +1092,12 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
|
|
if (ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb,
|
|
if (ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb,
|
|
hdr->port))
|
|
hdr->port))
|
|
goto drop;
|
|
goto drop;
|
|
-
|
|
|
|
|
|
+ sock_put(sk);
|
|
return NET_RX_SUCCESS;
|
|
return NET_RX_SUCCESS;
|
|
|
|
|
|
drop:
|
|
drop:
|
|
|
|
+ if (sk)
|
|
|
|
+ sock_put(sk);
|
|
kfree_skb(skb);
|
|
kfree_skb(skb);
|
|
return NET_RX_DROP;
|
|
return NET_RX_DROP;
|
|
}
|
|
}
|