diff options
Diffstat (limited to 'btt/mmap.c')
-rw-r--r-- | btt/mmap.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/btt/mmap.c b/btt/mmap.c new file mode 100644 index 0000000..9d4eb3d --- /dev/null +++ b/btt/mmap.c @@ -0,0 +1,150 @@ +/* + * blktrace output analysis: generate a timeline & gather statistics + * + * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <string.h> + +#include "blktrace.h" +#include "globals.h" + +#define DEF_LEN (16 * 1024 * 1024) + +static int fd; +static void *cur_map = MAP_FAILED; +static off_t cur_min, cur, cur_max, total_size; +static size_t len; +static struct blk_io_trace *next_t; +static long pgsz; + +int data_is_native = -1; + +static inline size_t min_len(size_t a, size_t b) +{ + return a < b ? a : b; +} + +static inline size_t convert_to_cpu(struct blk_io_trace *t, + struct blk_io_trace *tp, + void **pdu) +{ + if (data_is_native == -1) + check_data_endianness(t->magic); + + if (data_is_native) + memcpy(tp, t, sizeof(*tp)); + else { + tp->magic = be32_to_cpu(t->magic); + tp->sequence = be32_to_cpu(t->sequence); + tp->time = be64_to_cpu(t->time); + tp->sector = be64_to_cpu(t->sector); + tp->bytes = be32_to_cpu(t->bytes); + tp->action = be32_to_cpu(t->action); + tp->pid = be32_to_cpu(t->pid); + tp->device = be32_to_cpu(t->device); + tp->cpu = be16_to_cpu(t->cpu); + tp->error = be16_to_cpu(t->error); + tp->pdu_len = be16_to_cpu(t->pdu_len); + } + + if (tp->pdu_len) { + *pdu = malloc(tp->pdu_len); + memcpy(*pdu, t+1, tp->pdu_len); + } else + *pdu = NULL; + + return sizeof(*tp) + tp->pdu_len; +} + +static int move_map(void) +{ + if (cur_map != MAP_FAILED) + munmap(cur_map, len); + + cur_min = (cur & ~(pgsz-1)); + len = min_len(DEF_LEN, total_size - cur_min); + if (len < sizeof(*next_t)) + return 0; + + cur_map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, + cur_min); + if (cur_map == MAP_FAILED) { + perror("mmap"); + exit(1); + } + + cur_max = cur_min + len; + return (cur < cur_max); +} + +void setup_ifile(char *fname) +{ + struct stat buf; + + pgsz = sysconf(_SC_PAGESIZE); + + fd = my_open(fname, O_RDONLY); + if (fd < 0) { + perror(fname); + exit(1); + } + if (fstat(fd, &buf) < 0) { + perror(fname); + exit(1); + } + total_size = buf.st_size; + + if (!move_map()) + exit(0); +} + +void cleanup_ifile(void) +{ + if (cur_map != MAP_FAILED) + munmap(cur_map, len); + close(fd); +} + +int next_trace(struct blk_io_trace *t, void **pdu) +{ + size_t this_len; + + if ((cur + 512) > cur_max) + if (!move_map()) { + cleanup_ifile(); + return 0; + } + + next_t = cur_map + (cur - cur_min); + this_len = convert_to_cpu(next_t, t, pdu); + cur += this_len; + + return 1; +} + +double pct_done(void) +{ + return 100.0 * ((double)cur / (double)total_size); +} |