1e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 2e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Blktrace record utility - Convert binary trace data into bunches of IOs 3e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 4e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Copyright (C) 2007 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 Mehatstatic char build_date[] = __DATE__ " at "__TIME__; 22e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 23e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <assert.h> 24e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <fcntl.h> 25e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdio.h> 26e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdlib.h> 27e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <string.h> 28e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <unistd.h> 29e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/param.h> 30e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/stat.h> 31e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/types.h> 32e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <dirent.h> 33e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdarg.h> 34e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 35e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#if !defined(_GNU_SOURCE) 36e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat# define _GNU_SOURCE 37e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#endif 38e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <getopt.h> 39e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 40e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "list.h" 41e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "btrecord.h" 42e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "blktrace.h" 43e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 44e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 45e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Per input file information 46e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 47e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @head: Used to link up on input_files 48e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @devnm: Device name portion of this input file 49e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @file_name: Fully qualified name for this input file 50e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @cpu: CPU that this file was collected on 51e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @ifd: Input file descriptor (when opened) 52e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tpkts: Total number of packets processed. 53e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 54e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct ifile_info { 55e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head head; 56e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char *devnm, *file_name; 57e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int cpu, ifd; 58e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u64 tpkts, genesis; 59e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 60e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 61e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 62e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Per IO trace information 63e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 64e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @time: Time stamp when trace was emitted 65e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @sector: IO sector identifier 66e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @bytes: Number of bytes transferred 67e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @rw: Read (1) or write (0) 68e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 69e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct io_spec { 70e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u64 time; 71e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u64 sector; 72e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u32 bytes; 73e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int rw; 74e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 75e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 76e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 77e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Per output file information 78e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 79e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @ofp: Output file 80e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @vfp: Verbose output file 81e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @file_name: Fully qualified name for this file 82e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @vfn: Fully qualified name for this file 83e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @cur: Current IO bunch being collected 84e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iip: Input file this is associated with 85e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @start_time: Start time of th ecurrent bunch 86e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @last_time: Time of last packet put in 87e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @bunches: Number of bunches processed 88e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @pkts: Number of packets stored in bunches 89e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 90e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct io_stream { 91e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat FILE *ofp, *vfp; 92e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char *file_name, *vfn; 93e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_bunch *cur; 94e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct ifile_info *iip; 95e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u64 start_time, last_time, bunches, pkts; 96e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 97e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 98e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatint data_is_native; // Indicates whether to swap 99e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic LIST_HEAD(input_files); // List of all input files 100e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char *idir = "."; // Input directory base 101e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char *odir = "."; // Output directory base 102e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char *obase = "replay"; // Output file base 103e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic __u64 max_bunch_tm = (10 * 1000 * 1000); // 10 milliseconds 104e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic __u64 max_pkts_per_bunch = 8; // Default # of pkts per bunch 105e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int verbose = 0; // Boolean: output stats 106e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int find_traces = 0; // Boolean: Find traces in dir 107e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 108e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char usage_str[] = \ 109e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\n" \ 110e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -d <dir> : --input-directory=<dir> ] Default: .\n" \ 111e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -D <dir> : --output-directory=<dir>] Default: .\n" \ 112e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -F : --find-traces ] Default: Off\n" \ 113e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -h : --help ] Default: Off\n" \ 114e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -m <nsec> : --max-bunch-time=<nsec> ] Default: 10 msec\n" \ 115e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -M <pkts> : --max-pkts=<pkts> ] Default: 8\n" \ 116e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -o <base> : --output-base=<base> ] Default: replay\n" \ 117e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -v : --verbose ] Default: Off\n" \ 118e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t[ -V : --version ] Default: Off\n" \ 119e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t<dev>... Default: None\n" \ 120e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\n"; 121e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 122e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define S_OPTS "d:D:Fhm:M:o:vV" 123e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct option l_opts[] = { 124e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 125e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "input-directory", 126e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 127e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 128e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'd' 129e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 130e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 131e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "output-directory", 132e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 133e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 134e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'D' 135e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 136e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 137e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "find-traces", 138e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = no_argument, 139e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 140e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'F' 141e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 142e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 143e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "help", 144e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = no_argument, 145e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 146e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'h' 147e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 148e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 149e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "max-bunch-time", 150e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 151e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 152e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'm' 153e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 154e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 155e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "max-pkts", 156e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 157e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 158e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'M' 159e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 160e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 161e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "output-base", 162e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 163e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 164e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'o' 165e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 166e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 167e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "verbose", 168e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = no_argument, 169e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 170e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'v' 171e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 172e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 173e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "version", 174e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = no_argument, 175e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 176e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'V' 177e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 178e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 179e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = NULL 180e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 181e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 182e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 183e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define ERR_ARGS 1 184e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define ERR_SYSCALL 2 185e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void fatal(const char *errstring, const int exitval, 186e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat const char *fmt, ...) 187e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 188e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat va_list ap; 189e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 190e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (errstring) 191e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat perror(errstring); 192e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 193e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat va_start(ap, fmt); 194e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vfprintf(stderr, fmt, ap); 195e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat va_end(ap); 196e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 197e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat exit(exitval); 198e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 199e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 200e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 201e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 202e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * match - Return true if this trace is a proper QUEUE transaction 203e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @action: Action field from trace 204e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 205e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline int match(__u32 action) 206e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 207e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return ((action & 0xffff) == __BLK_TA_QUEUE) && 208e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (action & BLK_TC_ACT(BLK_TC_QUEUE)); 209e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 210e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 211e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 212e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * usage - Display usage string and version 213e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 214e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void usage(void) 215e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 216e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "Usage: btrecord -- version %s\n%s", 217e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat my_btversion, usage_str); 218e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 219e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 220e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 221e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * write_file_hdr - Seek to and write btrecord file header 222e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @stream: Output file information 223e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @hdr: Header to write 224e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 225e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void write_file_hdr(struct io_stream *stream, struct io_file_hdr *hdr) 226e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 227e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat hdr->version = mk_btversion(btver_mjr, btver_mnr, btver_sub); 228e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 229e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verbose) { 230e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "\t%s: %llx %llx %llx %llx\n", 231e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->file_name, 232e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned)hdr->version, 233e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned)hdr->genesis, 234e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned)hdr->nbunches, 235e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned)hdr->total_pkts); 236e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 237e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 238e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fseek(stream->ofp, 0, SEEK_SET); 239e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fwrite(hdr, sizeof(*hdr), 1, stream->ofp) != 1) { 240e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(stream->file_name, ERR_SYSCALL, "Hdr write failed\n"); 241e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 242e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 243e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 244e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 245e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 246e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * io_bunch_create - Allocate & initialize an io_bunch 247e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @io_stream: IO stream being added to 248e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @pre_stall: Amount of time that this bunch should be delayed by 249e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @start_time: Records current start 250e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 251e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void io_bunch_create(struct io_stream *stream, __u64 start_time) 252e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 253e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_bunch *cur = malloc(sizeof(*cur)); 254e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 255e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat memset(cur, 0, sizeof(*cur)); 256e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 257e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat cur->hdr.npkts = 0; 258e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat cur->hdr.time_stamp = stream->start_time = start_time; 259e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 260e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->cur = cur; 261e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 262e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 263e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 264e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * io_bunch_add - Add an IO to the current bunch of IOs 265e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @stream: Per-output file stream information 266e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @spec: IO trace specification 267e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 268e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Returns update bunch information 269e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 270e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void io_bunch_add(struct io_stream *stream, struct io_spec *spec) 271e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 272e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_bunch *cur = stream->cur; 273e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_pkt iop = { 274e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .sector = spec->sector, 275e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .nbytes = spec->bytes, 276e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .rw = spec->rw 277e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }; 278e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 279e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(cur != NULL); 280e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(cur->hdr.npkts < BT_MAX_PKTS); 281e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(stream->last_time == 0 || stream->last_time <= spec->time); 282e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 283e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat cur->pkts[cur->hdr.npkts++] = iop; // Struct copy 284e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->last_time = spec->time; 285e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 286e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 287e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 288e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * rem_input_file - Release resources associated with an input file 289e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iip: Per-input file information 290e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 291e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void rem_input_file(struct ifile_info *iip) 292e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 293e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_del(&iip->head); 294e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 295e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat close(iip->ifd); 296e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(iip->file_name); 297e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(iip->devnm); 298e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(iip); 299e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 300e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 301e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 302e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * __add_input_file - Allocate and initialize per-input file structure 303e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @cpu: CPU for this file 304e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @devnm: Device name for this file 305e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @file_name: Fully qualifed input file name 306e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 307e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void __add_input_file(int cpu, char *devnm, char *file_name) 308e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 309e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct ifile_info *iip = malloc(sizeof(*iip)); 310e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 311e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->cpu = cpu; 312e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->tpkts = 0; 313e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->genesis = 0; 314e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->devnm = strdup(devnm); 315e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->file_name = strdup(file_name); 316e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->ifd = open(file_name, O_RDONLY); 317e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (iip->ifd < 0) { 318e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(file_name, ERR_ARGS, "Unable to open\n"); 319e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 320e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 321e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 322e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_add_tail(&iip->head, &input_files); 323e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 324e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 325e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 326e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * add_input_file - Set up the input file name 327e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @devnm: Device name to use 328e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 329e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void add_input_file(char *devnm) 330e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 331e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p; 332e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int cpu, found = 0; 333e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 334e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __list_for_each(p, &input_files) { 335e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct ifile_info *iip = list_entry(p, struct ifile_info, head); 336e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (strcmp(iip->devnm, devnm) == 0) 337e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return; 338e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 339e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 340e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (cpu = 0; ; cpu++) { 341e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char full_name[MAXPATHLEN]; 342e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 343e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat sprintf(full_name, "%s/%s.blktrace.%d", idir, devnm, cpu); 344e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (access(full_name, R_OK) != 0) 345e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 346e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 347e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __add_input_file(cpu, devnm, full_name); 348e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat found++; 349e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 350e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 351e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!found) { 352e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(NULL, ERR_ARGS, "No traces found for %s\n", devnm); 353e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 354e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 355e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 356e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 357e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void find_input_files(char *idir) 358e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 359e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dirent *ent; 360e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat DIR *dir = opendir(idir); 361e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 362e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dir == NULL) { 363e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(idir, ERR_ARGS, "Unable to open %s\n", idir); 364e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 365e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 366e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 367e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while ((ent = readdir(dir)) != NULL) { 368e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char *p, *dsf = malloc(256); 369e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 370e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (strstr(ent->d_name, ".blktrace.") == NULL) 371e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat continue; 372e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 373e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dsf = strdup(ent->d_name); 374e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat p = index(dsf, '.'); 375e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(p != NULL); 376e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *p = '\0'; 377e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat add_input_file(dsf); 378e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(dsf); 379e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 380e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 381e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat closedir(dir); 382e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 383e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 384e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 385e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * handle_args - Parse passed in argument list 386e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argc: Number of arguments in argv 387e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argv: Arguments passed in 388e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 389e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Does rudimentary parameter verification as well. 390e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 391e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid handle_args(int argc, char *argv[]) 392e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 393e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int c; 394e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 395e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) != -1) { 396e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat switch (c) { 397e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'd': 398e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat idir = optarg; 399e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (access(idir, R_OK | X_OK) != 0) { 400e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(idir, ERR_ARGS, 401e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "Invalid input directory specified\n"); 402e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 403e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 404e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 405e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 406e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'D': 407e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat odir = optarg; 408e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (access(odir, R_OK | X_OK) != 0) { 409e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(odir, ERR_ARGS, 410e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "Invalid output directory specified\n"); 411e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 412e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 413e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 414e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 415e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'F': 416e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat find_traces = 1; 417e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 418e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 419e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'h': 420e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat usage(); 421e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat exit(0); 422e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 423e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 424e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'm': 425e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat max_bunch_tm = (__u64)atoll(optarg); 426e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (max_bunch_tm < 1) { 427e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "Invalid bunch time %llu\n", 428e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)max_bunch_tm); 429e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat exit(ERR_ARGS); 430e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 431e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 432e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 433e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 434e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'M': 435e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat max_pkts_per_bunch = (__u64)atoll(optarg); 436e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!((1 <= max_pkts_per_bunch) && 437e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (max_pkts_per_bunch < 513))) { 438e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "Invalid max pkts %llu\n", 439e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)max_pkts_per_bunch); 440e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat exit(ERR_ARGS); 441e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 442e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 443e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 444e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 445e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'o': 446e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat obase = optarg; 447e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 448e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 449e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'V': 450e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "btrecord -- version %s\n", 451e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat my_btversion); 452e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, " Built on %s\n", build_date); 453e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat exit(0); 454e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 455e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 456e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'v': 457e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat verbose++; 458e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 459e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 460e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat default: 461e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat usage(); 462e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(NULL, ERR_ARGS, "Invalid command line\n"); 463e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 464e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 465e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 466e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 467e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while (optind < argc) 468e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat add_input_file(argv[optind++]); 469e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 470e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (find_traces) 471e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat find_input_files(idir); 472e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 473e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (list_len(&input_files) == 0) { 474e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(NULL, ERR_ARGS, "Missing required input file name(s)\n"); 475e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 476e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 477e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 478e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 479e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 480e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * next_io - Retrieve next Q trace from input stream 481e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iip: Per-input file information 482e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @spec: IO specifier for trace 483e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 484e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Returns 0 on end of file, 1 if valid data returned. 485e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 486e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int next_io(struct ifile_info *iip, struct io_spec *spec) 487e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 488e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat ssize_t ret; 489e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u32 action; 490e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u16 pdu_len; 491e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blk_io_trace t; 492e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 493e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatagain: 494e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat ret = read(iip->ifd, &t, sizeof(t)); 495e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (ret < 0) { 496e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(iip->file_name, ERR_SYSCALL, "Read failed\n"); 497e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 498e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 499e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else if (ret == 0) 500e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 501e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else if (ret < (ssize_t)sizeof(t)) { 502e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "WARNING: Short read on %s (%d)\n", 503e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->file_name, (int)ret); 504e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 505e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 506e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 507e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (data_is_native == -1) 508e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat check_data_endianness(t.magic); 509e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 510e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(data_is_native >= 0); 511e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (data_is_native) { 512e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->time = t.time; 513e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->sector = t.sector; 514e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->bytes = t.bytes; 515e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat action = t.action; 516e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pdu_len = t.pdu_len; 517e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 518e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else { 519e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->time = be64_to_cpu(t.time); 520e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->sector = be64_to_cpu(t.sector); 521e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->bytes = be32_to_cpu(t.bytes); 522e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat action = be32_to_cpu(t.action); 523e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pdu_len = be16_to_cpu(t.pdu_len); 524e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 525e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 526e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 527e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (pdu_len) { 528e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char buf[pdu_len]; 529e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 530e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat ret = read(iip->ifd, buf, pdu_len); 531e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (ret < 0) { 532e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(iip->file_name, ERR_SYSCALL, "Read PDU failed\n"); 533e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 534e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 535e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else if (ret < (ssize_t)pdu_len) { 536e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "WARNING: Short PDU read on %s (%d)\n", 537e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->file_name, (int)ret); 538e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 539e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 540e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 541e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 542e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->tpkts++; 543e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!match(action)) 544e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto again; 545e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 546e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->rw = (action & BLK_TC_ACT(BLK_TC_READ)) ? 1 : 0; 547e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verbose > 1) 548e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "%2d: %10llu+%10llu (%d) @ %10llx\n", 549e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->cpu, (long long unsigned)spec->sector, 550e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned)spec->bytes / 512LLU, 551e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat spec->rw, (long long unsigned)spec->time); 552e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 553e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (iip->genesis == 0) { 554e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iip->genesis = spec->time; 555e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verbose > 1) 556e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "\tSetting new genesis: %llx(%d)\n", 557e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned)iip->genesis, iip->cpu); 558e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 559e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else if (iip->genesis > spec->time) 560e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(NULL, ERR_SYSCALL, 561e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "Time inversion? %llu ... %llu\n", 562e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned )iip->genesis, 563e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (long long unsigned )spec->time); 564e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 565e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 566e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 567e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 568e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 569e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * bunch_output_hdr - Output bunch header 570e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 571e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void bunch_output_hdr(struct io_stream *stream) 572e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 573e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_bunch_hdr *hdrp = &stream->cur->hdr; 574e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 575e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(0 < hdrp->npkts && hdrp->npkts <= BT_MAX_PKTS); 576e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fwrite(hdrp, sizeof(struct io_bunch_hdr), 1, stream->ofp) != 1) { 577e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(stream->file_name, ERR_SYSCALL, "fwrite(hdr) failed\n"); 578e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 579e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 580e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 581e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verbose) { 582e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u64 off = hdrp->time_stamp - stream->iip->genesis; 583e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 584e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(stream->vfp); 585e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stream->vfp, "------------------\n"); 586e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stream->vfp, "%4llu.%09llu %3llu\n", 587e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)off / (1000 * 1000 * 1000), 588e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)off % (1000 * 1000 * 1000), 589e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)hdrp->npkts); 590e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stream->vfp, "------------------\n"); 591e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 592e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 593e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 594e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 595e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * bunch_output_pkt - Output IO packets 596e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 597e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void bunch_output_pkts(struct io_stream *stream) 598e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 599e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_pkt *p = stream->cur->pkts; 600e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat size_t npkts = stream->cur->hdr.npkts; 601e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 602e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(0 < npkts && npkts <= BT_MAX_PKTS); 603e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fwrite(p, sizeof(struct io_pkt), npkts, stream->ofp) != npkts) { 604e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(stream->file_name, ERR_SYSCALL, "fwrite(pkts) failed\n"); 605e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 606e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 607e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 608e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verbose) { 609e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat size_t i; 610e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 611e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(stream->vfp); 612e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (i = 0; i < npkts; i++, p++) 613e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stream->vfp, "\t%1d %10llu\t%10llu\n", 614e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat p->rw, 615e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)p->sector, 616e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)p->nbytes / 512); 617e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 618e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 619e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 620e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 621e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * stream_flush - Flush current bunch of IOs out to the output stream 622e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @stream: Per-output file stream information 623e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 624e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void stream_flush(struct io_stream *stream) 625e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 626e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_bunch *cur = stream->cur; 627e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 628e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (cur) { 629e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (cur->hdr.npkts) { 630e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat assert(cur->hdr.npkts <= BT_MAX_PKTS); 631e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat bunch_output_hdr(stream); 632e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat bunch_output_pkts(stream); 633e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 634e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->bunches++; 635e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->pkts += cur->hdr.npkts; 636e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 637e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(cur); 638e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 639e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 640e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 641e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 642e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * bunch_done - Returns true if current bunch is either full, or next IO is late 643e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @stream: Output stream information 644e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @spec: IO trace specification 645e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 646e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline int bunch_done(struct io_stream *stream, struct io_spec *spec) 647e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 648e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (stream->cur->hdr.npkts >= max_pkts_per_bunch) 649e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 650e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 651e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if ((spec->time - stream->start_time) > max_bunch_tm) 652e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 653e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 654e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 655e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 656e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 657e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 658e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * stream_add_io - Add an IO trace to the current stream 659e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @stream: Output stream information 660e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @spec: IO trace specification 661e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 662e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void stream_add_io(struct io_stream *stream, struct io_spec *spec) 663e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 664e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 665e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (stream->cur == NULL) 666e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat io_bunch_create(stream, spec->time); 667e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else if (bunch_done(stream, spec)) { 668e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream_flush(stream); 669e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat io_bunch_create(stream, spec->time); 670e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 671e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 672e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat io_bunch_add(stream, spec); 673e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 674e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 675e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 676e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * stream_open - Open output stream for specified input stream 677e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iip: Per-input file information 678e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 679e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct io_stream *stream_open(struct ifile_info *iip) 680e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 681e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char ofile_name[MAXPATHLEN]; 682e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_stream *stream = malloc(sizeof(*stream)); 683e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_file_hdr io_file_hdr = { 684e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .genesis = 0, 685e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .nbunches = 0, 686e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .total_pkts = 0 687e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }; 688e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 689e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat memset(stream, 0, sizeof(*stream)); 690e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 691e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat sprintf(ofile_name, "%s/%s.%s.%d", odir, iip->devnm, obase, iip->cpu); 692e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->ofp = fopen(ofile_name, "w"); 693e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!stream->ofp) { 694e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(ofile_name, ERR_SYSCALL, "Open failed\n"); 695e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 696e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 697e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 698e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->iip = iip; 699e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->cur = NULL; 700e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->bunches = stream->pkts = 0; 701e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->last_time = 0; 702e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->file_name = strdup(ofile_name); 703e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 704e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat write_file_hdr(stream, &io_file_hdr); 705e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 706e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verbose) { 707e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char vfile_name[MAXPATHLEN]; 708e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 709e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat sprintf(vfile_name, "%s/%s.%s.%d.rec", odir, iip->devnm, 710e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat obase, iip->cpu); 711e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->vfp = fopen(vfile_name, "w"); 712e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!stream->vfp) { 713e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fatal(vfile_name, ERR_SYSCALL, "Open failed\n"); 714e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /*NOTREACHED*/ 715e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 716e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 717e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->vfn = strdup(vfile_name); 718e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 719e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 720e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat data_is_native = -1; 721e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return stream; 722e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 723e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 724e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 725e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * stream_close - Release resources associated with an output stream 726e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @stream: Stream to release 727e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 728e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void stream_close(struct io_stream *stream) 729e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 730e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_file_hdr io_file_hdr = { 731e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .genesis = stream->iip->genesis, 732e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .nbunches = stream->bunches, 733e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .total_pkts = stream->pkts 734e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }; 735e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 736e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream_flush(stream); 737e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat write_file_hdr(stream, &io_file_hdr); 738e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fclose(stream->ofp); 739e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 740e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verbose && stream->bunches) { 741e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, 742e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "%s:%d: %llu pkts (tot), %llu pkts (replay), " 743e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "%llu bunches, %.1lf pkts/bunch\n", 744e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream->iip->devnm, stream->iip->cpu, 745e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)stream->iip->tpkts, 746e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)stream->pkts, 747e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long long)stream->bunches, 748e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (double)(stream->pkts) / (double)(stream->bunches)); 749e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 750e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fclose(stream->vfp); 751e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(stream->vfn); 752e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 753e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 754e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(stream->file_name); 755e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(stream); 756e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 757e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 758e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 759e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * process - Process one input file to an output file 760e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iip: Per-input file information 761e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 762e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void process(struct ifile_info *iip) 763e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 764e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_spec spec; 765e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io_stream *stream; 766e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 767e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream = stream_open(iip); 768e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while (next_io(iip, &spec)) 769e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream_add_io(stream, &spec); 770e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat stream_close(stream); 771e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 772e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat rem_input_file(iip); 773e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 774e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 775e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/** 776e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * main - 777e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argc: Number of arguments 778e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argv: Array of arguments 779e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 780e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatint main(int argc, char *argv[]) 781e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 782e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p, *q; 783e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 784e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat handle_args(argc, argv); 785e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_for_each_safe(p, q, &input_files) 786e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat process(list_entry(p, struct ifile_info, head)); 787e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 788e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 789e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 790