aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/af_bluetooth.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/af_bluetooth.c')
-rw-r--r--net/bluetooth/af_bluetooth.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index f7db5792ec64..58f9762b339a 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -28,6 +28,7 @@
28#include <asm/ioctls.h> 28#include <asm/ioctls.h>
29 29
30#include <net/bluetooth/bluetooth.h> 30#include <net/bluetooth/bluetooth.h>
31#include <linux/proc_fs.h>
31 32
32#define VERSION "2.16" 33#define VERSION "2.16"
33 34
@@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
532} 533}
533EXPORT_SYMBOL(bt_sock_wait_state); 534EXPORT_SYMBOL(bt_sock_wait_state);
534 535
536#ifdef CONFIG_PROC_FS
537struct bt_seq_state {
538 struct bt_sock_list *l;
539};
540
541static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
542 __acquires(seq->private->l->lock)
543{
544 struct bt_seq_state *s = seq->private;
545 struct bt_sock_list *l = s->l;
546
547 read_lock(&l->lock);
548 return seq_hlist_start_head(&l->head, *pos);
549}
550
551static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
552{
553 struct bt_seq_state *s = seq->private;
554 struct bt_sock_list *l = s->l;
555
556 return seq_hlist_next(v, &l->head, pos);
557}
558
559static void bt_seq_stop(struct seq_file *seq, void *v)
560 __releases(seq->private->l->lock)
561{
562 struct bt_seq_state *s = seq->private;
563 struct bt_sock_list *l = s->l;
564
565 read_unlock(&l->lock);
566}
567
568static int bt_seq_show(struct seq_file *seq, void *v)
569{
570 struct sock *sk;
571 struct bt_sock *bt;
572 struct bt_seq_state *s = seq->private;
573 struct bt_sock_list *l = s->l;
574 bdaddr_t src_baswapped, dst_baswapped;
575
576 if (v == SEQ_START_TOKEN) {
577 seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
578
579 if (l->custom_seq_show) {
580 seq_putc(seq, ' ');
581 l->custom_seq_show(seq, v);
582 }
583
584 seq_putc(seq, '\n');
585 } else {
586 sk = sk_entry(v);
587 bt = bt_sk(sk);
588 baswap(&src_baswapped, &bt->src);
589 baswap(&dst_baswapped, &bt->dst);
590
591 seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
592 sk,
593 atomic_read(&sk->sk_refcnt),
594 sk_rmem_alloc_get(sk),
595 sk_wmem_alloc_get(sk),
596 sock_i_uid(sk),
597 sock_i_ino(sk),
598 &src_baswapped,
599 &dst_baswapped,
600 bt->parent? sock_i_ino(bt->parent): 0LU);
601
602 if (l->custom_seq_show) {
603 seq_putc(seq, ' ');
604 l->custom_seq_show(seq, v);
605 }
606
607 seq_putc(seq, '\n');
608 }
609 return 0;
610}
611
612static struct seq_operations bt_seq_ops = {
613 .start = bt_seq_start,
614 .next = bt_seq_next,
615 .stop = bt_seq_stop,
616 .show = bt_seq_show,
617};
618
619static int bt_seq_open(struct inode *inode, struct file *file)
620{
621 struct bt_sock_list *sk_list;
622 struct bt_seq_state *s;
623
624 sk_list = PDE(inode)->data;
625 s = __seq_open_private(file, &bt_seq_ops,
626 sizeof(struct bt_seq_state));
627 if (s == NULL)
628 return -ENOMEM;
629
630 s->l = sk_list;
631 return 0;
632}
633
634int bt_procfs_init(struct module* module, struct net *net, const char *name,
635 struct bt_sock_list* sk_list,
636 int (* seq_show)(struct seq_file *, void *))
637{
638 struct proc_dir_entry * pde;
639
640 sk_list->custom_seq_show = seq_show;
641
642 sk_list->fops.owner = module;
643 sk_list->fops.open = bt_seq_open;
644 sk_list->fops.read = seq_read;
645 sk_list->fops.llseek = seq_lseek;
646 sk_list->fops.release = seq_release_private;
647
648 pde = proc_net_fops_create(net, name, 0, &sk_list->fops);
649 if (pde == NULL)
650 return -ENOMEM;
651
652 pde->data = sk_list;
653
654 return 0;
655}
656
657void bt_procfs_cleanup(struct net *net, const char *name)
658{
659 proc_net_remove(net, name);
660}
661#else
662int bt_procfs_init(struct module* module, struct net *net, const char *name,
663 struct bt_sock_list* sk_list,
664 int (* seq_show)(struct seq_file *, void *))
665{
666 return 0;
667}
668
669void bt_procfs_cleanup(struct net *net, const char *name)
670{
671}
672#endif
673EXPORT_SYMBOL(bt_procfs_init);
674EXPORT_SYMBOL(bt_procfs_cleanup);
675
535static struct net_proto_family bt_sock_family_ops = { 676static struct net_proto_family bt_sock_family_ops = {
536 .owner = THIS_MODULE, 677 .owner = THIS_MODULE,
537 .family = PF_BLUETOOTH, 678 .family = PF_BLUETOOTH,