From: Amir Vadai Date: Wed, 3 Nov 2010 13:47:01 +0000 (+0200) Subject: sdp: access socket history from debugfs X-Git-Tag: v4.1.12-92~264^2~5^2~65 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=0b32af8e65c917d206e551f5cbba5f9b318e4742;p=users%2Fjedix%2Flinux-maple.git sdp: access socket history from debugfs Also moved sdpprf to /sys/kernel/debug/sdp - seems to be a better place than /proc/net Signed-off-by: Amir Vadai --- diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h index f83607ac00f9f..36c293741a7cf 100644 --- a/drivers/infiniband/ulp/sdp/sdp.h +++ b/drivers/infiniband/ulp/sdp/sdp.h @@ -62,10 +62,6 @@ #define SDP_OP_RDMA 0x200000000LL #define SDP_OP_NOP 0x100000000LL -#ifdef SDP_SOCK_HISTORY -#define SDP_SOCK_HISTORY_LEN 128 -#endif - /* how long (in jiffies) to block sender till tx completion*/ #define SDP_BZCOPY_POLL_TIMEOUT (HZ / 10) @@ -342,26 +338,6 @@ struct sdp_moderation { int moder_time; }; -#ifdef SDP_SOCK_HISTORY -enum sdp_ref_type { - NOT_REF, - HOLD_REF, - PUT_REF, - __PUT_REF, - BOTH_REF -}; - -struct sdp_sock_hist { - char *str; - char *func; - int line; - int pid; - u8 cnt; - u8 ref_type; /* enum sdp_ref_type */ - u8 ref_enum; /* enum sdp_ref */ -}; -#endif /* SDP_SOCK_HISTORY */ - struct sdp_sock { /* sk has to be the first member of inet_sock */ struct inet_sock isk; @@ -373,10 +349,13 @@ struct sdp_sock { struct sdp_device *sdp_dev; int cpu; + unsigned int sk_id; + #ifdef SDP_SOCK_HISTORY struct sdp_sock_hist hst[SDP_SOCK_HISTORY_LEN]; - unsigned hst_idx; /* next free slot */ + unsigned long hst_idx; /* next free slot */ spinlock_t hst_lock; + struct dentry *hst_dentr; #endif /* SDP_SOCK_HISTORY */ int qp_active; @@ -491,136 +470,6 @@ static inline struct sdp_sock *sdp_sk(const struct sock *sk) return (struct sdp_sock *)sk; } -#ifdef SDP_SOCK_HISTORY -static inline char *reftype2str(int reftype) -{ -#define ENUM2STR(e) [e] = #e - static char *enum2str[] = { - ENUM2STR(NOT_REF), - ENUM2STR(HOLD_REF), - ENUM2STR(PUT_REF), - ENUM2STR(__PUT_REF), - ENUM2STR(BOTH_REF) - }; - - if (reftype < 0 || reftype >= ARRAY_SIZE(enum2str)) { - printk(KERN_WARNING "reftype %d is illegal\n", reftype); - return NULL; - } - - return enum2str[reftype]; -} - -static inline void sdp_print_history(struct sock *sk) -{ - struct sdp_sock *ssk = sdp_sk(sk); - unsigned i; - unsigned long flags; - - spin_lock_irqsave(&ssk->hst_lock, flags); - - sdp_warn(sk, "############## %p %s %u/%lu ##############\n", - sk, sdp_state_str(sk->sk_state), - ssk->hst_idx, ARRAY_SIZE(ssk->hst)); - - for (i = 0; i < ssk->hst_idx; ++i) { - struct sdp_sock_hist *hst = &ssk->hst[i]; - char *ref_str = reftype2str(hst->ref_type); - - if (hst->ref_type == NOT_REF) - ref_str = ""; - - if (hst->cnt != 1) { - sdp_warn(sk, "[%s:%d pid: %d] %s %s : %d\n", - hst->func, hst->line, hst->pid, - ref_str, hst->str, hst->cnt); - } else { - sdp_warn(sk, "[%s:%d pid: %d] %s %s\n", - hst->func, hst->line, hst->pid, - ref_str, hst->str); - } - } - - spin_unlock_irqrestore(&ssk->hst_lock, flags); -} - -static inline void _sdp_add_to_history(struct sock *sk, const char *str, - const char *func, int line, int ref_type, int ref_enum) -{ - struct sdp_sock *ssk = sdp_sk(sk); - unsigned i; - unsigned long flags; - struct sdp_sock_hist *hst; - - spin_lock_irqsave(&ssk->hst_lock, flags); - - i = ssk->hst_idx; - - if (i >= ARRAY_SIZE(ssk->hst)) { - //sdp_warn(sk, "overflow, drop: %s\n", s); - ++ssk->hst_idx; - goto out; - } - - if (ssk->hst[i].str) - sdp_warn(sk, "overwriting %s\n", ssk->hst[i].str); - - switch (ref_type) { - case NOT_REF: - case HOLD_REF: -simple_add: - hst = &ssk->hst[i]; - hst->str = (char *)str; - hst->func = (char *)func; - hst->line = line; - hst->ref_type = ref_type; - hst->ref_enum = ref_enum; - hst->cnt = 1; - hst->pid = current->pid; - ++ssk->hst_idx; - break; - case PUT_REF: - case __PUT_REF: - /* Try to shrink history by attaching HOLD+PUT - * together */ - hst = i > 0 ? &ssk->hst[i - 1] : NULL; - if (hst && hst->ref_type == HOLD_REF && - hst->ref_enum == ref_enum) { - hst->ref_type = BOTH_REF; - hst->func = (char *)func; - hst->line = line; - hst->pid = current->pid; - - /* try to shrink some more - by summing up */ - --i; - hst = i > 0 ? &ssk->hst[i - 1] : NULL; - if (hst && hst->ref_type == BOTH_REF && - hst->ref_enum == ref_enum) { - ++hst->cnt; - hst->func = (char *)func; - hst->line = line; - hst->pid = current->pid; - ssk->hst[i].str = NULL; - - --ssk->hst_idx; - } - } else - goto simple_add; - break; - default: - sdp_warn(sk, "error\n"); - } -out: - spin_unlock_irqrestore(&ssk->hst_lock, flags); -} - -#define sdp_add_to_history(sk, str) \ - _sdp_add_to_history(sk, str, __func__, __LINE__, 0, 0) -#else -#define _sdp_add_to_history(sk, str, func, line, ref_type, ref_enum) -#define sdp_add_to_history(sk, str) -#endif /* SDP_SOCK_HISTORY */ - static inline int _sdp_exch_state(const char *func, int line, struct sock *sk, int from_states, int state) { diff --git a/drivers/infiniband/ulp/sdp/sdp_cma.c b/drivers/infiniband/ulp/sdp/sdp_cma.c index 1747929f4380a..c755ef14a94c6 100644 --- a/drivers/infiniband/ulp/sdp/sdp_cma.c +++ b/drivers/infiniband/ulp/sdp/sdp_cma.c @@ -169,6 +169,9 @@ static int sdp_connect_handler(struct sock *sk, struct rdma_cm_id *id, inet_sk(child)->dport = dst_addr->sin_port; inet_sk(child)->daddr = dst_addr->sin_addr.s_addr; +#ifdef SDP_SOCK_HISTORY + sdp_ssk_hist_rename(sk); +#endif __sock_put(child, SOCK_REF_CLONE); down_read(&device_removal_lock); @@ -248,6 +251,9 @@ static int sdp_response_handler(struct sock *sk, struct rdma_cm_id *id, inet_sk(sk)->dport = dst_addr->sin_port; inet_sk(sk)->daddr = dst_addr->sin_addr.s_addr; +#ifdef SDP_SOCK_HISTORY + sdp_ssk_hist_rename(sk); +#endif return 0; } @@ -261,6 +267,9 @@ static int sdp_connected_handler(struct sock *sk) sdp_exch_state(sk, TCPF_SYN_RECV, TCP_ESTABLISHED); +#ifdef SDP_SOCK_HISTORY + sdp_ssk_hist_rename(sk); +#endif sdp_set_default_moderation(sdp_sk(sk)); if (sock_flag(sk, SOCK_KEEPOPEN)) diff --git a/drivers/infiniband/ulp/sdp/sdp_dbg.h b/drivers/infiniband/ulp/sdp/sdp_dbg.h index 61cb1a35c1607..a0a4d85eb4ff0 100644 --- a/drivers/infiniband/ulp/sdp/sdp_dbg.h +++ b/drivers/infiniband/ulp/sdp/sdp_dbg.h @@ -12,6 +12,7 @@ #endif #define SDP_WARN_ON(x) WARN_ON(x) +static inline struct sdp_sock *sdp_sk(const struct sock *sk); #define _sdp_printk(func, line, level, sk, format, arg...) do { \ preempt_disable(); \ @@ -150,6 +151,52 @@ enum sdp_ref { }; #ifdef SDP_SOCK_HISTORY +#define SDP_SOCK_HISTORY_LEN 128 + +enum sdp_ref_type { + NOT_REF, + HOLD_REF, + PUT_REF, + __PUT_REF, + BOTH_REF +}; + +struct sdp_sock_hist { + char *str; + char *func; + int line; + int pid; + u8 cnt; + u8 ref_type; /* enum sdp_ref_type */ + u8 ref_enum; /* enum sdp_ref */ +}; + +static inline char *reftype2str(int reftype) +{ +#define ENUM2STR(e) [e] = #e + static char *enum2str[] = { + ENUM2STR(NOT_REF), + ENUM2STR(HOLD_REF), + ENUM2STR(PUT_REF), + ENUM2STR(__PUT_REF), + ENUM2STR(BOTH_REF) + }; + + if (reftype < 0 || reftype >= ARRAY_SIZE(enum2str)) { + printk(KERN_WARNING "reftype %d is illegal\n", reftype); + return NULL; + } + + return enum2str[reftype]; +} + +void _sdp_add_to_history(struct sock *sk, const char *str, + const char *func, int line, int ref_type, int ref_enum); +void sdp_print_history(struct sock *sk); + +#define sdp_add_to_history(sk, str) \ + _sdp_add_to_history(sk, str, __func__, __LINE__, 0, 0) + #define sock_hold(sk, msg) \ do { \ _sdp_add_to_history(sk, #msg, __func__, __LINE__, \ @@ -170,10 +217,20 @@ enum sdp_ref { __PUT_REF, msg); \ sock_ref(sk, #msg, __sock_put); \ } while (0) + +int sdp_ssk_hist_open(struct sock *sk); +int sdp_ssk_hist_close(struct sock *sk); +int sdp_ssk_hist_rename(struct sock *sk); + #else #define sock_hold(sk, msg) sock_ref(sk, #msg, sock_hold) #define sock_put(sk, msg) sock_ref(sk, #msg, sock_put) #define __sock_put(sk, msg) sock_ref(sk, #msg, __sock_put) + +#define _sdp_add_to_history(sk, str, func, line, ref_type, ref_enum) +#define sdp_add_to_history(sk, str) +#define sdp_print_history(sk) + #endif /* SDP_SOCK_HISTORY */ #define ENUM2STR(e) [e] = #e diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index 378ac73e9b0e5..5895ea4262e20 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -180,6 +180,9 @@ static int sdp_get_port(struct sock *sk, unsigned short snum) src_addr = (struct sockaddr_in *)&(ssk->id->route.addr.src_addr); inet_sk(sk)->num = ntohs(src_addr->sin_port); +#ifdef SDP_SOCK_HISTORY + sdp_ssk_hist_rename(sk); +#endif return 0; } @@ -545,6 +548,11 @@ static void sdp_destruct(struct sock *sk) sdp_destroy_resources(sk); up_read(&device_removal_lock); +#ifdef SDP_SOCK_HISTORY + sdp_add_to_history(sk, __func__); + sdp_ssk_hist_close(sk); +#endif + flush_workqueue(rx_comp_wq); /* Consider use cancel_work_sync(&ssk->rx_comp_work) */ @@ -1107,12 +1115,16 @@ static void sdp_destroy_work(struct work_struct *work); static void sdp_dreq_wait_timeout_work(struct work_struct *work); static void sdp_cma_timewait_timeout_work(struct work_struct *work); +atomic_t socket_idx = ATOMIC_INIT(0); + int sdp_init_sock(struct sock *sk) { struct sdp_sock *ssk = sdp_sk(sk); sdp_dbg(sk, "%s\n", __func__); + ssk->sk_id = atomic_inc_return(&socket_idx); + INIT_LIST_HEAD(&ssk->accept_queue); INIT_LIST_HEAD(&ssk->backlog_queue); INIT_DELAYED_WORK(&ssk->dreq_wait_work, sdp_dreq_wait_timeout_work); @@ -1157,6 +1169,7 @@ int sdp_init_sock(struct sock *sk) memset(ssk->hst, 0, sizeof ssk->hst); ssk->hst_idx = 0; spin_lock_init(&ssk->hst_lock); + sdp_ssk_hist_open(sk); #endif return 0; diff --git a/drivers/infiniband/ulp/sdp/sdp_proc.c b/drivers/infiniband/ulp/sdp/sdp_proc.c index c00093b8b8279..64c4933d34570 100644 --- a/drivers/infiniband/ulp/sdp/sdp_proc.c +++ b/drivers/infiniband/ulp/sdp/sdp_proc.c @@ -31,14 +31,23 @@ */ #include +#include #include #include "sdp.h" #ifdef CONFIG_PROC_FS +#define DEBUGFS_SDP_BASE "sdp" #define PROC_SDP_STATS "sdpstats" #define PROC_SDP_PERF "sdpprf" +#if defined(SDP_SOCK_HISTORY) || defined(SDP_PROFILING) +struct dentry *sdp_dbgfs_base; +#endif +#ifdef SDP_PROFILING +struct dentry *sdp_prof_file = NULL; +#endif + /* just like TCP fs */ struct sdp_seq_afinfo { struct module *owner; @@ -516,15 +525,222 @@ static struct file_operations sdpprf_fops = { }; #endif /* SDP_PROFILING */ +#ifdef SDP_SOCK_HISTORY + +void sdp_print_history(struct sock *sk) +{ + struct sdp_sock *ssk = sdp_sk(sk); + unsigned i; + unsigned long flags; + + spin_lock_irqsave(&ssk->hst_lock, flags); + + sdp_warn(sk, "############## %p %s %lu/%zu ##############\n", + sk, sdp_state_str(sk->sk_state), + ssk->hst_idx, ARRAY_SIZE(ssk->hst)); + + for (i = 0; i < ssk->hst_idx; ++i) { + struct sdp_sock_hist *hst = &ssk->hst[i]; + char *ref_str = reftype2str(hst->ref_type); + + if (hst->ref_type == NOT_REF) + ref_str = ""; + + if (hst->cnt != 1) { + sdp_warn(sk, "[%s:%d pid: %d] %s %s : %d\n", + hst->func, hst->line, hst->pid, + ref_str, hst->str, hst->cnt); + } else { + sdp_warn(sk, "[%s:%d pid: %d] %s %s\n", + hst->func, hst->line, hst->pid, + ref_str, hst->str); + } + } + + spin_unlock_irqrestore(&ssk->hst_lock, flags); +} + +void _sdp_add_to_history(struct sock *sk, const char *str, + const char *func, int line, int ref_type, int ref_enum) +{ + struct sdp_sock *ssk = sdp_sk(sk); + unsigned i; + unsigned long flags; + struct sdp_sock_hist *hst; + + spin_lock_irqsave(&ssk->hst_lock, flags); + + i = ssk->hst_idx; + + if (i >= ARRAY_SIZE(ssk->hst)) { + //sdp_warn(sk, "overflow, drop: %s\n", s); + ++ssk->hst_idx; + goto out; + } + + if (ssk->hst[i].str) + sdp_warn(sk, "overwriting %s\n", ssk->hst[i].str); + + switch (ref_type) { + case NOT_REF: + case HOLD_REF: +simple_add: + hst = &ssk->hst[i]; + hst->str = (char *)str; + hst->func = (char *)func; + hst->line = line; + hst->ref_type = ref_type; + hst->ref_enum = ref_enum; + hst->cnt = 1; + hst->pid = current->pid; + ++ssk->hst_idx; + break; + case PUT_REF: + case __PUT_REF: + /* Try to shrink history by attaching HOLD+PUT + * together */ + hst = i > 0 ? &ssk->hst[i - 1] : NULL; + if (hst && hst->ref_type == HOLD_REF && + hst->ref_enum == ref_enum) { + hst->ref_type = BOTH_REF; + hst->func = (char *)func; + hst->line = line; + hst->pid = current->pid; + + /* try to shrink some more - by summing up */ + --i; + hst = i > 0 ? &ssk->hst[i - 1] : NULL; + if (hst && hst->ref_type == BOTH_REF && + hst->ref_enum == ref_enum) { + ++hst->cnt; + hst->func = (char *)func; + hst->line = line; + hst->pid = current->pid; + ssk->hst[i].str = NULL; + + --ssk->hst_idx; + } + } else + goto simple_add; + break; + default: + sdp_warn(sk, "error\n"); + } +out: + spin_unlock_irqrestore(&ssk->hst_lock, flags); +} +static int sdp_ssk_hist_seq_show(struct seq_file *seq, void *v) +{ + struct sock *sk = seq->private; + struct sdp_sock *ssk = sdp_sk(sk); + unsigned i; + unsigned long flags; + + spin_lock_irqsave(&ssk->hst_lock, flags); + + seq_printf(seq, "############## %p %s %lu/%zu ##############\n", + sk, sdp_state_str(sk->sk_state), + ssk->hst_idx, ARRAY_SIZE(ssk->hst)); + + for (i = 0; i < ssk->hst_idx; ++i) { + struct sdp_sock_hist *hst = &ssk->hst[i]; + char *ref_str = reftype2str(hst->ref_type); + + if (hst->ref_type == NOT_REF) + ref_str = ""; + + if (hst->cnt != 1) { + seq_printf(seq, "[%30s:%-5d pid: %-6d] %s %s : %d\n", + hst->func, hst->line, hst->pid, + ref_str, hst->str, hst->cnt); + } else { + seq_printf(seq, "[%30s:%-5d pid: %-6d] %s %s\n", + hst->func, hst->line, hst->pid, + ref_str, hst->str); + } + } + + spin_unlock_irqrestore(&ssk->hst_lock, flags); + return 0; +} + +static int sdp_ssk_hist_seq_open(struct inode *inode, struct file *file) +{ + struct sock *sk = inode->i_private; + + return single_open(file, sdp_ssk_hist_seq_show, sk); +} + +static struct file_operations ssk_hist_fops = { + .owner = THIS_MODULE, + .open = sdp_ssk_hist_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void sdp_ssk_hist_name(char *sk_name, int len, struct sock *sk) +{ + int lport = inet_sk(sk)->num; + int rport = ntohs(inet_sk(sk)->dport); + + snprintf(sk_name, len, "%05x_%d:%d", + sdp_sk(sk)->sk_id, lport, rport); +} + +int sdp_ssk_hist_open(struct sock *sk) +{ + int ret = 0; + char sk_name[256]; + struct sdp_sock *ssk = sdp_sk(sk); + + if (!sdp_dbgfs_base) { + return 0; + } + + sdp_ssk_hist_name(sk_name, sizeof(sk_name), sk); + + ssk->hst_dentr = debugfs_create_file(sk_name, S_IRUGO | S_IWUGO, + sdp_dbgfs_base, sk, &ssk_hist_fops); + if (IS_ERR(ssk->hst_dentr)) { + ret = PTR_ERR(ssk->hst_dentr); + ssk->hst_dentr = NULL; + } + + return ret; +} + +int sdp_ssk_hist_close(struct sock *sk) +{ + if (sk && sdp_sk(sk)->hst_dentr) + debugfs_remove(sdp_sk(sk)->hst_dentr); + return 0; +} + +int sdp_ssk_hist_rename(struct sock *sk) +{ + char sk_name[256]; + struct dentry *d; + + if (!sk || !sdp_sk(sk)->hst_dentr) + return 0; + + sdp_ssk_hist_name(sk_name, sizeof(sk_name), sk); + + d = debugfs_rename(sdp_dbgfs_base, sdp_sk(sk)->hst_dentr, sdp_dbgfs_base, sk_name); + if (IS_ERR(d)) + return PTR_ERR(d); + + return 0; +} +#endif + int __init sdp_proc_init(void) { struct proc_dir_entry *p = NULL; #ifdef SDPSTATS_ON struct proc_dir_entry *stats = NULL; #endif -#ifdef SDP_PROFILING - struct proc_dir_entry *prof = NULL; -#endif sdp_seq_afinfo.seq_fops->owner = sdp_seq_afinfo.owner; sdp_seq_afinfo.seq_fops->open = sdp_seq_open; @@ -532,6 +748,19 @@ int __init sdp_proc_init(void) sdp_seq_afinfo.seq_fops->llseek = seq_lseek; sdp_seq_afinfo.seq_fops->release = seq_release_private; +#if defined(SDP_PROFILING) || defined(SDP_SOCK_HISTORY) + sdp_dbgfs_base = debugfs_create_dir(DEBUGFS_SDP_BASE, NULL); + if (!sdp_dbgfs_base || IS_ERR(sdp_dbgfs_base)) { + if (PTR_ERR(sdp_dbgfs_base) == -ENODEV) + printk(KERN_WARNING "sdp: debugfs is not supported.\n"); + else { + printk(KERN_ERR "sdp: error creating debugfs information %ld\n", + PTR_ERR(sdp_dbgfs_base)); + return -EINVAL; + } + } +#endif + p = proc_net_fops_create(&init_net, sdp_seq_afinfo.name, S_IRUGO, sdp_seq_afinfo.seq_fops); if (p) @@ -549,9 +778,9 @@ int __init sdp_proc_init(void) #endif #ifdef SDP_PROFILING - prof = proc_net_fops_create(&init_net, PROC_SDP_PERF, - S_IRUGO | S_IWUGO, &sdpprf_fops); - if (!prof) + sdp_prof_file = debugfs_create_file(PROC_SDP_PERF, S_IRUGO | S_IWUGO, + sdp_dbgfs_base, NULL, &sdpprf_fops); + if (!sdp_prof_file) goto no_mem_prof; #endif @@ -581,7 +810,10 @@ void sdp_proc_unregister(void) proc_net_remove(&init_net, PROC_SDP_STATS); #endif #ifdef SDP_PROFILING - proc_net_remove(&init_net, PROC_SDP_PERF); + debugfs_remove(sdp_prof_file); +#endif +#if defined(SDP_PROFILING) || defined(SDP_SOCK_HISTORY) + debugfs_remove(sdp_dbgfs_base); #endif }