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