1e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
2e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Blktrace replay utility - Play traces back
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 <errno.h>
25e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <fcntl.h>
26e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <libaio.h>
27e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <pthread.h>
28e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sched.h>
29e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <signal.h>
30e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdio.h>
31e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdlib.h>
32e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <string.h>
33e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <time.h>
34e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <unistd.h>
35e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/param.h>
36e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/stat.h>
37e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/time.h>
38e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/types.h>
39e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <dirent.h>
40e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdarg.h>
41e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
42e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#if !defined(_GNU_SOURCE)
43e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#	define _GNU_SOURCE
44e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#endif
45e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <getopt.h>
46e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
47e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "list.h"
48e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "btrecord.h"
49e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
50e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
51e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
52e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== STRUCTURE DEFINITIONS =============================================
53e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
54e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
55e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
56e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
57e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Each device map has one of these:
58e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
59e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @head:	Linked on to map_devs
60e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @from_dev:	Device name as seen on recorded system
61e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @to_dev:	Device name to be used on replay system
62e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
63e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct map_dev {
64e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head head;
65e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	char *from_dev, *to_dev;
66e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat};
67e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
68e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
69e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Each device name specified has one of these (until threads are created)
70e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
71e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @head: 	Linked onto input_devs
72e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @devnm: 	Device name -- 'sd*'
73e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
74e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct dev_info {
75e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head head;
76e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	char *devnm;
77e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat};
78e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
79e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
80e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Per input file information
81e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
82e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @head: 	Used to link up on input_files
83e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @free_iocbs: List of free iocb's available for use
84e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @used_iocbs: List of iocb's currently outstanding
85e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @mutex: 	Mutex used with condition variable to protect volatile values
86e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @cond: 	Condition variable used when waiting on a volatile value change
87e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @naios_out: 	Current number of AIOs outstanding on this context
88e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @naios_free: Number of AIOs on the free list (short cut for list_len)
89e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @send_wait: 	Boolean: When true, the sub thread is waiting on free IOCBs
90e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @reap_wait: 	Boolean: When true, the rec thread is waiting on used IOCBs
91e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @send_done: 	Boolean: When true, the sub thread has completed work
92e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @reap_done: 	Boolean: When true, the rec thread has completed work
93e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @sub_thread: Thread used to submit IOs.
94e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @rec_thread: Thread used to reclaim IOs.
95e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @ctx: 	IO context
96e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @devnm: 	Copy of the device name being managed by this thread
97e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @file_name: 	Full name of the input file
98e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @cpu: 	CPU this thread is pinned to
99e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @ifd: 	Input file descriptor
100e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @ofd: 	Output file descriptor
101e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iterations: Remaining iterations to process
102e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @vfp:	For verbose dumping of actions performed
103e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
104e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct thr_info {
105e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head head, free_iocbs, used_iocbs;
106e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_t mutex;
107e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_cond_t cond;
108e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	volatile long naios_out, naios_free;
109e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	volatile int send_wait, reap_wait, send_done, reap_done;
110e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_t sub_thread, rec_thread;
111e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	io_context_t ctx;
112e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	char *devnm, *file_name;
113e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int cpu, ifd, ofd, iterations;
114e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	FILE *vfp;
115e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat};
116e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
117e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
118e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Every Asynchronous IO used has one of these (naios per file/device).
119e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
120e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iocb:	IOCB sent down via io_submit
121e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @head:	Linked onto file_list.free_iocbs or file_list.used_iocbs
122e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip:	Pointer to per-thread information this IO is associated with
123e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @nbytes:	Number of bytes in buffer associated with iocb
124e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
125e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct iocb_pkt {
126e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct iocb iocb;
127e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head head;
128e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct thr_info *tip;
129e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int nbytes;
130e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat};
131e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
132e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
133e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
134e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== GLOBAL VARIABLES ==================================================
135e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
136e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
137e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
138e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic volatile int signal_done = 0;	// Boolean: Signal'ed, need to quit
139e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
140e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char *ibase = "replay";		// Input base name
141e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char *idir = ".";		// Input directory base
142e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int cpus_to_use = -1;		// Number of CPUs to use
143e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int def_iterations = 1;		// Default number of iterations
144e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int naios = 512;			// Number of AIOs per thread
145e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int ncpus = 0;			// Number of CPUs in the system
146e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int verbose = 0;			// Boolean: Output some extra info
147e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int write_enabled = 0;		// Boolean: Enable writing
148e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic __u64 genesis = ~0;		// Earliest time seen
149e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic __u64 rgenesis;			// Our start time
150e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic size_t pgsize;			// System Page size
151e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int nb_sec = 512;		// Number of bytes per sector
152e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic LIST_HEAD(input_devs);		// List of devices to handle
153e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic LIST_HEAD(input_files);		// List of input files to handle
154e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic LIST_HEAD(map_devs);		// List of device maps
155e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int nfiles = 0;			// Number of files to handle
156e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int no_stalls = 0;		// Boolean: Disable pre-stalls
157e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic unsigned acc_factor = 1;		// Int: Acceleration factor
158e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int find_records = 0;		// Boolean: Find record files auto
159e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
160e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
161e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Variables managed under control of condition variables.
162e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
163e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * n_reclaims_done: 	Counts number of reclaim threads that have completed.
164e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * n_replays_done:	Counts number of replay threads that have completed.
165e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * n_replays_ready:	Counts number of replay threads ready to start.
166e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * n_iters_done:	Counts number of replay threads done one iteration.
167e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * iter_start:		Starts an iteration for the replay threads.
168e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
169e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic volatile int n_reclaims_done = 0;
170e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_mutex_t reclaim_done_mutex = PTHREAD_MUTEX_INITIALIZER;
171e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_cond_t reclaim_done_cond = PTHREAD_COND_INITIALIZER;
172e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
173e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic volatile int n_replays_done = 0;
174e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_mutex_t replay_done_mutex = PTHREAD_MUTEX_INITIALIZER;
175e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_cond_t replay_done_cond = PTHREAD_COND_INITIALIZER;
176e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
177e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic volatile int n_replays_ready = 0;
178e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_mutex_t replay_ready_mutex = PTHREAD_MUTEX_INITIALIZER;
179e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_cond_t replay_ready_cond = PTHREAD_COND_INITIALIZER;
180e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
181e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic volatile int n_iters_done = 0;
182e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_mutex_t iter_done_mutex = PTHREAD_MUTEX_INITIALIZER;
183e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_cond_t iter_done_cond = PTHREAD_COND_INITIALIZER;
184e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
185e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic volatile int iter_start = 0;
186e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_mutex_t iter_start_mutex = PTHREAD_MUTEX_INITIALIZER;
187e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_cond_t iter_start_cond = PTHREAD_COND_INITIALIZER;
188e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
189e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
190e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
191e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== FORWARD REFERENECES ===============================================
192e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
193e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
194e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
195e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void *replay_sub(void *arg);
196e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void *replay_rec(void *arg);
197e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char usage_str[];
198e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
199e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
200e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
201e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== INLINE ROUTINES ===================================================
202e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
203e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
204e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
205e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
206e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * The 'fatal' macro will output a perror message (if errstring is !NULL)
207e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * and display a string (with variable arguments) and then exit with the
208e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * specified exit value.
209e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
210e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define ERR_ARGS			1
211e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define ERR_SYSCALL			2
212e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void fatal(const char *errstring, const int exitval,
213e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			 const char *fmt, ...)
214e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
215e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	va_list ap;
216e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
217e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (errstring)
218e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		perror(errstring);
219e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
220e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	va_start(ap, fmt);
221e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	vfprintf(stderr, fmt, ap);
222e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	va_end(ap);
223e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
224e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	exit(exitval);
225e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	/*NOTREACHED*/
226e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
227e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
228e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline long long unsigned du64_to_sec(__u64 du64)
229e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
230e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return (long long unsigned)du64 / (1000 * 1000 * 1000);
231e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
232e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
233e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline long long unsigned du64_to_nsec(__u64 du64)
234e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
235e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return llabs((long long)du64) % (1000 * 1000 * 1000);
236e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
237e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
238e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
239e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * min - Return minimum of two integers
240e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
241e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline int min(int a, int b)
242e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
243e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return a < b ? a : b;
244e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
245e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
246e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
247e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * minl - Return minimum of two longs
248e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
249e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline long minl(long a, long b)
250e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
251e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return a < b ? a : b;
252e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
253e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
254e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
255e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * usage - Display usage string and version
256e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
257e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void usage(void)
258e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
259e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	fprintf(stderr, "Usage: btreplay -- version %s\n%s",
260e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		my_btversion, usage_str);
261e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
262e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
263e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
264e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * is_send_done - Returns true if sender should quit early
265e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-thread information
266e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
267e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline int is_send_done(struct thr_info *tip)
268e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
269e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return signal_done || tip->send_done;
270e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
271e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
272e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
273e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * is_reap_done - Returns true if reaper should quit early
274e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-thread information
275e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
276e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline int is_reap_done(struct thr_info *tip)
277e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
278e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return tip->send_done && tip->naios_out == 0;
279e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
280e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
281e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
282e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ts2ns - Convert timespec values to a nanosecond value
283e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
284e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define NS_TICKS		((__u64)1000 * (__u64)1000 * (__u64)1000)
285e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline __u64 ts2ns(struct timespec *ts)
286e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
287e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return ((__u64)(ts->tv_sec) * NS_TICKS) + (__u64)(ts->tv_nsec);
288e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
289e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
290e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
291e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ts2ns - Convert timeval values to a nanosecond value
292e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
293e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline __u64 tv2ns(struct timeval *tp)
294e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
295e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return ((__u64)(tp->tv_sec)) + ((__u64)(tp->tv_usec) * (__u64)1000);
296e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
297e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
298e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
299e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * touch_memory - Force physical memory to be allocating it
300e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
301e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * For malloc()ed memory we need to /touch/ it to make it really
302e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * exist. Otherwise, for write's (to storage) things may not work
303e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * as planned - we see Linux just use a single area to /read/ from
304e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * (as there isn't any memory that has been associated with the
305e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * allocated virtual addresses yet).
306e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
307e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void touch_memory(char *buf, size_t bsize)
308e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
309e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#if defined(PREP_BUFS)
310e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	memset(buf, 0, bsize);
311e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#else
312e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	size_t i;
313e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
314e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (i = 0; i < bsize; i += pgsize)
315e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		buf[i] = 0;
316e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#endif
317e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
318e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
319e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
320e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * buf_alloc - Returns a page-aligned buffer of the specified size
321e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @nbytes: Number of bytes to allocate
322e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
323e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void *buf_alloc(size_t nbytes)
324e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
325e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	void *buf;
326e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
327e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (posix_memalign(&buf, pgsize, nbytes)) {
328e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("posix_memalign", ERR_SYSCALL, "Allocation failed\n");
329e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
330e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
331e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
332e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return buf;
333e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
334e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
335e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
336e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * gettime - Returns current time
337e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
338e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline __u64 gettime(void)
339e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
340e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	static int use_clock_gettime = -1;		// Which clock to use
341e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
342e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (use_clock_gettime < 0) {
343e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		use_clock_gettime = clock_getres(CLOCK_MONOTONIC, NULL) == 0;
344e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (use_clock_gettime) {
345e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			struct timespec ts = {
346e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				.tv_sec = 0,
347e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				.tv_nsec = 0
348e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			};
349e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			clock_settime(CLOCK_MONOTONIC, &ts);
350e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
351e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
352e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
353e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (use_clock_gettime) {
354e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct timespec ts;
355e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		clock_gettime(CLOCK_MONOTONIC, &ts);
356e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		return ts2ns(&ts);
357e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
358e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	else {
359e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct timeval tp;
360e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		gettimeofday(&tp, NULL);
361e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		return tv2ns(&tp);
362e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
363e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
364e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
365e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
366e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * setup_signal - Set up a signal handler for the specified signum
367e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
368e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void setup_signal(int signum, sighandler_t handler)
369e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
370e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (signal(signum, handler) == SIG_ERR) {
371e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("signal", ERR_SYSCALL, "Failed to set signal %d\n",
372e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			signum);
373e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
374e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
375e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
376e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
377e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
378e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
379e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== CONDITION VARIABLE ROUTINES =======================================
380e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
381e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
382e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
383e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
384e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * __set_cv - Increments a variable under condition variable control.
385e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @pmp: 	Pointer to the associated mutex
386e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @pcp: 	Pointer to the associated condition variable
387e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @vp: 	Pointer to the variable being incremented
388e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @mxv: 	Max value for variable (Used only when ASSERTS are on)
389e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
390e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void __set_cv(pthread_mutex_t *pmp, pthread_cond_t *pcp,
391e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			    volatile int *vp,
392e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			    __attribute__((__unused__))int mxv)
393e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
394e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_lock(pmp);
395e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(*vp < mxv);
396e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	*vp += 1;
397e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_cond_signal(pcp);
398e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_unlock(pmp);
399e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
400e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
401e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
402e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * __wait_cv - Waits for a variable under cond var control to hit a value
403e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @pmp: 	Pointer to the associated mutex
404e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @pcp: 	Pointer to the associated condition variable
405e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @vp: 	Pointer to the variable being incremented
406e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @mxv: 	Value to wait for
407e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
408e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void __wait_cv(pthread_mutex_t *pmp, pthread_cond_t *pcp,
409e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			     volatile int *vp, int mxv)
410e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
411e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_lock(pmp);
412e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (*vp < mxv)
413e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		pthread_cond_wait(pcp, pmp);
414e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	*vp = 0;
415e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_unlock(pmp);
416e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
417e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
418e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void set_reclaim_done(void)
419e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
420e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__set_cv(&reclaim_done_mutex, &reclaim_done_cond, &n_reclaims_done,
421e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		 nfiles);
422e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
423e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
424e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void wait_reclaims_done(void)
425e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
426e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__wait_cv(&reclaim_done_mutex, &reclaim_done_cond, &n_reclaims_done,
427e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		  nfiles);
428e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
429e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
430e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void set_replay_ready(void)
431e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
432e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__set_cv(&replay_ready_mutex, &replay_ready_cond, &n_replays_ready,
433e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		 nfiles);
434e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
435e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
436e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void wait_replays_ready(void)
437e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
438e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__wait_cv(&replay_ready_mutex, &replay_ready_cond, &n_replays_ready,
439e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		  nfiles);
440e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
441e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
442e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void set_replay_done(void)
443e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
444e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__set_cv(&replay_done_mutex, &replay_done_cond, &n_replays_done,
445e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		nfiles);
446e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
447e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
448e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void wait_replays_done(void)
449e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
450e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__wait_cv(&replay_done_mutex, &replay_done_cond, &n_replays_done,
451e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		  nfiles);
452e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
453e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
454e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void set_iter_done(void)
455e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
456e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__set_cv(&iter_done_mutex, &iter_done_cond, &n_iters_done,
457e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		nfiles);
458e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
459e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
460e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void wait_iters_done(void)
461e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
462e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__wait_cv(&iter_done_mutex, &iter_done_cond, &n_iters_done,
463e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		  nfiles);
464e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
465e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
466e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
467e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * wait_iter_start - Wait for an iteration to start
468e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
469e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * This is /slightly/ different: we are waiting for a value to become
470e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * non-zero, and then we decrement it and go on.
471e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
472e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void wait_iter_start(void)
473e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
474e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_lock(&iter_start_mutex);
475e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (iter_start == 0)
476e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		pthread_cond_wait(&iter_start_cond, &iter_start_mutex);
477e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(1 <= iter_start && iter_start <= nfiles);
478e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	iter_start--;
479e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_unlock(&iter_start_mutex);
480e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
481e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
482e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
483e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * start_iter - Start an iteration at the replay thread level
484e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
485e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void start_iter(void)
486e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
487e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_lock(&iter_start_mutex);
488e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(iter_start == 0);
489e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	iter_start = nfiles;
490e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_cond_broadcast(&iter_start_cond);
491e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_unlock(&iter_start_mutex);
492e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
493e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
494e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
495e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
496e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== CPU RELATED ROUTINES ==============================================
497e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
498e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
499e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
500e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
501e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * get_ncpus - Sets up the global 'ncpus' value
502e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
503e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void get_ncpus(void)
504e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
505e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	cpu_set_t cpus;
506e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
507e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (sched_getaffinity(getpid(), sizeof(cpus), &cpus)) {
508e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("sched_getaffinity", ERR_SYSCALL, "Can't get CPU info\n");
509e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
510e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
511e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
512e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	/*
513e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	 * XXX This assumes (perhaps wrongly) that there are no /holes/
514e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	 * XXX in the mask.
515e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	 */
516e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (ncpus = 0; ncpus < CPU_SETSIZE && CPU_ISSET(ncpus, &cpus); ncpus++)
517e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		;
518e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (ncpus == 0) {
519e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(NULL, ERR_SYSCALL, "Insufficient number of CPUs\n");
520e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
521e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
522e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
523e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
524e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
525e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * pin_to_cpu - Pin this thread to a specific CPU
526e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Thread information
527e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
528e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void pin_to_cpu(struct thr_info *tip)
529e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
530e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	cpu_set_t cpus;
531e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
532e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(0 <= tip->cpu && tip->cpu < ncpus);
533e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
534e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	CPU_ZERO(&cpus);
535e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	CPU_SET(tip->cpu, &cpus);
536e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (sched_setaffinity(getpid(), sizeof(cpus), &cpus)) {
537e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("sched_setaffinity", ERR_SYSCALL, "Failed to pin CPU\n");
538e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
539e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
540e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
541e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (verbose > 1) {
542e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		int i;
543e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		cpu_set_t now;
544e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
545e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		(void)sched_getaffinity(getpid(), sizeof(now), &now);
546e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fprintf(tip->vfp, "Pinned to CPU %02d ", tip->cpu);
547e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		for (i = 0; i < ncpus; i++)
548e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(tip->vfp, "%1d", CPU_ISSET(i, &now));
549e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fprintf(tip->vfp, "\n");
550e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
551e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
552e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
553e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
554e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
555e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== INPUT DEVICE HANDLERS =============================================
556e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
557e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
558e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
559e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
560e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * add_input_dev - Add a device ('sd*') to the list of devices to handle
561e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
562e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void add_input_dev(char *devnm)
563e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
564e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head *p;
565e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct dev_info *dip;
566e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
567e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__list_for_each(p, &input_devs) {
568e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		dip = list_entry(p, struct dev_info, head);
569e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (strcmp(dip->devnm, devnm) == 0)
570e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			return;
571e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
572e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
573e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	dip = malloc(sizeof(*dip));
574e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	dip->devnm = strdup(devnm);
575e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_add_tail(&dip->head, &input_devs);
576e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
577e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
578e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
579e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * rem_input_dev - Remove resources associated with this device
580e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
581e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void rem_input_dev(struct dev_info *dip)
582e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
583e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_del(&dip->head);
584e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	free(dip->devnm);
585e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	free(dip);
586e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
587e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
588e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void find_input_devs(char *idir)
589e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
590e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct dirent *ent;
591e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	DIR *dir = opendir(idir);
592e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
593e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (dir == NULL) {
594e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(idir, ERR_ARGS, "Unable to open %s\n", idir);
595e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
596e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
597e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
598e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while ((ent = readdir(dir)) != NULL) {
599e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		char *p, *dsf = malloc(256);
600e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
601e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (strstr(ent->d_name, ".replay.") == NULL)
602e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			continue;
603e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
604e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		dsf = strdup(ent->d_name);
605e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		p = index(dsf, '.');
606e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		assert(p != NULL);
607e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		*p = '\0';
608e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		add_input_dev(dsf);
609e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		free(dsf);
610e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
611e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
612e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	closedir(dir);
613e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
614e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
615e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
616e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
617e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== MAP DEVICE INTERFACES =============================================
618e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
619e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
620e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
621e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
622e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * read_map_devs - Read in a set of device mapping from the provided file.
623e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @file_name:	File containing device maps
624e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
625e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * We support the notion of multiple such files being specifed on the cmd line
626e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
627e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void read_map_devs(char *file_name)
628e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
629e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	FILE *fp;
630e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	char *from_dev, *to_dev;
631e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
632e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	fp = fopen(file_name, "r");
633e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (!fp) {
634e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(file_name, ERR_SYSCALL, "Could not open map devs file\n");
635e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
636e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
637e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
638e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (fscanf(fp, "%as %as", &from_dev, &to_dev) == 2) {
639e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct map_dev *mdp = malloc(sizeof(*mdp));
640e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
641e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		mdp->from_dev = from_dev;
642e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		mdp->to_dev = to_dev;
643e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		list_add_tail(&mdp->head, &map_devs);
644e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
645e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
646e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	fclose(fp);
647e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
648e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
649e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
650e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * release_map_devs - Release resources associated with device mappings.
651e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
652e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void release_map_devs(void)
653e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
654e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head *p, *q;
655e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
656e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_for_each_safe(p, q, &map_devs) {
657e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct map_dev *mdp = list_entry(p, struct map_dev, head);
658e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
659e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		list_del(&mdp->head);
660e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
661e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		free(mdp->from_dev);
662e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		free(mdp->to_dev);
663e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		free(mdp);
664e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
665e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
666e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
667e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
668e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * map_dev - Return the mapped device for that specified
669e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @from_dev:	Device name as seen on recorded system
670e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
671e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Note: If there is no such mapping, we return the same name.
672e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
673e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char *map_dev(char *from_dev)
674e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
675e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head *p;
676e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
677e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__list_for_each(p, &map_devs) {
678e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct map_dev *mdp = list_entry(p, struct map_dev, head);
679e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
680e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (strcmp(from_dev, mdp->from_dev) == 0)
681e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			return mdp->to_dev;
682e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
683e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
684e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return from_dev;
685e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
686e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
687e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
688e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
689e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== IOCB MANAGEMENT ROUTINES ==========================================
690e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
691e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
692e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
693e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
694e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * iocb_init - Initialize the fields of an IOCB
695e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-thread information
696e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * iocbp: IOCB pointer to update
697e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
698e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void iocb_init(struct thr_info *tip, struct iocb_pkt *iocbp)
699e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
700e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	iocbp->tip = tip;
701e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	iocbp->nbytes = 0;
702e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	iocbp->iocb.u.c.buf = NULL;
703e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
704e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
705e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
706e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * iocb_setup - Set up an iocb with this AIOs information
707e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @iocbp: IOCB pointer to update
708e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @rw: Direction (0 == write, 1 == read)
709e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @n: Number of bytes to transfer
710e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @off: Offset (in bytes)
711e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
712e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void iocb_setup(struct iocb_pkt *iocbp, int rw, int n, long long off)
713e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
714e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	char *buf;
715e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct iocb *iop = &iocbp->iocb;
716e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
717e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(rw == 0 || rw == 1);
718e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(0 < n && (n % nb_sec) == 0);
719e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(0 <= off);
720e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
721e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (iocbp->nbytes) {
722e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (iocbp->nbytes >= n) {
723e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			buf = iop->u.c.buf;
724e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			goto prep;
725e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
726e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
727e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		assert(iop->u.c.buf);
728e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		free(iop->u.c.buf);
729e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
730e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
731e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	buf = buf_alloc(n);
732e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	iocbp->nbytes = n;
733e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
734e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatprep:
735e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (rw)
736e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		io_prep_pread(iop, iocbp->tip->ofd, buf, n, off);
737e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	else {
738e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		assert(write_enabled);
739e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		io_prep_pwrite(iop, iocbp->tip->ofd, buf, n, off);
740e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		touch_memory(buf, n);
741e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
742e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
743e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	iop->data = iocbp;
744e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
745e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
746e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
747e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
748e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== PER-THREAD SET UP & TEAR DOWN =====================================
749e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
750e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
751e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
752e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
753e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * tip_init - Per thread initialization function
754e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
755e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void tip_init(struct thr_info *tip)
756e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
757e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int i;
758e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
759e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	INIT_LIST_HEAD(&tip->free_iocbs);
760e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	INIT_LIST_HEAD(&tip->used_iocbs);
761e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
762e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_init(&tip->mutex, NULL);
763e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_cond_init(&tip->cond, NULL);
764e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
765e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (io_setup(naios, &tip->ctx)) {
766e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("io_setup", ERR_SYSCALL, "io_setup failed\n");
767e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
768e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
769e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
770e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->ofd = -1;
771e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->naios_out = 0;
772e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->send_done = tip->reap_done = 0;
773e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->send_wait = tip->reap_wait = 0;
774e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
775e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	memset(&tip->sub_thread, 0, sizeof(tip->sub_thread));
776e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	memset(&tip->rec_thread, 0, sizeof(tip->rec_thread));
777e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
778e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (i = 0; i < naios; i++) {
779e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct iocb_pkt *iocbp = buf_alloc(sizeof(*iocbp));
780e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
781e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		iocb_init(tip, iocbp);
782e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		list_add_tail(&iocbp->head, &tip->free_iocbs);
783e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
784e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->naios_free = naios;
785e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
786e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (verbose > 1) {
787e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		char fn[MAXPATHLEN];
788e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
789e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		sprintf(fn, "%s/%s.%s.%d.rep", idir, tip->devnm, ibase,
790e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			tip->cpu);
791e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		tip->vfp = fopen(fn, "w");
792e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (!tip->vfp) {
793e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fatal(fn, ERR_SYSCALL, "Failed to open report\n");
794e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			/*NOTREACHED*/
795e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
796e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
797e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		setlinebuf(tip->vfp);
798e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
799e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
800e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (pthread_create(&tip->sub_thread, NULL, replay_sub, tip)) {
801e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("pthread_create", ERR_SYSCALL,
802e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			"thread create failed\n");
803e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
804e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
805e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
806e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (pthread_create(&tip->rec_thread, NULL, replay_rec, tip)) {
807e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("pthread_create", ERR_SYSCALL,
808e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			"thread create failed\n");
809e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
810e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
811e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
812e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
813e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
814e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * tip_release - Release resources associated with this thread
815e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
816e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void tip_release(struct thr_info *tip)
817e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
818e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head *p, *q;
819e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
820e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(tip->send_done);
821e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(tip->reap_done);
822e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(list_len(&tip->used_iocbs) == 0);
823e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(tip->naios_free == naios);
824e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
825e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (pthread_join(tip->sub_thread, NULL)) {
826e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("pthread_join", ERR_SYSCALL, "pthread sub join failed\n");
827e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
828e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
829e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (pthread_join(tip->rec_thread, NULL)) {
830e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal("pthread_join", ERR_SYSCALL, "pthread rec join failed\n");
831e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
832e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
833e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
834e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	io_destroy(tip->ctx);
835e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
836e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_splice(&tip->used_iocbs, &tip->free_iocbs);
837e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_for_each_safe(p, q, &tip->free_iocbs) {
838e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct iocb_pkt *iocbp = list_entry(p, struct iocb_pkt, head);
839e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
840e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		list_del(&iocbp->head);
841e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (iocbp->nbytes)
842e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			free(iocbp->iocb.u.c.buf);
843e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		free(iocbp);
844e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
845e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
846e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_cond_destroy(&tip->cond);
847e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_destroy(&tip->mutex);
848e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
849e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
850e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
851e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * add_input_file - Allocate and initialize per-input file structure
852e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @cpu: CPU for this file
853e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @devnm: Device name for this file
854e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @file_name: Fully qualifed input file name
855e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
856e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void add_input_file(int cpu, char *devnm, char *file_name)
857e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
858e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct stat buf;
859e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct io_file_hdr hdr;
860e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct thr_info *tip = buf_alloc(sizeof(*tip));
861e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__u64 my_version = mk_btversion(btver_mjr, btver_mnr, btver_sub);
862e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
863e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(0 <= cpu && cpu < ncpus);
864e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
865e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	memset(&hdr, 0, sizeof(hdr));
866e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	memset(tip, 0, sizeof(*tip));
867e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->cpu = cpu % cpus_to_use;
868e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->iterations = def_iterations;
869e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
870e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->ifd = open(file_name, O_RDONLY);
871e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (tip->ifd < 0) {
872e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(file_name, ERR_ARGS, "Unable to open\n");
873e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
874e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
875e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (fstat(tip->ifd, &buf) < 0) {
876e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(file_name, ERR_SYSCALL, "fstat failed\n");
877e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
878e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
879e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (buf.st_size < (off_t)sizeof(hdr)) {
880e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (verbose)
881e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(stderr, "\t%s empty\n", file_name);
882e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		goto empty_file;
883e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
884e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
885e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (read(tip->ifd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
886e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(file_name, ERR_ARGS, "Header read failed\n");
887e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
888e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
889e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
890e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (hdr.version != my_version) {
891e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fprintf(stderr, "%llx %llx %llx %llx\n",
892e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long long unsigned)hdr.version,
893e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long long unsigned)hdr.genesis,
894e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long long unsigned)hdr.nbunches,
895e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long long unsigned)hdr.total_pkts);
896e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(NULL, ERR_ARGS,
897e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			"BT version mismatch: %lx versus my %lx\n",
898e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long)hdr.version, (long)my_version);
899e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
900e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
901e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
902e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (hdr.nbunches == 0) {
903e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatempty_file:
904e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		close(tip->ifd);
905e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		free(tip);
906e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		return;
907e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
908e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
909e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (hdr.genesis < genesis) {
910e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (verbose > 1)
911e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(stderr, "Setting genesis to %llu.%llu\n",
912e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				du64_to_sec(hdr.genesis),
913e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				du64_to_nsec(hdr.genesis));
914e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		genesis = hdr.genesis;
915e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
916e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
917e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->devnm = strdup(devnm);
918e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->file_name = strdup(file_name);
919e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
920e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_add_tail(&tip->head, &input_files);
921e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
922e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (verbose)
923e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fprintf(stderr, "Added %s %llu\n", file_name,
924e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long long)hdr.genesis);
925e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
926e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
927e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
928e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * rem_input_file - Release resources associated with an input file
929e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-input file information
930e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
931e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void rem_input_file(struct thr_info *tip)
932e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
933e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_del(&tip->head);
934e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
935e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip_release(tip);
936e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
937e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	close(tip->ofd);
938e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	close(tip->ifd);
939e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	free(tip->file_name);
940e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	free(tip->devnm);
941e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	free(tip);
942e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
943e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
944e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
945e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * rem_input_files - Remove all input files
946e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
947e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void rem_input_files(void)
948e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
949e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head *p, *q;
950e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
951e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_for_each_safe(p, q, &input_files) {
952e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		rem_input_file(list_entry(p, struct thr_info, head));
953e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
954e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
955e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
956e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
957e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * __find_input_files - Find input files associated with this device (per cpu)
958e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
959e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void __find_input_files(struct dev_info *dip)
960e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
961e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int cpu = 0;
962e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
963e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (;;) {
964e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		char full_name[MAXPATHLEN];
965e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
966e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		sprintf(full_name, "%s/%s.%s.%d", idir, dip->devnm, ibase, cpu);
967e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (access(full_name, R_OK) != 0)
968e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
969e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
970e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		add_input_file(cpu, dip->devnm, full_name);
971e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		cpu++;
972e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
973e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
974e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (!cpu) {
975e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(NULL, ERR_ARGS, "No traces found for %s\n", dip->devnm);
976e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
977e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
978e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
979e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	rem_input_dev(dip);
980e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
981e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
982e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
983e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
984e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * find_input_files - Find input files for all devices
985e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
986e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void find_input_files(void)
987e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
988e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head *p, *q;
989e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
990e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	list_for_each_safe(p, q, &input_devs) {
991e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		__find_input_files(list_entry(p, struct dev_info, head));
992e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
993e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
994e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
995e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
996e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
997e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== RECLAIM ROUTINES ==================================================
998e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
999e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1000e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1001e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1002e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * reap_wait_aios - Wait for and return number of outstanding AIOs
1003e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
1004e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Will return 0 if we are done
1005e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1006e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int reap_wait_aios(struct thr_info *tip)
1007e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1008e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int naios = 0;
1009e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1010e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (!is_reap_done(tip)) {
1011e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		pthread_mutex_lock(&tip->mutex);
1012e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		while (tip->naios_out == 0) {
1013e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			tip->reap_wait = 1;
1014e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (pthread_cond_wait(&tip->cond, &tip->mutex)) {
1015e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fatal("pthread_cond_wait", ERR_SYSCALL,
1016e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					"nfree_current cond wait failed\n");
1017e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				/*NOTREACHED*/
1018e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			}
1019e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
1020e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		naios = tip->naios_out;
1021e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		pthread_mutex_unlock(&tip->mutex);
1022e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1023e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(is_reap_done(tip) || naios > 0);
1024e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1025e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return is_reap_done(tip) ? 0 : naios;
1026e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1027e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1028e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1029e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * reclaim_ios - Reclaim AIOs completed, recycle IOCBs
1030e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-thread information
1031e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @naios_out: Number of AIOs we have outstanding (min)
1032e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1033e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void reclaim_ios(struct thr_info *tip, long naios_out)
1034e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1035e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	long i, ndone;
1036e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct io_event *evp, events[naios_out];
1037e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1038e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatagain:
1039e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(naios > 0);
1040e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (;;) {
1041e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		ndone = io_getevents(tip->ctx, 1, naios_out, events, NULL);
1042e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (ndone > 0)
1043e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1044e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1045e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (errno && errno != EINTR) {
1046e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fatal("io_getevents", ERR_SYSCALL,
1047e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				"io_getevents failed\n");
1048e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			/*NOTREACHED*/
1049e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
1050e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1051e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(0 < ndone && ndone <= naios_out);
1052e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1053e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_lock(&tip->mutex);
1054e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (i = 0, evp = events; i < ndone; i++, evp++) {
1055e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct iocb_pkt *iocbp = evp->data;
1056e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1057e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                if (evp->res != iocbp->iocb.u.c.nbytes) {
1058e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                        fatal(NULL, ERR_SYSCALL,
1059e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                              "Event failure %ld/%ld\t(%ld + %ld)\n",
1060e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                              (long)evp->res, (long)evp->res2,
1061e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                              (long)iocbp->iocb.u.c.offset / nb_sec,
1062e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			      (long)iocbp->iocb.u.c.nbytes / nb_sec);
1063e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                        /*NOTREACHED*/
1064e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat                }
1065e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1066e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		list_move_tail(&iocbp->head, &tip->free_iocbs);
1067e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1068e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1069e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->naios_free += ndone;
1070e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->naios_out -= ndone;
1071e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	naios_out = minl(naios_out, tip->naios_out);
1072e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1073e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (tip->send_wait) {
1074e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		tip->send_wait = 0;
1075e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		pthread_cond_signal(&tip->cond);
1076e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1077e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_unlock(&tip->mutex);
1078e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1079e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	/*
1080e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	 * Short cut: If we /know/ there are some more AIOs, go handle them
1081e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	 */
1082e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (naios_out)
1083e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		goto again;
1084e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1085e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1086e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1087e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * replay_rec - Worker thread to reclaim AIOs
1088e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @arg: Pointer to thread information
1089e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1090e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void *replay_rec(void *arg)
1091e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1092e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	long naios_out;
1093e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct thr_info *tip = arg;
1094e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1095e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while ((naios_out = reap_wait_aios(tip)) > 0)
1096e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		reclaim_ios(tip, naios_out);
1097e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1098e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(tip->send_done);
1099e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->reap_done = 1;
1100e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	set_reclaim_done();
1101e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1102e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return NULL;
1103e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1104e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1105e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
1106e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
1107e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== REPLAY ROUTINES ===================================================
1108e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
1109e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1110e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1111e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1112e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * next_bunch - Retrieve next bunch of AIOs to process
1113e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-thread information
1114e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @bunch: Bunch information
1115e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
1116e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Returns TRUE if we recovered a bunch of IOs, else hit EOF
1117e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1118e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int next_bunch(struct thr_info *tip, struct io_bunch *bunch)
1119e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1120e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	size_t count, result;
1121e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1122e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	result = read(tip->ifd, &bunch->hdr, sizeof(bunch->hdr));
1123e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (result != sizeof(bunch->hdr)) {
1124e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (result == 0)
1125e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			return 0;
1126e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1127e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(tip->file_name, ERR_SYSCALL, "Short hdr(%ld)\n",
1128e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long)result);
1129e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
1130e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1131e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(bunch->hdr.npkts <= BT_MAX_PKTS);
1132e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1133e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	count = bunch->hdr.npkts * sizeof(struct io_pkt);
1134e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	result = read(tip->ifd, &bunch->pkts, count);
1135e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (result != count) {
1136e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(tip->file_name, ERR_SYSCALL, "Short pkts(%ld/%ld)\n",
1137e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			(long)result, (long)count);
1138e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
1139e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1140e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1141e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return 1;
1142e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1143e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1144e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1145e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * nfree_current - Returns current number of AIOs that are free
1146e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
1147e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Will wait for available ones...
1148e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
1149e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Returns 0 if we have some condition that causes us to exit
1150e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1151e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int nfree_current(struct thr_info *tip)
1152e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1153e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int nfree = 0;
1154e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1155e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_lock(&tip->mutex);
1156e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (!is_send_done(tip) && ((nfree = tip->naios_free) == 0)) {
1157e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		tip->send_wait = 1;
1158e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (pthread_cond_wait(&tip->cond, &tip->mutex)) {
1159e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fatal("pthread_cond_wait", ERR_SYSCALL,
1160e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				"nfree_current cond wait failed\n");
1161e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			/*NOTREACHED*/
1162e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
1163e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1164e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_unlock(&tip->mutex);
1165e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1166e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return nfree;
1167e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1168e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1169e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1170e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * stall - Stall for the number of nanoseconds requested
1171e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
1172e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * We may be late, in which case we just return.
1173e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1174e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void stall(struct thr_info *tip, long long oclock)
1175e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1176e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct timespec req;
1177e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	long long dreal, tclock = gettime() - rgenesis;
1178e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1179e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	oclock /= acc_factor;
1180e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1181e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (verbose > 1)
1182e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fprintf(tip->vfp, "   stall(%lld.%09lld, %lld.%09lld)\n",
1183e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			du64_to_sec(oclock), du64_to_nsec(oclock),
1184e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			du64_to_sec(tclock), du64_to_nsec(tclock));
1185e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1186e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (!is_send_done(tip) && tclock < oclock) {
1187e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		dreal = oclock - tclock;
1188e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		req.tv_sec = dreal / (1000 * 1000 * 1000);
1189e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		req.tv_nsec = dreal % (1000 * 1000 * 1000);
1190e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1191e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (verbose > 1) {
1192e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(tip->vfp, "++ stall(%lld.%09lld) ++\n",
1193e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				(long long)req.tv_sec,
1194e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				(long long)req.tv_nsec);
1195e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
1196e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1197e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (nanosleep(&req, NULL) < 0 && signal_done)
1198e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1199e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1200e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		tclock = gettime() - rgenesis;
1201e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1202e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1203e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1204e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1205e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * iocbs_map - Map a set of AIOs onto a set of IOCBs
1206e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-thread information
1207e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @list: List of AIOs created
1208e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @pkts: AIOs to map
1209e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @ntodo: Number of AIOs to map
1210e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1211e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void iocbs_map(struct thr_info *tip, struct iocb **list,
1212e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					     struct io_pkt *pkts, int ntodo)
1213e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1214e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int i;
1215e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct io_pkt *pkt;
1216e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1217e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(0 < ntodo && ntodo <= naios);
1218e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1219e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_lock(&tip->mutex);
1220e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(ntodo <= list_len(&tip->free_iocbs));
1221e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (i = 0, pkt = pkts; i < ntodo; i++, pkt++) {
1222e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		__u32 rw = pkt->rw;
1223e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		struct iocb_pkt *iocbp;
1224e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1225e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (!pkt->rw && !write_enabled)
1226e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			rw = 1;
1227e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1228e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (verbose > 1)
1229e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(tip->vfp, "\t%10llu + %10llu %c%c\n",
1230e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				(unsigned long long)pkt->sector,
1231e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				(unsigned long long)pkt->nbytes / nb_sec,
1232e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				rw ? 'R' : 'W',
1233e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				(rw == 1 && pkt->rw == 0) ? '!' : ' ');
1234e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1235e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		iocbp = list_entry(tip->free_iocbs.next, struct iocb_pkt, head);
1236e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		iocb_setup(iocbp, rw, pkt->nbytes, pkt->sector * nb_sec);
1237e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1238e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		list_move_tail(&iocbp->head, &tip->used_iocbs);
1239e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		list[i] = &iocbp->iocb;
1240e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1241e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1242e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->naios_free -= ntodo;
1243e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(tip->naios_free >= 0);
1244e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pthread_mutex_unlock(&tip->mutex);
1245e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1246e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1247e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1248e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * process_bunch - Process a bunch of requests
1249e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Per-thread information
1250e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @bunch: Bunch to process
1251e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1252e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void process_bunch(struct thr_info *tip, struct io_bunch *bunch)
1253e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1254e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__u64 i = 0;
1255e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct iocb *list[bunch->hdr.npkts];
1256e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1257e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(0 < bunch->hdr.npkts && bunch->hdr.npkts <= BT_MAX_PKTS);
1258e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (!is_send_done(tip) && (i < bunch->hdr.npkts)) {
1259e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		long ndone;
1260e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		int ntodo = min(nfree_current(tip), bunch->hdr.npkts - i);
1261e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1262e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		assert(0 < ntodo && ntodo <= naios);
1263e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		iocbs_map(tip, list, &bunch->pkts[i], ntodo);
1264e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (!no_stalls)
1265e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			stall(tip, bunch->hdr.time_stamp - genesis);
1266e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1267e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (ntodo) {
1268e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (verbose > 1)
1269e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fprintf(tip->vfp, "submit(%d)\n", ntodo);
1270e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			ndone = io_submit(tip->ctx, ntodo, list);
1271e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (ndone != (long)ntodo) {
1272e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fatal("io_submit", ERR_SYSCALL,
1273e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					"%d: io_submit(%d:%ld) failed (%s)\n",
1274e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					tip->cpu, ntodo, ndone,
1275e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					strerror(labs(ndone)));
1276e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				/*NOTREACHED*/
1277e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			}
1278e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1279e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			pthread_mutex_lock(&tip->mutex);
1280e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			tip->naios_out += ndone;
1281e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			assert(tip->naios_out <= naios);
1282e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (tip->reap_wait) {
1283e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				tip->reap_wait = 0;
1284e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				pthread_cond_signal(&tip->cond);
1285e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			}
1286e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			pthread_mutex_unlock(&tip->mutex);
1287e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1288e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			i += ndone;
1289e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			assert(i <= bunch->hdr.npkts);
1290e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
1291e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1292e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1293e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1294e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1295e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * reset_input_file - Reset the input file for the next iteration
1296e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @tip: Thread information
1297e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
1298e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * We also do a dummy read of the file header to get us to the first bunch.
1299e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1300e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void reset_input_file(struct thr_info *tip)
1301e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1302e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct io_file_hdr hdr;
1303e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1304e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	lseek(tip->ifd, 0, 0);
1305e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1306e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (read(tip->ifd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
1307e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(tip->file_name, ERR_ARGS, "Header reread failed\n");
1308e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
1309e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1310e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1311e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1312e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1313e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * replay_sub - Worker thread to submit AIOs that are being replayed
1314e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1315e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void *replay_sub(void *arg)
1316e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1317e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	char path[MAXPATHLEN];
1318e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct io_bunch bunch;
1319e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct thr_info *tip = arg;
1320e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int oflags;
1321e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1322e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pin_to_cpu(tip);
1323e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1324e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	sprintf(path, "/dev/%s", map_dev(tip->devnm));
1325e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1326e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#ifdef O_NOATIME
1327e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	oflags = O_NOATIME;
1328e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#else
1329e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	oflags = 0;
1330e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#endif
1331e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->ofd = open(path, O_RDWR | O_DIRECT | oflags);
1332e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (tip->ofd < 0) {
1333e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(path, ERR_SYSCALL, "Failed device open\n");
1334e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
1335e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1336e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1337e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	set_replay_ready();
1338e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (!is_send_done(tip) && tip->iterations--) {
1339e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		wait_iter_start();
1340e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (verbose > 1)
1341e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(tip->vfp, "\n=== %d ===\n", tip->iterations);
1342e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		while (!is_send_done(tip) && next_bunch(tip, &bunch))
1343e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			process_bunch(tip, &bunch);
1344e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		set_iter_done();
1345e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		reset_input_file(tip);
1346e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1347e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	tip->send_done = 1;
1348e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	set_replay_done();
1349e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1350e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return NULL;
1351e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1352e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1353e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
1354e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
1355e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== COMMAND LINE ARGUMENT HANDLING ====================================
1356e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
1357e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1358e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1359e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char usage_str[] = 						\
1360e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\n"								\
1361e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -c <cpus> : --cpus=<cpus>           ] Default: 1\n"        \
1362e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -d <dir>  : --input-directory=<dir> ] Default: .\n"        \
1363e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	"\t[ -F        : --find-records          ] Default: Off\n"	\
1364e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -h        : --help                  ] Default: Off\n"      \
1365e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -i <base> : --input-base=<base>     ] Default: replay\n"   \
1366e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -I <iters>: --iterations=<iters>    ] Default: 1\n"        \
1367e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -M <file> : --map-devs=<file>       ] Default: None\n"     \
1368e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -N        : --no-stalls             ] Default: Off\n"      \
1369e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -x        : --acc-factor            ] Default: 1\n"	\
1370e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -v        : --verbose               ] Default: Off\n"      \
1371e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -V        : --version               ] Default: Off\n"      \
1372e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t[ -W        : --write-enable          ] Default: Off\n"      \
1373e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\t<dev...>                                Default: None\n"     \
1374e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat        "\n";
1375e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1376e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define S_OPTS	"c:d:Fhi:I:M:Nx:t:vVW"
1377e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct option l_opts[] = {
1378e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1379e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "cpus",
1380e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = required_argument,
1381e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1382e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'c'
1383e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1384e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1385e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "input-directory",
1386e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = required_argument,
1387e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1388e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'd'
1389e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1390e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1391e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "find-records",
1392e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = no_argument,
1393e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1394e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'F'
1395e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1396e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1397e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "help",
1398e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = no_argument,
1399e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1400e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'h'
1401e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1402e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1403e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "input-base",
1404e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = required_argument,
1405e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1406e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'i'
1407e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1408e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1409e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "iterations",
1410e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = required_argument,
1411e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1412e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'I'
1413e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1414e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1415e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "map-devs",
1416e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = required_argument,
1417e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1418e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'M'
1419e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1420e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1421e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "no-stalls",
1422e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = no_argument,
1423e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1424e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'N'
1425e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1426e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1427e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "acc-factor",
1428e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = required_argument,
1429e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1430e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'x'
1431e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1432e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1433e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "verbose",
1434e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = no_argument,
1435e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1436e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'v'
1437e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1438e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1439e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "version",
1440e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = no_argument,
1441e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1442e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'V'
1443e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1444e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1445e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = "write-enable",
1446e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.has_arg = no_argument,
1447e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.flag = NULL,
1448e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.val = 'W'
1449e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	},
1450e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	{
1451e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		.name = NULL
1452e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1453e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat};
1454e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1455e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1456e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * handle_args: Parse passed in argument list
1457e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argc: Number of arguments in argv
1458e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argv: Arguments passed in
1459e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat *
1460e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Does rudimentary parameter verification as well.
1461e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1462e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void handle_args(int argc, char *argv[])
1463e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1464e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int c;
1465e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int r;
1466e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1467e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) != -1) {
1468e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		switch (c) {
1469e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'c':
1470e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			cpus_to_use = atoi(optarg);
1471e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (cpus_to_use <= 0 || cpus_to_use > ncpus) {
1472e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fatal(NULL, ERR_ARGS,
1473e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				      "Invalid number of cpus %d (0<x<%d)\n",
1474e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				      cpus_to_use, ncpus);
1475e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				/*NOTREACHED*/
1476e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			}
1477e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1478e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1479e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'd':
1480e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			idir = optarg;
1481e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (access(idir, R_OK | X_OK) != 0) {
1482e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fatal(idir, ERR_ARGS,
1483e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				      "Invalid input directory specified\n");
1484e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				/*NOTREACHED*/
1485e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			}
1486e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1487e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1488e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'F':
1489e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			find_records = 1;
1490e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1491e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1492e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'h':
1493e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			usage();
1494e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			exit(0);
1495e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			/*NOTREACHED*/
1496e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1497e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'i':
1498e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			ibase = optarg;
1499e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1500e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1501e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'I':
1502e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			def_iterations = atoi(optarg);
1503e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (def_iterations <= 0) {
1504e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fprintf(stderr,
1505e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					"Invalid number of iterations %d\n",
1506e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					def_iterations);
1507e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				exit(ERR_ARGS);
1508e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				/*NOTREACHED*/
1509e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			}
1510e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1511e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1512e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'M':
1513e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			read_map_devs(optarg);
1514e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1515e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1516e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'N':
1517e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			no_stalls = 1;
1518e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1519e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1520e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'x':
1521e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			r = sscanf(optarg,"%u",&acc_factor);
1522e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			if (r!=1) {
1523e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				fprintf(stderr,
1524e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat					"Invalid acceleration factor\n");
1525e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				exit(ERR_ARGS);
1526e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				/*NOTREACHED*/
1527e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			}
1528e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1529e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1530e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'V':
1531e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(stderr, "btreplay -- version %s\n",
1532e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				my_btversion);
1533e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(stderr, "            Built on %s\n",
1534e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat				build_date);
1535e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			exit(0);
1536e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			/*NOTREACHED*/
1537e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1538e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'v':
1539e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			verbose++;
1540e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1541e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1542e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		case 'W':
1543e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			write_enabled = 1;
1544e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			break;
1545e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1546e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		default:
1547e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			usage();
1548e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fatal(NULL, ERR_ARGS,
1549e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			      "Invalid command line argument %c\n", c);
1550e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			/*NOTREACHED*/
1551e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		}
1552e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1553e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1554e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	while (optind < argc)
1555e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		add_input_dev(argv[optind++]);
1556e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1557e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (find_records)
1558e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		find_input_devs(idir);
1559e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1560e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (list_len(&input_devs) == 0) {
1561e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fatal(NULL, ERR_ARGS, "Missing required input dev name(s)\n");
1562e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		/*NOTREACHED*/
1563e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1564e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1565e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (cpus_to_use < 0)
1566e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		cpus_to_use = ncpus;
1567e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1568e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1569e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/*
1570e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
1571e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ==== MAIN ROUTINE ======================================================
1572e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * ========================================================================
1573e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1574e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1575e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1576e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * set_signal_done - Signal handler, catches signals & sets signal_done
1577e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1578e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void set_signal_done(__attribute__((__unused__))int signum)
1579e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1580e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	signal_done = 1;
1581e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1582e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1583e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/**
1584e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * main -
1585e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argc: Number of arguments
1586e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * @argv: Array of arguments
1587e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */
1588e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatint main(int argc, char *argv[])
1589e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{
1590e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	int i;
1591e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	struct list_head *p;
1592e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1593e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	pgsize = getpagesize();
1594e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	assert(pgsize > 0);
1595e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1596e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	setup_signal(SIGINT, set_signal_done);
1597e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	setup_signal(SIGTERM, set_signal_done);
1598e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1599e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	get_ncpus();
1600e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	handle_args(argc, argv);
1601e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	find_input_files();
1602e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1603e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	nfiles = list_len(&input_files);
1604e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	__list_for_each(p, &input_files) {
1605e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		tip_init(list_entry(p, struct thr_info, head));
1606e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1607e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1608e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	wait_replays_ready();
1609e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	for (i = 0; i < def_iterations; i++) {
1610e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		rgenesis = gettime();
1611e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		start_iter();
1612e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		if (verbose)
1613e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat			fprintf(stderr, "I");
1614e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		wait_iters_done();
1615e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	}
1616e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1617e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	wait_replays_done();
1618e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	wait_reclaims_done();
1619e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1620e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	if (verbose)
1621e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat		fprintf(stderr, "\n");
1622e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1623e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	rem_input_files();
1624e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	release_map_devs();
1625e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat
1626e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat	return 0;
1627e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}
1628