aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-02-24 16:48:30 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-02-24 17:28:04 -0500
commitc8a66458295aa0ae03929c8948ec102ff0683d4e (patch)
tree74a4611a1988e9beb0322bae20c84f8da429cb5a
parentbb3b0de175c3aa8ccc40572fe2aef03ad1349fc8 (diff)
trace-cmd: Use TCP if page size is too big for UDP
If the kernel page size is too big (as it can be with PPC and other archs), we switch to using TCP for the live reads. This may impact performance, but still lets the code work. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--trace-cmd.c34
-rw-r--r--trace-listen.c69
2 files changed, 97 insertions, 6 deletions
diff --git a/trace-cmd.c b/trace-cmd.c
index 3476320..432523e 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -50,6 +50,10 @@
50#define ITER_CTRL "trace_options" 50#define ITER_CTRL "trace_options"
51#define MAX_LATENCY "tracing_max_latency" 51#define MAX_LATENCY "tracing_max_latency"
52 52
53#define UDP_MAX_PACKET (65536 - 20)
54
55static int use_tcp;
56
53static unsigned int page_size; 57static unsigned int page_size;
54 58
55static const char *output_file = "trace.dat"; 59static const char *output_file = "trace.dat";
@@ -912,11 +916,12 @@ static void connect_port(int cpu)
912 916
913 memset(&hints, 0, sizeof(hints)); 917 memset(&hints, 0, sizeof(hints));
914 hints.ai_family = AF_UNSPEC; 918 hints.ai_family = AF_UNSPEC;
915 hints.ai_socktype = SOCK_DGRAM; 919 hints.ai_socktype = use_tcp ? SOCK_STREAM : SOCK_DGRAM;
916 920
917 s = getaddrinfo(host, buf, &hints, &results); 921 s = getaddrinfo(host, buf, &hints, &results);
918 if (s != 0) 922 if (s != 0)
919 die("connecting to UDP server %s:%s", host, buf); 923 die("connecting to %s server %s:%s",
924 use_tcp ? "TCP" : "UDP", host, buf);
920 925
921 for (rp = results; rp != NULL; rp = rp->ai_next) { 926 for (rp = results; rp != NULL; rp = rp->ai_next) {
922 sfd = socket(rp->ai_family, rp->ai_socktype, 927 sfd = socket(rp->ai_family, rp->ai_socktype,
@@ -929,7 +934,8 @@ static void connect_port(int cpu)
929 } 934 }
930 935
931 if (rp == NULL) 936 if (rp == NULL)
932 die("Can not connect to UDP server %s:%s", host, buf); 937 die("Can not connect to %s server %s:%s",
938 use_tcp ? "TCP" : "UDP", host, buf);
933 939
934 freeaddrinfo(results); 940 freeaddrinfo(results);
935 941
@@ -1047,6 +1053,28 @@ static void setup_network(void)
1047 /* include \0 */ 1053 /* include \0 */
1048 write(sfd, buf, strlen(buf)+1); 1054 write(sfd, buf, strlen(buf)+1);
1049 1055
1056 /*
1057 * If we are using IPV4 and our page size is greater than
1058 * or equal to 64K, we need to punt and use TCP. :-(
1059 */
1060
1061 /* TODO, test for ipv4 */
1062 if (page_size >= UDP_MAX_PACKET) {
1063 warning("page size too big for UDP using TCP in live read");
1064 use_tcp = 1;
1065 }
1066
1067 if (use_tcp) {
1068 /* Send one option */
1069 write(sfd, "1", 2);
1070 /* Size 4 */
1071 write(sfd, "4", 2);
1072 /* use TCP */
1073 write(sfd, "TCP", 4);
1074 } else
1075 /* No options */
1076 write(sfd, "0", 2);
1077
1050 client_ports = malloc_or_die(sizeof(int) * cpu_count); 1078 client_ports = malloc_or_die(sizeof(int) * cpu_count);
1051 1079
1052 /* 1080 /*
diff --git a/trace-listen.c b/trace-listen.c
index 24525ac..47e98f4 100644
--- a/trace-listen.c
+++ b/trace-listen.c
@@ -35,11 +35,15 @@
35 35
36#include "trace-local.h" 36#include "trace-local.h"
37 37
38#define MAX_OPTION_SIZE 4096
39
38static char *default_output_dir = "."; 40static char *default_output_dir = ".";
39static char *output_dir; 41static char *output_dir;
40static char *default_output_file = "trace"; 42static char *default_output_file = "trace";
41static char *output_file; 43static char *output_file;
42 44
45static int use_tcp;
46
43static int backlog = 5; 47static int backlog = 5;
44 48
45#define TEMP_FILE_STR "%s.%s:%s.cpu%d", output_file, host, port, cpu 49#define TEMP_FILE_STR "%s.%s:%s.cpu%d", output_file, host, port, cpu
@@ -84,6 +88,16 @@ static int read_string(int fd, char *buf, size_t size)
84 return i; 88 return i;
85} 89}
86 90
91static int process_option(char *option)
92{
93 /* currently the only option we have is to us TCP */
94 if (strcmp(option, "TCP") == 0) {
95 use_tcp = 1;
96 return 1;
97 }
98 return 0;
99}
100
87static int done; 101static int done;
88static void finish(int sig) 102static void finish(int sig)
89{ 103{
@@ -97,6 +111,7 @@ static void process_udp_child(int sfd, const char *host, const char *port,
97 socklen_t peer_addr_len; 111 socklen_t peer_addr_len;
98 char buf[page_size]; 112 char buf[page_size];
99 char *tempfile; 113 char *tempfile;
114 int cfd;
100 int fd; 115 int fd;
101 int n; 116 int n;
102 int once = 0; 117 int once = 0;
@@ -108,13 +123,22 @@ static void process_udp_child(int sfd, const char *host, const char *port,
108 if (fd < 0) 123 if (fd < 0)
109 die("creating %s", tempfile); 124 die("creating %s", tempfile);
110 125
126 if (use_tcp) {
127 if (listen(sfd, backlog) < 0)
128 die("listen");
129 cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len);
130 close(sfd);
131 sfd = cfd;
132 }
133
111 do { 134 do {
112 peer_addr_len = sizeof(peer_addr); 135 peer_addr_len = sizeof(peer_addr);
113 /* TODO, make this copyless! */ 136 /* TODO, make this copyless! */
114 n = read(sfd, buf, page_size); 137 n = read(sfd, buf, page_size);
115 if (!n) 138 if (!n)
116 break; 139 break;
117 if (n < page_size && !once) { 140 /* UDP requires that we get the full size in one go */
141 if (!use_tcp && n < page_size && !once) {
118 once = 1; 142 once = 1;
119 warning("read %d bytes, expected %d", n, page_size); 143 warning("read %d bytes, expected %d", n, page_size);
120 } 144 }
@@ -142,7 +166,7 @@ static int open_udp(const char *node, const char *port, int *pid,
142 166
143 memset(&hints, 0, sizeof(hints)); 167 memset(&hints, 0, sizeof(hints));
144 hints.ai_family = AF_UNSPEC; 168 hints.ai_family = AF_UNSPEC;
145 hints.ai_socktype = SOCK_DGRAM; 169 hints.ai_socktype = use_tcp ? SOCK_STREAM : SOCK_DGRAM;
146 hints.ai_flags = AI_PASSIVE; 170 hints.ai_flags = AI_PASSIVE;
147 171
148 s = getaddrinfo(NULL, buf, &hints, &result); 172 s = getaddrinfo(NULL, buf, &hints, &result);
@@ -187,15 +211,18 @@ static void process_client(const char *node, const char *port, int fd)
187{ 211{
188 char **temp_files; 212 char **temp_files;
189 char buf[BUFSIZ]; 213 char buf[BUFSIZ];
214 char *option;
190 int *port_array; 215 int *port_array;
191 int *pid_array; 216 int *pid_array;
192 int pagesize; 217 int pagesize;
193 int udp_port; 218 int udp_port;
219 int options;
220 int size;
194 int cpus; 221 int cpus;
195 int cpu; 222 int cpu;
196 int pid; 223 int pid;
197 int ofd; 224 int ofd;
198 int n, s, t; 225 int n, s, t, i;
199 226
200 /* Let the client know what we are */ 227 /* Let the client know what we are */
201 write(fd, "tracecmd", 8); 228 write(fd, "tracecmd", 8);
@@ -224,6 +251,42 @@ static void process_client(const char *node, const char *port, int fd)
224 if (pagesize <= 0) 251 if (pagesize <= 0)
225 return; 252 return;
226 253
254 /* Now the number of options */
255 n = read_string(fd, buf, BUFSIZ);
256 if (n == BUFSIZ)
257 /** ERROR **/
258 return;
259
260 options = atoi(buf);
261
262 for (i = 0; i < options; i++) {
263 /* next is the size of the options */
264 n = read_string(fd, buf, BUFSIZ);
265 if (n == BUFSIZ)
266 /** ERROR **/
267 return;
268 size = atoi(buf);
269 /* prevent a client from killing us */
270 if (size > MAX_OPTION_SIZE)
271 return;
272 option = malloc_or_die(size);
273 do {
274 t = size;
275 s = 0;
276 s = read(fd, option+s, t);
277 if (s <= 0)
278 return;
279 t -= s;
280 s = size - t;
281 } while (t);
282
283 s = process_option(option);
284 free(option);
285 /* do we understand this option? */
286 if (!s)
287 return;
288 }
289
227 /* Create the client file */ 290 /* Create the client file */
228 snprintf(buf, BUFSIZ, "%s.%s:%s.dat", output_file, node, port); 291 snprintf(buf, BUFSIZ, "%s.%s:%s.dat", output_file, node, port);
229 292