Commit dc1aed37 authored by Erik Hugne's avatar Erik Hugne Committed by Paul Gortmaker

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: default avatarErik Hugne <erik.hugne@ericsson.com>
Signed-off-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
parent e2dbd601
...@@ -701,48 +701,43 @@ void tipc_bcbearer_sort(void) ...@@ -701,48 +701,43 @@ void tipc_bcbearer_sort(void)
int tipc_bclink_stats(char *buf, const u32 buf_size) int tipc_bclink_stats(char *buf, const u32 buf_size)
{ {
struct print_buf pb; int ret;
struct tipc_stats *s;
if (!bcl) if (!bcl)
return 0; return 0;
tipc_printbuf_init(&pb, buf, buf_size);
spin_lock_bh(&bc_lock); spin_lock_bh(&bc_lock);
tipc_printf(&pb, "Link <%s>\n" s = &bcl->stats;
" Window:%u packets\n",
bcl->name, bcl->queue_limit[0]); ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", " Window:%u packets\n",
bcl->stats.recv_info, bcl->name, bcl->queue_limit[0]);
bcl->stats.recv_fragments, ret += tipc_snprintf(buf + ret, buf_size - ret,
bcl->stats.recv_fragmented, " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
bcl->stats.recv_bundles, s->recv_info, s->recv_fragments,
bcl->stats.recv_bundled); s->recv_fragmented, s->recv_bundles,
tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", s->recv_bundled);
bcl->stats.sent_info, ret += tipc_snprintf(buf + ret, buf_size - ret,
bcl->stats.sent_fragments, " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
bcl->stats.sent_fragmented, s->sent_info, s->sent_fragments,
bcl->stats.sent_bundles, s->sent_fragmented, s->sent_bundles,
bcl->stats.sent_bundled); s->sent_bundled);
tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n", ret += tipc_snprintf(buf + ret, buf_size - ret,
bcl->stats.recv_nacks, " RX naks:%u defs:%u dups:%u\n",
bcl->stats.deferred_recv, s->recv_nacks, s->deferred_recv, s->duplicates);
bcl->stats.duplicates); ret += tipc_snprintf(buf + ret, buf_size - ret,
tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n", " TX naks:%u acks:%u dups:%u\n",
bcl->stats.sent_nacks, s->sent_nacks, s->sent_acks, s->retransmitted);
bcl->stats.sent_acks, ret += tipc_snprintf(buf + ret, buf_size - ret,
bcl->stats.retransmitted); " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", s->bearer_congs, s->link_congs, s->max_queue_sz,
bcl->stats.bearer_congs, s->queue_sz_counts ?
bcl->stats.link_congs, (s->accu_queue_sz / s->queue_sz_counts) : 0);
bcl->stats.max_queue_sz,
bcl->stats.queue_sz_counts
? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts)
: 0);
spin_unlock_bh(&bc_lock); spin_unlock_bh(&bc_lock);
return tipc_printbuf_validate(&pb); return ret;
} }
int tipc_bclink_reset_stats(void) int tipc_bclink_reset_stats(void)
......
...@@ -130,21 +130,23 @@ int tipc_register_media(struct tipc_media *m_ptr) ...@@ -130,21 +130,23 @@ int tipc_register_media(struct tipc_media *m_ptr)
/** /**
* tipc_media_addr_printf - record media address in print buffer * tipc_media_addr_printf - record media address in print buffer
*/ */
void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
{ {
char addr_str[MAX_ADDR_STR]; char addr_str[MAX_ADDR_STR];
struct tipc_media *m_ptr; struct tipc_media *m_ptr;
int ret;
m_ptr = media_find_id(a->media_id); m_ptr = media_find_id(a->media_id);
if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str))) if (m_ptr && !m_ptr->addr2str(a, addr_str, sizeof(addr_str)))
tipc_printf(pb, "%s(%s)", m_ptr->name, addr_str); ret = tipc_snprintf(buf, len, "%s(%s)", m_ptr->name, addr_str);
else { else {
u32 i; u32 i;
tipc_printf(pb, "UNKNOWN(%u)", a->media_id); ret = tipc_snprintf(buf, len, "UNKNOWN(%u)", a->media_id);
for (i = 0; i < sizeof(a->value); i++) for (i = 0; i < sizeof(a->value); i++)
tipc_printf(pb, "-%02x", a->value[i]); ret += tipc_snprintf(buf - ret, len + ret,
"-%02x", a->value[i]);
} }
} }
......
...@@ -179,7 +179,7 @@ void tipc_eth_media_stop(void); ...@@ -179,7 +179,7 @@ void tipc_eth_media_stop(void);
int tipc_media_set_priority(const char *name, u32 new_value); int tipc_media_set_priority(const char *name, u32 new_value);
int tipc_media_set_window(const char *name, u32 new_value); int tipc_media_set_window(const char *name, u32 new_value);
void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
struct sk_buff *tipc_media_get_names(void); struct sk_buff *tipc_media_get_names(void);
struct sk_buff *tipc_bearer_get_names(void); struct sk_buff *tipc_bearer_get_names(void);
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include "name_table.h" #include "name_table.h"
#include "config.h" #include "config.h"
#define REPLY_TRUNCATED "<truncated>\n"
static u32 config_port_ref; static u32 config_port_ref;
static DEFINE_SPINLOCK(config_lock); static DEFINE_SPINLOCK(config_lock);
...@@ -104,13 +106,12 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) ...@@ -104,13 +106,12 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
return buf; return buf;
} }
#define MAX_STATS_INFO 2000
static struct sk_buff *tipc_show_stats(void) static struct sk_buff *tipc_show_stats(void)
{ {
struct sk_buff *buf; struct sk_buff *buf;
struct tlv_desc *rep_tlv; struct tlv_desc *rep_tlv;
struct print_buf pb; char *pb;
int pb_len;
int str_len; int str_len;
u32 value; u32 value;
...@@ -121,17 +122,16 @@ static struct sk_buff *tipc_show_stats(void) ...@@ -121,17 +122,16 @@ static struct sk_buff *tipc_show_stats(void)
if (value != 0) if (value != 0)
return tipc_cfg_reply_error_string("unsupported argument"); return tipc_cfg_reply_error_string("unsupported argument");
buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
rep_tlv = (struct tlv_desc *)buf->data; rep_tlv = (struct tlv_desc *)buf->data;
tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); pb = TLV_DATA(rep_tlv);
pb_len = ULTRA_STRING_MAX_LEN;
tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n");
/* Use additional tipc_printf()'s to return more info ... */ str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n");
str_len = tipc_printbuf_validate(&pb); str_len += 1; /* for "\0" */
skb_put(buf, TLV_SPACE(str_len)); skb_put(buf, TLV_SPACE(str_len));
TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
...@@ -408,6 +408,15 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area ...@@ -408,6 +408,15 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
break; break;
} }
WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN));
/* Append an error message if we cannot return all requested data */
if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) {
if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0')
sprintf(rep_tlv_buf->data + rep_tlv_buf->len -
sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED);
}
/* Return reply buffer */ /* Return reply buffer */
exit: exit:
spin_unlock_bh(&config_lock); spin_unlock_bh(&config_lock);
......
...@@ -60,6 +60,8 @@ ...@@ -60,6 +60,8 @@
#define TIPC_MOD_VER "2.0.0" #define TIPC_MOD_VER "2.0.0"
#define ULTRA_STRING_MAX_LEN 32768
struct tipc_msg; /* msg.h */ struct tipc_msg; /* msg.h */
struct print_buf; /* log.h */ struct print_buf; /* log.h */
...@@ -82,7 +84,7 @@ extern struct print_buf *const TIPC_NULL; ...@@ -82,7 +84,7 @@ extern struct print_buf *const TIPC_NULL;
extern struct print_buf *const TIPC_CONS; extern struct print_buf *const TIPC_CONS;
extern struct print_buf *const TIPC_LOG; extern struct print_buf *const TIPC_LOG;
void tipc_printf(struct print_buf *, const char *fmt, ...); int tipc_snprintf(char *buf, int len, const char *fmt, ...);
/* /*
* TIPC_OUTPUT is the destination print buffer for system messages. * TIPC_OUTPUT is the destination print buffer for system messages.
......
...@@ -100,12 +100,10 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr, ...@@ -100,12 +100,10 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
{ {
char node_addr_str[16]; char node_addr_str[16];
char media_addr_str[64]; char media_addr_str[64];
struct print_buf pb;
tipc_addr_string_fill(node_addr_str, node_addr); tipc_addr_string_fill(node_addr_str, node_addr);
tipc_printbuf_init(&pb, media_addr_str, sizeof(media_addr_str)); tipc_media_addr_printf(media_addr_str, sizeof(media_addr_str),
tipc_media_addr_printf(&pb, media_addr); media_addr);
tipc_printbuf_validate(&pb);
pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str, pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str,
media_addr_str, b_ptr->name); media_addr_str, b_ptr->name);
} }
......
...@@ -2866,112 +2866,114 @@ static u32 percent(u32 count, u32 total) ...@@ -2866,112 +2866,114 @@ static u32 percent(u32 count, u32 total)
*/ */
static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
{ {
struct print_buf pb; struct tipc_link *l;
struct tipc_link *l_ptr; struct tipc_stats *s;
struct tipc_node *node; struct tipc_node *node;
char *status; char *status;
u32 profile_total = 0; u32 profile_total = 0;
int ret;
if (!strcmp(name, tipc_bclink_name)) if (!strcmp(name, tipc_bclink_name))
return tipc_bclink_stats(buf, buf_size); return tipc_bclink_stats(buf, buf_size);
tipc_printbuf_init(&pb, buf, buf_size);
read_lock_bh(&tipc_net_lock); read_lock_bh(&tipc_net_lock);
l_ptr = link_find_link(name, &node); l = link_find_link(name, &node);
if (!l_ptr) { if (!l) {
read_unlock_bh(&tipc_net_lock); read_unlock_bh(&tipc_net_lock);
return 0; return 0;
} }
tipc_node_lock(node); tipc_node_lock(node);
s = &l->stats;
if (tipc_link_is_active(l_ptr)) if (tipc_link_is_active(l))
status = "ACTIVE"; status = "ACTIVE";
else if (tipc_link_is_up(l_ptr)) else if (tipc_link_is_up(l))
status = "STANDBY"; status = "STANDBY";
else else
status = "DEFUNCT"; status = "DEFUNCT";
tipc_printf(&pb, "Link <%s>\n"
" %s MTU:%u Priority:%u Tolerance:%u ms" ret = tipc_snprintf(buf, buf_size, "Link <%s>\n"
" Window:%u packets\n", " %s MTU:%u Priority:%u Tolerance:%u ms"
l_ptr->name, status, l_ptr->max_pkt, " Window:%u packets\n",
l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); l->name, status, l->max_pkt, l->priority,
tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", l->tolerance, l->queue_limit[0]);
l_ptr->next_in_no - l_ptr->stats.recv_info,
l_ptr->stats.recv_fragments, ret += tipc_snprintf(buf + ret, buf_size - ret,
l_ptr->stats.recv_fragmented, " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
l_ptr->stats.recv_bundles, l->next_in_no - s->recv_info, s->recv_fragments,
l_ptr->stats.recv_bundled); s->recv_fragmented, s->recv_bundles,
tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", s->recv_bundled);
l_ptr->next_out_no - l_ptr->stats.sent_info,
l_ptr->stats.sent_fragments, ret += tipc_snprintf(buf + ret, buf_size - ret,
l_ptr->stats.sent_fragmented, " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
l_ptr->stats.sent_bundles, l->next_out_no - s->sent_info, s->sent_fragments,
l_ptr->stats.sent_bundled); s->sent_fragmented, s->sent_bundles,
profile_total = l_ptr->stats.msg_length_counts; s->sent_bundled);
profile_total = s->msg_length_counts;
if (!profile_total) if (!profile_total)
profile_total = 1; profile_total = 1;
tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n"
" 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " ret += tipc_snprintf(buf + ret, buf_size - ret,
"-16384:%u%% -32768:%u%% -66000:%u%%\n", " TX profile sample:%u packets average:%u octets\n"
l_ptr->stats.msg_length_counts, " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
l_ptr->stats.msg_lengths_total / profile_total, "-16384:%u%% -32768:%u%% -66000:%u%%\n",
percent(l_ptr->stats.msg_length_profile[0], profile_total), s->msg_length_counts,
percent(l_ptr->stats.msg_length_profile[1], profile_total), s->msg_lengths_total / profile_total,
percent(l_ptr->stats.msg_length_profile[2], profile_total), percent(s->msg_length_profile[0], profile_total),
percent(l_ptr->stats.msg_length_profile[3], profile_total), percent(s->msg_length_profile[1], profile_total),
percent(l_ptr->stats.msg_length_profile[4], profile_total), percent(s->msg_length_profile[2], profile_total),
percent(l_ptr->stats.msg_length_profile[5], profile_total), percent(s->msg_length_profile[3], profile_total),
percent(l_ptr->stats.msg_length_profile[6], profile_total)); percent(s->msg_length_profile[4], profile_total),
tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", percent(s->msg_length_profile[5], profile_total),
l_ptr->stats.recv_states, percent(s->msg_length_profile[6], profile_total));
l_ptr->stats.recv_probes,
l_ptr->stats.recv_nacks, ret += tipc_snprintf(buf + ret, buf_size - ret,
l_ptr->stats.deferred_recv, " RX states:%u probes:%u naks:%u defs:%u"
l_ptr->stats.duplicates); " dups:%u\n", s->recv_states, s->recv_probes,
tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", s->recv_nacks, s->deferred_recv, s->duplicates);
l_ptr->stats.sent_states,
l_ptr->stats.sent_probes, ret += tipc_snprintf(buf + ret, buf_size - ret,
l_ptr->stats.sent_nacks, " TX states:%u probes:%u naks:%u acks:%u"
l_ptr->stats.sent_acks, " dups:%u\n", s->sent_states, s->sent_probes,
l_ptr->stats.retransmitted); s->sent_nacks, s->sent_acks, s->retransmitted);
tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
l_ptr->stats.bearer_congs, ret += tipc_snprintf(buf + ret, buf_size - ret,
l_ptr->stats.link_congs, " Congestion bearer:%u link:%u Send queue"
l_ptr->stats.max_queue_sz, " max:%u avg:%u\n", s->bearer_congs, s->link_congs,
l_ptr->stats.queue_sz_counts s->max_queue_sz, s->queue_sz_counts ?
? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts) (s->accu_queue_sz / s->queue_sz_counts) : 0);
: 0);
tipc_node_unlock(node); tipc_node_unlock(node);
read_unlock_bh(&tipc_net_lock); read_unlock_bh(&tipc_net_lock);
return tipc_printbuf_validate(&pb); return ret;
} }
#define MAX_LINK_STATS_INFO 2000
struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
{ {
struct sk_buff *buf; struct sk_buff *buf;
struct tlv_desc *rep_tlv; struct tlv_desc *rep_tlv;
int str_len; int str_len;
int pb_len;
char *pb;
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
if (!buf) if (!buf)
return NULL; return NULL;
rep_tlv = (struct tlv_desc *)buf->data; rep_tlv = (struct tlv_desc *)buf->data;
pb = TLV_DATA(rep_tlv);
pb_len = ULTRA_STRING_MAX_LEN;
str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area), str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area),
(char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); pb, pb_len);
if (!str_len) { if (!str_len) {
kfree_skb(buf); kfree_skb(buf);
return tipc_cfg_reply_error_string("link not found"); return tipc_cfg_reply_error_string("link not found");
} }
str_len += 1; /* for "\0" */
skb_put(buf, TLV_SPACE(str_len)); skb_put(buf, TLV_SPACE(str_len));
TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
......
...@@ -124,40 +124,6 @@ static int tipc_printbuf_empty(struct print_buf *pb) ...@@ -124,40 +124,6 @@ static int tipc_printbuf_empty(struct print_buf *pb)
return !pb->buf || (pb->crs == pb->buf); return !pb->buf || (pb->crs == pb->buf);
} }
/**
* tipc_printbuf_validate - check for print buffer overflow
* @pb: pointer to print buffer structure
*
* Verifies that a print buffer has captured all data written to it.
* If data has been lost, linearize buffer and prepend an error message
*
* Returns length of print buffer data string (including trailing NUL)
*/
int tipc_printbuf_validate(struct print_buf *pb)
{
char *err = "\n\n*** PRINT BUFFER OVERFLOW ***\n\n";
char *cp_buf;
struct print_buf cb;
if (!pb->buf)
return 0;
if (pb->buf[pb->size - 1] == 0) {
cp_buf = kmalloc(pb->size, GFP_ATOMIC);
if (cp_buf) {
tipc_printbuf_init(&cb, cp_buf, pb->size);
tipc_printbuf_move(&cb, pb);
tipc_printbuf_move(pb, &cb);
kfree(cp_buf);
memcpy(pb->buf, err, strlen(err));
} else {
tipc_printbuf_reset(pb);
tipc_printf(pb, err);
}
}
return pb->crs - pb->buf + 1;
}
/** /**
* tipc_printbuf_move - move print buffer contents to another print buffer * tipc_printbuf_move - move print buffer contents to another print buffer
* @pb_to: pointer to destination print buffer structure * @pb_to: pointer to destination print buffer structure
...@@ -204,23 +170,20 @@ static void tipc_printbuf_move(struct print_buf *pb_to, ...@@ -204,23 +170,20 @@ static void tipc_printbuf_move(struct print_buf *pb_to,
} }
/** /**
* tipc_printf - append formatted output to print buffer * tipc_snprintf - append formatted output to print buffer
* @pb: pointer to print buffer * @buf: pointer to print buffer
* @len: buffer length
* @fmt: formatted info to be printed * @fmt: formatted info to be printed
*/ */
void tipc_printf(struct print_buf *pb, const char *fmt, ...) int tipc_snprintf(char *buf, int len, const char *fmt, ...)
{ {
int i; int i;
va_list args; va_list args;
char *buf;
int len;
buf = pb->crs;
len = pb->buf + pb->size - pb->crs;
va_start(args, fmt); va_start(args, fmt);
i = vscnprintf(buf, len, fmt, args); i = vscnprintf(buf, len, fmt, args);
va_end(args); va_end(args);
pb->crs += i; return i;
} }
/** /**
......
...@@ -753,19 +753,20 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) ...@@ -753,19 +753,20 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
/** /**
* subseq_list - print specified sub-sequence contents into the given buffer * subseq_list - print specified sub-sequence contents into the given buffer
*/ */
static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth,
u32 index) u32 index)
{ {
char portIdStr[27]; char portIdStr[27];
const char *scope_str[] = {"", " zone", " cluster", " node"}; const char *scope_str[] = {"", " zone", " cluster", " node"};
struct publication *publ; struct publication *publ;
struct name_info *info; struct name_info *info;
int ret;
tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper);
if (depth == 2) { if (depth == 2) {
tipc_printf(buf, "\n"); ret += tipc_snprintf(buf - ret, len + ret, "\n");
return; return ret;
} }
info = sseq->info; info = sseq->info;
...@@ -774,52 +775,58 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, ...@@ -774,52 +775,58 @@ static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
sprintf(portIdStr, "<%u.%u.%u:%u>", sprintf(portIdStr, "<%u.%u.%u:%u>",
tipc_zone(publ->node), tipc_cluster(publ->node), tipc_zone(publ->node), tipc_cluster(publ->node),
tipc_node(publ->node), publ->ref); tipc_node(publ->node), publ->ref);
tipc_printf(buf, "%-26s ", portIdStr); ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr);
if (depth > 3) { if (depth > 3) {
tipc_printf(buf, "%-10u %s", publ->key, ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s",
scope_str[publ->scope]); publ->key, scope_str[publ->scope]);
} }
if (!list_is_last(&publ->zone_list, &info->zone_list)) if (!list_is_last(&publ->zone_list, &info->zone_list))
tipc_printf(buf, "\n%33s", " "); ret += tipc_snprintf(buf + ret, len - ret,
"\n%33s", " ");
}; };
tipc_printf(buf, "\n"); ret += tipc_snprintf(buf + ret, len - ret, "\n");
return ret;
} }
/** /**
* nameseq_list - print specified name sequence contents into the given buffer * nameseq_list - print specified name sequence contents into the given buffer
*/ */
static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth,
u32 type, u32 lowbound, u32 upbound, u32 index) u32 type, u32 lowbound, u32 upbound, u32 index)
{ {
struct sub_seq *sseq; struct sub_seq *sseq;
char typearea[11]; char typearea[11];
int ret = 0;
if (seq->first_free == 0) if (seq->first_free == 0)
return; return 0;
sprintf(typearea, "%-10u", seq->type); sprintf(typearea, "%-10u", seq->type);
if (depth == 1) { if (depth == 1) {
tipc_printf(buf, "%s\n", typearea); ret += tipc_snprintf(buf, len, "%s\n", typearea);
return; return ret;
} }
for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
tipc_printf(buf, "%s ", typearea); ret += tipc_snprintf(buf + ret, len - ret, "%s ",
typearea);
spin_lock_bh(&seq->lock); spin_lock_bh(&seq->lock);
subseq_list(sseq, buf, depth, index); ret += subseq_list(sseq, buf + ret, len - ret,
depth, index);
spin_unlock_bh(&seq->lock); spin_unlock_bh(&seq->lock);
sprintf(typearea, "%10s", " "); sprintf(typearea, "%10s", " ");
} }
} }
return ret;
} }
/** /**
* nametbl_header - print name table header into the given buffer * nametbl_header - print name table header into the given buffer
*/ */
static void nametbl_header(struct print_buf *buf, u32 depth) static int nametbl_header(char *buf, int len, u32 depth)
{ {
const char *header[] = { const char *header[] = {
"Type ", "Type ",
...@@ -829,24 +836,27 @@ static void nametbl_header(struct print_buf *buf, u32 depth) ...@@ -829,24 +836,27 @@ static void nametbl_header(struct print_buf *buf, u32 depth)
}; };
int i; int i;
int ret = 0;
if (depth > 4) if (depth > 4)
depth = 4; depth = 4;
for (i = 0; i < depth; i++) for (i = 0; i < depth; i++)
tipc_printf(buf, header[i]); ret += tipc_snprintf(buf + ret, len - ret, header[i]);
tipc_printf(buf, "\n"); ret += tipc_snprintf(buf + ret, len - ret, "\n");
return ret;
} }
/** /**
* nametbl_list - print specified name table contents into the given buffer * nametbl_list - print specified name table contents into the given buffer
*/ */
static void nametbl_list(struct print_buf *buf, u32 depth_info, static int nametbl_list(char *buf, int len, u32 depth_info,
u32 type, u32 lowbound, u32 upbound) u32 type, u32 lowbound, u32 upbound)
{ {
struct hlist_head *seq_head; struct hlist_head *seq_head;
struct hlist_node *seq_node; struct hlist_node *seq_node;
struct name_seq *seq; struct name_seq *seq;
int all_types; int all_types;
int ret = 0;
u32 depth; u32 depth;
u32 i; u32 i;
...@@ -854,65 +864,69 @@ static void nametbl_list(struct print_buf *buf, u32 depth_info, ...@@ -854,65 +864,69 @@ static void nametbl_list(struct print_buf *buf, u32 depth_info,
depth = (depth_info & ~TIPC_NTQ_ALLTYPES); depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
if (depth == 0) if (depth == 0)
return; return 0;
if (all_types) { if (all_types) {
/* display all entries in name table to specified depth */ /* display all entries in name table to specified depth */
nametbl_header(buf, depth); ret += nametbl_header(buf, len, depth);
lowbound = 0; lowbound = 0;
upbound = ~0; upbound = ~0;
for (i = 0; i < tipc_nametbl_size; i++) { for (i = 0; i < tipc_nametbl_size; i++) {
seq_head = &table.types[i]; seq_head = &table.types[i];
hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
nameseq_list(seq, buf, depth, seq->type, ret += nameseq_list(seq, buf + ret, len - ret,
lowbound, upbound, i); depth, seq->type,
lowbound, upbound, i);
} }
} }
} else { } else {
/* display only the sequence that matches the specified type */ /* display only the sequence that matches the specified type */
if (upbound < lowbound) { if (upbound < lowbound) {
tipc_printf(buf, "invalid name sequence specified\n"); ret += tipc_snprintf(buf + ret, len - ret,
return; "invalid name sequence specified\n");
return ret;
} }
nametbl_header(buf, depth); ret += nametbl_header(buf + ret, len - ret, depth);
i = hash(type); i = hash(type);
seq_head = &table.types[i]; seq_head = &table.types[i];
hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
if (seq->type == type) { if (seq->type == type) {
nameseq_list(seq, buf, depth, type, ret += nameseq_list(seq, buf + ret, len - ret,
lowbound, upbound, i); depth, type,
lowbound, upbound, i);
break; break;
} }
} }
} }
return ret;
} }
#define MAX_NAME_TBL_QUERY 32768
struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
{ {
struct sk_buff *buf; struct sk_buff *buf;
struct tipc_name_table_query *argv; struct tipc_name_table_query *argv;
struct tlv_desc *rep_tlv; struct tlv_desc *rep_tlv;
struct print_buf b; char *pb;
int pb_len;
int str_len; int str_len;
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
if (!buf) if (!buf)
return NULL; return NULL;
rep_tlv = (struct tlv_desc *)buf->data; rep_tlv = (struct tlv_desc *)buf->data;
tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); pb = TLV_DATA(rep_tlv);
pb_len = ULTRA_STRING_MAX_LEN;
argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
read_lock_bh(&tipc_nametbl_lock); read_lock_bh(&tipc_nametbl_lock);
nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), str_len = nametbl_list(pb, pb_len, ntohl(argv->depth),
ntohl(argv->lowbound), ntohl(argv->upbound)); ntohl(argv->type),
ntohl(argv->lowbound), ntohl(argv->upbound));
read_unlock_bh(&tipc_nametbl_lock); read_unlock_bh(&tipc_nametbl_lock);
str_len = tipc_printbuf_validate(&b); str_len += 1; /* for "\0" */
skb_put(buf, TLV_SPACE(str_len)); skb_put(buf, TLV_SPACE(str_len));
TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
......
...@@ -581,67 +581,73 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) ...@@ -581,67 +581,73 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
kfree_skb(buf); kfree_skb(buf);
} }
static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id) static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id)
{ {
struct publication *publ; struct publication *publ;
int ret;
if (full_id) if (full_id)
tipc_printf(buf, "<%u.%u.%u:%u>:", ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), tipc_zone(tipc_own_addr),
tipc_node(tipc_own_addr), p_ptr->ref); tipc_cluster(tipc_own_addr),
tipc_node(tipc_own_addr), p_ptr->ref);
else else
tipc_printf(buf, "%-10u:", p_ptr->ref); ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref);
if (p_ptr->connected) { if (p_ptr->connected) {
u32 dport = port_peerport(p_ptr); u32 dport = port_peerport(p_ptr);
u32 destnode = port_peernode(p_ptr); u32 destnode = port_peernode(p_ptr);
tipc_printf(buf, " connected to <%u.%u.%u:%u>", ret += tipc_snprintf(buf + ret, len - ret,
tipc_zone(destnode), tipc_cluster(destnode), " connected to <%u.%u.%u:%u>",
tipc_node(destnode), dport); tipc_zone(destnode),
tipc_cluster(destnode),
tipc_node(destnode), dport);
if (p_ptr->conn_type != 0) if (p_ptr->conn_type != 0)
tipc_printf(buf, " via {%u,%u}", ret += tipc_snprintf(buf + ret, len - ret,
p_ptr->conn_type, " via {%u,%u}", p_ptr->conn_type,
p_ptr->conn_instance); p_ptr->conn_instance);
} else if (p_ptr->published) { } else if (p_ptr->published) {
tipc_printf(buf, " bound to"); ret += tipc_snprintf(buf + ret, len - ret, " bound to");
list_for_each_entry(publ, &p_ptr->publications, pport_list) { list_for_each_entry(publ, &p_ptr->publications, pport_list) {
if (publ->lower == publ->upper) if (publ->lower == publ->upper)
tipc_printf(buf, " {%u,%u}", publ->type, ret += tipc_snprintf(buf + ret, len - ret,
publ->lower); " {%u,%u}", publ->type,
publ->lower);
else else
tipc_printf(buf, " {%u,%u,%u}", publ->type, ret += tipc_snprintf(buf + ret, len - ret,
publ->lower, publ->upper); " {%u,%u,%u}", publ->type,
publ->lower, publ->upper);
} }
} }
tipc_printf(buf, "\n"); ret += tipc_snprintf(buf + ret, len - ret, "\n");
return ret;
} }
#define MAX_PORT_QUERY 32768
struct sk_buff *tipc_port_get_ports(void) struct sk_buff *tipc_port_get_ports(void)
{ {
struct sk_buff *buf; struct sk_buff *buf;
struct tlv_desc *rep_tlv; struct tlv_desc *rep_tlv;
struct print_buf pb; char *pb;
int pb_len;
struct tipc_port *p_ptr; struct tipc_port *p_ptr;
int str_len; int str_len = 0;
buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
if (!buf) if (!buf)
return NULL; return NULL;
rep_tlv = (struct tlv_desc *)buf->data; rep_tlv = (struct tlv_desc *)buf->data;
pb = TLV_DATA(rep_tlv);
pb_len = ULTRA_STRING_MAX_LEN;
tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
spin_lock_bh(&tipc_port_list_lock); spin_lock_bh(&tipc_port_list_lock);
list_for_each_entry(p_ptr, &ports, port_list) { list_for_each_entry(p_ptr, &ports, port_list) {
spin_lock_bh(p_ptr->lock); spin_lock_bh(p_ptr->lock);
port_print(p_ptr, &pb, 0); str_len += port_print(p_ptr, pb, pb_len, 0);
spin_unlock_bh(p_ptr->lock); spin_unlock_bh(p_ptr->lock);
} }
spin_unlock_bh(&tipc_port_list_lock); spin_unlock_bh(&tipc_port_list_lock);
str_len = tipc_printbuf_validate(&pb); str_len += 1; /* for "\0" */
skb_put(buf, TLV_SPACE(str_len)); skb_put(buf, TLV_SPACE(str_len));
TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment