From: Amir Vadai Date: Sun, 5 Apr 2009 15:22:45 +0000 (+0300) Subject: sdp: added /proc/net/sdpstats + packets dump X-Git-Tag: v4.1.12-92~264^2~5^2~290 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=c62c2eacfee1aae6e656404dfbded3379664304c;p=users%2Fjedix%2Flinux-maple.git sdp: added /proc/net/sdpstats + packets dump Signed-off-by: Amir Vadai --- diff --git a/drivers/infiniband/ulp/sdp/Makefile b/drivers/infiniband/ulp/sdp/Makefile index c889cce2bb42e..5da4b7bbcd4b0 100644 --- a/drivers/infiniband/ulp/sdp/Makefile +++ b/drivers/infiniband/ulp/sdp/Makefile @@ -3,4 +3,4 @@ EXTRA_CFLAGS += -ggdb obj-$(CONFIG_INFINIBAND_SDP) += ib_sdp.o -ib_sdp-objs := sdp_main.o sdp_cma.o sdp_bcopy.o +ib_sdp-objs := sdp_main.o sdp_cma.o sdp_bcopy.o sdp_proc.o diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h index f9c2421c1838c..e36f786d4072c 100644 --- a/drivers/infiniband/ulp/sdp/sdp.h +++ b/drivers/infiniband/ulp/sdp/sdp.h @@ -7,9 +7,12 @@ #include /* For urgent data flags */ #include +#define SDPSTATS_ON + #define sdp_printk(level, sk, format, arg...) \ - printk(level "%s:%d sdp_sock(%d:%d): " format, \ + printk(level "%s:%d sdp_sock(%d %d:%d): " format, \ __func__, __LINE__, \ + current->pid, \ (sk) ? inet_sk(sk)->num : -1, \ (sk) ? ntohs(inet_sk(sk)->dport) : -1, ## arg) #define sdp_warn(sk, format, arg...) \ @@ -50,15 +53,72 @@ extern int sdp_debug_level; #endif /* CONFIG_INFINIBAND_SDP_DEBUG */ #ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA + extern int sdp_data_debug_level; #define sdp_dbg_data(sk, format, arg...) \ do { \ - if (sdp_data_debug_level > 0) \ + if (sdp_data_debug_level & 0x2) \ sdp_printk(KERN_DEBUG, sk, format , ## arg); \ } while (0) +#define SDP_DUMP_PACKET(sk, str, skb, h) \ + do { \ + if (sdp_data_debug_level & 0x1) \ + dump_packet(sk, str, skb, h); \ + } while (0) #else -#define sdp_dbg_data(priv, format, arg...) \ - do { (void) (priv); } while (0) +#define sdp_dbg_data(priv, format, arg...) +// do { (void) (priv); } while (0) +#define SDP_DUMP_PACKET(sk, str, skb, h) +#endif + +#ifdef SDPSTATS_ON + +struct sdpstats { + u32 post_send[256]; + u32 sendmsg_bcopy_segment; + u32 sendmsg_bzcopy_segment; + u32 sendmsg; + u32 post_send_credits; + u32 sendmsg_nagle_skip; + u32 sendmsg_seglen[25]; + u32 send_size[25]; + u32 post_recv; + u32 rx_int_count; + u32 tx_int_count; + u32 bzcopy_poll_miss; + u32 send_wait_for_mem; + u32 send_miss_no_credits; + u32 rx_poll_miss; + u32 tx_poll_miss; + u32 memcpy_count; + u32 credits_before_update[64]; + u32 send_interval[25]; +}; +extern struct sdpstats sdpstats; + +static inline void sdpstats_hist(u32 *h, u32 val, u32 maxidx, int is_log) +{ + int idx = is_log ? ilog2(val) : val; + if (idx > maxidx) + idx = maxidx; + + h[idx]++; +} + +#define SDPSTATS_COUNTER_INC(stat) do {sdpstats.stat++;} while (0) +#define SDPSTATS_COUNTER_ADD(stat, val) do {sdpstats.stat+=val;} while (0) +#define SDPSTATS_COUNTER_MID_INC(stat, mid) do {sdpstats.stat[mid]++;} while (0) +#define SDPSTATS_HIST(stat, size) \ + sdpstats_hist(sdpstats.stat, size, ARRAY_SIZE(sdpstats.stat) - 1, 1) + +#define SDPSTATS_HIST_LINEAR(stat, size) \ + sdpstats_hist(sdpstats.stat, size, ARRAY_SIZE(sdpstats.stat) - 1, 0) + +#else +#define SDPSTATS_COUNTER_INC(stat) +#define SDPSTATS_COUNTER_ADD(stat, val) +#define SDPSTATS_COUNTER_MID_INC(stat, mid) +#define SDPSTATS_HIST(stat, size) #endif #define SOCK_REF_RESET "RESET" @@ -92,6 +152,9 @@ extern int sdp_data_debug_level; #define SDP_OP_RECV 0x800000000LL #define SDP_OP_SEND 0x400000000LL +extern struct list_head sock_list; +extern spinlock_t sock_list_lock; + enum sdp_mid { SDP_MID_HELLO = 0x0, SDP_MID_HELLO_ACK = 0x1, @@ -129,6 +192,38 @@ struct sdp_bsdh { __u32 mseq_ack; }; +union cma_ip_addr { + struct in6_addr ip6; + struct { + __u32 pad[3]; + __u32 addr; + } ip4; +}; + +/* TODO: too much? Can I avoid having the src/dst and port here? */ +struct sdp_hh { + struct sdp_bsdh bsdh; + u8 majv_minv; + u8 ipv_cap; + u8 rsvd1; + u8 max_adverts; + __u32 desremrcvsz; + __u32 localrcvsz; + __u16 port; + __u16 rsvd2; + union cma_ip_addr src_addr; + union cma_ip_addr dst_addr; +}; + +struct sdp_hah { + struct sdp_bsdh bsdh; + u8 majv_minv; + u8 ipv_cap; + u8 rsvd1; + u8 ext_max_adverts; + __u32 actrcvsz; +}; + struct sdp_buf { struct sk_buff *skb; u64 mapping[SDP_MAX_SEND_SKB_FRAGS + 1]; @@ -329,6 +424,9 @@ static inline void sdp_set_error(struct sock *sk, int err) extern struct workqueue_struct *sdp_workqueue; +#ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA +void dump_packet(struct sock *sk, char *str, struct sk_buff *skb, const struct sdp_bsdh *h); +#endif int sdp_cma_handler(struct rdma_cm_id *, struct rdma_cm_event *); void sdp_reset(struct sock *sk); void sdp_reset_sk(struct sock *sk, int rc); @@ -354,6 +452,8 @@ void sdp_post_keepalive(struct sdp_sock *ssk); void sdp_start_keepalive_timer(struct sock *sk); void sdp_bzcopy_write_space(struct sdp_sock *ssk); int sdp_init_sock(struct sock *sk); +int __init sdp_proc_init(void); +void sdp_proc_unregister(void); static inline struct sk_buff *sdp_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) { diff --git a/drivers/infiniband/ulp/sdp/sdp_bcopy.c b/drivers/infiniband/ulp/sdp/sdp_bcopy.c index 475d7c3629915..7c7271c861747 100644 --- a/drivers/infiniband/ulp/sdp/sdp_bcopy.c +++ b/drivers/infiniband/ulp/sdp/sdp_bcopy.c @@ -186,6 +186,64 @@ void sdp_post_keepalive(struct sdp_sock *ssk) sdp_cnt(sdp_keepalive_probes_sent); } +#ifdef CONFIG_INFINIBAND_SDP_DEBUG_DATA +void dump_packet(struct sock *sk, char *str, struct sk_buff *skb, const struct sdp_bsdh *h) +{ + int len = 0; + char buf[256]; +#define ENUM2STR(e) [e] = #e + static char *mid2str[] = { + ENUM2STR(SDP_MID_HELLO), + ENUM2STR(SDP_MID_HELLO_ACK), + ENUM2STR(SDP_MID_DISCONN), + ENUM2STR(SDP_MID_CHRCVBUF), + ENUM2STR(SDP_MID_CHRCVBUF_ACK), + ENUM2STR(SDP_MID_DATA), + }; + len += snprintf(buf, 255-len, "skb: %p mid: %2x:%-20s flags: 0x%x bufs: %d " + "len: %d mseq: %d mseq_ack: %d", + skb, h->mid, mid2str[h->mid], h->flags, + ntohs(h->bufs), ntohl(h->len),ntohl(h->mseq), + ntohl(h->mseq_ack)); + + switch (h->mid) { + case SDP_MID_HELLO: + { + const struct sdp_hh *hh = (struct sdp_hh *)h; + len += snprintf(buf + len, 255-len, + " | max_adverts: %d majv_minv: %d localrcvsz: %d " + "desremrcvsz: %d |", + hh->max_adverts, + hh->majv_minv, + ntohl(hh->localrcvsz), + ntohl(hh->desremrcvsz)); + } + break; + case SDP_MID_HELLO_ACK: + { + const struct sdp_hah *hah = (struct sdp_hah *)h; + len += snprintf(buf + len, 255-len, " | actrcvz: %d |", + ntohl(hah->actrcvsz)); + } + break; + case SDP_MID_CHRCVBUF: + case SDP_MID_CHRCVBUF_ACK: + { + struct sdp_chrecvbuf *req_size = (struct sdp_chrecvbuf *)(h+1); + len += snprintf(buf + len, 255-len, + " | req_size: %d |", ntohl(req_size->size)); + } + break; + case SDP_MID_DATA: + len += snprintf(buf + len, 255-len, " | data_len: %ld |", ntohl(h->len) - sizeof(struct sdp_bsdh)); + default: + break; + } + buf[len] = 0; + sdp_warn(sk, "%s: %s\n", str, buf); +} +#endif + void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid) { struct sdp_buf *tx_req; @@ -197,6 +255,9 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid) struct ib_sge *sge; struct ib_send_wr *bad_wr; + SDPSTATS_COUNTER_MID_INC(post_send, mid); + SDPSTATS_HIST(send_size, skb->len); + h->mid = mid; if (unlikely(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) h->flags = SDP_OOB_PRES | SDP_OOB_PEND; @@ -208,6 +269,7 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid) h->mseq = htonl(mseq); h->mseq_ack = htonl(ssk->mseq_ack); + SDP_DUMP_PACKET(&ssk->isk.sk, "TX", skb, h); tx_req = &ssk->tx_ring[mseq & (SDP_TX_SIZE - 1)]; tx_req->skb = skb; dev = ssk->ib_device; @@ -244,6 +306,16 @@ void sdp_post_send(struct sdp_sock *ssk, struct sk_buff *skb, u8 mid) ssk->tx_wr.send_flags = IB_SEND_SIGNALED; if (unlikely(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_URG)) ssk->tx_wr.send_flags |= IB_SEND_SOLICITED; + + { + static unsigned long last_send = 0; + int delta = jiffies - last_send; + + if (likely(last_send)) + SDPSTATS_HIST(send_interval, delta); + + last_send = jiffies; + } rc = ib_post_send(ssk->qp, &ssk->tx_wr, &bad_wr); ++ssk->tx_head; --ssk->bufs; @@ -292,7 +364,6 @@ struct sk_buff *sdp_send_completion(struct sdp_sock *ssk, int mseq) return skb; } - static void sdp_post_recv(struct sdp_sock *ssk) { struct sdp_buf *rx_req; @@ -375,6 +446,7 @@ static void sdp_post_recv(struct sdp_sock *ssk) ssk->rx_wr.sg_list = ssk->ibsge; ssk->rx_wr.num_sge = frags + 1; rc = ib_post_recv(ssk->qp, &ssk->rx_wr, &bad_wr); + SDPSTATS_COUNTER_INC(post_recv); ++ssk->rx_head; if (unlikely(rc)) { sdp_dbg(&ssk->isk.sk, "ib_post_recv failed with status %d\n", rc); @@ -583,6 +655,7 @@ void sdp_post_sends(struct sdp_sock *ssk, int nonagle) GFP_KERNEL); /* FIXME */ BUG_ON(!skb); + SDPSTATS_COUNTER_INC(post_send_credits); sdp_post_send(ssk, skb, SDP_MID_DATA); } @@ -701,11 +774,14 @@ static int sdp_handle_recv_comp(struct sdp_sock *ssk, struct ib_wc *wc) skb->tail = skb->head + skb_headlen(skb); #endif h = (struct sdp_bsdh *)skb->data; + SDP_DUMP_PACKET(&ssk->isk.sk, "RX", skb, h); skb_reset_transport_header(skb); ssk->mseq_ack = ntohl(h->mseq); if (ssk->mseq_ack != (int)wc->wr_id) printk(KERN_WARNING "SDP BUG! mseq %d != wrid %d\n", ssk->mseq_ack, (int)wc->wr_id); + + SDPSTATS_HIST_LINEAR(credits_before_update, ssk->bufs); ssk->bufs = ntohl(h->mseq_ack) - ssk->tx_head + 1 + ntohs(h->bufs); @@ -782,7 +858,7 @@ static int sdp_handle_send_comp(struct sdp_sock *ssk, struct ib_wc *wc) if (unlikely(wc->status)) { if (wc->status != IB_WC_WR_FLUSH_ERR) { struct sock *sk = &ssk->isk.sk; - sdp_dbg(sk, "Send completion with error. " + sdp_warn(sk, "Send completion with error. " "Status %d\n", wc->status); sdp_set_error(sk, -ECONNRESET); wake_up(&ssk->wq); diff --git a/drivers/infiniband/ulp/sdp/sdp_cma.c b/drivers/infiniband/ulp/sdp/sdp_cma.c index 96d65bdfb9072..b6bc4e5f35c6b 100644 --- a/drivers/infiniband/ulp/sdp/sdp_cma.c +++ b/drivers/infiniband/ulp/sdp/sdp_cma.c @@ -46,40 +46,8 @@ #include "sdp_socket.h" #include "sdp.h" -union cma_ip_addr { - struct in6_addr ip6; - struct { - __u32 pad[3]; - __u32 addr; - } ip4; -}; - #define SDP_MAJV_MINV 0x22 -/* TODO: too much? Can I avoid having the src/dst and port here? */ -struct sdp_hh { - struct sdp_bsdh bsdh; - u8 majv_minv; - u8 ipv_cap; - u8 rsvd1; - u8 max_adverts; - __u32 desremrcvsz; - __u32 localrcvsz; - __u16 port; - __u16 rsvd2; - union cma_ip_addr src_addr; - union cma_ip_addr dst_addr; -}; - -struct sdp_hah { - struct sdp_bsdh bsdh; - u8 majv_minv; - u8 ipv_cap; - u8 rsvd1; - u8 ext_max_adverts; - __u32 actrcvsz; -}; - enum { SDP_HH_SIZE = 76, SDP_HAH_SIZE = 180, @@ -206,6 +174,7 @@ static int sdp_connect_handler(struct sock *sk, struct rdma_cm_id *id, sdp_dbg(sk, "%s %p -> %p\n", __func__, sdp_sk(sk)->id, id); h = event->param.conn.private_data; + SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh); if (!h->max_adverts) return -EINVAL; @@ -277,6 +246,7 @@ static int sdp_response_handler(struct sock *sk, struct rdma_cm_id *id, return 0; h = event->param.conn.private_data; + SDP_DUMP_PACKET(sk, "RX", NULL, &h->bsdh); sdp_sk(sk)->max_bufs = sdp_sk(sk)->bufs = ntohs(h->bsdh.bufs); sdp_sk(sk)->min_bufs = sdp_sk(sk)->bufs / 4; sdp_sk(sk)->xmit_size_goal = ntohl(h->actrcvsz) - @@ -428,6 +398,7 @@ int sdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) conn_param.responder_resources = 4 /* TODO */; conn_param.initiator_depth = 4 /* TODO */; conn_param.retry_count = SDP_RETRY_COUNT; + SDP_DUMP_PACKET(NULL, "TX", NULL, &hh.bsdh); rc = rdma_connect(id, &conn_param); break; case RDMA_CM_EVENT_ROUTE_ERROR: @@ -458,6 +429,7 @@ int sdp_cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) conn_param.responder_resources = 4 /* TODO */; conn_param.initiator_depth = 4 /* TODO */; conn_param.retry_count = SDP_RETRY_COUNT; + SDP_DUMP_PACKET(sk, "TX", NULL, &hah.bsdh); rc = rdma_accept(id, &conn_param); if (rc) { sdp_sk(child)->id = NULL; diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index 7a38c47f0fa01..c9b5ba2b69070 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -67,7 +67,6 @@ 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 */ @@ -138,8 +137,8 @@ MODULE_PARM_DESC(sdp_zcopy_thresh, "Zero copy send threshold; 0=0ff."); struct workqueue_struct *sdp_workqueue; -static struct list_head sock_list; -static spinlock_t sock_list_lock; +struct list_head sock_list; +spinlock_t sock_list_lock; static DEFINE_RWLOCK(device_removal_lock); @@ -1288,6 +1287,8 @@ static inline struct bzcopy_state *sdp_bz_cleanup(struct bzcopy_state *bz) if (!bz->busy) break; + + SDPSTATS_COUNTER_INC(bzcopy_poll_miss); } if (bz->busy) @@ -1319,11 +1320,14 @@ static struct bzcopy_state *sdp_bz_setup(struct sdp_sock *ssk, int thresh; mm_segment_t cur_fs; - cur_fs = get_fs(); - thresh = ssk->zcopy_thresh ? : sdp_zcopy_thresh; - if (thresh == 0 || len < thresh || !capable(CAP_IPC_LOCK)) + if (thresh == 0 || len < thresh || !capable(CAP_IPC_LOCK)) { + SDPSTATS_COUNTER_INC(sendmsg_bcopy_segment); return NULL; + } + SDPSTATS_COUNTER_INC(sendmsg_bzcopy_segment); + + cur_fs = get_fs(); /* * Since we use the TCP segmentation fields of the skb to map user @@ -1445,6 +1449,8 @@ static inline int sdp_bcopy_get(struct sock *sk, struct sk_buff *skb, /* Time to copy data. We are close to * the end! */ + SDPSTATS_COUNTER_ADD(memcpy_count, copy); + sdp_dbg_data(sk, "Copying from: %p offset: %d size: %d\n", from, off, copy); err = skb_copy_to_page(sk, from, skb, page, off, copy); if (err) { @@ -1463,6 +1469,8 @@ static inline int sdp_bcopy_get(struct sock *sk, struct sk_buff *skb, skb_shinfo(skb)->frags[i - 1].size += copy; } else { + sdp_dbg_data(sk, "Adding to frage %d: page: %p off: %d size: %d\n", + i, page, off, copy); skb_fill_page_desc(skb, i, page, off, copy); if (TCP_PAGE(sk)) { get_page(page); @@ -1651,7 +1659,7 @@ static int sdp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, int err, copied; long timeo; struct bzcopy_state *bz = NULL; - + SDPSTATS_COUNTER_INC(sendmsg); lock_sock(sk); sdp_dbg_data(sk, "%s\n", __func__); @@ -1688,6 +1696,8 @@ static int sdp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (size_goal > SDP_MAX_PAYLOAD) size_goal = SDP_MAX_PAYLOAD; + SDPSTATS_HIST(sendmsg_seglen, seglen); + if (bz) sdp_bz_cleanup(bz); bz = sdp_bz_setup(ssk, from, seglen, size_goal); @@ -1737,8 +1747,14 @@ new_segment: NETIF_F_HW_CSUM)) skb->ip_summed = CHECKSUM_PARTIAL; + sdp_dbg_data(sk, "entail new skb: %p len = %d\n", skb, skb->len); skb_entail(sk, ssk, skb); copy = size_goal; + } else { + sdp_dbg_data(sk, "adding to existing skb: %p" + " len = %d, sk_send_head: %p copy: %d\n", + skb, skb->len, sk->sk_send_head, copy); + } /* Try to append data to the end of skb. */ @@ -1791,6 +1807,7 @@ new_segment: wait_for_sndbuf: set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); wait_for_memory: + SDPSTATS_COUNTER_INC(send_wait_for_mem); if (copied) sdp_push(sk, ssk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); @@ -2266,192 +2283,6 @@ static int sdp_create_socket(struct net *net, struct socket *sock, int protocol) 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, SOCK_REF_SEQ); - 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, SOCK_REF_SEQ); - 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; - int uid; - unsigned long inode; - __u16 destp; - __u16 srcp; - __u32 rx_queue, tx_queue; - - if (v == SEQ_START_TOKEN) { - seq_printf(seq, "%-*s\n", TMPSZ - 1, - " sl local_address rem_address uid inode" - " rx_queue tx_queue state"); - 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); - uid = sock_i_uid(sk); - inode = sock_i_ino(sk); - rx_queue = sdp_sk(sk)->rcv_nxt - sdp_sk(sk)->copied_seq; - tx_queue = sdp_sk(sk)->write_seq - sdp_sk(sk)->snd_una; - - sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %5d %lu %08X:%08X %X", - st->num, src, srcp, dest, destp, uid, inode, - rx_queue, tx_queue, sk->sk_state); - - seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf); - - sock_put(sk, SOCK_REF_SEQ); -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(&init_net, 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(&init_net, 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 void sdp_add_device(struct ib_device *device) { } diff --git a/drivers/infiniband/ulp/sdp/sdp_proc.c b/drivers/infiniband/ulp/sdp/sdp_proc.c new file mode 100644 index 0000000000000..8971517a93b25 --- /dev/null +++ b/drivers/infiniband/ulp/sdp/sdp_proc.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2008 Mellanox Technologies Ltd. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include "sdp_socket.h" +#include "sdp.h" + +#ifdef CONFIG_PROC_FS + +#define PROC_SDP_STATS "sdpstats" + +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, SOCK_REF_SEQ); + 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, SOCK_REF_SEQ); + 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; + int uid; + unsigned long inode; + __u16 destp; + __u16 srcp; + __u32 rx_queue, tx_queue; + + if (v == SEQ_START_TOKEN) { + seq_printf(seq, "%-*s\n", TMPSZ - 1, + " sl local_address rem_address uid inode" + " rx_queue tx_queue state"); + 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); + uid = sock_i_uid(sk); + inode = sock_i_ino(sk); + rx_queue = sdp_sk(sk)->rcv_nxt - sdp_sk(sk)->copied_seq; + tx_queue = sdp_sk(sk)->write_seq - sdp_sk(sk)->snd_una; + + sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %5d %lu %08X:%08X %X", + st->num, src, srcp, dest, destp, uid, inode, + rx_queue, tx_queue, sk->sk_state); + + seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf); + + sock_put(sk, SOCK_REF_SEQ); +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, +}; + +#ifdef SDPSTATS_ON +struct sdpstats sdpstats = { { 0 } }; + +static void sdpstats_seq_hist(struct seq_file *seq, char *str, u32 *h, int n, int is_log) +{ + int i; + u32 max = 0; + + seq_printf(seq, "%s:\n", str); + + for (i = 0; i < n; i++) { + if (h[i] > max) + max = h[i]; + } + + if (max == 0) { + seq_printf(seq, " - all values are 0\n"); + return; + } + + for (i = 0; i < n; i++) { + char s[51]; + int j = 50 * h[i] / max; + int val = is_log ? (i == n-1 ? 0 : 1<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 + goto no_mem;; + +#ifdef SDPSTATS_ON + + sdpstats = proc_net_fops_create(PROC_SDP_STATS, + S_IRUGO | S_IWUGO, &sdpstats_fops); + if (!sdpstats) + goto no_mem;; + + return 0; +#endif + +no_mem: + if (sdpstats) + proc_net_remove(PROC_SDP_STATS); + + if (p) + proc_net_remove(sdp_seq_afinfo.name); + + return -ENOMEM; +} + +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)); + +#ifdef SDPSTATS_ON + proc_net_remove(PROC_SDP_STATS); +#endif +} + +#else /* CONFIG_PROC_FS */ + +int __init sdp_proc_init(void) +{ + return 0; +} + +void sdp_proc_unregister(void) +{ + +} +#endif /* CONFIG_PROC_FS */