X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=btt%2Fmisc.c;h=2e27c81e099dffaa330704d6660bb14ab2126b61;hb=e63098f39398bde67be9b64a49deece1c60614df;hp=1ec05cbd593e3d34c95c21af4dd10c168d62b3d7;hpb=6eb42155679cfa6fcd03d23199c5ba0a233b53e7;p=blktrace.git diff --git a/btt/misc.c b/btt/misc.c index 1ec05cb..2e27c81 100644 --- a/btt/misc.c +++ b/btt/misc.c @@ -18,99 +18,159 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#include #include #include +#include #include #include -#include +#include +#include +#include #define INLINE_DECLARE #include "globals.h" -int data_is_native = -1; +struct file_info { + struct list_head head; + FILE *ofp; + char *oname; +}; + +struct buf_info { + struct list_head head; + void *buf; +}; -struct blk_io_trace *convert_to_cpu(struct blk_io_trace *t) +LIST_HEAD(files_to_clean); +LIST_HEAD(all_bufs); + +static void clean_files(void) { - if (data_is_native == -1) - check_data_endianness(t->magic); + struct list_head *p, *q; - trace_to_cpu(t); + list_for_each_safe(p, q, &files_to_clean) { + struct stat buf; + struct file_info *fip = list_entry(p, struct file_info, head); - ASSERT(CHECK_MAGIC(t)); - ASSERT((t->magic & 0xff) == SUPPORTED_VERSION); + fclose(fip->ofp); + if (!stat(fip->oname, &buf) && (buf.st_size == 0)) + unlink(fip->oname); - return t; + list_del(&fip->head); + free(fip->oname); + free(fip); + } } -int in_devices(struct blk_io_trace *t) +static void clean_bufs(void) { - int i; - unsigned int mjr, mnr; - char *p = devices; + struct list_head *p, *q; - if (p == NULL) return 1; /* Allow anything */ + list_for_each_safe(p, q, &all_bufs) { + struct buf_info *bip = list_entry(p, struct buf_info, head); - for (;;) { - i = sscanf(p, "%u,%u;", &mjr, &mnr); - ASSERT(i == 2); + list_del(&bip->head); + free(bip->buf); + free(bip); + } +} - if ((mjr == MAJOR(t->device) && (mnr == MINOR(t->device)))) - return 1; +/* + * Due to the N(devs) parts of a lot of the output features provided + * by btt, it will fail opens on large(ish) systems. Here we try to + * keep bumping our open file limits, and if those fail, we return NULL. + * + * Root users will probably be OK with this, others... + */ +static int increase_limit(int resource, rlim_t increase) +{ + struct rlimit rlim; + int save_errno = errno; + + if (!getrlimit(resource, &rlim)) { + rlim.rlim_cur += increase; + if (rlim.rlim_cur >= rlim.rlim_max) + rlim.rlim_max = rlim.rlim_cur + increase; - p = strchr(p, ';'); - if (!p) - break; - p++; + if (!setrlimit(resource, &rlim)) + return 1; } + errno = save_errno; return 0; } -unsigned int do_read(int ifd, void *buf, int len) +static int handle_open_failure(void) { - int n; - - n = read(ifd, buf, len); - if (n < 0) { - perror(input_name); - return 1; - } - else if (0 < n && n < len) { - fprintf(stderr,"Short read on %s\n", input_name); - return 1; - } - else if (n == 0) /* EOF */ - return 1; + if (errno == ENFILE || errno == EMFILE) + return increase_limit(RLIMIT_NOFILE, 16); return 0; } -void add_file(struct file_info **fipp, FILE *fp, char *oname) +void add_file(FILE *fp, char *oname) { - struct file_info *fip; - - fip = malloc(sizeof(struct file_info) + strlen(oname) + 1); - - fip->next = *fipp; - *fipp = fip; + struct file_info *fip = malloc(sizeof(*fip)); fip->ofp = fp; - strcpy(fip->oname, oname); + fip->oname = oname; + list_add_tail(&fip->head, &files_to_clean); } -void clean_files(struct file_info **fipp) +void add_buf(void *buf) { - struct stat buf; - struct file_info *fip; + struct buf_info *bip = malloc(sizeof(*bip)); - while ((fip = *fipp) != NULL) { - *fipp = fip->next; + bip->buf = buf; + list_add_tail(&bip->head, &all_bufs); +} - fclose(fip->ofp); - if (!stat(fip->oname, &buf) && (buf.st_size == 0)) - unlink(fip->oname); - free(fip); - } +void clean_allocs(void) +{ + clean_files(); + clean_bufs(); +} + +char *make_dev_hdr(char *pad, size_t len, struct d_info *dip, int add_parens) +{ + if (dip->devmap) + snprintf(pad, len, "%s", dip->devmap); + else if (add_parens) + snprintf(pad, len, "(%3d,%3d)", + MAJOR(dip->device), MINOR(dip->device)); + else + snprintf(pad, len, "%d,%d", + MAJOR(dip->device), MINOR(dip->device)); + + return pad; +} + +char *mkhandle(struct d_info *dip, char *str, size_t len) +{ + return make_dev_hdr(str, len, dip, 0); +} + +FILE *my_fopen(const char *path, const char *mode) +{ + FILE *fp; + + do { + fp = fopen(path, mode); + } while (fp == NULL && handle_open_failure()); + + return fp; +} + +int my_open(const char *path, int flags) +{ + int fd; + + do { + fd = open(path, flags); + } while (fd < 0 && handle_open_failure()); + + return fd; } void dbg_ping(void) {}