diff options
Diffstat (limited to 'net/bluetooth/af_bluetooth.c')
| -rw-r--r-- | net/bluetooth/af_bluetooth.c | 117 |
1 files changed, 76 insertions, 41 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 5355df63d39..2021c481cdb 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -25,12 +25,13 @@ /* Bluetooth address family and sockets. */ #include <linux/module.h> +#include <linux/debugfs.h> #include <asm/ioctls.h> #include <net/bluetooth/bluetooth.h> #include <linux/proc_fs.h> -#define VERSION "2.16" +#define VERSION "2.19" /* Bluetooth sockets */ #define BT_MAX_PROTO 8 @@ -92,23 +93,14 @@ int bt_sock_register(int proto, const struct net_proto_family *ops) } EXPORT_SYMBOL(bt_sock_register); -int bt_sock_unregister(int proto) +void bt_sock_unregister(int proto) { - int err = 0; - if (proto < 0 || proto >= BT_MAX_PROTO) - return -EINVAL; + return; write_lock(&bt_proto_lock); - - if (!bt_proto[proto]) - err = -ENOENT; - else - bt_proto[proto] = NULL; - + bt_proto[proto] = NULL; write_unlock(&bt_proto_lock); - - return err; } EXPORT_SYMBOL(bt_sock_unregister); @@ -234,11 +226,10 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) return 0; + return err; } - msg->msg_namelen = 0; - copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; @@ -247,9 +238,14 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, skb_reset_transport_header(skb); err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (err == 0) + if (err == 0) { sock_recv_ts_and_drops(msg, sk, skb); + if (bt_sk(sk)->skb_msg_name) + bt_sk(sk)->skb_msg_name(skb, msg->msg_name, + &msg->msg_namelen); + } + skb_free_datagram(sk, skb); return err ? : copied; @@ -296,8 +292,6 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & MSG_OOB) return -EOPNOTSUPP; - msg->msg_namelen = 0; - BT_DBG("sk %p size %zu", sk, size); lock_sock(sk); @@ -422,7 +416,8 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock, return bt_accept_poll(sk); if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) - mask |= POLLERR; + mask |= POLLERR | + (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0); if (sk->sk_shutdown & RCV_SHUTDOWN) mask |= POLLRDHUP | POLLIN | POLLRDNORM; @@ -498,6 +493,7 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } EXPORT_SYMBOL(bt_sock_ioctl); +/* This function expects the sk lock to be held when called */ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) { DECLARE_WAITQUEUE(wait, current); @@ -533,6 +529,46 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) } EXPORT_SYMBOL(bt_sock_wait_state); +/* This function expects the sk lock to be held when called */ +int bt_sock_wait_ready(struct sock *sk, unsigned long flags) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long timeo; + int err = 0; + + BT_DBG("sk %p", sk); + + timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); + + add_wait_queue(sk_sleep(sk), &wait); + set_current_state(TASK_INTERRUPTIBLE); + while (test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags)) { + if (!timeo) { + err = -EAGAIN; + break; + } + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + break; + } + + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + set_current_state(TASK_INTERRUPTIBLE); + + err = sock_error(sk); + if (err) + break; + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(sk_sleep(sk), &wait); + + return err; +} +EXPORT_SYMBOL(bt_sock_wait_ready); + #ifdef CONFIG_PROC_FS struct bt_seq_state { struct bt_sock_list *l; @@ -571,7 +607,7 @@ static int bt_seq_show(struct seq_file *seq, void *v) struct bt_sock_list *l = s->l; if (v == SEQ_START_TOKEN) { - seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); + seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Parent"); if (l->custom_seq_show) { seq_putc(seq, ' '); @@ -584,15 +620,13 @@ static int bt_seq_show(struct seq_file *seq, void *v) struct bt_sock *bt = bt_sk(sk); seq_printf(seq, - "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu", + "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu", sk, atomic_read(&sk->sk_refcnt), sk_rmem_alloc_get(sk), sk_wmem_alloc_get(sk), from_kuid(seq_user_ns(seq), sock_i_uid(sk)), sock_i_ino(sk), - &bt->src, - &bt->dst, bt->parent? sock_i_ino(bt->parent): 0LU); if (l->custom_seq_show) { @@ -617,7 +651,7 @@ static int bt_seq_open(struct inode *inode, struct file *file) struct bt_sock_list *sk_list; struct bt_seq_state *s; - sk_list = PDE(inode)->data; + sk_list = PDE_DATA(inode); s = __seq_open_private(file, &bt_seq_ops, sizeof(struct bt_seq_state)); if (!s) @@ -627,35 +661,30 @@ static int bt_seq_open(struct inode *inode, struct file *file) return 0; } -int bt_procfs_init(struct module* module, struct net *net, const char *name, +static const struct file_operations bt_fops = { + .open = bt_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private +}; + +int bt_procfs_init(struct net *net, const char *name, struct bt_sock_list* sk_list, int (* seq_show)(struct seq_file *, void *)) { - struct proc_dir_entry * pde; - sk_list->custom_seq_show = seq_show; - sk_list->fops.owner = module; - sk_list->fops.open = bt_seq_open; - sk_list->fops.read = seq_read; - sk_list->fops.llseek = seq_lseek; - sk_list->fops.release = seq_release_private; - - pde = proc_net_fops_create(net, name, 0, &sk_list->fops); - if (!pde) + if (!proc_create_data(name, 0, net->proc_net, &bt_fops, sk_list)) return -ENOMEM; - - pde->data = sk_list; - return 0; } void bt_procfs_cleanup(struct net *net, const char *name) { - proc_net_remove(net, name); + remove_proc_entry(name, net->proc_net); } #else -int bt_procfs_init(struct module* module, struct net *net, const char *name, +int bt_procfs_init(struct net *net, const char *name, struct bt_sock_list* sk_list, int (* seq_show)(struct seq_file *, void *)) { @@ -675,12 +704,17 @@ static struct net_proto_family bt_sock_family_ops = { .create = bt_sock_create, }; +struct dentry *bt_debugfs; +EXPORT_SYMBOL_GPL(bt_debugfs); + static int __init bt_init(void) { int err; BT_INFO("Core ver %s", VERSION); + bt_debugfs = debugfs_create_dir("bluetooth", NULL); + err = bt_sysfs_init(); if (err < 0) return err; @@ -721,7 +755,6 @@ error: static void __exit bt_exit(void) { - sco_exit(); l2cap_exit(); @@ -731,6 +764,8 @@ static void __exit bt_exit(void) sock_unregister(PF_BLUETOOTH); bt_sysfs_cleanup(); + + debugfs_remove_recursive(bt_debugfs); } subsys_initcall(bt_init); |
