aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/bcast.c63
-rw-r--r--net/tipc/bearer.c10
-rw-r--r--net/tipc/bearer.h2
-rw-r--r--net/tipc/config.c27
-rw-r--r--net/tipc/core.h4
-rw-r--r--net/tipc/discover.c6
-rw-r--r--net/tipc/link.c130
-rw-r--r--net/tipc/log.c47
-rw-r--r--net/tipc/name_table.c88
-rw-r--r--net/tipc/port.c58
10 files changed, 213 insertions, 222 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index fef3689bcf2..e4e6d8cd47e 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -701,48 +701,43 @@ void tipc_bcbearer_sort(void)
701 701
702int tipc_bclink_stats(char *buf, const u32 buf_size) 702int tipc_bclink_stats(char *buf, const u32 buf_size)
703{ 703{
704 struct print_buf pb; 704 int ret;
705 struct tipc_stats *s;
705 706
706 if (!bcl) 707 if (!bcl)
707 return 0; 708 return 0;
708 709
709 tipc_printbuf_init(&pb, buf, buf_size);
710
711 spin_lock_bh(&bc_lock); 710 spin_lock_bh(&bc_lock);
712 711
713 tipc_printf(&pb, "Link <%s>\n" 712 s = &bcl->stats;
714 " Window:%u packets\n", 713
715 bcl->name, bcl->queue_limit[0]); 714 ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
716 tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", 715 " Window:%u packets\n",
717 bcl->stats.recv_info, 716 bcl->name, bcl->queue_limit[0]);
718 bcl->stats.recv_fragments, 717 ret += tipc_snprintf(buf + ret, buf_size - ret,
719 bcl->stats.recv_fragmented, 718 " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
720 bcl->stats.recv_bundles, 719 s->recv_info, s->recv_fragments,
721 bcl->stats.recv_bundled); 720 s->recv_fragmented, s->recv_bundles,
722 tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", 721 s->recv_bundled);
723 bcl->stats.sent_info, 722 ret += tipc_snprintf(buf + ret, buf_size - ret,
724 bcl->stats.sent_fragments, 723 " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
725 bcl->stats.sent_fragmented, 724 s->sent_info, s->sent_fragments,
726 bcl->stats.sent_bundles, 725 s->sent_fragmented, s->sent_bundles,
727 bcl->stats.sent_bundled); 726 s->sent_bundled);
728 tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n", 727 ret += tipc_snprintf(buf + ret, buf_size - ret,
729 bcl->stats.recv_nacks, 728 " RX naks:%u defs:%u dups:%u\n",
730 bcl->stats.deferred_recv, 729 s->recv_nacks, s->deferred_recv, s->duplicates);
731 bcl->stats.duplicates); 730 ret += tipc_snprintf(buf + ret, buf_size - ret,
732 tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n", 731 " TX naks:%u acks:%u dups:%u\n",
733 bcl->stats.sent_nacks, 732 s->sent_nacks, s->sent_acks, s->retransmitted);
734 bcl->stats.sent_acks, 733 ret += tipc_snprintf(buf + ret, buf_size - ret,
735 bcl->stats.retransmitted); 734 " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
736 tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", 735 s->bearer_congs, s->link_congs, s->max_queue_sz,
737 bcl->stats.bearer_congs, 736 s->queue_sz_counts ?
738 bcl->stats.link_congs, 737 (s->accu_queue_sz / s->queue_sz_counts) : 0);
739 bcl->stats.max_queue_sz,
740 bcl->stats.queue_sz_counts
741 ? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts)
742 : 0);
743 738
744 spin_unlock_bh(&bc_lock); 739 spin_unlock_bh(&bc_lock);
745 return tipc_printbuf_validate(&pb); 740 return ret;
746} 741}
747 742
748int tipc_bclink_reset_stats(void) 743int tipc_bclink_reset_stats(void)
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 1840e1fadd2..09e71241265 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -130,21 +130,23 @@ exit:
130/** 130/**
131 * tipc_media_addr_printf - record media address in print buffer 131 * tipc_media_addr_printf - record media address in print buffer
132 */ 132 */
133void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) 133void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
134{ 134{
135 char addr_str[MAX_ADDR_STR]; 135 char addr_str[MAX_ADDR_STR];
136 struct tipc_media *m_ptr; 136 struct tipc_media *m_ptr;
137 int ret;
137 138
138 m_ptr = media_find_id(a->media_id); 139 m_ptr = media_find_id(a->media_id);
139 140
140 if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str))) 141 if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
141 tipc_printf(pb, "%s(%s)", m_ptr->name, addr_str); 142 ret = tipc_snprintf(buf, len, "%s(%s)", m_ptr->name, addr_str);
142 else { 143 else {
143 u32 i; 144 u32 i;
144 145
145 tipc_printf(pb, "UNKNOWN(%u)", a->media_id); 146 ret = tipc_snprintf(buf, len, "UNKNOWN(%u)", a->media_id);
146 for (i = 0; i < sizeof(a->value); i++) 147 for (i = 0; i < sizeof(a->value); i++)
147 tipc_printf(pb, "-%02x", a->value[i]); 148 ret += tipc_snprintf(buf - ret, len + ret,
149 "-%02x", a->value[i]);
148 } 150 }
149} 151}
150 152
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 4680de118af..dd4c2abf08e 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -179,7 +179,7 @@ void tipc_eth_media_stop(void);
179 179
180int tipc_media_set_priority(const char *name, u32 new_value); 180int tipc_media_set_priority(const char *name, u32 new_value);
181int tipc_media_set_window(const char *name, u32 new_value); 181int tipc_media_set_window(const char *name, u32 new_value);
182void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); 182void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
183struct sk_buff *tipc_media_get_names(void); 183struct sk_buff *tipc_media_get_names(void);
184 184
185struct sk_buff *tipc_bearer_get_names(void); 185struct sk_buff *tipc_bearer_get_names(void);
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 7978fdd9929..96cfbf834a1 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -39,6 +39,8 @@
39#include "name_table.h" 39#include "name_table.h"
40#include "config.h" 40#include "config.h"
41 41
42#define REPLY_TRUNCATED "<truncated>\n"
43
42static u32 config_port_ref; 44static u32 config_port_ref;
43 45
44static DEFINE_SPINLOCK(config_lock); 46static DEFINE_SPINLOCK(config_lock);
@@ -104,13 +106,12 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
104 return buf; 106 return buf;
105} 107}
106 108
107#define MAX_STATS_INFO 2000
108
109static struct sk_buff *tipc_show_stats(void) 109static struct sk_buff *tipc_show_stats(void)
110{ 110{
111 struct sk_buff *buf; 111 struct sk_buff *buf;
112 struct tlv_desc *rep_tlv; 112 struct tlv_desc *rep_tlv;
113 struct print_buf pb; 113 char *pb;
114 int pb_len;
114 int str_len; 115 int str_len;
115 u32 value; 116 u32 value;
116 117
@@ -121,17 +122,16 @@ static struct sk_buff *tipc_show_stats(void)
121 if (value != 0) 122 if (value != 0)
122 return tipc_cfg_reply_error_string("unsupported argument"); 123 return tipc_cfg_reply_error_string("unsupported argument");
123 124
124 buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); 125 buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
125 if (buf == NULL) 126 if (buf == NULL)
126 return NULL; 127 return NULL;
127 128
128 rep_tlv = (struct tlv_desc *)buf->data; 129 rep_tlv = (struct tlv_desc *)buf->data;
129 tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); 130 pb = TLV_DATA(rep_tlv);
130 131 pb_len = ULTRA_STRING_MAX_LEN;
131 tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n");
132 132
133 /* Use additional tipc_printf()'s to return more info ... */ 133 str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n");
134 str_len = tipc_printbuf_validate(&pb); 134 str_len += 1; /* for "\0" */
135 skb_put(buf, TLV_SPACE(str_len)); 135 skb_put(buf, TLV_SPACE(str_len));
136 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); 136 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
137 137
@@ -408,6 +408,15 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
408 break; 408 break;
409 } 409 }
410 410
411 WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN));
412
413 /* Append an error message if we cannot return all requested data */
414 if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) {
415 if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0')
416 sprintf(rep_tlv_buf->data + rep_tlv_buf->len -
417 sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED);
418 }
419
411 /* Return reply buffer */ 420 /* Return reply buffer */
412exit: 421exit:
413 spin_unlock_bh(&config_lock); 422 spin_unlock_bh(&config_lock);
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 600c433e146..4dcdb485902 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -60,6 +60,8 @@
60 60
61#define TIPC_MOD_VER "2.0.0" 61#define TIPC_MOD_VER "2.0.0"
62 62
63#define ULTRA_STRING_MAX_LEN 32768
64
63struct tipc_msg; /* msg.h */ 65struct tipc_msg; /* msg.h */
64struct print_buf; /* log.h */ 66struct print_buf; /* log.h */
65 67
@@ -82,7 +84,7 @@ extern struct print_buf *const TIPC_NULL;
82extern struct print_buf *const TIPC_CONS; 84extern struct print_buf *const TIPC_CONS;
83extern struct print_buf *const TIPC_LOG; 85extern struct print_buf *const TIPC_LOG;
84 86
85void tipc_printf(struct print_buf *, const char *fmt, ...); 87int tipc_snprintf(char *buf, int len, const char *fmt, ...);
86 88
87/* 89/*
88 * TIPC_OUTPUT is the destination print buffer for system messages. 90 * TIPC_OUTPUT is the destination print buffer for system messages.
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 2f91f377009..50eaa403eb6 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -100,12 +100,10 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
100{ 100{
101 char node_addr_str[16]; 101 char node_addr_str[16];
102 char media_addr_str[64]; 102 char media_addr_str[64];
103 struct print_buf pb;
104 103
105 tipc_addr_string_fill(node_addr_str, node_addr); 104 tipc_addr_string_fill(node_addr_str, node_addr);
106 tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str)); 105 tipc_media_addr_printf(media_addr_str, sizeof(media_addr_str),
107 tipc_media_addr_printf(&pb, media_addr); 106 media_addr);
108 tipc_printbuf_validate(&pb);
109 pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str, 107 pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str,
110 media_addr_str, b_ptr->name); 108 media_addr_str, b_ptr->name);
111} 109}
diff --git a/net/tipc/link.c b/net/tipc/link.c
index a9a8b866d30..1c1e6151875 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2866,112 +2866,114 @@ static u32 percent(u32 count, u32 total)
2866 */ 2866 */
2867static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) 2867static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
2868{ 2868{
2869 struct print_buf pb; 2869 struct tipc_link *l;
2870 struct tipc_link *l_ptr; 2870 struct tipc_stats *s;
2871 struct tipc_node *node; 2871 struct tipc_node *node;
2872 char *status; 2872 char *status;
2873 u32 profile_total = 0; 2873 u32 profile_total = 0;
2874 int ret;
2874 2875
2875 if (!strcmp(name, tipc_bclink_name)) 2876 if (!strcmp(name, tipc_bclink_name))
2876 return tipc_bclink_stats(buf, buf_size); 2877 return tipc_bclink_stats(buf, buf_size);
2877 2878
2878 tipc_printbuf_init(&pb, buf, buf_size);
2879
2880 read_lock_bh(&tipc_net_lock); 2879 read_lock_bh(&tipc_net_lock);
2881 l_ptr = link_find_link(name, &node); 2880 l = link_find_link(name, &node);
2882 if (!l_ptr) { 2881 if (!l) {
2883 read_unlock_bh(&tipc_net_lock); 2882 read_unlock_bh(&tipc_net_lock);
2884 return 0; 2883 return 0;
2885 } 2884 }
2886 tipc_node_lock(node); 2885 tipc_node_lock(node);
2886 s = &l->stats;
2887 2887
2888 if (tipc_link_is_active(l_ptr)) 2888 if (tipc_link_is_active(l))
2889 status = "ACTIVE"; 2889 status = "ACTIVE";
2890 else if (tipc_link_is_up(l_ptr)) 2890 else if (tipc_link_is_up(l))
2891 status = "STANDBY"; 2891 status = "STANDBY";
2892 else 2892 else
2893 status = "DEFUNCT"; 2893 status = "DEFUNCT";
2894 tipc_printf(&pb, "Link <%s>\n" 2894
2895 " %s MTU:%u Priority:%u Tolerance:%u ms" 2895 ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
2896 " Window:%u packets\n", 2896 " %s MTU:%u Priority:%u Tolerance:%u ms"
2897 l_ptr->name, status, l_ptr->max_pkt, 2897 " Window:%u packets\n",
2898 l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); 2898 l->name, status, l->max_pkt, l->priority,
2899 tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", 2899 l->tolerance, l->queue_limit[0]);
2900 l_ptr->next_in_no - l_ptr->stats.recv_info, 2900
2901 l_ptr->stats.recv_fragments, 2901 ret += tipc_snprintf(buf + ret, buf_size - ret,
2902 l_ptr->stats.recv_fragmented, 2902 " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
2903 l_ptr->stats.recv_bundles, 2903 l->next_in_no - s->recv_info, s->recv_fragments,
2904 l_ptr->stats.recv_bundled); 2904 s->recv_fragmented, s->recv_bundles,
2905 tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", 2905 s->recv_bundled);
2906 l_ptr->next_out_no - l_ptr->stats.sent_info, 2906
2907 l_ptr->stats.sent_fragments, 2907 ret += tipc_snprintf(buf + ret, buf_size - ret,
2908 l_ptr->stats.sent_fragmented, 2908 " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
2909 l_ptr->stats.sent_bundles, 2909 l->next_out_no - s->sent_info, s->sent_fragments,
2910 l_ptr->stats.sent_bundled); 2910 s->sent_fragmented, s->sent_bundles,
2911 profile_total = l_ptr->stats.msg_length_counts; 2911 s->sent_bundled);
2912
2913 profile_total = s->msg_length_counts;
2912 if (!profile_total) 2914 if (!profile_total)
2913 profile_total = 1; 2915 profile_total = 1;
2914 tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n" 2916
2915 " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " 2917 ret += tipc_snprintf(buf + ret, buf_size - ret,
2916 "-16384:%u%% -32768:%u%% -66000:%u%%\n", 2918 " TX profile sample:%u packets average:%u octets\n"
2917 l_ptr->stats.msg_length_counts, 2919 " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
2918 l_ptr->stats.msg_lengths_total / profile_total, 2920 "-16384:%u%% -32768:%u%% -66000:%u%%\n",
2919 percent(l_ptr->stats.msg_length_profile[0], profile_total), 2921 s->msg_length_counts,
2920 percent(l_ptr->stats.msg_length_profile[1], profile_total), 2922 s->msg_lengths_total / profile_total,
2921 percent(l_ptr->stats.msg_length_profile[2], profile_total), 2923 percent(s->msg_length_profile[0], profile_total),
2922 percent(l_ptr->stats.msg_length_profile[3], profile_total), 2924 percent(s->msg_length_profile[1], profile_total),
2923 percent(l_ptr->stats.msg_length_profile[4], profile_total), 2925 percent(s->msg_length_profile[2], profile_total),
2924 percent(l_ptr->stats.msg_length_profile[5], profile_total), 2926 percent(s->msg_length_profile[3], profile_total),
2925 percent(l_ptr->stats.msg_length_profile[6], profile_total)); 2927 percent(s->msg_length_profile[4], profile_total),
2926 tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", 2928 percent(s->msg_length_profile[5], profile_total),
2927 l_ptr->stats.recv_states, 2929 percent(s->msg_length_profile[6], profile_total));
2928 l_ptr->stats.recv_probes, 2930
2929 l_ptr->stats.recv_nacks, 2931 ret += tipc_snprintf(buf + ret, buf_size - ret,
2930 l_ptr->stats.deferred_recv, 2932 " RX states:%u probes:%u naks:%u defs:%u"
2931 l_ptr->stats.duplicates); 2933 " dups:%u\n", s->recv_states, s->recv_probes,
2932 tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", 2934 s->recv_nacks, s->deferred_recv, s->duplicates);
2933 l_ptr->stats.sent_states, 2935
2934 l_ptr->stats.sent_probes, 2936 ret += tipc_snprintf(buf + ret, buf_size - ret,
2935 l_ptr->stats.sent_nacks, 2937 " TX states:%u probes:%u naks:%u acks:%u"
2936 l_ptr->stats.sent_acks, 2938 " dups:%u\n", s->sent_states, s->sent_probes,
2937 l_ptr->stats.retransmitted); 2939 s->sent_nacks, s->sent_acks, s->retransmitted);
2938 tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", 2940
2939 l_ptr->stats.bearer_congs, 2941 ret += tipc_snprintf(buf + ret, buf_size - ret,
2940 l_ptr->stats.link_congs, 2942 " Congestion bearer:%u link:%u Send queue"
2941 l_ptr->stats.max_queue_sz, 2943 " max:%u avg:%u\n", s->bearer_congs, s->link_congs,
2942 l_ptr->stats.queue_sz_counts 2944 s->max_queue_sz, s->queue_sz_counts ?
2943 ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts) 2945 (s->accu_queue_sz / s->queue_sz_counts) : 0);
2944 : 0);
2945 2946
2946 tipc_node_unlock(node); 2947 tipc_node_unlock(node);
2947 read_unlock_bh(&tipc_net_lock); 2948 read_unlock_bh(&tipc_net_lock);
2948 return tipc_printbuf_validate(&pb); 2949 return ret;
2949} 2950}
2950 2951
2951#define MAX_LINK_STATS_INFO 2000
2952
2953struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) 2952struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
2954{ 2953{
2955 struct sk_buff *buf; 2954 struct sk_buff *buf;
2956 struct tlv_desc *rep_tlv; 2955 struct tlv_desc *rep_tlv;
2957 int str_len; 2956 int str_len;
2957 int pb_len;
2958 char *pb;
2958 2959
2959 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) 2960 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
2960 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 2961 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
2961 2962
2962 buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); 2963 buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
2963 if (!buf) 2964 if (!buf)
2964 return NULL; 2965 return NULL;
2965 2966
2966 rep_tlv = (struct tlv_desc *)buf->data; 2967 rep_tlv = (struct tlv_desc *)buf->data;
2967 2968 pb = TLV_DATA(rep_tlv);
2969 pb_len = ULTRA_STRING_MAX_LEN;
2968 str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), 2970 str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area),
2969 (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); 2971 pb, pb_len);
2970 if (!str_len) { 2972 if (!str_len) {
2971 kfree_skb(buf); 2973 kfree_skb(buf);
2972 return tipc_cfg_reply_error_string("link not found"); 2974 return tipc_cfg_reply_error_string("link not found");
2973 } 2975 }
2974 2976 str_len += 1; /* for "\0" */
2975 skb_put(buf, TLV_SPACE(str_len)); 2977 skb_put(buf, TLV_SPACE(str_len));
2976 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); 2978 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
2977 2979
diff --git a/net/tipc/log.c b/net/tipc/log.c
index d01e37a61b9..fa7ce927fda 100644
--- a/net/tipc/log.c
+++ b/net/tipc/log.c
@@ -125,40 +125,6 @@ static int tipc_printbuf_empty(struct print_buf *pb)
125} 125}
126 126
127/** 127/**
128 * tipc_printbuf_validate - check for print buffer overflow
129 * @pb: pointer to print buffer structure
130 *
131 * Verifies that a print buffer has captured all data written to it.
132 * If data has been lost, linearize buffer and prepend an error message
133 *
134 * Returns length of print buffer data string (including trailing NUL)
135 */
136int tipc_printbuf_validate(struct print_buf *pb)
137{
138 char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
139 char *cp_buf;
140 struct print_buf cb;
141
142 if (!pb->buf)
143 return 0;
144
145 if (pb->buf[pb->size - 1] == 0) {
146 cp_buf = kmalloc(pb->size, GFP_ATOMIC);
147 if (cp_buf) {
148 tipc_printbuf_init(&cb, cp_buf, pb->size);
149 tipc_printbuf_move(&cb, pb);
150 tipc_printbuf_move(pb, &cb);
151 kfree(cp_buf);
152 memcpy(pb->buf, err, strlen(err));
153 } else {
154 tipc_printbuf_reset(pb);
155 tipc_printf(pb, err);
156 }
157 }
158 return pb->crs - pb->buf + 1;
159}
160
161/**
162 * tipc_printbuf_move - move print buffer contents to another print buffer 128 * tipc_printbuf_move - move print buffer contents to another print buffer
163 * @pb_to: pointer to destination print buffer structure 129 * @pb_to: pointer to destination print buffer structure
164 * @pb_from: pointer to source print buffer structure 130 * @pb_from: pointer to source print buffer structure
@@ -204,23 +170,20 @@ static void tipc_printbuf_move(struct print_buf *pb_to,
204} 170}
205 171
206/** 172/**
207 * tipc_printf - append formatted output to print buffer 173 * tipc_snprintf - append formatted output to print buffer
208 * @pb: pointer to print buffer 174 * @buf: pointer to print buffer
175 * @len: buffer length
209 * @fmt: formatted info to be printed 176 * @fmt: formatted info to be printed
210 */ 177 */
211void tipc_printf(struct print_buf *pb, const char *fmt, ...) 178int tipc_snprintf(char *buf, int len, const char *fmt, ...)
212{ 179{
213 int i; 180 int i;
214 va_list args; 181 va_list args;
215 char *buf;
216 int len;
217 182
218 buf = pb->crs;
219 len = pb->buf + pb->size - pb->crs;
220 va_start(args, fmt); 183 va_start(args, fmt);
221 i = vscnprintf(buf, len, fmt, args); 184 i = vscnprintf(buf, len, fmt, args);
222 va_end(args); 185 va_end(args);
223 pb->crs += i; 186 return i;
224} 187}
225 188
226/** 189/**
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index c8b0b5c3c56..360c478b0b5 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -753,19 +753,20 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
753/** 753/**
754 * subseq_list - print specified sub-sequence contents into the given buffer 754 * subseq_list - print specified sub-sequence contents into the given buffer
755 */ 755 */
756static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, 756static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth,
757 u32 index) 757 u32 index)
758{ 758{
759 char portIdStr[27]; 759 char portIdStr[27];
760 const char *scope_str[] = {"", " zone", " cluster", " node"}; 760 const char *scope_str[] = {"", " zone", " cluster", " node"};
761 struct publication *publ; 761 struct publication *publ;
762 struct name_info *info; 762 struct name_info *info;
763 int ret;
763 764
764 tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); 765 ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper);
765 766
766 if (depth == 2) { 767 if (depth == 2) {
767 tipc_printf(buf, "\n"); 768 ret += tipc_snprintf(buf - ret, len + ret, "\n");
768 return; 769 return ret;
769 } 770 }
770 771
771 info = sseq->info; 772 info = sseq->info;
@@ -774,52 +775,58 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
774 sprintf(portIdStr, "<%u.%u.%u:%u>", 775 sprintf(portIdStr, "<%u.%u.%u:%u>",
775 tipc_zone(publ->node), tipc_cluster(publ->node), 776 tipc_zone(publ->node), tipc_cluster(publ->node),
776 tipc_node(publ->node), publ->ref); 777 tipc_node(publ->node), publ->ref);
777 tipc_printf(buf, "%-26s ", portIdStr); 778 ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr);
778 if (depth > 3) { 779 if (depth > 3) {
779 tipc_printf(buf, "%-10u %s", publ->key, 780 ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s",
780 scope_str[publ->scope]); 781 publ->key, scope_str[publ->scope]);
781 } 782 }
782 if (!list_is_last(&publ->zone_list, &info->zone_list)) 783 if (!list_is_last(&publ->zone_list, &info->zone_list))
783 tipc_printf(buf, "\n%33s", " "); 784 ret += tipc_snprintf(buf + ret, len - ret,
785 "\n%33s", " ");
784 }; 786 };
785 787
786 tipc_printf(buf, "\n"); 788 ret += tipc_snprintf(buf + ret, len - ret, "\n");
789 return ret;
787} 790}
788 791
789/** 792/**
790 * nameseq_list - print specified name sequence contents into the given buffer 793 * nameseq_list - print specified name sequence contents into the given buffer
791 */ 794 */
792static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, 795static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth,
793 u32 type, u32 lowbound, u32 upbound, u32 index) 796 u32 type, u32 lowbound, u32 upbound, u32 index)
794{ 797{
795 struct sub_seq *sseq; 798 struct sub_seq *sseq;
796 char typearea[11]; 799 char typearea[11];
800 int ret = 0;
797 801
798 if (seq->first_free == 0) 802 if (seq->first_free == 0)
799 return; 803 return 0;
800 804
801 sprintf(typearea, "%-10u", seq->type); 805 sprintf(typearea, "%-10u", seq->type);
802 806
803 if (depth == 1) { 807 if (depth == 1) {
804 tipc_printf(buf, "%s\n", typearea); 808 ret += tipc_snprintf(buf, len, "%s\n", typearea);
805 return; 809 return ret;
806 } 810 }
807 811
808 for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { 812 for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
809 if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { 813 if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
810 tipc_printf(buf, "%s ", typearea); 814 ret += tipc_snprintf(buf + ret, len - ret, "%s ",
815 typearea);
811 spin_lock_bh(&seq->lock); 816 spin_lock_bh(&seq->lock);
812 subseq_list(sseq, buf, depth, index); 817 ret += subseq_list(sseq, buf + ret, len - ret,
818 depth, index);
813 spin_unlock_bh(&seq->lock); 819 spin_unlock_bh(&seq->lock);
814 sprintf(typearea, "%10s", " "); 820 sprintf(typearea, "%10s", " ");
815 } 821 }
816 } 822 }
823 return ret;
817} 824}
818 825
819/** 826/**
820 * nametbl_header - print name table header into the given buffer 827 * nametbl_header - print name table header into the given buffer
821 */ 828 */
822static void nametbl_header(struct print_buf *buf, u32 depth) 829static int nametbl_header(char *buf, int len, u32 depth)
823{ 830{
824 const char *header[] = { 831 const char *header[] = {
825 "Type ", 832 "Type ",
@@ -829,24 +836,27 @@ static void nametbl_header(struct print_buf *buf, u32 depth)
829 }; 836 };
830 837
831 int i; 838 int i;
839 int ret = 0;
832 840
833 if (depth > 4) 841 if (depth > 4)
834 depth = 4; 842 depth = 4;
835 for (i = 0; i < depth; i++) 843 for (i = 0; i < depth; i++)
836 tipc_printf(buf, header[i]); 844 ret += tipc_snprintf(buf + ret, len - ret, header[i]);
837 tipc_printf(buf, "\n"); 845 ret += tipc_snprintf(buf + ret, len - ret, "\n");
846 return ret;
838} 847}
839 848
840/** 849/**
841 * nametbl_list - print specified name table contents into the given buffer 850 * nametbl_list - print specified name table contents into the given buffer
842 */ 851 */
843static void nametbl_list(struct print_buf *buf, u32 depth_info, 852static int nametbl_list(char *buf, int len, u32 depth_info,
844 u32 type, u32 lowbound, u32 upbound) 853 u32 type, u32 lowbound, u32 upbound)
845{ 854{
846 struct hlist_head *seq_head; 855 struct hlist_head *seq_head;
847 struct hlist_node *seq_node; 856 struct hlist_node *seq_node;
848 struct name_seq *seq; 857 struct name_seq *seq;
849 int all_types; 858 int all_types;
859 int ret = 0;
850 u32 depth; 860 u32 depth;
851 u32 i; 861 u32 i;
852 862
@@ -854,65 +864,69 @@ static void nametbl_list(struct print_buf *buf, u32 depth_info,
854 depth = (depth_info & ~TIPC_NTQ_ALLTYPES); 864 depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
855 865
856 if (depth == 0) 866 if (depth == 0)
857 return; 867 return 0;
858 868
859 if (all_types) { 869 if (all_types) {
860 /* display all entries in name table to specified depth */ 870 /* display all entries in name table to specified depth */
861 nametbl_header(buf, depth); 871 ret += nametbl_header(buf, len, depth);
862 lowbound = 0; 872 lowbound = 0;
863 upbound = ~0; 873 upbound = ~0;
864 for (i = 0; i < tipc_nametbl_size; i++) { 874 for (i = 0; i < tipc_nametbl_size; i++) {
865 seq_head = &table.types[i]; 875 seq_head = &table.types[i];
866 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { 876 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
867 nameseq_list(seq, buf, depth, seq->type, 877 ret += nameseq_list(seq, buf + ret, len - ret,
868 lowbound, upbound, i); 878 depth, seq->type,
879 lowbound, upbound, i);
869 } 880 }
870 } 881 }
871 } else { 882 } else {
872 /* display only the sequence that matches the specified type */ 883 /* display only the sequence that matches the specified type */
873 if (upbound < lowbound) { 884 if (upbound < lowbound) {
874 tipc_printf(buf, "invalid name sequence specified\n"); 885 ret += tipc_snprintf(buf + ret, len - ret,
875 return; 886 "invalid name sequence specified\n");
887 return ret;
876 } 888 }
877 nametbl_header(buf, depth); 889 ret += nametbl_header(buf + ret, len - ret, depth);
878 i = hash(type); 890 i = hash(type);
879 seq_head = &table.types[i]; 891 seq_head = &table.types[i];
880 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { 892 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
881 if (seq->type == type) { 893 if (seq->type == type) {
882 nameseq_list(seq, buf, depth, type, 894 ret += nameseq_list(seq, buf + ret, len - ret,
883 lowbound, upbound, i); 895 depth, type,
896 lowbound, upbound, i);
884 break; 897 break;
885 } 898 }
886 } 899 }
887 } 900 }
901 return ret;
888} 902}
889 903
890#define MAX_NAME_TBL_QUERY 32768
891
892struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) 904struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
893{ 905{
894 struct sk_buff *buf; 906 struct sk_buff *buf;
895 struct tipc_name_table_query *argv; 907 struct tipc_name_table_query *argv;
896 struct tlv_desc *rep_tlv; 908 struct tlv_desc *rep_tlv;
897 struct print_buf b; 909 char *pb;
910 int pb_len;
898 int str_len; 911 int str_len;
899 912
900 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) 913 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
901 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 914 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
902 915
903 buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); 916 buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
904 if (!buf) 917 if (!buf)
905 return NULL; 918 return NULL;
906 919
907 rep_tlv = (struct tlv_desc *)buf->data; 920 rep_tlv = (struct tlv_desc *)buf->data;
908 tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); 921 pb = TLV_DATA(rep_tlv);
922 pb_len = ULTRA_STRING_MAX_LEN;
909 argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); 923 argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
910 read_lock_bh(&tipc_nametbl_lock); 924 read_lock_bh(&tipc_nametbl_lock);
911 nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), 925 str_len = nametbl_list(pb, pb_len, ntohl(argv->depth),
912 ntohl(argv->lowbound), ntohl(argv->upbound)); 926 ntohl(argv->type),
927 ntohl(argv->lowbound), ntohl(argv->upbound));
913 read_unlock_bh(&tipc_nametbl_lock); 928 read_unlock_bh(&tipc_nametbl_lock);
914 str_len = tipc_printbuf_validate(&b); 929 str_len += 1; /* for "\0" */
915
916 skb_put(buf, TLV_SPACE(str_len)); 930 skb_put(buf, TLV_SPACE(str_len));
917 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); 931 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
918 932
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 2cbac3956fc..07c42fba672 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -581,67 +581,73 @@ exit:
581 kfree_skb(buf); 581 kfree_skb(buf);
582} 582}
583 583
584static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id) 584static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id)
585{ 585{
586 struct publication *publ; 586 struct publication *publ;
587 int ret;
587 588
588 if (full_id) 589 if (full_id)
589 tipc_printf(buf, "<%u.%u.%u:%u>:", 590 ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
590 tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), 591 tipc_zone(tipc_own_addr),
591 tipc_node(tipc_own_addr), p_ptr->ref); 592 tipc_cluster(tipc_own_addr),
593 tipc_node(tipc_own_addr), p_ptr->ref);
592 else 594 else
593 tipc_printf(buf, "%-10u:", p_ptr->ref); 595 ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref);
594 596
595 if (p_ptr->connected) { 597 if (p_ptr->connected) {
596 u32 dport = port_peerport(p_ptr); 598 u32 dport = port_peerport(p_ptr);
597 u32 destnode = port_peernode(p_ptr); 599 u32 destnode = port_peernode(p_ptr);
598 600
599 tipc_printf(buf, " connected to <%u.%u.%u:%u>", 601 ret += tipc_snprintf(buf + ret, len - ret,
600 tipc_zone(destnode), tipc_cluster(destnode), 602 " connected to <%u.%u.%u:%u>",
601 tipc_node(destnode), dport); 603 tipc_zone(destnode),
604 tipc_cluster(destnode),
605 tipc_node(destnode), dport);
602 if (p_ptr->conn_type != 0) 606 if (p_ptr->conn_type != 0)
603 tipc_printf(buf, " via {%u,%u}", 607 ret += tipc_snprintf(buf + ret, len - ret,
604 p_ptr->conn_type, 608 " via {%u,%u}", p_ptr->conn_type,
605 p_ptr->conn_instance); 609 p_ptr->conn_instance);
606 } else if (p_ptr->published) { 610 } else if (p_ptr->published) {
607 tipc_printf(buf, " bound to"); 611 ret += tipc_snprintf(buf + ret, len - ret, " bound to");
608 list_for_each_entry(publ, &p_ptr->publications, pport_list) { 612 list_for_each_entry(publ, &p_ptr->publications, pport_list) {
609 if (publ->lower == publ->upper) 613 if (publ->lower == publ->upper)
610 tipc_printf(buf, " {%u,%u}", publ->type, 614 ret += tipc_snprintf(buf + ret, len - ret,
611 publ->lower); 615 " {%u,%u}", publ->type,
616 publ->lower);
612 else 617 else
613 tipc_printf(buf, " {%u,%u,%u}", publ->type, 618 ret += tipc_snprintf(buf + ret, len - ret,
614 publ->lower, publ->upper); 619 " {%u,%u,%u}", publ->type,
620 publ->lower, publ->upper);
615 } 621 }
616 } 622 }
617 tipc_printf(buf, "\n"); 623 ret += tipc_snprintf(buf + ret, len - ret, "\n");
624 return ret;
618} 625}
619 626
620#define MAX_PORT_QUERY 32768
621
622struct sk_buff *tipc_port_get_ports(void) 627struct sk_buff *tipc_port_get_ports(void)
623{ 628{
624 struct sk_buff *buf; 629 struct sk_buff *buf;
625 struct tlv_desc *rep_tlv; 630 struct tlv_desc *rep_tlv;
626 struct print_buf pb; 631 char *pb;
632 int pb_len;
627 struct tipc_port *p_ptr; 633 struct tipc_port *p_ptr;
628 int str_len; 634 int str_len = 0;
629 635
630 buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); 636 buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
631 if (!buf) 637 if (!buf)
632 return NULL; 638 return NULL;
633 rep_tlv = (struct tlv_desc *)buf->data; 639 rep_tlv = (struct tlv_desc *)buf->data;
640 pb = TLV_DATA(rep_tlv);
641 pb_len = ULTRA_STRING_MAX_LEN;
634 642
635 tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
636 spin_lock_bh(&tipc_port_list_lock); 643 spin_lock_bh(&tipc_port_list_lock);
637 list_for_each_entry(p_ptr, &ports, port_list) { 644 list_for_each_entry(p_ptr, &ports, port_list) {
638 spin_lock_bh(p_ptr->lock); 645 spin_lock_bh(p_ptr->lock);
639 port_print(p_ptr, &pb, 0); 646 str_len += port_print(p_ptr, pb, pb_len, 0);
640 spin_unlock_bh(p_ptr->lock); 647 spin_unlock_bh(p_ptr->lock);
641 } 648 }
642 spin_unlock_bh(&tipc_port_list_lock); 649 spin_unlock_bh(&tipc_port_list_lock);
643 str_len = tipc_printbuf_validate(&pb); 650 str_len += 1; /* for "\0" */
644
645 skb_put(buf, TLV_SPACE(str_len)); 651 skb_put(buf, TLV_SPACE(str_len));
646 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); 652 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
647 653