aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorErik Hugne <erik.hugne@ericsson.com>2012-06-29 00:50:23 -0400
committerPaul Gortmaker <paul.gortmaker@windriver.com>2012-07-13 19:33:28 -0400
commitdc1aed37d17b4fe4f28a74d804c065b877bc7bed (patch)
tree83907b44c25a9a10c84106d17eecfceff00864ce /net/tipc
parente2dbd601346aeb64b1b387168b217fd5c301644e (diff)
tipc: phase out most of the struct print_buf usage
The tipc_printf is renamed to tipc_snprintf, as the new name describes more what the function actually does. It is also changed to take a buffer and length parameter and return number of characters written to the buffer. All callers of this function that used to pass a print_buf are updated. Final removal of the struct print_buf itself will be done synchronously with the pending removal of the deprecated logging code that also was using it. Functions that build up a response message with a list of ports, nametable contents etc. are changed to return the number of characters written to the output buffer. This information was previously hidden in a field of the print_buf struct, and the number of chars written was fetched with a call to tipc_printbuf_validate. This function is removed since it is no longer referenced nor needed. A generic max size ULTRA_STRING_MAX_LEN is defined, named in keeping with the existing TIPC_TLV_ULTRA_STRING, and the various definitions in port, link and nametable code that largely duplicated this information are removed. This means that amount of link statistics that can be returned is now increased from 2k to 32k. The buffer overflow check is now done just before the reply message is passed over netlink or TIPC to a remote node and the message indicating a truncated buffer is changed to a less dramatic one (less CAPS), placed at the end of the message. Signed-off-by: Erik Hugne <erik.hugne@ericsson.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
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