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