iowatcher: Add bounds checking in find_step
[blktrace.git] / iowatcher / tracers.c
index 3309befa10c6e8e4c470464cb8929ca160bf2d45..d70c4a60a46910f7f5937fa99986c93982b5a872 100644 (file)
@@ -12,7 +12,7 @@
  *
  *  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
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  *
  *  Parts of this file were imported from Jens Axboe's blktrace sources (also GPL)
  */
 #include "blkparse.h"
 #include "list.h"
 
+static int line_len = 1024;
+static char line[1024];
+
 static pid_t blktrace_pid = 0;
+static pid_t mpstat_pid = 0;
 
-char *blktrace_args[] = {
-       "-d", NULL,
-       "-b", "16384",
-       "-o", "trace",
-       "-D", ".",
+char *blktrace_args[17 + MAX_DEVICES_PER_TRACE * 2] = {
+       "blktrace",
+       "-b", "8192",
        "-a", "queue",
        "-a", "complete",
        "-a", "issue",
+       "-a", "notify",
+       "-D", ".",
+       NULL,
+};
+
+char *mpstat_args[] = {
+       "mpstat",
+       "-P", "ALL", "1",
        NULL,
 };
 
-#define DEVICE_INDEX 1
-#define DEST_DIR_INDEX 7
-#define TRACE_NAME_INDEX 5
+#define DEST_DIR_INDEX 12
+#define LAST_ARG 13
 
-int stop_blktrace(void)
+int stop_tracer(pid_t *tracer_pid)
 {
        int ret;
-       pid_t pid;
+       pid_t pid = *tracer_pid;
        pid_t pid_ret;
        int status = 0;
 
-       if (blktrace_pid == 0)
+       if (pid == 0)
                return 0;
 
-       pid = blktrace_pid;
-       blktrace_pid = 0;
+       *tracer_pid = 0;
        ret = kill(pid, SIGTERM);
        if (ret) {
-               fprintf(stderr, "failed to stop blktrace pid %lu error %s\n",
-                       (unsigned long)blktrace_pid, strerror(errno));
+               fprintf(stderr, "failed to stop tracer pid %lu error %s\n",
+                       (unsigned long)pid, strerror(errno));
                return -errno;
        }
        pid_ret = waitpid(pid, &status, WUNTRACED);
@@ -81,7 +89,8 @@ int stop_blktrace(void)
 
 void stop_all_tracers(void)
 {
-       stop_blktrace();
+       stop_tracer(&blktrace_pid);
+       stop_tracer(&mpstat_pid);
 }
 
 void sig_handler_for_quit(int val)
@@ -91,18 +100,42 @@ void sig_handler_for_quit(int val)
 }
 
 
-int start_blktrace(char *device, char *trace_name, char *dest)
+int start_blktrace(char **devices, int num_devices, char *trace_name, char *dest)
 {
        pid_t pid;
        int ret;
        char **arg = blktrace_args;
-       blktrace_args[DEVICE_INDEX] = device;
+       int i;
+       int arg_index;
 
        fprintf(stderr, "running blktrace");
-       if (dest)
-               blktrace_args[DEST_DIR_INDEX] = dest;
-       if (trace_name)
-               blktrace_args[TRACE_NAME_INDEX] = trace_name;
+       if (!trace_name)
+               trace_name = "trace";
+
+       arg_index = LAST_ARG;
+       for (i = 0; i < num_devices; i++) {
+               blktrace_args[arg_index++] = "-d";
+               blktrace_args[arg_index++] = devices[i];
+       }
+
+       /*
+        * single device traces use -o and are put into
+        * the dest dir if provided
+        */
+       if (num_devices == 1) {
+               blktrace_args[arg_index++] = "-o";
+               blktrace_args[arg_index++] = trace_name;
+               if (dest)
+                       blktrace_args[DEST_DIR_INDEX] = dest;
+       } else {
+               /*
+                * multi device traces are put into a dest
+                * dir based on the trace name
+                */
+               blktrace_args[DEST_DIR_INDEX] = trace_name;
+       }
+
+       blktrace_args[arg_index] = NULL;
 
        while(*arg) {
                fprintf(stderr, " %s", *arg);
@@ -138,27 +171,63 @@ int run_program(char *str)
                stop_all_tracers();
                return -errno;
        }
-       stop_blktrace();
+       stop_all_tracers();
        return 0;
 }
 
 int wait_for_tracers(void)
 {
        int status = 0;
-       if (blktrace_pid == 0)
-               return 0;
-
-       waitpid(blktrace_pid, &status, WUNTRACED);
-       blktrace_pid = 0;
+       if (blktrace_pid != 0) {
+               waitpid(blktrace_pid, &status, WUNTRACED);
+               blktrace_pid = 0;
+       }
+       if (mpstat_pid != 0) {
+               waitpid(mpstat_pid, &status, WUNTRACED);
+               mpstat_pid = 0;
+       }
        return 0;
 }
 
 int blktrace_to_dump(char *trace_name)
 {
-       char line[1024];
-       snprintf(line, 1024, "blkparse -O -i %s -d '%s.%s'",
+       snprintf(line, line_len, "blkparse -O -i %s -d '%s.%s'",
                trace_name, trace_name, "dump");
 
        system(line);
        return 0;
 }
+
+int start_mpstat(char *trace_name)
+{
+       int fd;
+       pid_t pid;
+
+       snprintf(line, line_len, "%s.mpstat", trace_name);
+
+       fd = open(line, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+       if (fd < 0) {
+               fprintf(stderr, "unable to open %s for writing err %s\n",
+                       line, strerror(errno));
+               exit(1);
+       }
+       pid = fork();
+       if (pid == 0) {
+               int ret;
+
+               close(1);
+               ret = dup2(fd, 1);
+               if (ret < 0) {
+                       fprintf(stderr, "failed to setup output file for mpstat\n");
+                       exit(1);
+               }
+               ret = execvp("mpstat", mpstat_args);
+               if (ret < 0) {
+                       fprintf(stderr, "failed to exec mpstat err %s\n",
+                               strerror(ret));
+                       exit(1);
+               }
+       }
+       mpstat_pid = pid;
+       return 0;
+}