1e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 2e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * blktrace output analysis: generate a timeline & gather statistics 3e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 4e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com> 5e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 6e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * This program is free software; you can redistribute it and/or modify 7e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * it under the terms of the GNU General Public License as published by 8e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * the Free Software Foundation; either version 2 of the License, or 9e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * (at your option) any later version. 10e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 11e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * This program is distributed in the hope that it will be useful, 12e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * but WITHOUT ANY WARRANTY; without even the implied warranty of 13e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * GNU General Public License for more details. 15e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 16e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * You should have received a copy of the GNU General Public License 17e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * along with this program; if not, write to the Free Software 18e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 20e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 21e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <errno.h> 22e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdio.h> 23e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <string.h> 24e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <unistd.h> 25e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/types.h> 26e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/stat.h> 27e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/time.h> 28e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/resource.h> 29e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <fcntl.h> 30e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 31e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define INLINE_DECLARE 32e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "globals.h" 33e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 34e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct file_info { 35e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head head; 36e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat FILE *ofp; 37e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char *oname; 38e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 39e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 40e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct buf_info { 41e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head head; 42e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat void *buf; 43e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 44e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 45e20e1347b9914aa05e30548c15d7cd5e412cc0e2San MehatLIST_HEAD(files_to_clean); 46e20e1347b9914aa05e30548c15d7cd5e412cc0e2San MehatLIST_HEAD(all_bufs); 47e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 48e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void clean_files(void) 49e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 50e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p, *q; 51e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 52e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_for_each_safe(p, q, &files_to_clean) { 53e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct stat buf; 54e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct file_info *fip = list_entry(p, struct file_info, head); 55e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 56e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fclose(fip->ofp); 57e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!stat(fip->oname, &buf) && (buf.st_size == 0)) 58e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat unlink(fip->oname); 59e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 60e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_del(&fip->head); 61e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(fip->oname); 62e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(fip); 63e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 64e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 65e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 66e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void clean_bufs(void) 67e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 68e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p, *q; 69e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 70e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_for_each_safe(p, q, &all_bufs) { 71e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct buf_info *bip = list_entry(p, struct buf_info, head); 72e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 73e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_del(&bip->head); 74e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(bip->buf); 75e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(bip); 76e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 77e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 78e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 79e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#ifndef _ANDROID_ 80e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 81e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Due to the N(devs) parts of a lot of the output features provided 82e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * by btt, it will fail opens on large(ish) systems. Here we try to 83e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * keep bumping our open file limits, and if those fail, we return NULL. 84e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 85e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Root users will probably be OK with this, others... 86e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 87e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int increase_limit(int resource, rlim_t increase) 88e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 89e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rlimit rlim; 90e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int save_errno = errno; 91e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 92e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!getrlimit(resource, &rlim)) { 93e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat rlim.rlim_cur += increase; 94e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (rlim.rlim_cur >= rlim.rlim_max) 95e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat rlim.rlim_max = rlim.rlim_cur + increase; 96e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 97e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!setrlimit(resource, &rlim)) 98e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 99e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 100e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 101e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat errno = save_errno; 102e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 103e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 104e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#endif 105e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 106e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int handle_open_failure(void) 107e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 108e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (errno == ENFILE || errno == EMFILE) 109e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#ifndef _ANDROID_ 110e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return increase_limit(RLIMIT_NOFILE, 16); 111e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#else 112e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return -ENOSYS; 113e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#endif 114e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 115e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 116e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 117e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 118e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid add_file(FILE *fp, char *oname) 119e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 120e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct file_info *fip = malloc(sizeof(*fip)); 121e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 122e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fip->ofp = fp; 123e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fip->oname = oname; 124e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_add_tail(&fip->head, &files_to_clean); 125e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 126e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 127e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid add_buf(void *buf) 128e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 129e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct buf_info *bip = malloc(sizeof(*bip)); 130e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 131e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat bip->buf = buf; 132e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_add_tail(&bip->head, &all_bufs); 133e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 134e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 135e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid clean_allocs(void) 136e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 137e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat clean_files(); 138e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat clean_bufs(); 139e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 140e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 141e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatchar *make_dev_hdr(char *pad, size_t len, struct d_info *dip, int add_parens) 142e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 143e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip->devmap) 144e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat snprintf(pad, len, "%s", dip->devmap); 145e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else if (add_parens) 146e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat snprintf(pad, len, "(%3d,%3d)", 147e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat MAJOR(dip->device), MINOR(dip->device)); 148e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else 149e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat snprintf(pad, len, "%d,%d", 150e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat MAJOR(dip->device), MINOR(dip->device)); 151e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 152e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return pad; 153e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 154e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 155e20e1347b9914aa05e30548c15d7cd5e412cc0e2San MehatFILE *my_fopen(const char *path, const char *mode) 156e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 157e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat FILE *fp; 158e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 159e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat do { 160e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fp = fopen(path, mode); 161e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } while (fp == NULL && handle_open_failure()); 162e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 163e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return fp; 164e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 165e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 166e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatint my_open(const char *path, int flags) 167e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 168e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int fd; 169e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 170e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat do { 171e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fd = open(path, flags); 172e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } while (fd < 0 && handle_open_failure()); 173e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 174e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return fd; 175e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 176e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 177e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dbg_ping(void) {} 178