• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Fusion-io
3  *
4  *  This program is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU General Public
6  *  License v2 as published by the Free Software Foundation.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <inttypes.h>
25 #include <string.h>
26 #include <asm/types.h>
27 #include <errno.h>
28 #include <sys/mman.h>
29 #include <time.h>
30 #include <math.h>
31 
32 #include "plot.h"
33 #include "blkparse.h"
34 #include "list.h"
35 #include "tracers.h"
36 #include "fio.h"
37 
past_eof(struct trace * trace,char * cur)38 static int past_eof(struct trace *trace, char *cur)
39 {
40 	if (cur >= trace->fio_start + trace->fio_len)
41 		return 1;
42 	return 0;
43 }
44 
parse_fio_line(struct trace * trace,int * time,int * rate,int * dir,int * bs)45 static int parse_fio_line(struct trace *trace, int *time, int *rate, int *dir, int *bs)
46 {
47 	char *cur = trace->fio_cur;
48 	char *p;
49 	int *res[] = { time, rate, dir, bs, NULL };
50 	int val;
51 	int i = 0;
52 	int *t;
53 	char *end = index(cur, '\n');
54 	char *tmp;
55 
56 	if (!end)
57 		return 1;
58 
59 	tmp = strndup(cur, end - cur);
60 	if (!tmp)
61 		return 1;
62 	p = strtok(tmp, ",");
63 	while (p && *res) {
64 		val = atoi(p);
65 		t = res[i++];
66 		*t = val;
67 		p = strtok(NULL, ",");
68 	}
69 
70 	free(tmp);
71 
72 	if (i < 3)
73 		return 1;
74 	return 0;
75 }
76 
next_fio_line(struct trace * trace)77 int next_fio_line(struct trace *trace)
78 {
79 	char *next;
80 	char *cur = trace->fio_cur;
81 
82 	next = strchr(cur, '\n');
83 	if (!next)
84 		return 1;
85 	next++;
86 	if (past_eof(trace, next))
87 		return 1;
88 	trace->fio_cur = next;
89 	return 0;
90 }
91 
first_fio(struct trace * trace)92 char *first_fio(struct trace *trace)
93 {
94 	trace->fio_cur = trace->fio_start;
95 	return trace->fio_cur;
96 }
97 
find_last_fio_time(struct trace * trace)98 static void find_last_fio_time(struct trace *trace)
99 {
100 	double d;
101 	int time, rate, dir, bs;
102 	int ret;
103 	int last_time = 0;
104 
105 	if (trace->fio_len == 0)
106 		return;
107 
108 	first_fio(trace);
109 	while (1) {
110 		ret = parse_fio_line(trace, &time, &rate, &dir, &bs);
111 		if (ret)
112 			break;
113 		if (dir <= 1 && time > last_time)
114 			last_time = time;
115 		ret = next_fio_line(trace);
116 		if (ret)
117 			break;
118 	}
119 	d = (double)time / 1000;
120 	trace->fio_seconds = ceil(d);
121 	return;
122 }
123 
read_fio(struct trace * trace,char * trace_name)124 static int read_fio(struct trace *trace, char *trace_name)
125 {
126 	int fd;
127 	struct stat st;
128 	int ret;
129 	char *p;
130 
131 	fd = open(trace_name, O_RDONLY);
132 	if (fd < 0)
133 		return 1;
134 
135 	ret = fstat(fd, &st);
136 	if (ret < 0) {
137 		fprintf(stderr, "stat failed on %s err %s\n",
138 			trace_name, strerror(errno));
139 		goto fail_fd;
140 	}
141 	p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
142 	if (p == MAP_FAILED) {
143 		fprintf(stderr, "Unable to mmap trace file %s, err %s\n",
144 			trace_name, strerror(errno));
145 		goto fail_fd;
146 	}
147 	trace->fio_start = p;
148 	trace->fio_len = st.st_size;
149 	trace->fio_cur = p;
150 	trace->fio_fd = fd;
151 	find_last_fio_time(trace);
152 	first_fio(trace);
153 	return 0;
154 
155 fail_fd:
156 	close(fd);
157 	return 1;
158 }
159 
open_fio_trace(char * path)160 struct trace *open_fio_trace(char *path)
161 {
162 	int ret;
163 	struct trace *trace;
164 
165 	trace = calloc(1, sizeof(*trace));
166 	if (!trace) {
167 		fprintf(stderr, "unable to allocate memory for trace\n");
168 		exit(1);
169 	}
170 
171 	ret = read_fio(trace, path);
172 	if (ret) {
173 		free(trace);
174 		return NULL;
175 	}
176 
177 	return trace;
178 }
179 
read_fio_event(struct trace * trace,int * time_ret,u64 * bw_ret,int * dir_ret)180 int read_fio_event(struct trace *trace, int *time_ret, u64 *bw_ret, int *dir_ret)
181 {
182 	char *cur = trace->fio_cur;
183 	int time, rate, dir, bs;
184 	int ret;
185 
186 	if (past_eof(trace, cur))
187 		return 1;
188 
189 	ret = parse_fio_line(trace, &time, &rate, &dir, &bs);
190 	if (ret)
191 		return 1;
192 
193 	time = floor((double)time / 1000);
194 	*time_ret = time;
195 	*bw_ret = (u64)rate * 1024;
196 
197 	*dir_ret = dir;
198 	return 0;
199 }
200 
add_fio_gld(unsigned int time,u64 bw,struct graph_line_data * gld)201 int add_fio_gld(unsigned int time, u64 bw, struct graph_line_data *gld)
202 {
203 	double val;
204 
205 	if (time > gld->max_seconds)
206 		return 0;
207 
208 	gld->data[time].sum += bw;
209 	gld->data[time].count++;
210 
211 	val = ((double)gld->data[time].sum) / gld->data[time].count;
212 
213 	if (val > gld->max)
214 		gld->max = ceil(val);
215 	return 0;
216 
217 }
218