aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2016-09-14 16:13:04 -0400
committerSteven Rostedt <rostedt@goodmis.org>2016-10-30 19:46:49 -0400
commit7a9bb2d85096327d02836f6587de78784ce1b9ca (patch)
treebb6e954efa751d2a9b0383da9a30e972c964e5ce
parent5cfe15f00db02dd55f76d8f578eac20422fe2238 (diff)
downloadtrace-cmd-7a9bb2d85096327d02836f6587de78784ce1b9ca.tar.gz
trace-cmd msg: Rewrote a lot of code to be more flexible in transfers
Cleaned up a lot of trace-msg.c to not be fixed in the sizes. Able to allocate only what is needed and not to be making allocation when not needed. Also shortened a lot of local macro names as TRACECMD doesn't need to be specified when not exported for other files to share. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--trace-msg.c454
1 files changed, 214 insertions, 240 deletions
diff --git a/trace-msg.c b/trace-msg.c
index 98c330aa..03c48ceb 100644
--- a/trace-msg.c
+++ b/trace-msg.c
@@ -39,25 +39,24 @@
typedef __u32 u32;
typedef __be32 be32;
-#define TRACECMD_MSG_MAX_LEN BUFSIZ
+/* Two (4k) pages is the max transfer for now */
+#define MSG_MAX_LEN 8192
/* size + cmd */
-#define TRACECMD_MSG_HDR_LEN ((sizeof(be32)) + (sizeof(be32)))
+#define MSG_HDR_LEN ((sizeof(be32)) + (sizeof(be32)))
- /* + size of the metadata */
-#define TRACECMD_MSG_META_MIN_LEN \
- ((TRACECMD_MSG_HDR_LEN) + (sizeof(be32)))
+#define MSG_DATA_LEN (MSG_MAX_LEN - MSG_HDR_LEN)
/* - header size for error msg */
-#define TRACECMD_MSG_META_MAX_LEN \
-((TRACECMD_MSG_MAX_LEN) - (TRACECMD_MSG_META_MIN_LEN) - TRACECMD_MSG_HDR_LEN)
+#define MSG_META_MAX_LEN (MSG_MAX_LEN - MIN_META_SIZE)
- /* size + opt_cmd + size of str */
-#define TRACECMD_OPT_MIN_LEN \
- ((sizeof(be32)) + (sizeof(be32)) + (sizeof(be32)))
+#define MIN_TINIT_SIZE offsetof(struct tracecmd_msg, data.tinit.opt)
-#define CPU_MAX 256
+/* Not really the minimum, but I couldn't think of a better name */
+#define MIN_RINIT_SIZE offsetof(struct tracecmd_msg, data.rinit.port_array)
+
+#define MIN_META_SIZE offsetof(struct tracecmd_msg, data.meta.buf)
/* for both client and server */
bool use_tcp;
@@ -75,7 +74,7 @@ bool done;
struct tracecmd_msg_str {
be32 size;
- char *buf;
+ char buf[];
} __attribute__((packed));
struct tracecmd_msg_opt {
@@ -93,12 +92,13 @@ struct tracecmd_msg_tinit {
struct tracecmd_msg_rinit {
be32 cpus;
- be32 port_array[CPU_MAX];
+ be32 *port_array;
} __attribute__((packed));
struct tracecmd_msg_meta {
- struct tracecmd_msg_str str;
-};
+ be32 size;
+ void *buf;
+} __attribute__((packed));
struct tracecmd_msg_error {
be32 size;
@@ -133,175 +133,109 @@ struct tracecmd_msg *errmsg;
static ssize_t msg_do_write_check(int fd, struct tracecmd_msg *msg)
{
- return __do_write_check(fd, msg, ntohl(msg->size));
-}
-
-static void tracecmd_msg_init(u32 cmd, u32 len, struct tracecmd_msg *msg)
-{
- memset(msg, 0, len);
- msg->size = htonl(len);
- msg->cmd = htonl(cmd);
-}
-
-static int tracecmd_msg_alloc(u32 cmd, u32 len, struct tracecmd_msg **msg)
-{
- len += TRACECMD_MSG_HDR_LEN;
- *msg = malloc(len);
- if (!*msg)
- return -ENOMEM;
-
- tracecmd_msg_init(cmd, len, *msg);
- return 0;
-}
-
-static int msgcpy(struct tracecmd_msg *msg, u32 offset,
- const void *buf, u32 buflen)
-{
- if (offset + buflen > ntohl(msg->size))
- return -EINVAL;
-
- memcpy(((void *)msg)+offset, buf, buflen);
- return 0;
-}
+ int wsize;
+ int ret;
-static int optcpy(struct tracecmd_msg_opt *opt, u32 offset,
- const void *buf, u32 buflen)
-{
- if (offset + buflen > ntohl(opt->size))
- return -EINVAL;
+ switch (ntohl(msg->cmd)) {
+ case MSG_TINIT:
+ wsize = MIN_TINIT_SIZE;
+ ret = __do_write_check(fd, msg, wsize);
+ if (ret < 0)
+ break;
+ if (ntohl(msg->size) <= MIN_TINIT_SIZE)
+ break;
+ ret = __do_write_check(fd, msg->data.tinit.opt,
+ ntohl(msg->size) - wsize);
+ break;
+ case MSG_RINIT:
+ wsize = MIN_RINIT_SIZE;
+ ret = __do_write_check(fd, msg, wsize);
+ if (ret < 0)
+ break;
+ ret = __do_write_check(fd, msg->data.rinit.port_array,
+ ntohl(msg->size) - wsize);
+ break;
+ case MSG_SENDMETA:
+ wsize = MIN_META_SIZE;
+ ret = __do_write_check(fd, msg, wsize);
+ if (ret < 0)
+ break;
+ ret = __do_write_check(fd, msg->data.meta.buf,
+ ntohl(msg->size) - wsize);
+ break;
+ default:
+ ret = __do_write_check(fd, msg, ntohl(msg->size));
+ }
- memcpy(((void *)opt)+offset, buf, buflen);
- return 0;
+ return ret;
}
enum msg_opt_command {
MSGOPT_USETCP = 1,
};
-static int add_option_to_tinit(u32 cmd, const char *buf,
- struct tracecmd_msg *msg, int offset)
-{
- struct tracecmd_msg_opt *opt;
- u32 len = TRACECMD_OPT_MIN_LEN;
- u32 buflen = 0;
-
- if (buf) {
- buflen = strlen(buf);
- len += buflen;
- }
-
- opt = malloc(len);
- if (!opt)
- return -ENOMEM;
-
- opt->size = htonl(len);
- opt->opt_cmd = htonl(cmd);
- opt->str.size = htonl(buflen);
-
- if (buf)
- optcpy(opt, TRACECMD_OPT_MIN_LEN, buf, buflen);
-
- /* add option to msg */
- msgcpy(msg, offset, opt, ntohl(opt->size));
-
- free(opt);
- return len;
-}
-
-static int add_options_to_tinit(struct tracecmd_msg *msg)
-{
- int offset = offsetof(struct tracecmd_msg, data.tinit.opt);
- int ret;
-
- if (use_tcp) {
- ret = add_option_to_tinit(MSGOPT_USETCP, NULL, msg, offset);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
static int make_tinit(struct tracecmd_msg *msg)
{
+ struct tracecmd_msg_opt *opt;
int opt_num = 0;
- int ret = 0;
+ int size = MIN_TINIT_SIZE;
- if (use_tcp)
+ if (use_tcp) {
opt_num++;
-
- if (opt_num) {
- ret = add_options_to_tinit(msg);
- if (ret < 0)
- return ret;
+ opt = malloc(sizeof(*opt));
+ if (!opt)
+ return -ENOMEM;
+ opt->size = htonl(sizeof(*opt));
+ opt->opt_cmd = htonl(MSGOPT_USETCP);
+ msg->data.tinit.opt = opt;
+ size += sizeof(*opt);
}
msg->data.tinit.cpus = htonl(cpu_count);
msg->data.tinit.page_size = htonl(page_size);
msg->data.tinit.opt_num = htonl(opt_num);
+ msg->size = htonl(size);
+
return 0;
}
static int make_rinit(struct tracecmd_msg *msg)
{
- int i;
- u32 offset = TRACECMD_MSG_HDR_LEN;
+ int size = MIN_RINIT_SIZE;
+ be32 *ptr;
be32 port;
+ int i;
msg->data.rinit.cpus = htonl(cpu_count);
+ msg->data.rinit.port_array = malloc(sizeof(*port_array) * cpu_count);
+ if (!msg->data.rinit.port_array)
+ return -ENOMEM;
+
+ size += sizeof(*port_array) * cpu_count;
+
+ ptr = msg->data.rinit.port_array;
+
for (i = 0; i < cpu_count; i++) {
/* + rrqports->cpus or rrqports->port_array[i] */
- offset += sizeof(be32);
port = htonl(port_array[i]);
- msgcpy(msg, offset, &port, sizeof(be32) * cpu_count);
+ *ptr = port;
+ ptr++;
}
+ msg->size = htonl(size);
+
return 0;
}
-static u32 tracecmd_msg_get_body_length(u32 cmd)
+static int tracecmd_msg_create(u32 cmd, struct tracecmd_msg *msg)
{
- struct tracecmd_msg *msg;
- u32 len = 0;
-
- switch (cmd) {
- case MSG_TINIT:
- len = sizeof(msg->data.tinit.cpus)
- + sizeof(msg->data.tinit.page_size)
- + sizeof(msg->data.tinit.opt_num);
-
- /*
- * If we are using IPV4 and our page size is greater than
- * or equal to 64K, we need to punt and use TCP. :-(
- */
-
- /* TODO, test for ipv4 */
- if (page_size >= UDP_MAX_PACKET) {
- warning("page size too big for UDP using TCP in live read");
- use_tcp = true;
- }
-
- if (use_tcp)
- len += TRACECMD_OPT_MIN_LEN;
-
- return len;
- case MSG_RINIT:
- return sizeof(msg->data.rinit.cpus)
- + sizeof(msg->data.rinit.port_array);
- case MSG_SENDMETA:
- return TRACECMD_MSG_MAX_LEN - TRACECMD_MSG_HDR_LEN;
- case MSG_CLOSE:
- case MSG_FINMETA:
- break;
- }
+ int ret = 0;
- return 0;
-}
+ memset(msg, 0, sizeof(*msg));
+ msg->cmd = htonl(cmd);
-static int tracecmd_msg_make_body(u32 cmd, struct tracecmd_msg *msg)
-{
switch (cmd) {
case MSG_TINIT:
return make_tinit(msg);
@@ -313,34 +247,29 @@ static int tracecmd_msg_make_body(u32 cmd, struct tracecmd_msg *msg)
break;
}
- return 0;
+ msg->size = htonl(MSG_HDR_LEN);
+
+ return ret;
}
-static int tracecmd_msg_create(u32 cmd, struct tracecmd_msg **msg)
+static void msg_free(struct tracecmd_msg *msg)
{
- u32 len = 0;
- int ret = 0;
-
- len = tracecmd_msg_get_body_length(cmd);
- if (len > (TRACECMD_MSG_MAX_LEN - TRACECMD_MSG_HDR_LEN)) {
- plog("Exceed maximum message size cmd=%d\n", cmd);
- return -EINVAL;
+ switch (ntohl(msg->cmd)) {
+ case MSG_TINIT:
+ free(msg->data.tinit.opt);
+ break;
+ case MSG_RINIT:
+ free(msg->data.rinit.port_array);
+ break;
+ case MSG_SENDMETA:
+ free(msg->data.meta.buf);
+ break;
}
-
- ret = tracecmd_msg_alloc(cmd, len, msg);
- if (ret < 0)
- return ret;
-
- ret = tracecmd_msg_make_body(cmd, *msg);
- if (ret < 0)
- free(*msg);
-
- return ret;
}
static int tracecmd_msg_send(int fd, u32 cmd)
{
- struct tracecmd_msg *msg = NULL;
+ struct tracecmd_msg msg;
int ret = 0;
if (cmd > MSG_FINMETA) {
@@ -352,17 +281,18 @@ static int tracecmd_msg_send(int fd, u32 cmd)
if (ret < 0)
return ret;
- ret = msg_do_write_check(fd, msg);
+ ret = msg_do_write_check(fd, &msg);
if (ret < 0)
ret = -ECOMM;
- free(msg);
+ msg_free(&msg);
+
return ret;
}
-static int tracecmd_msg_read_extra(int fd, void *buf, u32 size, int *n)
+static int msg_read(int fd, void *buf, u32 size, int *n)
{
- int r = 0;
+ int r;
do {
r = read(fd, buf + *n, size);
@@ -379,6 +309,62 @@ static int tracecmd_msg_read_extra(int fd, void *buf, u32 size, int *n)
return 0;
}
+static int tracecmd_msg_read_extra(int fd, struct tracecmd_msg *msg, int *n)
+{
+ int size = ntohl(msg->size);
+ int rsize;
+ int ret;
+
+ switch (ntohl(msg->cmd)) {
+ case MSG_TINIT:
+ msg->data.tinit.opt = NULL;
+
+ rsize = MIN_TINIT_SIZE - *n;
+
+ ret = msg_read(fd, msg, rsize, n);
+ if (ret < 0)
+ return ret;
+
+ if (size > *n) {
+ size -= *n;
+ msg->data.tinit.opt = malloc(size);
+ if (!msg->data.tinit.opt)
+ return -ENOMEM;
+ *n = 0;
+ return msg_read(fd, msg->data.tinit.opt, size, n);
+ }
+ return 0;
+ case MSG_RINIT:
+ rsize = MIN_RINIT_SIZE - *n;
+ ret = msg_read(fd, msg, rsize, n);
+ if (ret < 0)
+ return ret;
+ size -= *n;
+ if (size < 0)
+ return -ENOMSG;
+ msg->data.rinit.port_array = malloc(size);
+ if (!msg->data.rinit.port_array)
+ return -ENOMEM;
+ *n = 0;
+ return msg_read(fd, msg->data.rinit.port_array, size, n);
+ case MSG_SENDMETA:
+ rsize = MIN_META_SIZE - *n;
+ ret = msg_read(fd, msg, rsize, n);
+ if (ret < 0)
+ return ret;
+ size -= *n;
+ if (size < 0)
+ return -ENOMSG;
+ msg->data.meta.buf = malloc(size);
+ if (!msg->data.meta.buf)
+ return -ENOMEM;
+ *n = 0;
+ return msg_read(fd, msg->data.meta.buf, size, n);
+ }
+
+ return msg_read(fd, msg, size - MSG_HDR_LEN, n);
+}
+
/*
* Read header information of msg first, then read all data
*/
@@ -388,21 +374,19 @@ static int tracecmd_msg_recv(int fd, struct tracecmd_msg *msg)
int n = 0;
int ret;
- ret = tracecmd_msg_read_extra(fd, msg, TRACECMD_MSG_HDR_LEN, &n);
+ ret = msg_read(fd, msg, MSG_HDR_LEN, &n);
if (ret < 0)
return ret;
size = ntohl(msg->size);
- if (size > TRACECMD_MSG_MAX_LEN)
+ if (size > MSG_MAX_LEN)
/* too big */
goto error;
- else if (size < TRACECMD_MSG_HDR_LEN)
+ else if (size < MSG_HDR_LEN)
/* too small */
goto error;
- else if (size > TRACECMD_MSG_HDR_LEN) {
- size -= TRACECMD_MSG_HDR_LEN;
- return tracecmd_msg_read_extra(fd, msg, size, &n);
- }
+ else if (size > MSG_HDR_LEN)
+ return tracecmd_msg_read_extra(fd, msg, &n);
return 0;
error:
@@ -440,11 +424,6 @@ static int tracecmd_msg_recv_wait(int fd, struct tracecmd_msg *msg)
return tracecmd_msg_recv(fd, msg);
}
-static void *tracecmd_msg_buf_access(struct tracecmd_msg *msg, int offset)
-{
- return (void *)msg + offset;
-}
-
static int tracecmd_msg_wait_for_msg(int fd, struct tracecmd_msg *msg)
{
u32 cmd;
@@ -481,20 +460,18 @@ static int tracecmd_msg_send_and_wait_for_msg(int fd, u32 cmd, struct tracecmd_m
int tracecmd_msg_send_init_data(int fd)
{
- char buf[TRACECMD_MSG_MAX_LEN];
- struct tracecmd_msg *msg;
+ struct tracecmd_msg msg;
int i, cpus;
int ret;
- msg = (struct tracecmd_msg *)buf;
- ret = tracecmd_msg_send_and_wait_for_msg(fd, MSG_TINIT, msg);
+ ret = tracecmd_msg_send_and_wait_for_msg(fd, MSG_TINIT, &msg);
if (ret < 0)
return ret;
- cpus = ntohl(msg->data.rinit.cpus);
+ cpus = ntohl(msg.data.rinit.cpus);
client_ports = malloc_or_die(sizeof(int) * cpus);
for (i = 0; i < cpus; i++)
- client_ports[i] = ntohl(msg->data.rinit.port_array[i]);
+ client_ports[i] = ntohl(msg.data.rinit.port_array[i]);
/* Next, send meta data */
send_metadata = true;
@@ -525,50 +502,58 @@ static void error_operation_for_server(struct tracecmd_msg *msg)
int tracecmd_msg_initial_setting(int fd, int *cpus, int *pagesize)
{
- struct tracecmd_msg *msg;
struct tracecmd_msg_opt *opt;
- char buf[TRACECMD_MSG_MAX_LEN];
- int offset = offsetof(struct tracecmd_msg, data.tinit.opt);
+ struct tracecmd_msg msg;
int options, i, s;
int ret;
- u32 size = 0;
+ int offset = 0;
+ u32 size = MIN_TINIT_SIZE;
u32 cmd;
- msg = (struct tracecmd_msg *)buf;
- ret = tracecmd_msg_recv_wait(fd, msg);
+ ret = tracecmd_msg_recv_wait(fd, &msg);
if (ret < 0) {
if (ret == -ETIMEDOUT)
warning("Connection timed out\n");
return ret;
}
- cmd = ntohl(msg->cmd);
+ cmd = ntohl(msg.cmd);
if (cmd != MSG_TINIT) {
ret = -EINVAL;
goto error;
}
- *cpus = ntohl(msg->data.tinit.cpus);
+ *cpus = ntohl(msg.data.tinit.cpus);
plog("cpus=%d\n", *cpus);
if (*cpus < 0) {
ret = -EINVAL;
goto error;
}
- *pagesize = ntohl(msg->data.tinit.page_size);
+ *pagesize = ntohl(msg.data.tinit.page_size);
plog("pagesize=%d\n", *pagesize);
if (*pagesize <= 0) {
ret = -EINVAL;
goto error;
}
- options = ntohl(msg->data.tinit.opt_num);
+ options = ntohl(msg.data.tinit.opt_num);
for (i = 0; i < options; i++) {
- offset += size;
- opt = tracecmd_msg_buf_access(msg, offset);
- size = ntohl(opt->size);
+ if (size + sizeof(*opt) > ntohl(msg.size)) {
+ plog("Not enough message for options\n");
+ ret = -EINVAL;
+ goto error;
+ }
+ opt = (void *)msg.data.tinit.opt + offset;
+ offset += ntohl(opt->size);
+ size += ntohl(opt->size);
+ if (ntohl(msg.size) < size) {
+ plog("Not enough message for options\n");
+ ret = -EINVAL;
+ goto error;
+ }
/* prevent a client from killing us */
- if (size > MAX_OPTION_SIZE) {
+ if (ntohl(opt->size) > MAX_OPTION_SIZE) {
plog("Exceed MAX_OPTION_SIZE\n");
ret = -EINVAL;
goto error;
@@ -586,7 +571,7 @@ int tracecmd_msg_initial_setting(int fd, int *cpus, int *pagesize)
return 0;
error:
- error_operation_for_server(msg);
+ error_operation_for_server(&msg);
return ret;
}
@@ -609,18 +594,10 @@ void tracecmd_msg_send_close_msg(void)
tracecmd_msg_send(psfd, MSG_CLOSE);
}
-static void make_meta(const char *buf, int buflen, struct tracecmd_msg *msg)
-{
- int offset = offsetof(struct tracecmd_msg, data.meta.str.buf);
-
- msg->data.meta.str.size = htonl(buflen);
- msgcpy(msg, offset, buf, buflen);
-}
-
int tracecmd_msg_metadata_send(int fd, const char *buf, int size)
{
- struct tracecmd_msg *msg;
- int n, len;
+ struct tracecmd_msg msg;
+ int n;
int ret;
int count = 0;
@@ -628,29 +605,31 @@ int tracecmd_msg_metadata_send(int fd, const char *buf, int size)
if (ret < 0)
return ret;
+ msg.data.meta.buf = malloc(MSG_META_MAX_LEN);
+ if (!msg.data.meta.buf)
+ return -ENOMEM;
+
+ msg.data.meta.size = htonl(MSG_META_MAX_LEN);
+ msg.size = htonl(MIN_META_SIZE + MSG_META_MAX_LEN);
+
n = size;
do {
- if (n > TRACECMD_MSG_META_MAX_LEN) {
- make_meta(buf+count, TRACECMD_MSG_META_MAX_LEN, msg);
- n -= TRACECMD_MSG_META_MAX_LEN;
- count += TRACECMD_MSG_META_MAX_LEN;
+ if (n > MSG_META_MAX_LEN) {
+ memcpy(msg.data.meta.buf, buf+count, MSG_META_MAX_LEN);
+ n -= MSG_META_MAX_LEN;
+ count += MSG_META_MAX_LEN;
} else {
- make_meta(buf+count, n, msg);
- /*
- * TRACECMD_MSG_META_MAX_LEN is stored in msg->size,
- * so update the size to the correct value.
- */
- len = TRACECMD_MSG_META_MIN_LEN + n;
- msg->size = htonl(len);
+ msg.size = htonl(MIN_META_SIZE + n);
+ msg.data.meta.size = htonl(n);
+ memcpy(msg.data.meta.buf, buf+count, n);
n = 0;
}
-
- ret = msg_do_write_check(fd, msg);
+ ret = msg_do_write_check(fd, &msg);
if (ret < 0)
break;
} while (n);
- free(msg);
+ msg_free(&msg);
return ret;
}
@@ -669,16 +648,12 @@ int tracecmd_msg_finish_sending_metadata(int fd)
int tracecmd_msg_collect_metadata(int ifd, int ofd)
{
- struct tracecmd_msg *msg;
- char buf[TRACECMD_MSG_MAX_LEN];
+ struct tracecmd_msg msg;
u32 s, t, n, cmd;
- int offset = TRACECMD_MSG_META_MIN_LEN;
int ret;
- msg = (struct tracecmd_msg *)buf;
-
do {
- ret = tracecmd_msg_recv_wait(ifd, msg);
+ ret = tracecmd_msg_recv_wait(ifd, &msg);
if (ret < 0) {
if (ret == -ETIMEDOUT)
warning("Connection timed out\n");
@@ -687,18 +662,18 @@ int tracecmd_msg_collect_metadata(int ifd, int ofd)
return ret;
}
- cmd = ntohl(msg->cmd);
+ cmd = ntohl(msg.cmd);
if (cmd == MSG_FINMETA) {
/* Finish receiving meta data */
break;
} else if (cmd != MSG_SENDMETA)
goto error;
- n = ntohl(msg->data.meta.str.size);
+ n = ntohl(msg.data.meta.size);
t = n;
s = 0;
do {
- s = write(ofd, buf+s+offset, t);
+ s = write(ofd, msg.data.meta.buf+s, t);
if (s < 0) {
if (errno == EINTR)
continue;
@@ -712,19 +687,18 @@ int tracecmd_msg_collect_metadata(int ifd, int ofd)
/* check the finish message of the client */
while (!done) {
- ret = tracecmd_msg_recv(ifd, msg);
+ ret = tracecmd_msg_recv(ifd, &msg);
if (ret < 0) {
warning("reading client");
return ret;
}
- msg = (struct tracecmd_msg *)buf;
- cmd = ntohl(msg->cmd);
+ cmd = ntohl(msg.cmd);
if (cmd == MSG_CLOSE)
/* Finish this connection */
break;
else {
- warning("Not accept the message %d", ntohl(msg->cmd));
+ warning("Not accept the message %d", ntohl(msg.cmd));
ret = -EINVAL;
goto error;
}
@@ -733,6 +707,6 @@ int tracecmd_msg_collect_metadata(int ifd, int ofd)
return 0;
error:
- error_operation_for_server(msg);
+ error_operation_for_server(&msg);
return ret;
}