diff options
Diffstat (limited to 'net/bluetooth/l2cap_sock.c')
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 34bbe1c5e389..083f2bf065d4 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -34,6 +34,10 @@ | |||
34 | #include <net/bluetooth/l2cap.h> | 34 | #include <net/bluetooth/l2cap.h> |
35 | #include <net/bluetooth/smp.h> | 35 | #include <net/bluetooth/smp.h> |
36 | 36 | ||
37 | static struct bt_sock_list l2cap_sk_list = { | ||
38 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | ||
39 | }; | ||
40 | |||
37 | static const struct proto_ops l2cap_sock_ops; | 41 | static const struct proto_ops l2cap_sock_ops; |
38 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); | 42 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); |
39 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); | 43 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); |
@@ -824,7 +828,7 @@ static void l2cap_sock_kill(struct sock *sk) | |||
824 | 828 | ||
825 | /* Kill poor orphan */ | 829 | /* Kill poor orphan */ |
826 | 830 | ||
827 | l2cap_chan_destroy(l2cap_pi(sk)->chan); | 831 | l2cap_chan_put(l2cap_pi(sk)->chan); |
828 | sock_set_flag(sk, SOCK_DEAD); | 832 | sock_set_flag(sk, SOCK_DEAD); |
829 | sock_put(sk); | 833 | sock_put(sk); |
830 | } | 834 | } |
@@ -887,6 +891,8 @@ static int l2cap_sock_release(struct socket *sock) | |||
887 | if (!sk) | 891 | if (!sk) |
888 | return 0; | 892 | return 0; |
889 | 893 | ||
894 | bt_sock_unlink(&l2cap_sk_list, sk); | ||
895 | |||
890 | err = l2cap_sock_shutdown(sock, 2); | 896 | err = l2cap_sock_shutdown(sock, 2); |
891 | 897 | ||
892 | sock_orphan(sk); | 898 | sock_orphan(sk); |
@@ -1211,6 +1217,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |||
1211 | return -ENOMEM; | 1217 | return -ENOMEM; |
1212 | 1218 | ||
1213 | l2cap_sock_init(sk, NULL); | 1219 | l2cap_sock_init(sk, NULL); |
1220 | bt_sock_link(&l2cap_sk_list, sk); | ||
1214 | return 0; | 1221 | return 0; |
1215 | } | 1222 | } |
1216 | 1223 | ||
@@ -1249,21 +1256,30 @@ int __init l2cap_init_sockets(void) | |||
1249 | return err; | 1256 | return err; |
1250 | 1257 | ||
1251 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); | 1258 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); |
1252 | if (err < 0) | 1259 | if (err < 0) { |
1260 | BT_ERR("L2CAP socket registration failed"); | ||
1253 | goto error; | 1261 | goto error; |
1262 | } | ||
1263 | |||
1264 | err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); | ||
1265 | if (err < 0) { | ||
1266 | BT_ERR("Failed to create L2CAP proc file"); | ||
1267 | bt_sock_unregister(BTPROTO_L2CAP); | ||
1268 | goto error; | ||
1269 | } | ||
1254 | 1270 | ||
1255 | BT_INFO("L2CAP socket layer initialized"); | 1271 | BT_INFO("L2CAP socket layer initialized"); |
1256 | 1272 | ||
1257 | return 0; | 1273 | return 0; |
1258 | 1274 | ||
1259 | error: | 1275 | error: |
1260 | BT_ERR("L2CAP socket registration failed"); | ||
1261 | proto_unregister(&l2cap_proto); | 1276 | proto_unregister(&l2cap_proto); |
1262 | return err; | 1277 | return err; |
1263 | } | 1278 | } |
1264 | 1279 | ||
1265 | void l2cap_cleanup_sockets(void) | 1280 | void l2cap_cleanup_sockets(void) |
1266 | { | 1281 | { |
1282 | bt_procfs_cleanup(&init_net, "l2cap"); | ||
1267 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 1283 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) |
1268 | BT_ERR("L2CAP socket unregistration failed"); | 1284 | BT_ERR("L2CAP socket unregistration failed"); |
1269 | 1285 | ||