diff options
author | Xin Li <delphij@google.com> | 2019-07-01 20:59:18 +0000 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2019-07-01 20:59:18 +0000 |
commit | c8a6a475f46ae2cf8a9d3c32262b00b14123d9e6 (patch) | |
tree | 28ce16b16a7e52db33e3f6e094e396893e0d2001 /iowatcher/fio.c | |
parent | fcf2bbd5a3d2553125dfc4055fe4ae57c5499669 (diff) | |
parent | 9c82183ae7fb7dc4db787b8796c652a732b4d552 (diff) | |
download | blktrace-c8a6a475f46ae2cf8a9d3c32262b00b14123d9e6.tar.gz |
DO NOT MERGE - Merge qt-dev-plus-aosp-without-vendor (5699924) into stage-aosp-mastertemp_140451723
Bug: 134405016
Change-Id: Icd38ba6290b413fe410869e29eae8e02699e32a8
Diffstat (limited to 'iowatcher/fio.c')
-rw-r--r-- | iowatcher/fio.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/iowatcher/fio.c b/iowatcher/fio.c new file mode 100644 index 0000000..b680f66 --- /dev/null +++ b/iowatcher/fio.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2013 Fusion-io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <inttypes.h> +#include <string.h> +#include <asm/types.h> +#include <errno.h> +#include <sys/mman.h> +#include <time.h> +#include <math.h> + +#include "plot.h" +#include "blkparse.h" +#include "list.h" +#include "tracers.h" +#include "fio.h" + +static int past_eof(struct trace *trace, char *cur) +{ + if (cur >= trace->fio_start + trace->fio_len) + return 1; + return 0; +} + +static int parse_fio_line(struct trace *trace, int *time, int *rate, int *dir, int *bs) +{ + char *cur = trace->fio_cur; + char *p; + int *res[] = { time, rate, dir, bs, NULL }; + int val; + int i = 0; + int *t; + char *end = index(cur, '\n'); + char *tmp; + + if (!end) + return 1; + + tmp = strndup(cur, end - cur); + if (!tmp) + return 1; + p = strtok(tmp, ","); + while (p && *res) { + val = atoi(p); + t = res[i++]; + *t = val; + p = strtok(NULL, ","); + } + + free(tmp); + + if (i < 3) + return 1; + return 0; +} + +int next_fio_line(struct trace *trace) +{ + char *next; + char *cur = trace->fio_cur; + + next = strchr(cur, '\n'); + if (!next) + return 1; + next++; + if (past_eof(trace, next)) + return 1; + trace->fio_cur = next; + return 0; +} + +char *first_fio(struct trace *trace) +{ + trace->fio_cur = trace->fio_start; + return trace->fio_cur; +} + +static void find_last_fio_time(struct trace *trace) +{ + double d; + int time, rate, dir, bs; + int ret; + int last_time = 0; + + if (trace->fio_len == 0) + return; + + first_fio(trace); + while (1) { + ret = parse_fio_line(trace, &time, &rate, &dir, &bs); + if (ret) + break; + if (dir <= 1 && time > last_time) + last_time = time; + ret = next_fio_line(trace); + if (ret) + break; + } + d = (double)time / 1000; + trace->fio_seconds = ceil(d); + return; +} + +static int read_fio(struct trace *trace, char *trace_name) +{ + int fd; + struct stat st; + int ret; + char *p; + + fd = open(trace_name, O_RDONLY); + if (fd < 0) + return 1; + + ret = fstat(fd, &st); + if (ret < 0) { + fprintf(stderr, "stat failed on %s err %s\n", + trace_name, strerror(errno)); + goto fail_fd; + } + p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (p == MAP_FAILED) { + fprintf(stderr, "Unable to mmap trace file %s, err %s\n", + trace_name, strerror(errno)); + goto fail_fd; + } + trace->fio_start = p; + trace->fio_len = st.st_size; + trace->fio_cur = p; + trace->fio_fd = fd; + find_last_fio_time(trace); + first_fio(trace); + return 0; + +fail_fd: + close(fd); + return 1; +} + +struct trace *open_fio_trace(char *path) +{ + int ret; + struct trace *trace; + + trace = calloc(1, sizeof(*trace)); + if (!trace) { + fprintf(stderr, "unable to allocate memory for trace\n"); + exit(1); + } + + ret = read_fio(trace, path); + if (ret) { + free(trace); + return NULL; + } + + return trace; +} + +int read_fio_event(struct trace *trace, int *time_ret, u64 *bw_ret, int *dir_ret) +{ + char *cur = trace->fio_cur; + int time, rate, dir, bs; + int ret; + + if (past_eof(trace, cur)) + return 1; + + ret = parse_fio_line(trace, &time, &rate, &dir, &bs); + if (ret) + return 1; + + time = floor((double)time / 1000); + *time_ret = time; + *bw_ret = (u64)rate * 1024; + + *dir_ret = dir; + return 0; +} + +int add_fio_gld(unsigned int time, u64 bw, struct graph_line_data *gld) +{ + double val; + + if (time > gld->max_seconds) + return 0; + + gld->data[time].sum += bw; + gld->data[time].count++; + + val = ((double)gld->data[time].sum) / gld->data[time].count; + + if (val > gld->max) + gld->max = ceil(val); + return 0; + +} |