diff options
| author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-09-22 03:43:05 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-09-22 03:43:05 -0400 |
| commit | 6e2144b76840be09924de1626e2dcd7b315f75b3 (patch) | |
| tree | 33044cb63f368270229e2b40aa2ad024325c7e8b /net/llc | |
| parent | 04e4223f44b89e50f275cb6b95a58ebe2c4909be (diff) | |
[LLC]: Use refcounting with struct llc_sap
Signed-off-by: Jochen Friedrich <jochen@scram.de>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Diffstat (limited to 'net/llc')
| -rw-r--r-- | net/llc/af_llc.c | 11 | ||||
| -rw-r--r-- | net/llc/llc_c_ac.c | 1 | ||||
| -rw-r--r-- | net/llc/llc_conn.c | 28 | ||||
| -rw-r--r-- | net/llc/llc_core.c | 34 | ||||
| -rw-r--r-- | net/llc/llc_input.c | 9 |
5 files changed, 39 insertions, 44 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index ad9aad807aa8..a75b8f2aab19 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | * See the GNU General Public License for more details. | 21 | * See the GNU General Public License for more details. |
| 22 | */ | 22 | */ |
| 23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
| 24 | #include <linux/compiler.h> | ||
| 24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 26 | #include <linux/rtnetlink.h> | 27 | #include <linux/rtnetlink.h> |
| @@ -188,10 +189,6 @@ static int llc_ui_release(struct socket *sock) | |||
| 188 | if (!sock_flag(sk, SOCK_ZAPPED)) | 189 | if (!sock_flag(sk, SOCK_ZAPPED)) |
| 189 | llc_sap_remove_socket(llc->sap, sk); | 190 | llc_sap_remove_socket(llc->sap, sk); |
| 190 | release_sock(sk); | 191 | release_sock(sk); |
| 191 | if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) { | ||
| 192 | llc_release_sockets(llc->sap); | ||
| 193 | llc_sap_close(llc->sap); | ||
| 194 | } | ||
| 195 | if (llc->dev) | 192 | if (llc->dev) |
| 196 | dev_put(llc->dev); | 193 | dev_put(llc->dev); |
| 197 | sock_put(sk); | 194 | sock_put(sk); |
| @@ -220,6 +217,7 @@ static int llc_ui_autoport(void) | |||
| 220 | llc_ui_sap_last_autoport = i + 2; | 217 | llc_ui_sap_last_autoport = i + 2; |
| 221 | goto out; | 218 | goto out; |
| 222 | } | 219 | } |
| 220 | llc_sap_put(sap); | ||
| 223 | } | 221 | } |
| 224 | llc_ui_sap_last_autoport = LLC_SAP_DYN_START; | 222 | llc_ui_sap_last_autoport = LLC_SAP_DYN_START; |
| 225 | tries++; | 223 | tries++; |
| @@ -310,6 +308,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) | |||
| 310 | rc = -EBUSY; /* some other network layer is using the sap */ | 308 | rc = -EBUSY; /* some other network layer is using the sap */ |
| 311 | if (!sap) | 309 | if (!sap) |
| 312 | goto out; | 310 | goto out; |
| 311 | llc_sap_hold(sap); | ||
| 313 | } else { | 312 | } else { |
| 314 | struct llc_addr laddr, daddr; | 313 | struct llc_addr laddr, daddr; |
| 315 | struct sock *ask; | 314 | struct sock *ask; |
| @@ -326,7 +325,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) | |||
| 326 | ask = llc_lookup_established(sap, &daddr, &laddr); | 325 | ask = llc_lookup_established(sap, &daddr, &laddr); |
| 327 | if (ask) { | 326 | if (ask) { |
| 328 | sock_put(ask); | 327 | sock_put(ask); |
| 329 | goto out; | 328 | goto out_put; |
| 330 | } | 329 | } |
| 331 | } | 330 | } |
| 332 | llc->laddr.lsap = addr->sllc_sap; | 331 | llc->laddr.lsap = addr->sllc_sap; |
| @@ -336,6 +335,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) | |||
| 336 | llc_sap_add_socket(sap, sk); | 335 | llc_sap_add_socket(sap, sk); |
| 337 | sock_reset_flag(sk, SOCK_ZAPPED); | 336 | sock_reset_flag(sk, SOCK_ZAPPED); |
| 338 | rc = 0; | 337 | rc = 0; |
| 338 | out_put: | ||
| 339 | llc_sap_put(sap); | ||
| 339 | out: | 340 | out: |
| 340 | return rc; | 341 | return rc; |
| 341 | } | 342 | } |
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index c1e75103189a..05236c2cbb9e 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c | |||
| @@ -75,6 +75,7 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) | |||
| 75 | llc->dev = skb->dev; | 75 | llc->dev = skb->dev; |
| 76 | ev->ind_prim = LLC_CONN_PRIM; | 76 | ev->ind_prim = LLC_CONN_PRIM; |
| 77 | rc = 0; | 77 | rc = 0; |
| 78 | llc_sap_put(sap); | ||
| 78 | } | 79 | } |
| 79 | return rc; | 80 | return rc; |
| 80 | } | 81 | } |
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 9f0e10e0978d..ab9e6d7e2875 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c | |||
| @@ -633,6 +633,7 @@ static int llc_find_offset(int state, int ev_type) | |||
| 633 | */ | 633 | */ |
| 634 | void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) | 634 | void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) |
| 635 | { | 635 | { |
| 636 | llc_sap_hold(sap); | ||
| 636 | write_lock_bh(&sap->sk_list.lock); | 637 | write_lock_bh(&sap->sk_list.lock); |
| 637 | llc_sk(sk)->sap = sap; | 638 | llc_sk(sk)->sap = sap; |
| 638 | sk_add_node(sk, &sap->sk_list.list); | 639 | sk_add_node(sk, &sap->sk_list.list); |
| @@ -652,6 +653,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) | |||
| 652 | write_lock_bh(&sap->sk_list.lock); | 653 | write_lock_bh(&sap->sk_list.lock); |
| 653 | sk_del_node_init(sk); | 654 | sk_del_node_init(sk); |
| 654 | write_unlock_bh(&sap->sk_list.lock); | 655 | write_unlock_bh(&sap->sk_list.lock); |
| 656 | llc_sap_put(sap); | ||
| 655 | } | 657 | } |
| 656 | 658 | ||
| 657 | /** | 659 | /** |
| @@ -731,32 +733,6 @@ static atomic_t llc_sock_nr; | |||
| 731 | #endif | 733 | #endif |
| 732 | 734 | ||
| 733 | /** | 735 | /** |
| 734 | * llc_release_sockets - releases all sockets in a sap | ||
| 735 | * @sap: sap to release its sockets | ||
| 736 | * | ||
| 737 | * Releases all connections of a sap. Returns 0 if all actions complete | ||
| 738 | * successfully, nonzero otherwise | ||
| 739 | */ | ||
| 740 | int llc_release_sockets(struct llc_sap *sap) | ||
| 741 | { | ||
| 742 | int rc = 0; | ||
| 743 | struct sock *sk; | ||
| 744 | struct hlist_node *node; | ||
| 745 | |||
| 746 | write_lock_bh(&sap->sk_list.lock); | ||
| 747 | |||
| 748 | sk_for_each(sk, node, &sap->sk_list.list) { | ||
| 749 | llc_sk(sk)->state = LLC_CONN_STATE_TEMP; | ||
| 750 | |||
| 751 | if (llc_send_disc(sk)) | ||
| 752 | rc = 1; | ||
| 753 | } | ||
| 754 | |||
| 755 | write_unlock_bh(&sap->sk_list.lock); | ||
| 756 | return rc; | ||
| 757 | } | ||
| 758 | |||
| 759 | /** | ||
| 760 | * llc_backlog_rcv - Processes rx frames and expired timers. | 736 | * llc_backlog_rcv - Processes rx frames and expired timers. |
| 761 | * @sk: LLC sock (p8022 connection) | 737 | * @sk: LLC sock (p8022 connection) |
| 762 | * @skb: queued rx frame or event | 738 | * @skb: queued rx frame or event |
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 9727455bf0e7..9ccff1266b26 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c | |||
| @@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void) | |||
| 40 | sap->state = LLC_SAP_STATE_ACTIVE; | 40 | sap->state = LLC_SAP_STATE_ACTIVE; |
| 41 | memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); | 41 | memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); |
| 42 | rwlock_init(&sap->sk_list.lock); | 42 | rwlock_init(&sap->sk_list.lock); |
| 43 | atomic_set(&sap->refcnt, 1); | ||
| 43 | } | 44 | } |
| 44 | return sap; | 45 | return sap; |
| 45 | } | 46 | } |
| @@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void) | |||
| 52 | */ | 53 | */ |
| 53 | static void llc_add_sap(struct llc_sap *sap) | 54 | static void llc_add_sap(struct llc_sap *sap) |
| 54 | { | 55 | { |
| 55 | write_lock_bh(&llc_sap_list_lock); | ||
| 56 | list_add_tail(&sap->node, &llc_sap_list); | 56 | list_add_tail(&sap->node, &llc_sap_list); |
| 57 | write_unlock_bh(&llc_sap_list_lock); | ||
| 58 | } | 57 | } |
| 59 | 58 | ||
| 60 | /** | 59 | /** |
| @@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap) | |||
| 70 | write_unlock_bh(&llc_sap_list_lock); | 69 | write_unlock_bh(&llc_sap_list_lock); |
| 71 | } | 70 | } |
| 72 | 71 | ||
| 72 | struct llc_sap *__llc_sap_find(unsigned char sap_value) | ||
| 73 | { | ||
| 74 | struct llc_sap* sap; | ||
| 75 | |||
| 76 | list_for_each_entry(sap, &llc_sap_list, node) | ||
| 77 | if (sap->laddr.lsap == sap_value) | ||
| 78 | goto out; | ||
| 79 | sap = NULL; | ||
| 80 | out: | ||
| 81 | return sap; | ||
| 82 | } | ||
| 83 | |||
| 73 | /** | 84 | /** |
| 74 | * llc_sap_find - searchs a SAP in station | 85 | * llc_sap_find - searchs a SAP in station |
| 75 | * @sap_value: sap to be found | 86 | * @sap_value: sap to be found |
| 76 | * | 87 | * |
| 77 | * Searchs for a sap in the sap list of the LLC's station upon the sap ID. | 88 | * Searchs for a sap in the sap list of the LLC's station upon the sap ID. |
| 89 | * If the sap is found it will be refcounted and the user will have to do | ||
| 90 | * a llc_sap_put after use. | ||
| 78 | * Returns the sap or %NULL if not found. | 91 | * Returns the sap or %NULL if not found. |
| 79 | */ | 92 | */ |
| 80 | struct llc_sap *llc_sap_find(unsigned char sap_value) | 93 | struct llc_sap *llc_sap_find(unsigned char sap_value) |
| @@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) | |||
| 82 | struct llc_sap* sap; | 95 | struct llc_sap* sap; |
| 83 | 96 | ||
| 84 | read_lock_bh(&llc_sap_list_lock); | 97 | read_lock_bh(&llc_sap_list_lock); |
| 85 | list_for_each_entry(sap, &llc_sap_list, node) | 98 | sap = __llc_sap_find(sap_value); |
| 86 | if (sap->laddr.lsap == sap_value) | 99 | if (sap) |
| 87 | goto out; | 100 | llc_sap_hold(sap); |
| 88 | sap = NULL; | ||
| 89 | out: | ||
| 90 | read_unlock_bh(&llc_sap_list_lock); | 101 | read_unlock_bh(&llc_sap_list_lock); |
| 91 | return sap; | 102 | return sap; |
| 92 | } | 103 | } |
| @@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap, | |||
| 106 | struct packet_type *pt, | 117 | struct packet_type *pt, |
| 107 | struct net_device *orig_dev)) | 118 | struct net_device *orig_dev)) |
| 108 | { | 119 | { |
| 109 | struct llc_sap *sap = llc_sap_find(lsap); | 120 | struct llc_sap *sap = NULL; |
| 110 | 121 | ||
| 111 | if (sap) { /* SAP already exists */ | 122 | write_lock_bh(&llc_sap_list_lock); |
| 112 | sap = NULL; | 123 | if (__llc_sap_find(lsap)) /* SAP already exists */ |
| 113 | goto out; | 124 | goto out; |
| 114 | } | ||
| 115 | sap = llc_sap_alloc(); | 125 | sap = llc_sap_alloc(); |
| 116 | if (!sap) | 126 | if (!sap) |
| 117 | goto out; | 127 | goto out; |
| 118 | sap->laddr.lsap = lsap; | 128 | sap->laddr.lsap = lsap; |
| 119 | sap->rcv_func = func; | 129 | sap->rcv_func = func; |
| 130 | llc_sap_hold(sap); | ||
| 120 | llc_add_sap(sap); | 131 | llc_add_sap(sap); |
| 121 | out: | 132 | out: |
| 133 | write_unlock_bh(&llc_sap_list_lock); | ||
| 122 | return sap; | 134 | return sap; |
| 123 | } | 135 | } |
| 124 | 136 | ||
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 60c1acac7c97..789eec426451 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c | |||
| @@ -166,17 +166,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 166 | */ | 166 | */ |
| 167 | if (sap->rcv_func) { | 167 | if (sap->rcv_func) { |
| 168 | sap->rcv_func(skb, dev, pt, orig_dev); | 168 | sap->rcv_func(skb, dev, pt, orig_dev); |
| 169 | goto out; | 169 | goto out_put; |
| 170 | } | 170 | } |
| 171 | dest = llc_pdu_type(skb); | 171 | dest = llc_pdu_type(skb); |
| 172 | if (unlikely(!dest || !llc_type_handlers[dest - 1])) | 172 | if (unlikely(!dest || !llc_type_handlers[dest - 1])) |
| 173 | goto drop; | 173 | goto drop_put; |
| 174 | llc_type_handlers[dest - 1](sap, skb); | 174 | llc_type_handlers[dest - 1](sap, skb); |
| 175 | out_put: | ||
| 176 | llc_sap_put(sap); | ||
| 175 | out: | 177 | out: |
| 176 | return 0; | 178 | return 0; |
| 177 | drop: | 179 | drop: |
| 178 | kfree_skb(skb); | 180 | kfree_skb(skb); |
| 179 | goto out; | 181 | goto out; |
| 182 | drop_put: | ||
| 183 | kfree_skb(skb); | ||
| 184 | goto out_put; | ||
| 180 | handle_station: | 185 | handle_station: |
| 181 | if (!llc_station_handler) | 186 | if (!llc_station_handler) |
| 182 | goto drop; | 187 | goto drop; |
