diff options
Diffstat (limited to 'net/econet/af_econet.c')
| -rw-r--r-- | net/econet/af_econet.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 2a5a8053e000..dc54bd0d083b 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
| @@ -48,7 +48,7 @@ | |||
| 48 | 48 | ||
| 49 | static const struct proto_ops econet_ops; | 49 | static const struct proto_ops econet_ops; |
| 50 | static struct hlist_head econet_sklist; | 50 | static struct hlist_head econet_sklist; |
| 51 | static DEFINE_RWLOCK(econet_lock); | 51 | static DEFINE_SPINLOCK(econet_lock); |
| 52 | static DEFINE_MUTEX(econet_mutex); | 52 | static DEFINE_MUTEX(econet_mutex); |
| 53 | 53 | ||
| 54 | /* Since there are only 256 possible network numbers (or fewer, depends | 54 | /* Since there are only 256 possible network numbers (or fewer, depends |
| @@ -98,16 +98,16 @@ struct ec_cb | |||
| 98 | 98 | ||
| 99 | static void econet_remove_socket(struct hlist_head *list, struct sock *sk) | 99 | static void econet_remove_socket(struct hlist_head *list, struct sock *sk) |
| 100 | { | 100 | { |
| 101 | write_lock_bh(&econet_lock); | 101 | spin_lock_bh(&econet_lock); |
| 102 | sk_del_node_init(sk); | 102 | sk_del_node_init(sk); |
| 103 | write_unlock_bh(&econet_lock); | 103 | spin_unlock_bh(&econet_lock); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static void econet_insert_socket(struct hlist_head *list, struct sock *sk) | 106 | static void econet_insert_socket(struct hlist_head *list, struct sock *sk) |
| 107 | { | 107 | { |
| 108 | write_lock_bh(&econet_lock); | 108 | spin_lock_bh(&econet_lock); |
| 109 | sk_add_node(sk, list); | 109 | sk_add_node(sk, list); |
| 110 | write_unlock_bh(&econet_lock); | 110 | spin_unlock_bh(&econet_lock); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | /* | 113 | /* |
| @@ -782,15 +782,19 @@ static struct sock *ec_listening_socket(unsigned char port, unsigned char | |||
| 782 | struct sock *sk; | 782 | struct sock *sk; |
| 783 | struct hlist_node *node; | 783 | struct hlist_node *node; |
| 784 | 784 | ||
| 785 | spin_lock(&econet_lock); | ||
| 785 | sk_for_each(sk, node, &econet_sklist) { | 786 | sk_for_each(sk, node, &econet_sklist) { |
| 786 | struct econet_sock *opt = ec_sk(sk); | 787 | struct econet_sock *opt = ec_sk(sk); |
| 787 | if ((opt->port == port || opt->port == 0) && | 788 | if ((opt->port == port || opt->port == 0) && |
| 788 | (opt->station == station || opt->station == 0) && | 789 | (opt->station == station || opt->station == 0) && |
| 789 | (opt->net == net || opt->net == 0)) | 790 | (opt->net == net || opt->net == 0)) { |
| 791 | sock_hold(sk); | ||
| 790 | goto found; | 792 | goto found; |
| 793 | } | ||
| 791 | } | 794 | } |
| 792 | sk = NULL; | 795 | sk = NULL; |
| 793 | found: | 796 | found: |
| 797 | spin_unlock(&econet_lock); | ||
| 794 | return sk; | 798 | return sk; |
| 795 | } | 799 | } |
| 796 | 800 | ||
| @@ -852,7 +856,7 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len) | |||
| 852 | { | 856 | { |
| 853 | struct iphdr *ip = ip_hdr(skb); | 857 | struct iphdr *ip = ip_hdr(skb); |
| 854 | unsigned char stn = ntohl(ip->saddr) & 0xff; | 858 | unsigned char stn = ntohl(ip->saddr) & 0xff; |
| 855 | struct sock *sk; | 859 | struct sock *sk = NULL; |
| 856 | struct sk_buff *newskb; | 860 | struct sk_buff *newskb; |
| 857 | struct ec_device *edev = skb->dev->ec_ptr; | 861 | struct ec_device *edev = skb->dev->ec_ptr; |
| 858 | 862 | ||
| @@ -882,10 +886,13 @@ static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len) | |||
| 882 | } | 886 | } |
| 883 | 887 | ||
| 884 | aun_send_response(ip->saddr, ah->handle, 3, 0); | 888 | aun_send_response(ip->saddr, ah->handle, 3, 0); |
| 889 | sock_put(sk); | ||
| 885 | return; | 890 | return; |
| 886 | 891 | ||
| 887 | bad: | 892 | bad: |
| 888 | aun_send_response(ip->saddr, ah->handle, 4, 0); | 893 | aun_send_response(ip->saddr, ah->handle, 4, 0); |
| 894 | if (sk) | ||
| 895 | sock_put(sk); | ||
| 889 | } | 896 | } |
| 890 | 897 | ||
| 891 | /* | 898 | /* |
| @@ -1050,7 +1057,7 @@ release: | |||
| 1050 | static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) | 1057 | static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) |
| 1051 | { | 1058 | { |
| 1052 | struct ec_framehdr *hdr; | 1059 | struct ec_framehdr *hdr; |
| 1053 | struct sock *sk; | 1060 | struct sock *sk = NULL; |
| 1054 | struct ec_device *edev = dev->ec_ptr; | 1061 | struct ec_device *edev = dev->ec_ptr; |
| 1055 | 1062 | ||
| 1056 | if (!net_eq(dev_net(dev), &init_net)) | 1063 | 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 | |||
| 1085 | if (ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb, | 1092 | if (ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb, |
| 1086 | hdr->port)) | 1093 | hdr->port)) |
| 1087 | goto drop; | 1094 | goto drop; |
| 1088 | 1095 | sock_put(sk); | |
| 1089 | return NET_RX_SUCCESS; | 1096 | return NET_RX_SUCCESS; |
| 1090 | 1097 | ||
| 1091 | drop: | 1098 | drop: |
| 1099 | if (sk) | ||
| 1100 | sock_put(sk); | ||
| 1092 | kfree_skb(skb); | 1101 | kfree_skb(skb); |
| 1093 | return NET_RX_DROP; | 1102 | return NET_RX_DROP; |
| 1094 | } | 1103 | } |
