From 12e46867e312fe86c4d5c24090e502a38fd7baea Mon Sep 17 00:00:00 2001 From: Amiram Perlmutter Date: Mon, 22 Jan 2007 14:00:04 +0200 Subject: [PATCH] IB/sdp: add proc_fs support Signed-off-by: Amiram Perlmutter --- drivers/infiniband/ulp/sdp/sdp.h | 18 +++ drivers/infiniband/ulp/sdp/sdp_cma.c | 1 + drivers/infiniband/ulp/sdp/sdp_main.c | 210 ++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h index 32f64b82e4ce..21679de6835f 100644 --- a/drivers/infiniband/ulp/sdp/sdp.h +++ b/drivers/infiniband/ulp/sdp/sdp.h @@ -88,6 +88,7 @@ struct sdp_buf { struct sdp_sock { /* sk has to be the first member of inet_sock */ struct inet_sock isk; + struct list_head sock_list; struct list_head accept_queue; struct list_head backlog_queue; struct sock *parent; @@ -141,6 +142,21 @@ struct sdp_sock { extern struct proto sdp_proto; extern struct workqueue_struct *sdp_workqueue; +/* just like TCP fs */ +struct sdp_seq_afinfo { + struct module *owner; + char *name; + sa_family_t family; + int (*seq_show) (struct seq_file *m, void *v); + struct file_operations *seq_fops; +}; + +struct sdp_iter_state { + sa_family_t family; + int num; + struct seq_operations seq_ops; +}; + static inline struct sdp_sock *sdp_sk(const struct sock *sk) { return (struct sdp_sock *)sk; @@ -185,5 +201,7 @@ void sdp_time_wait_work(struct delayed_work *work); struct sk_buff *sdp_recv_completion(struct sdp_sock *ssk, int id); struct sk_buff *sdp_send_completion(struct sdp_sock *ssk, int mseq); void sdp_urg(struct sdp_sock *ssk, struct sk_buff *skb); +void sdp_add_sock(struct sdp_sock *ssk); +void sdp_remove_sock(struct sdp_sock *ssk); #endif diff --git a/drivers/infiniband/ulp/sdp/sdp_cma.c b/drivers/infiniband/ulp/sdp/sdp_cma.c index 54a3209adbd5..59c805205e9c 100644 --- a/drivers/infiniband/ulp/sdp/sdp_cma.c +++ b/drivers/infiniband/ulp/sdp/sdp_cma.c @@ -208,6 +208,7 @@ int sdp_connect_handler(struct sock *sk, struct rdma_cm_id *id, if (!child) return -ENOMEM; + sdp_add_sock(sdp_sk(child)); INIT_LIST_HEAD(&sdp_sk(child)->accept_queue); INIT_LIST_HEAD(&sdp_sk(child)->backlog_queue); INIT_DELAYED_WORK(&sdp_sk(child)->time_wait_work, sdp_time_wait_work); diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index 87ae56bf569c..d70df1a4c55a 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -37,6 +37,7 @@ #include #include + static inline unsigned int csum_partial_copy_from_user_new (const char *src, char *dst, int len, unsigned int sum, @@ -56,6 +57,7 @@ unsigned int csum_partial_copy_from_user_new (const char *src, char *dst, #include #include #include +#include #include #include /* TODO: remove when sdp_socket.h becomes part of include/linux/socket.h */ @@ -117,6 +119,24 @@ MODULE_PARM_DESC(send_poll_thresh, "Send message size thresh hold over which to struct workqueue_struct *sdp_workqueue; +static struct list_head sock_list; +static spinlock_t sock_list_lock; + +inline void sdp_add_sock(struct sdp_sock *ssk) +{ + spin_lock_irq(&sock_list_lock); + list_add_tail(&ssk->sock_list, &sock_list); + spin_unlock_irq(&sock_list_lock); +} + +inline void sdp_remove_sock(struct sdp_sock *ssk) +{ + spin_lock_irq(&sock_list_lock); + BUG_ON(list_empty(&sock_list)); + list_del_init(&(ssk->sock_list)); + spin_unlock_irq(&sock_list_lock); +} + static int sdp_get_port(struct sock *sk, unsigned short snum) { struct sdp_sock *ssk = sdp_sk(sk); @@ -283,6 +303,8 @@ static void sdp_destruct(struct sock *sk) sdp_dbg(sk, "%s\n", __func__); + sdp_remove_sock(ssk); + sdp_close_sk(sk); if (ssk->parent) @@ -294,6 +316,7 @@ static void sdp_destruct(struct sock *sk) list_for_each_entry_safe(s, t, &ssk->accept_queue, accept_queue) { sk_common_release(&s->isk.sk); } + done: sdp_dbg(sk, "%s done\n", __func__); } @@ -1650,9 +1673,187 @@ static int sdp_create_socket(struct socket *sock, int protocol) sock->ops = &sdp_proto_ops; sock->state = SS_UNCONNECTED; + + sdp_add_sock(sdp_sk(sk)); + + return 0; +} + +#ifdef CONFIG_PROC_FS + +static void *sdp_get_idx(struct seq_file *seq, loff_t pos) +{ + int i = 0; + struct sdp_sock *ssk; + + if (!list_empty(&sock_list)) + list_for_each_entry(ssk, &sock_list, sock_list) { + if (i == pos) + return ssk; + i++; + } + + return NULL; +} + +static void *sdp_seq_start(struct seq_file *seq, loff_t *pos) +{ + void *start = NULL; + struct sdp_iter_state* st = seq->private; + + st->num = 0; + + if (!*pos) + return SEQ_START_TOKEN; + + spin_lock_irq(&sock_list_lock); + start = sdp_get_idx(seq, *pos - 1); + if (start) + sock_hold((struct sock *)start); + spin_unlock_irq(&sock_list_lock); + + return start; +} + +static void *sdp_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct sdp_iter_state* st = seq->private; + void *next = NULL; + + spin_lock_irq(&sock_list_lock); + if (v == SEQ_START_TOKEN) + next = sdp_get_idx(seq, 0); + else + next = sdp_get_idx(seq, *pos); + if (next) + sock_hold((struct sock *)next); + spin_unlock_irq(&sock_list_lock); + + *pos += 1; + st->num++; + + return next; +} + +static void sdp_seq_stop(struct seq_file *seq, void *v) +{ +} + +#define TMPSZ 150 + +static int sdp_seq_show(struct seq_file *seq, void *v) +{ + struct sdp_iter_state* st; + struct sock *sk = v; + char tmpbuf[TMPSZ + 1]; + unsigned int dest; + unsigned int src; + __u16 destp; + __u16 srcp; + + if (v == SEQ_START_TOKEN) { + seq_printf(seq, "%-*s\n", TMPSZ - 1, + " sl local_address rem_address "); + goto out; + } + + st = seq->private; + + dest = inet_sk(sk)->daddr; + src = inet_sk(sk)->rcv_saddr; + destp = ntohs(inet_sk(sk)->dport); + srcp = ntohs(inet_sk(sk)->sport); + + sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X", st->num, src, srcp, dest, destp); + + seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf); + + sock_put(sk); +out: + return 0; +} + +static int sdp_seq_open(struct inode *inode, struct file *file) +{ + struct sdp_seq_afinfo *afinfo = PDE(inode)->data; + struct seq_file *seq; + struct sdp_iter_state *s; + int rc; + + if (unlikely(afinfo == NULL)) + return -EINVAL; + + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) + return -ENOMEM; + s->family = afinfo->family; + s->seq_ops.start = sdp_seq_start; + s->seq_ops.next = sdp_seq_next; + s->seq_ops.show = afinfo->seq_show; + s->seq_ops.stop = sdp_seq_stop; + + rc = seq_open(file, &s->seq_ops); + if (rc) + goto out_kfree; + seq = file->private_data; + seq->private = s; +out: + return rc; +out_kfree: + kfree(s); + goto out; +} + + +static struct file_operations sdp_seq_fops; +static struct sdp_seq_afinfo sdp_seq_afinfo = { + .owner = THIS_MODULE, + .name = "sdp", + .family = AF_INET_SDP, + .seq_show = sdp_seq_show, + .seq_fops = &sdp_seq_fops, +}; + + +static int __init sdp_proc_init(void) +{ + int rc = 0; + struct proc_dir_entry *p; + + sdp_seq_afinfo.seq_fops->owner = sdp_seq_afinfo.owner; + sdp_seq_afinfo.seq_fops->open = sdp_seq_open; + sdp_seq_afinfo.seq_fops->read = seq_read; + sdp_seq_afinfo.seq_fops->llseek = seq_lseek; + sdp_seq_afinfo.seq_fops->release = seq_release_private; + + p = proc_net_fops_create(sdp_seq_afinfo.name, S_IRUGO, sdp_seq_afinfo.seq_fops); + if (p) + p->data = &sdp_seq_afinfo; + else + rc = -ENOMEM; + + return rc; +} + +static void sdp_proc_unregister(void) +{ + proc_net_remove(sdp_seq_afinfo.name); + memset(sdp_seq_afinfo.seq_fops, 0, sizeof(*sdp_seq_afinfo.seq_fops)); +} + +#else /* CONFIG_PROC_FS */ + +static int __init sdp_proc_init(void) +{ return 0; } +static void sdp_proc_unregister(void) +{ + +} +#endif /* CONFIG_PROC_FS */ + static struct net_proto_family sdp_net_proto = { .family = AF_INET_SDP, .create = sdp_create_socket, @@ -1663,6 +1864,9 @@ static int __init sdp_init(void) { int rc; + INIT_LIST_HEAD(&sock_list); + spin_lock_init(&sock_list_lock); + sdp_workqueue = create_singlethread_workqueue("sdp"); if (!sdp_workqueue) { return -ENOMEM; @@ -1683,6 +1887,8 @@ static int __init sdp_init(void) return rc; } + sdp_proc_init(); + return 0; } @@ -1696,6 +1902,10 @@ static void __exit sdp_exit(void) atomic_read(&orphan_count)); destroy_workqueue(sdp_workqueue); flush_scheduled_work(); + + BUG_ON(!list_empty(&sock_list)); + + sdp_proc_unregister(); } module_init(sdp_init); -- 2.50.1