1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
18*288bf522SAndroid Build Coastguard Worker #include <sys/time.h>
19*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
20*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
21*288bf522SAndroid Build Coastguard Worker #include <sys/syscall.h>
22*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
23*288bf522SAndroid Build Coastguard Worker #include <string.h>
24*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
25*288bf522SAndroid Build Coastguard Worker #include <errno.h>
26*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
27*288bf522SAndroid Build Coastguard Worker #include <string.h>
28*288bf522SAndroid Build Coastguard Worker #include <assert.h>
29*288bf522SAndroid Build Coastguard Worker #include <pthread.h>
30*288bf522SAndroid Build Coastguard Worker #include <sys/statfs.h>
31*288bf522SAndroid Build Coastguard Worker #include <sys/resource.h>
32*288bf522SAndroid Build Coastguard Worker #include <inttypes.h>
33*288bf522SAndroid Build Coastguard Worker #include "ioshark.h"
34*288bf522SAndroid Build Coastguard Worker #define IOSHARK_MAIN
35*288bf522SAndroid Build Coastguard Worker #include "ioshark_bench.h"
36*288bf522SAndroid Build Coastguard Worker
37*288bf522SAndroid Build Coastguard Worker /*
38*288bf522SAndroid Build Coastguard Worker * Note on "quick" mode where we do reads on existing /system,
39*288bf522SAndroid Build Coastguard Worker * /vendor and other files in ro partitions, instead of creating
40*288bf522SAndroid Build Coastguard Worker * them. The ioshark compiler builds up a table of all the files
41*288bf522SAndroid Build Coastguard Worker * in /system, /vendor and other ro partitions. For files in this
42*288bf522SAndroid Build Coastguard Worker * list, the benchmark skips the pre-creation of these files and
43*288bf522SAndroid Build Coastguard Worker * reads them directly.
44*288bf522SAndroid Build Coastguard Worker * The code relevant to this is in *filename_cache*.
45*288bf522SAndroid Build Coastguard Worker */
46*288bf522SAndroid Build Coastguard Worker
47*288bf522SAndroid Build Coastguard Worker char *progname;
48*288bf522SAndroid Build Coastguard Worker
49*288bf522SAndroid Build Coastguard Worker #define MAX_INPUT_FILES 8192
50*288bf522SAndroid Build Coastguard Worker #define MAX_THREADS 8192
51*288bf522SAndroid Build Coastguard Worker
52*288bf522SAndroid Build Coastguard Worker struct thread_state_s {
53*288bf522SAndroid Build Coastguard Worker char *filename;
54*288bf522SAndroid Build Coastguard Worker FILE *fp;
55*288bf522SAndroid Build Coastguard Worker int num_files;
56*288bf522SAndroid Build Coastguard Worker void *db_handle;
57*288bf522SAndroid Build Coastguard Worker };
58*288bf522SAndroid Build Coastguard Worker
59*288bf522SAndroid Build Coastguard Worker struct thread_state_s thread_state[MAX_INPUT_FILES];
60*288bf522SAndroid Build Coastguard Worker int num_input_files = 0;
61*288bf522SAndroid Build Coastguard Worker int next_input_file;
62*288bf522SAndroid Build Coastguard Worker
63*288bf522SAndroid Build Coastguard Worker pthread_t tid[MAX_THREADS];
64*288bf522SAndroid Build Coastguard Worker
65*288bf522SAndroid Build Coastguard Worker /*
66*288bf522SAndroid Build Coastguard Worker * Global options
67*288bf522SAndroid Build Coastguard Worker */
68*288bf522SAndroid Build Coastguard Worker int do_delay = 0;
69*288bf522SAndroid Build Coastguard Worker int verbose = 0;
70*288bf522SAndroid Build Coastguard Worker int summary_mode = 0;
71*288bf522SAndroid Build Coastguard Worker int quick_mode = 0;
72*288bf522SAndroid Build Coastguard Worker char *blockdev_name = NULL; /* if user would like to specify blockdev */
73*288bf522SAndroid Build Coastguard Worker
74*288bf522SAndroid Build Coastguard Worker #if 0
75*288bf522SAndroid Build Coastguard Worker static long gettid()
76*288bf522SAndroid Build Coastguard Worker {
77*288bf522SAndroid Build Coastguard Worker return syscall(__NR_gettid);
78*288bf522SAndroid Build Coastguard Worker }
79*288bf522SAndroid Build Coastguard Worker #endif
80*288bf522SAndroid Build Coastguard Worker
usage()81*288bf522SAndroid Build Coastguard Worker void usage()
82*288bf522SAndroid Build Coastguard Worker {
83*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s [-b blockdev_name] [-d preserve_delays] [-n num_iterations] [-t num_threads] -q -v | -s <list of parsed input files>\n",
84*288bf522SAndroid Build Coastguard Worker progname);
85*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s -s, -v are mutually exclusive\n",
86*288bf522SAndroid Build Coastguard Worker progname);
87*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
88*288bf522SAndroid Build Coastguard Worker }
89*288bf522SAndroid Build Coastguard Worker
90*288bf522SAndroid Build Coastguard Worker pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER;
91*288bf522SAndroid Build Coastguard Worker pthread_mutex_t stats_mutex = PTHREAD_MUTEX_INITIALIZER;
92*288bf522SAndroid Build Coastguard Worker pthread_mutex_t work_mutex = PTHREAD_MUTEX_INITIALIZER;
93*288bf522SAndroid Build Coastguard Worker struct timeval aggregate_file_create_time;
94*288bf522SAndroid Build Coastguard Worker struct timeval debug_file_create_time;
95*288bf522SAndroid Build Coastguard Worker struct timeval aggregate_file_remove_time;
96*288bf522SAndroid Build Coastguard Worker struct timeval aggregate_IO_time;
97*288bf522SAndroid Build Coastguard Worker struct timeval aggregate_delay_time;
98*288bf522SAndroid Build Coastguard Worker
99*288bf522SAndroid Build Coastguard Worker u_int64_t aggr_op_counts[IOSHARK_MAX_FILE_OP];
100*288bf522SAndroid Build Coastguard Worker struct rw_bytes_s aggr_io_rw_bytes;
101*288bf522SAndroid Build Coastguard Worker struct rw_bytes_s aggr_create_rw_bytes;
102*288bf522SAndroid Build Coastguard Worker
103*288bf522SAndroid Build Coastguard Worker /*
104*288bf522SAndroid Build Coastguard Worker * Locking needed here because aggregate_delay_time is updated
105*288bf522SAndroid Build Coastguard Worker * from multiple threads concurrently.
106*288bf522SAndroid Build Coastguard Worker */
107*288bf522SAndroid Build Coastguard Worker static void
update_time(struct timeval * aggr_time,struct timeval * delta_time)108*288bf522SAndroid Build Coastguard Worker update_time(struct timeval *aggr_time,
109*288bf522SAndroid Build Coastguard Worker struct timeval *delta_time)
110*288bf522SAndroid Build Coastguard Worker {
111*288bf522SAndroid Build Coastguard Worker struct timeval tmp;
112*288bf522SAndroid Build Coastguard Worker
113*288bf522SAndroid Build Coastguard Worker pthread_mutex_lock(&time_mutex);
114*288bf522SAndroid Build Coastguard Worker timeradd(aggr_time, delta_time, &tmp);
115*288bf522SAndroid Build Coastguard Worker *aggr_time = tmp;
116*288bf522SAndroid Build Coastguard Worker pthread_mutex_unlock(&time_mutex);
117*288bf522SAndroid Build Coastguard Worker }
118*288bf522SAndroid Build Coastguard Worker
119*288bf522SAndroid Build Coastguard Worker static void
update_op_counts(u_int64_t * op_counts)120*288bf522SAndroid Build Coastguard Worker update_op_counts(u_int64_t *op_counts)
121*288bf522SAndroid Build Coastguard Worker {
122*288bf522SAndroid Build Coastguard Worker int i;
123*288bf522SAndroid Build Coastguard Worker
124*288bf522SAndroid Build Coastguard Worker pthread_mutex_lock(&stats_mutex);
125*288bf522SAndroid Build Coastguard Worker for (i = IOSHARK_LSEEK ; i < IOSHARK_MAX_FILE_OP ; i++)
126*288bf522SAndroid Build Coastguard Worker aggr_op_counts[i] += op_counts[i];
127*288bf522SAndroid Build Coastguard Worker pthread_mutex_unlock(&stats_mutex);
128*288bf522SAndroid Build Coastguard Worker }
129*288bf522SAndroid Build Coastguard Worker
130*288bf522SAndroid Build Coastguard Worker static void
update_byte_counts(struct rw_bytes_s * dest,struct rw_bytes_s * delta)131*288bf522SAndroid Build Coastguard Worker update_byte_counts(struct rw_bytes_s *dest, struct rw_bytes_s *delta)
132*288bf522SAndroid Build Coastguard Worker {
133*288bf522SAndroid Build Coastguard Worker pthread_mutex_lock(&stats_mutex);
134*288bf522SAndroid Build Coastguard Worker dest->bytes_read += delta->bytes_read;
135*288bf522SAndroid Build Coastguard Worker dest->bytes_written += delta->bytes_written;
136*288bf522SAndroid Build Coastguard Worker pthread_mutex_unlock(&stats_mutex);
137*288bf522SAndroid Build Coastguard Worker }
138*288bf522SAndroid Build Coastguard Worker
139*288bf522SAndroid Build Coastguard Worker static int work_next_file;
140*288bf522SAndroid Build Coastguard Worker static int work_num_files;
141*288bf522SAndroid Build Coastguard Worker
142*288bf522SAndroid Build Coastguard Worker void
init_work(int next_file,int num_files)143*288bf522SAndroid Build Coastguard Worker init_work(int next_file, int num_files)
144*288bf522SAndroid Build Coastguard Worker {
145*288bf522SAndroid Build Coastguard Worker pthread_mutex_lock(&work_mutex);
146*288bf522SAndroid Build Coastguard Worker work_next_file = next_file;
147*288bf522SAndroid Build Coastguard Worker work_num_files = work_next_file + num_files;
148*288bf522SAndroid Build Coastguard Worker pthread_mutex_unlock(&work_mutex);
149*288bf522SAndroid Build Coastguard Worker }
150*288bf522SAndroid Build Coastguard Worker
151*288bf522SAndroid Build Coastguard Worker /* Dole out the next file to work on to the thread */
152*288bf522SAndroid Build Coastguard Worker static struct thread_state_s *
get_work()153*288bf522SAndroid Build Coastguard Worker get_work()
154*288bf522SAndroid Build Coastguard Worker {
155*288bf522SAndroid Build Coastguard Worker struct thread_state_s *work = NULL;
156*288bf522SAndroid Build Coastguard Worker
157*288bf522SAndroid Build Coastguard Worker pthread_mutex_lock(&work_mutex);
158*288bf522SAndroid Build Coastguard Worker if (work_next_file < work_num_files)
159*288bf522SAndroid Build Coastguard Worker work = &thread_state[work_next_file++];
160*288bf522SAndroid Build Coastguard Worker pthread_mutex_unlock(&work_mutex);
161*288bf522SAndroid Build Coastguard Worker return work;
162*288bf522SAndroid Build Coastguard Worker }
163*288bf522SAndroid Build Coastguard Worker
164*288bf522SAndroid Build Coastguard Worker static void
create_files(struct thread_state_s * state)165*288bf522SAndroid Build Coastguard Worker create_files(struct thread_state_s *state)
166*288bf522SAndroid Build Coastguard Worker {
167*288bf522SAndroid Build Coastguard Worker int i;
168*288bf522SAndroid Build Coastguard Worker struct ioshark_file_state file_state;
169*288bf522SAndroid Build Coastguard Worker char path[MAX_IOSHARK_PATHLEN];
170*288bf522SAndroid Build Coastguard Worker void *db_node;
171*288bf522SAndroid Build Coastguard Worker struct rw_bytes_s rw_bytes;
172*288bf522SAndroid Build Coastguard Worker char *filename;
173*288bf522SAndroid Build Coastguard Worker int readonly;
174*288bf522SAndroid Build Coastguard Worker
175*288bf522SAndroid Build Coastguard Worker memset(&rw_bytes, 0, sizeof(struct rw_bytes_s));
176*288bf522SAndroid Build Coastguard Worker for (i = 0 ; i < state->num_files ; i++) {
177*288bf522SAndroid Build Coastguard Worker if (ioshark_read_file_state(state->fp, &file_state) != 1) {
178*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s read error tracefile\n",
179*288bf522SAndroid Build Coastguard Worker progname);
180*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
181*288bf522SAndroid Build Coastguard Worker }
182*288bf522SAndroid Build Coastguard Worker /*
183*288bf522SAndroid Build Coastguard Worker * Check to see if the file is in a readonly partition,
184*288bf522SAndroid Build Coastguard Worker * in which case, we don't have to pre-create the file
185*288bf522SAndroid Build Coastguard Worker * we can just read the existing file.
186*288bf522SAndroid Build Coastguard Worker */
187*288bf522SAndroid Build Coastguard Worker filename =
188*288bf522SAndroid Build Coastguard Worker get_ro_filename(file_state.global_filename_ix);
189*288bf522SAndroid Build Coastguard Worker if (quick_mode)
190*288bf522SAndroid Build Coastguard Worker assert(filename != NULL);
191*288bf522SAndroid Build Coastguard Worker if (quick_mode == 0 ||
192*288bf522SAndroid Build Coastguard Worker is_readonly_mount(filename, file_state.size) == 0) {
193*288bf522SAndroid Build Coastguard Worker sprintf(path, "file.%d.%"PRIu64"",
194*288bf522SAndroid Build Coastguard Worker (int)(state - thread_state),
195*288bf522SAndroid Build Coastguard Worker file_state.fileno);
196*288bf522SAndroid Build Coastguard Worker create_file(path, file_state.size,
197*288bf522SAndroid Build Coastguard Worker &rw_bytes);
198*288bf522SAndroid Build Coastguard Worker filename = path;
199*288bf522SAndroid Build Coastguard Worker readonly = 0;
200*288bf522SAndroid Build Coastguard Worker } else {
201*288bf522SAndroid Build Coastguard Worker readonly = 1;
202*288bf522SAndroid Build Coastguard Worker }
203*288bf522SAndroid Build Coastguard Worker db_node = files_db_add_byfileno(state->db_handle,
204*288bf522SAndroid Build Coastguard Worker file_state.fileno,
205*288bf522SAndroid Build Coastguard Worker readonly);
206*288bf522SAndroid Build Coastguard Worker files_db_update_size(db_node, file_state.size);
207*288bf522SAndroid Build Coastguard Worker files_db_update_filename(db_node, filename);
208*288bf522SAndroid Build Coastguard Worker }
209*288bf522SAndroid Build Coastguard Worker update_byte_counts(&aggr_create_rw_bytes, &rw_bytes);
210*288bf522SAndroid Build Coastguard Worker }
211*288bf522SAndroid Build Coastguard Worker
212*288bf522SAndroid Build Coastguard Worker static void
do_one_io(void * db_node,struct ioshark_file_operation * file_op,u_int64_t * op_counts,struct rw_bytes_s * rw_bytes,char ** bufp,int * buflen)213*288bf522SAndroid Build Coastguard Worker do_one_io(void *db_node,
214*288bf522SAndroid Build Coastguard Worker struct ioshark_file_operation *file_op,
215*288bf522SAndroid Build Coastguard Worker u_int64_t *op_counts,
216*288bf522SAndroid Build Coastguard Worker struct rw_bytes_s *rw_bytes,
217*288bf522SAndroid Build Coastguard Worker char **bufp, int *buflen)
218*288bf522SAndroid Build Coastguard Worker {
219*288bf522SAndroid Build Coastguard Worker assert(file_op->ioshark_io_op < IOSHARK_MAX_FILE_OP);
220*288bf522SAndroid Build Coastguard Worker op_counts[file_op->ioshark_io_op]++;
221*288bf522SAndroid Build Coastguard Worker switch (file_op->ioshark_io_op) {
222*288bf522SAndroid Build Coastguard Worker int ret;
223*288bf522SAndroid Build Coastguard Worker char *p;
224*288bf522SAndroid Build Coastguard Worker int fd;
225*288bf522SAndroid Build Coastguard Worker
226*288bf522SAndroid Build Coastguard Worker case IOSHARK_LSEEK:
227*288bf522SAndroid Build Coastguard Worker case IOSHARK_LLSEEK:
228*288bf522SAndroid Build Coastguard Worker ret = lseek(files_db_get_fd(db_node),
229*288bf522SAndroid Build Coastguard Worker file_op->lseek_offset,
230*288bf522SAndroid Build Coastguard Worker file_op->lseek_action);
231*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
232*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
233*288bf522SAndroid Build Coastguard Worker "%s: lseek(%s %"PRIu64" %d) returned error %d\n",
234*288bf522SAndroid Build Coastguard Worker progname, files_db_get_filename(db_node),
235*288bf522SAndroid Build Coastguard Worker file_op->lseek_offset,
236*288bf522SAndroid Build Coastguard Worker file_op->lseek_action, errno);
237*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
238*288bf522SAndroid Build Coastguard Worker }
239*288bf522SAndroid Build Coastguard Worker break;
240*288bf522SAndroid Build Coastguard Worker case IOSHARK_PREAD64:
241*288bf522SAndroid Build Coastguard Worker p = get_buf(bufp, buflen, file_op->prw_len, 0);
242*288bf522SAndroid Build Coastguard Worker ret = pread(files_db_get_fd(db_node), p,
243*288bf522SAndroid Build Coastguard Worker file_op->prw_len, file_op->prw_offset);
244*288bf522SAndroid Build Coastguard Worker rw_bytes->bytes_read += file_op->prw_len;
245*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
246*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
247*288bf522SAndroid Build Coastguard Worker "%s: pread(%s %"PRIu64" %"PRIu64") error %d\n",
248*288bf522SAndroid Build Coastguard Worker progname,
249*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
250*288bf522SAndroid Build Coastguard Worker file_op->prw_len,
251*288bf522SAndroid Build Coastguard Worker file_op->prw_offset, errno);
252*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
253*288bf522SAndroid Build Coastguard Worker }
254*288bf522SAndroid Build Coastguard Worker break;
255*288bf522SAndroid Build Coastguard Worker case IOSHARK_PWRITE64:
256*288bf522SAndroid Build Coastguard Worker p = get_buf(bufp, buflen, file_op->prw_len, 1);
257*288bf522SAndroid Build Coastguard Worker ret = pwrite(files_db_get_fd(db_node), p,
258*288bf522SAndroid Build Coastguard Worker file_op->prw_len, file_op->prw_offset);
259*288bf522SAndroid Build Coastguard Worker rw_bytes->bytes_written += file_op->prw_len;
260*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
261*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
262*288bf522SAndroid Build Coastguard Worker "%s: pwrite(%s %"PRIu64" %"PRIu64") error %d\n",
263*288bf522SAndroid Build Coastguard Worker progname,
264*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
265*288bf522SAndroid Build Coastguard Worker file_op->prw_len,
266*288bf522SAndroid Build Coastguard Worker file_op->prw_offset, errno);
267*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
268*288bf522SAndroid Build Coastguard Worker }
269*288bf522SAndroid Build Coastguard Worker break;
270*288bf522SAndroid Build Coastguard Worker case IOSHARK_READ:
271*288bf522SAndroid Build Coastguard Worker p = get_buf(bufp, buflen, file_op->rw_len, 0);
272*288bf522SAndroid Build Coastguard Worker ret = read(files_db_get_fd(db_node), p,
273*288bf522SAndroid Build Coastguard Worker file_op->rw_len);
274*288bf522SAndroid Build Coastguard Worker rw_bytes->bytes_read += file_op->rw_len;
275*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
276*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
277*288bf522SAndroid Build Coastguard Worker "%s: read(%s %"PRIu64") error %d\n",
278*288bf522SAndroid Build Coastguard Worker progname,
279*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
280*288bf522SAndroid Build Coastguard Worker file_op->rw_len,
281*288bf522SAndroid Build Coastguard Worker errno);
282*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
283*288bf522SAndroid Build Coastguard Worker }
284*288bf522SAndroid Build Coastguard Worker break;
285*288bf522SAndroid Build Coastguard Worker case IOSHARK_WRITE:
286*288bf522SAndroid Build Coastguard Worker p = get_buf(bufp, buflen, file_op->rw_len, 1);
287*288bf522SAndroid Build Coastguard Worker ret = write(files_db_get_fd(db_node), p,
288*288bf522SAndroid Build Coastguard Worker file_op->rw_len);
289*288bf522SAndroid Build Coastguard Worker rw_bytes->bytes_written += file_op->rw_len;
290*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
291*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
292*288bf522SAndroid Build Coastguard Worker "%s: write(%s %"PRIu64") error %d\n",
293*288bf522SAndroid Build Coastguard Worker progname,
294*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
295*288bf522SAndroid Build Coastguard Worker file_op->rw_len,
296*288bf522SAndroid Build Coastguard Worker errno);
297*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
298*288bf522SAndroid Build Coastguard Worker }
299*288bf522SAndroid Build Coastguard Worker break;
300*288bf522SAndroid Build Coastguard Worker case IOSHARK_MMAP:
301*288bf522SAndroid Build Coastguard Worker case IOSHARK_MMAP2:
302*288bf522SAndroid Build Coastguard Worker ioshark_handle_mmap(db_node, file_op,
303*288bf522SAndroid Build Coastguard Worker bufp, buflen, op_counts,
304*288bf522SAndroid Build Coastguard Worker rw_bytes);
305*288bf522SAndroid Build Coastguard Worker break;
306*288bf522SAndroid Build Coastguard Worker case IOSHARK_OPEN:
307*288bf522SAndroid Build Coastguard Worker if (file_op->open_flags & O_CREAT) {
308*288bf522SAndroid Build Coastguard Worker fd = open(files_db_get_filename(db_node),
309*288bf522SAndroid Build Coastguard Worker file_op->open_flags,
310*288bf522SAndroid Build Coastguard Worker file_op->open_mode);
311*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
312*288bf522SAndroid Build Coastguard Worker /*
313*288bf522SAndroid Build Coastguard Worker * EEXIST error acceptable, others are fatal.
314*288bf522SAndroid Build Coastguard Worker * Although we failed to O_CREAT the file (O_EXCL)
315*288bf522SAndroid Build Coastguard Worker * We will force an open of the file before any
316*288bf522SAndroid Build Coastguard Worker * IO.
317*288bf522SAndroid Build Coastguard Worker */
318*288bf522SAndroid Build Coastguard Worker if (errno == EEXIST) {
319*288bf522SAndroid Build Coastguard Worker return;
320*288bf522SAndroid Build Coastguard Worker } else {
321*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
322*288bf522SAndroid Build Coastguard Worker "%s: O_CREAT open(%s %x %o) error %d\n",
323*288bf522SAndroid Build Coastguard Worker progname,
324*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
325*288bf522SAndroid Build Coastguard Worker file_op->open_flags,
326*288bf522SAndroid Build Coastguard Worker file_op->open_mode, errno);
327*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
328*288bf522SAndroid Build Coastguard Worker }
329*288bf522SAndroid Build Coastguard Worker }
330*288bf522SAndroid Build Coastguard Worker } else {
331*288bf522SAndroid Build Coastguard Worker fd = open(files_db_get_filename(db_node),
332*288bf522SAndroid Build Coastguard Worker file_op->open_flags);
333*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
334*288bf522SAndroid Build Coastguard Worker if (file_op->open_flags & O_DIRECTORY) {
335*288bf522SAndroid Build Coastguard Worker /* O_DIRECTORY open()s should fail */
336*288bf522SAndroid Build Coastguard Worker return;
337*288bf522SAndroid Build Coastguard Worker } else {
338*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
339*288bf522SAndroid Build Coastguard Worker "%s: open(%s %x) error %d\n",
340*288bf522SAndroid Build Coastguard Worker progname,
341*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
342*288bf522SAndroid Build Coastguard Worker file_op->open_flags,
343*288bf522SAndroid Build Coastguard Worker errno);
344*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
345*288bf522SAndroid Build Coastguard Worker }
346*288bf522SAndroid Build Coastguard Worker }
347*288bf522SAndroid Build Coastguard Worker }
348*288bf522SAndroid Build Coastguard Worker files_db_close_fd(db_node);
349*288bf522SAndroid Build Coastguard Worker files_db_update_fd(db_node, fd);
350*288bf522SAndroid Build Coastguard Worker break;
351*288bf522SAndroid Build Coastguard Worker case IOSHARK_FSYNC:
352*288bf522SAndroid Build Coastguard Worker case IOSHARK_FDATASYNC:
353*288bf522SAndroid Build Coastguard Worker if (file_op->ioshark_io_op == IOSHARK_FSYNC) {
354*288bf522SAndroid Build Coastguard Worker ret = fsync(files_db_get_fd(db_node));
355*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
356*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
357*288bf522SAndroid Build Coastguard Worker "%s: fsync(%s) error %d\n",
358*288bf522SAndroid Build Coastguard Worker progname,
359*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
360*288bf522SAndroid Build Coastguard Worker errno);
361*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
362*288bf522SAndroid Build Coastguard Worker }
363*288bf522SAndroid Build Coastguard Worker } else {
364*288bf522SAndroid Build Coastguard Worker ret = fdatasync(files_db_get_fd(db_node));
365*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
366*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
367*288bf522SAndroid Build Coastguard Worker "%s: fdatasync(%s) error %d\n",
368*288bf522SAndroid Build Coastguard Worker progname,
369*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
370*288bf522SAndroid Build Coastguard Worker errno);
371*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
372*288bf522SAndroid Build Coastguard Worker }
373*288bf522SAndroid Build Coastguard Worker }
374*288bf522SAndroid Build Coastguard Worker break;
375*288bf522SAndroid Build Coastguard Worker case IOSHARK_CLOSE:
376*288bf522SAndroid Build Coastguard Worker ret = close(files_db_get_fd(db_node));
377*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
378*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
379*288bf522SAndroid Build Coastguard Worker "%s: close(%s) error %d\n",
380*288bf522SAndroid Build Coastguard Worker progname,
381*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node), errno);
382*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
383*288bf522SAndroid Build Coastguard Worker }
384*288bf522SAndroid Build Coastguard Worker files_db_update_fd(db_node, -1);
385*288bf522SAndroid Build Coastguard Worker break;
386*288bf522SAndroid Build Coastguard Worker default:
387*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: unknown FILE_OP %d\n",
388*288bf522SAndroid Build Coastguard Worker progname, file_op->ioshark_io_op);
389*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
390*288bf522SAndroid Build Coastguard Worker break;
391*288bf522SAndroid Build Coastguard Worker }
392*288bf522SAndroid Build Coastguard Worker }
393*288bf522SAndroid Build Coastguard Worker
394*288bf522SAndroid Build Coastguard Worker static void
do_io(struct thread_state_s * state)395*288bf522SAndroid Build Coastguard Worker do_io(struct thread_state_s *state)
396*288bf522SAndroid Build Coastguard Worker {
397*288bf522SAndroid Build Coastguard Worker void *db_node;
398*288bf522SAndroid Build Coastguard Worker struct ioshark_header header;
399*288bf522SAndroid Build Coastguard Worker struct ioshark_file_operation file_op;
400*288bf522SAndroid Build Coastguard Worker int fd;
401*288bf522SAndroid Build Coastguard Worker int i;
402*288bf522SAndroid Build Coastguard Worker char *buf = NULL;
403*288bf522SAndroid Build Coastguard Worker int buflen = 0;
404*288bf522SAndroid Build Coastguard Worker struct timeval total_delay_time;
405*288bf522SAndroid Build Coastguard Worker u_int64_t op_counts[IOSHARK_MAX_FILE_OP];
406*288bf522SAndroid Build Coastguard Worker struct rw_bytes_s rw_bytes;
407*288bf522SAndroid Build Coastguard Worker
408*288bf522SAndroid Build Coastguard Worker rewind(state->fp);
409*288bf522SAndroid Build Coastguard Worker if (ioshark_read_header(state->fp, &header) != 1) {
410*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s read error %s\n",
411*288bf522SAndroid Build Coastguard Worker progname, state->filename);
412*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
413*288bf522SAndroid Build Coastguard Worker }
414*288bf522SAndroid Build Coastguard Worker /*
415*288bf522SAndroid Build Coastguard Worker * First open and pre-create all the files. Indexed by fileno.
416*288bf522SAndroid Build Coastguard Worker */
417*288bf522SAndroid Build Coastguard Worker timerclear(&total_delay_time);
418*288bf522SAndroid Build Coastguard Worker memset(&rw_bytes, 0, sizeof(struct rw_bytes_s));
419*288bf522SAndroid Build Coastguard Worker memset(op_counts, 0, sizeof(op_counts));
420*288bf522SAndroid Build Coastguard Worker fseek(state->fp,
421*288bf522SAndroid Build Coastguard Worker sizeof(struct ioshark_header) +
422*288bf522SAndroid Build Coastguard Worker header.num_files * sizeof(struct ioshark_file_state),
423*288bf522SAndroid Build Coastguard Worker SEEK_SET);
424*288bf522SAndroid Build Coastguard Worker /*
425*288bf522SAndroid Build Coastguard Worker * Loop over all the IOs, and launch each
426*288bf522SAndroid Build Coastguard Worker */
427*288bf522SAndroid Build Coastguard Worker for (i = 0 ; i < (int)header.num_io_operations ; i++) {
428*288bf522SAndroid Build Coastguard Worker if (ioshark_read_file_op(state->fp, &file_op) != 1) {
429*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s read error trace.outfile\n",
430*288bf522SAndroid Build Coastguard Worker progname);
431*288bf522SAndroid Build Coastguard Worker goto fail;
432*288bf522SAndroid Build Coastguard Worker }
433*288bf522SAndroid Build Coastguard Worker if (do_delay) {
434*288bf522SAndroid Build Coastguard Worker struct timeval start;
435*288bf522SAndroid Build Coastguard Worker
436*288bf522SAndroid Build Coastguard Worker (void)gettimeofday(&start, (struct timezone *)NULL);
437*288bf522SAndroid Build Coastguard Worker usleep(file_op.delta_us);
438*288bf522SAndroid Build Coastguard Worker update_delta_time(&start, &total_delay_time);
439*288bf522SAndroid Build Coastguard Worker }
440*288bf522SAndroid Build Coastguard Worker db_node = files_db_lookup_byfileno(state->db_handle,
441*288bf522SAndroid Build Coastguard Worker file_op.fileno);
442*288bf522SAndroid Build Coastguard Worker if (db_node == NULL) {
443*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
444*288bf522SAndroid Build Coastguard Worker "%s Can't lookup fileno %"PRIu64", fatal error\n",
445*288bf522SAndroid Build Coastguard Worker progname, file_op.fileno);
446*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
447*288bf522SAndroid Build Coastguard Worker "%s state filename %s, i %d\n",
448*288bf522SAndroid Build Coastguard Worker progname, state->filename, i);
449*288bf522SAndroid Build Coastguard Worker goto fail;
450*288bf522SAndroid Build Coastguard Worker }
451*288bf522SAndroid Build Coastguard Worker if (file_op.ioshark_io_op != IOSHARK_OPEN &&
452*288bf522SAndroid Build Coastguard Worker files_db_get_fd(db_node) == -1) {
453*288bf522SAndroid Build Coastguard Worker int openflags;
454*288bf522SAndroid Build Coastguard Worker
455*288bf522SAndroid Build Coastguard Worker /*
456*288bf522SAndroid Build Coastguard Worker * This is a hack to workaround the fact that we did not
457*288bf522SAndroid Build Coastguard Worker * see an open() for this file until now. open() the
458*288bf522SAndroid Build Coastguard Worker * file O_RDWR, so that we can perform the IO.
459*288bf522SAndroid Build Coastguard Worker */
460*288bf522SAndroid Build Coastguard Worker if (files_db_readonly(db_node))
461*288bf522SAndroid Build Coastguard Worker openflags = O_RDONLY;
462*288bf522SAndroid Build Coastguard Worker else
463*288bf522SAndroid Build Coastguard Worker openflags = O_RDWR;
464*288bf522SAndroid Build Coastguard Worker fd = open(files_db_get_filename(db_node),
465*288bf522SAndroid Build Coastguard Worker openflags);
466*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
467*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: open(%s %x) error %d\n",
468*288bf522SAndroid Build Coastguard Worker progname,
469*288bf522SAndroid Build Coastguard Worker files_db_get_filename(db_node),
470*288bf522SAndroid Build Coastguard Worker openflags,
471*288bf522SAndroid Build Coastguard Worker errno);
472*288bf522SAndroid Build Coastguard Worker goto fail;
473*288bf522SAndroid Build Coastguard Worker }
474*288bf522SAndroid Build Coastguard Worker files_db_update_fd(db_node, fd);
475*288bf522SAndroid Build Coastguard Worker }
476*288bf522SAndroid Build Coastguard Worker do_one_io(db_node, &file_op,
477*288bf522SAndroid Build Coastguard Worker op_counts, &rw_bytes, &buf, &buflen);
478*288bf522SAndroid Build Coastguard Worker }
479*288bf522SAndroid Build Coastguard Worker
480*288bf522SAndroid Build Coastguard Worker free(buf);
481*288bf522SAndroid Build Coastguard Worker files_db_fsync_discard_files(state->db_handle);
482*288bf522SAndroid Build Coastguard Worker files_db_close_files(state->db_handle);
483*288bf522SAndroid Build Coastguard Worker update_time(&aggregate_delay_time, &total_delay_time);
484*288bf522SAndroid Build Coastguard Worker update_op_counts(op_counts);
485*288bf522SAndroid Build Coastguard Worker update_byte_counts(&aggr_io_rw_bytes, &rw_bytes);
486*288bf522SAndroid Build Coastguard Worker return;
487*288bf522SAndroid Build Coastguard Worker
488*288bf522SAndroid Build Coastguard Worker fail:
489*288bf522SAndroid Build Coastguard Worker free(buf);
490*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
491*288bf522SAndroid Build Coastguard Worker }
492*288bf522SAndroid Build Coastguard Worker
493*288bf522SAndroid Build Coastguard Worker void *
io_thread(void * unused)494*288bf522SAndroid Build Coastguard Worker io_thread(void *unused __attribute__((unused)))
495*288bf522SAndroid Build Coastguard Worker {
496*288bf522SAndroid Build Coastguard Worker struct thread_state_s *state;
497*288bf522SAndroid Build Coastguard Worker
498*288bf522SAndroid Build Coastguard Worker srand(gettid());
499*288bf522SAndroid Build Coastguard Worker while ((state = get_work()))
500*288bf522SAndroid Build Coastguard Worker do_io(state);
501*288bf522SAndroid Build Coastguard Worker pthread_exit(NULL);
502*288bf522SAndroid Build Coastguard Worker return(NULL);
503*288bf522SAndroid Build Coastguard Worker }
504*288bf522SAndroid Build Coastguard Worker
505*288bf522SAndroid Build Coastguard Worker static void
do_create(struct thread_state_s * state)506*288bf522SAndroid Build Coastguard Worker do_create(struct thread_state_s *state)
507*288bf522SAndroid Build Coastguard Worker {
508*288bf522SAndroid Build Coastguard Worker struct ioshark_header header;
509*288bf522SAndroid Build Coastguard Worker
510*288bf522SAndroid Build Coastguard Worker if (ioshark_read_header(state->fp, &header) != 1) {
511*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s read error %s\n",
512*288bf522SAndroid Build Coastguard Worker progname, state->filename);
513*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
514*288bf522SAndroid Build Coastguard Worker }
515*288bf522SAndroid Build Coastguard Worker state->num_files = header.num_files;
516*288bf522SAndroid Build Coastguard Worker state->db_handle = files_db_create_handle();
517*288bf522SAndroid Build Coastguard Worker create_files(state);
518*288bf522SAndroid Build Coastguard Worker }
519*288bf522SAndroid Build Coastguard Worker
520*288bf522SAndroid Build Coastguard Worker void *
create_files_thread(void * unused)521*288bf522SAndroid Build Coastguard Worker create_files_thread(void *unused __attribute__((unused)))
522*288bf522SAndroid Build Coastguard Worker {
523*288bf522SAndroid Build Coastguard Worker struct thread_state_s *state;
524*288bf522SAndroid Build Coastguard Worker
525*288bf522SAndroid Build Coastguard Worker while ((state = get_work()))
526*288bf522SAndroid Build Coastguard Worker do_create(state);
527*288bf522SAndroid Build Coastguard Worker pthread_exit(NULL);
528*288bf522SAndroid Build Coastguard Worker return(NULL);
529*288bf522SAndroid Build Coastguard Worker }
530*288bf522SAndroid Build Coastguard Worker
531*288bf522SAndroid Build Coastguard Worker int
get_start_end(int * start_ix)532*288bf522SAndroid Build Coastguard Worker get_start_end(int *start_ix)
533*288bf522SAndroid Build Coastguard Worker {
534*288bf522SAndroid Build Coastguard Worker int i, j, ret_numfiles;
535*288bf522SAndroid Build Coastguard Worker u_int64_t free_fs_bytes;
536*288bf522SAndroid Build Coastguard Worker char *infile;
537*288bf522SAndroid Build Coastguard Worker FILE *fp;
538*288bf522SAndroid Build Coastguard Worker struct ioshark_header header;
539*288bf522SAndroid Build Coastguard Worker struct ioshark_file_state file_state;
540*288bf522SAndroid Build Coastguard Worker struct statfs fsstat;
541*288bf522SAndroid Build Coastguard Worker static int fssize_clamp_next_index = 0;
542*288bf522SAndroid Build Coastguard Worker static int chunk = 0;
543*288bf522SAndroid Build Coastguard Worker
544*288bf522SAndroid Build Coastguard Worker if (fssize_clamp_next_index == num_input_files)
545*288bf522SAndroid Build Coastguard Worker return 0;
546*288bf522SAndroid Build Coastguard Worker if (statfs("/data/local/tmp", &fsstat) < 0) {
547*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't statfs /data/local/tmp\n",
548*288bf522SAndroid Build Coastguard Worker progname);
549*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
550*288bf522SAndroid Build Coastguard Worker }
551*288bf522SAndroid Build Coastguard Worker free_fs_bytes = (fsstat.f_bavail * fsstat.f_bsize) * 9 /10;
552*288bf522SAndroid Build Coastguard Worker for (i = fssize_clamp_next_index; i < num_input_files; i++) {
553*288bf522SAndroid Build Coastguard Worker infile = thread_state[i].filename;
554*288bf522SAndroid Build Coastguard Worker fp = fopen(infile, "r");
555*288bf522SAndroid Build Coastguard Worker if (fp == NULL) {
556*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't open %s\n",
557*288bf522SAndroid Build Coastguard Worker progname, infile);
558*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
559*288bf522SAndroid Build Coastguard Worker }
560*288bf522SAndroid Build Coastguard Worker if (ioshark_read_header(fp, &header) != 1) {
561*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s read error %s\n",
562*288bf522SAndroid Build Coastguard Worker progname, infile);
563*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
564*288bf522SAndroid Build Coastguard Worker }
565*288bf522SAndroid Build Coastguard Worker for (j = 0 ; j < (int)header.num_files ; j++) {
566*288bf522SAndroid Build Coastguard Worker if (ioshark_read_file_state(fp, &file_state) != 1) {
567*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s read error tracefile\n",
568*288bf522SAndroid Build Coastguard Worker progname);
569*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
570*288bf522SAndroid Build Coastguard Worker }
571*288bf522SAndroid Build Coastguard Worker if (quick_mode == 0 ||
572*288bf522SAndroid Build Coastguard Worker !is_readonly_mount(
573*288bf522SAndroid Build Coastguard Worker get_ro_filename(file_state.global_filename_ix),
574*288bf522SAndroid Build Coastguard Worker file_state.size)) {
575*288bf522SAndroid Build Coastguard Worker if (file_state.size > free_fs_bytes) {
576*288bf522SAndroid Build Coastguard Worker fclose(fp);
577*288bf522SAndroid Build Coastguard Worker goto out;
578*288bf522SAndroid Build Coastguard Worker }
579*288bf522SAndroid Build Coastguard Worker free_fs_bytes -= file_state.size;
580*288bf522SAndroid Build Coastguard Worker }
581*288bf522SAndroid Build Coastguard Worker }
582*288bf522SAndroid Build Coastguard Worker fclose(fp);
583*288bf522SAndroid Build Coastguard Worker }
584*288bf522SAndroid Build Coastguard Worker out:
585*288bf522SAndroid Build Coastguard Worker if (verbose) {
586*288bf522SAndroid Build Coastguard Worker if (chunk > 0 || i < num_input_files) {
587*288bf522SAndroid Build Coastguard Worker printf("Breaking up input files, Chunk %d: %d to %d\n",
588*288bf522SAndroid Build Coastguard Worker chunk++, fssize_clamp_next_index, i - 1);
589*288bf522SAndroid Build Coastguard Worker } else {
590*288bf522SAndroid Build Coastguard Worker printf("Entire Dataset fits start = %d to %d, free_bytes = %ju\n",
591*288bf522SAndroid Build Coastguard Worker fssize_clamp_next_index,
592*288bf522SAndroid Build Coastguard Worker i - fssize_clamp_next_index,
593*288bf522SAndroid Build Coastguard Worker free_fs_bytes);
594*288bf522SAndroid Build Coastguard Worker }
595*288bf522SAndroid Build Coastguard Worker }
596*288bf522SAndroid Build Coastguard Worker *start_ix = fssize_clamp_next_index;
597*288bf522SAndroid Build Coastguard Worker ret_numfiles = i - fssize_clamp_next_index;
598*288bf522SAndroid Build Coastguard Worker fssize_clamp_next_index = i;
599*288bf522SAndroid Build Coastguard Worker return ret_numfiles;
600*288bf522SAndroid Build Coastguard Worker }
601*288bf522SAndroid Build Coastguard Worker
602*288bf522SAndroid Build Coastguard Worker int
ioshark_pthread_create(pthread_t * tidp,void * (* start_routine)(void *))603*288bf522SAndroid Build Coastguard Worker ioshark_pthread_create(pthread_t *tidp, void *(*start_routine)(void *))
604*288bf522SAndroid Build Coastguard Worker {
605*288bf522SAndroid Build Coastguard Worker pthread_attr_t attr;
606*288bf522SAndroid Build Coastguard Worker
607*288bf522SAndroid Build Coastguard Worker pthread_attr_init(&attr);
608*288bf522SAndroid Build Coastguard Worker pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
609*288bf522SAndroid Build Coastguard Worker pthread_attr_setstacksize(&attr, (size_t)(1024*1024));
610*288bf522SAndroid Build Coastguard Worker return pthread_create(tidp, &attr, start_routine, (void *)NULL);
611*288bf522SAndroid Build Coastguard Worker }
612*288bf522SAndroid Build Coastguard Worker
613*288bf522SAndroid Build Coastguard Worker void
wait_for_threads(int num_threads)614*288bf522SAndroid Build Coastguard Worker wait_for_threads(int num_threads)
615*288bf522SAndroid Build Coastguard Worker {
616*288bf522SAndroid Build Coastguard Worker int i;
617*288bf522SAndroid Build Coastguard Worker
618*288bf522SAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
619*288bf522SAndroid Build Coastguard Worker pthread_join(tid[i], NULL);
620*288bf522SAndroid Build Coastguard Worker tid[i] = 0;
621*288bf522SAndroid Build Coastguard Worker }
622*288bf522SAndroid Build Coastguard Worker }
623*288bf522SAndroid Build Coastguard Worker
624*288bf522SAndroid Build Coastguard Worker #define IOSHARK_FD_LIM 8192
625*288bf522SAndroid Build Coastguard Worker
626*288bf522SAndroid Build Coastguard Worker static void
sizeup_fd_limits(void)627*288bf522SAndroid Build Coastguard Worker sizeup_fd_limits(void)
628*288bf522SAndroid Build Coastguard Worker {
629*288bf522SAndroid Build Coastguard Worker struct rlimit r;
630*288bf522SAndroid Build Coastguard Worker
631*288bf522SAndroid Build Coastguard Worker getrlimit(RLIMIT_NOFILE, &r);
632*288bf522SAndroid Build Coastguard Worker if (r.rlim_cur >= IOSHARK_FD_LIM)
633*288bf522SAndroid Build Coastguard Worker /* cur limit already at what we want */
634*288bf522SAndroid Build Coastguard Worker return;
635*288bf522SAndroid Build Coastguard Worker /*
636*288bf522SAndroid Build Coastguard Worker * Size up both the Max and Cur to IOSHARK_FD_LIM.
637*288bf522SAndroid Build Coastguard Worker * If we are not running as root, this will fail,
638*288bf522SAndroid Build Coastguard Worker * catch that below and exit.
639*288bf522SAndroid Build Coastguard Worker */
640*288bf522SAndroid Build Coastguard Worker if (r.rlim_max < IOSHARK_FD_LIM)
641*288bf522SAndroid Build Coastguard Worker r.rlim_max = IOSHARK_FD_LIM;
642*288bf522SAndroid Build Coastguard Worker r.rlim_cur = IOSHARK_FD_LIM;
643*288bf522SAndroid Build Coastguard Worker if (setrlimit(RLIMIT_NOFILE, &r) < 0) {
644*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't setrlimit (RLIMIT_NOFILE, 8192)\n",
645*288bf522SAndroid Build Coastguard Worker progname);
646*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
647*288bf522SAndroid Build Coastguard Worker }
648*288bf522SAndroid Build Coastguard Worker getrlimit(RLIMIT_NOFILE, &r);
649*288bf522SAndroid Build Coastguard Worker if (r.rlim_cur < IOSHARK_FD_LIM) {
650*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't setrlimit up to 8192\n",
651*288bf522SAndroid Build Coastguard Worker progname);
652*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Running as root ?\n",
653*288bf522SAndroid Build Coastguard Worker progname);
654*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
655*288bf522SAndroid Build Coastguard Worker }
656*288bf522SAndroid Build Coastguard Worker }
657*288bf522SAndroid Build Coastguard Worker
658*288bf522SAndroid Build Coastguard Worker int
main(int argc,char ** argv)659*288bf522SAndroid Build Coastguard Worker main(int argc, char **argv)
660*288bf522SAndroid Build Coastguard Worker {
661*288bf522SAndroid Build Coastguard Worker int i;
662*288bf522SAndroid Build Coastguard Worker FILE *fp;
663*288bf522SAndroid Build Coastguard Worker struct stat st;
664*288bf522SAndroid Build Coastguard Worker char *infile;
665*288bf522SAndroid Build Coastguard Worker int num_threads = 0;
666*288bf522SAndroid Build Coastguard Worker int num_iterations = 1;
667*288bf522SAndroid Build Coastguard Worker int c;
668*288bf522SAndroid Build Coastguard Worker int num_files, start_file;
669*288bf522SAndroid Build Coastguard Worker struct thread_state_s *state;
670*288bf522SAndroid Build Coastguard Worker
671*288bf522SAndroid Build Coastguard Worker progname = argv[0];
672*288bf522SAndroid Build Coastguard Worker while ((c = getopt(argc, argv, "b:dn:st:qv")) != EOF) {
673*288bf522SAndroid Build Coastguard Worker switch (c) {
674*288bf522SAndroid Build Coastguard Worker case 'b':
675*288bf522SAndroid Build Coastguard Worker blockdev_name = strdup(optarg);
676*288bf522SAndroid Build Coastguard Worker break;
677*288bf522SAndroid Build Coastguard Worker case 'd':
678*288bf522SAndroid Build Coastguard Worker do_delay = 1;
679*288bf522SAndroid Build Coastguard Worker break;
680*288bf522SAndroid Build Coastguard Worker case 'n':
681*288bf522SAndroid Build Coastguard Worker num_iterations = atoi(optarg);
682*288bf522SAndroid Build Coastguard Worker break;
683*288bf522SAndroid Build Coastguard Worker case 's':
684*288bf522SAndroid Build Coastguard Worker /* Non-verbose summary mode for nightly runs */
685*288bf522SAndroid Build Coastguard Worker summary_mode = 1;
686*288bf522SAndroid Build Coastguard Worker break;
687*288bf522SAndroid Build Coastguard Worker case 't':
688*288bf522SAndroid Build Coastguard Worker num_threads = atoi(optarg);
689*288bf522SAndroid Build Coastguard Worker break;
690*288bf522SAndroid Build Coastguard Worker case 'q':
691*288bf522SAndroid Build Coastguard Worker /*
692*288bf522SAndroid Build Coastguard Worker * If quick mode is enabled, then we won't
693*288bf522SAndroid Build Coastguard Worker * pre-create files that we are doing IO on that
694*288bf522SAndroid Build Coastguard Worker * live in readonly partitions (/system, /vendor etc)
695*288bf522SAndroid Build Coastguard Worker */
696*288bf522SAndroid Build Coastguard Worker quick_mode = 1;
697*288bf522SAndroid Build Coastguard Worker break;
698*288bf522SAndroid Build Coastguard Worker case 'v':
699*288bf522SAndroid Build Coastguard Worker verbose = 1;
700*288bf522SAndroid Build Coastguard Worker break;
701*288bf522SAndroid Build Coastguard Worker default:
702*288bf522SAndroid Build Coastguard Worker usage();
703*288bf522SAndroid Build Coastguard Worker }
704*288bf522SAndroid Build Coastguard Worker }
705*288bf522SAndroid Build Coastguard Worker
706*288bf522SAndroid Build Coastguard Worker if ((verbose + summary_mode) == 2)
707*288bf522SAndroid Build Coastguard Worker usage();
708*288bf522SAndroid Build Coastguard Worker
709*288bf522SAndroid Build Coastguard Worker if (num_threads > MAX_THREADS)
710*288bf522SAndroid Build Coastguard Worker usage();
711*288bf522SAndroid Build Coastguard Worker
712*288bf522SAndroid Build Coastguard Worker if (optind == argc)
713*288bf522SAndroid Build Coastguard Worker usage();
714*288bf522SAndroid Build Coastguard Worker
715*288bf522SAndroid Build Coastguard Worker sizeup_fd_limits();
716*288bf522SAndroid Build Coastguard Worker
717*288bf522SAndroid Build Coastguard Worker for (i = optind; i < argc; i++) {
718*288bf522SAndroid Build Coastguard Worker infile = argv[i];
719*288bf522SAndroid Build Coastguard Worker if (stat(infile, &st) < 0) {
720*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't stat %s\n",
721*288bf522SAndroid Build Coastguard Worker progname, infile);
722*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
723*288bf522SAndroid Build Coastguard Worker }
724*288bf522SAndroid Build Coastguard Worker if (st.st_size == 0) {
725*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Empty file %s\n",
726*288bf522SAndroid Build Coastguard Worker progname, infile);
727*288bf522SAndroid Build Coastguard Worker continue;
728*288bf522SAndroid Build Coastguard Worker }
729*288bf522SAndroid Build Coastguard Worker fp = fopen(infile, "r");
730*288bf522SAndroid Build Coastguard Worker if (fp == NULL) {
731*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "%s: Can't open %s\n",
732*288bf522SAndroid Build Coastguard Worker progname, infile);
733*288bf522SAndroid Build Coastguard Worker continue;
734*288bf522SAndroid Build Coastguard Worker }
735*288bf522SAndroid Build Coastguard Worker thread_state[num_input_files].filename = infile;
736*288bf522SAndroid Build Coastguard Worker thread_state[num_input_files].fp = fp;
737*288bf522SAndroid Build Coastguard Worker num_input_files++;
738*288bf522SAndroid Build Coastguard Worker }
739*288bf522SAndroid Build Coastguard Worker
740*288bf522SAndroid Build Coastguard Worker if (num_input_files == 0) {
741*288bf522SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
742*288bf522SAndroid Build Coastguard Worker }
743*288bf522SAndroid Build Coastguard Worker if (verbose) {
744*288bf522SAndroid Build Coastguard Worker printf("Total Input Files = %d\n", num_input_files);
745*288bf522SAndroid Build Coastguard Worker printf("Num Iterations = %d\n", num_iterations);
746*288bf522SAndroid Build Coastguard Worker }
747*288bf522SAndroid Build Coastguard Worker timerclear(&aggregate_file_create_time);
748*288bf522SAndroid Build Coastguard Worker timerclear(&aggregate_file_remove_time);
749*288bf522SAndroid Build Coastguard Worker timerclear(&aggregate_IO_time);
750*288bf522SAndroid Build Coastguard Worker
751*288bf522SAndroid Build Coastguard Worker if (quick_mode)
752*288bf522SAndroid Build Coastguard Worker init_filename_cache();
753*288bf522SAndroid Build Coastguard Worker
754*288bf522SAndroid Build Coastguard Worker capture_util_state_before();
755*288bf522SAndroid Build Coastguard Worker
756*288bf522SAndroid Build Coastguard Worker /*
757*288bf522SAndroid Build Coastguard Worker * We pre-create the files that we need once and then we
758*288bf522SAndroid Build Coastguard Worker * loop around N times doing IOs on the pre-created files.
759*288bf522SAndroid Build Coastguard Worker *
760*288bf522SAndroid Build Coastguard Worker * get_start_end() breaks up the total work here to make sure
761*288bf522SAndroid Build Coastguard Worker * that all the files we need to pre-create fit into the
762*288bf522SAndroid Build Coastguard Worker * available space in /data/local/tmp (hardcoded for now).
763*288bf522SAndroid Build Coastguard Worker *
764*288bf522SAndroid Build Coastguard Worker * If it won't fit, then we do several sweeps.
765*288bf522SAndroid Build Coastguard Worker */
766*288bf522SAndroid Build Coastguard Worker while ((num_files = get_start_end(&start_file))) {
767*288bf522SAndroid Build Coastguard Worker struct timeval time_for_pass;
768*288bf522SAndroid Build Coastguard Worker
769*288bf522SAndroid Build Coastguard Worker /* Create files once */
770*288bf522SAndroid Build Coastguard Worker if (!summary_mode)
771*288bf522SAndroid Build Coastguard Worker printf("Doing Pre-creation of Files\n");
772*288bf522SAndroid Build Coastguard Worker if (quick_mode && !summary_mode)
773*288bf522SAndroid Build Coastguard Worker printf("Skipping Pre-creation of read-only Files\n");
774*288bf522SAndroid Build Coastguard Worker if (num_threads == 0 || num_threads > num_files)
775*288bf522SAndroid Build Coastguard Worker num_threads = num_files;
776*288bf522SAndroid Build Coastguard Worker (void)system("echo 3 > /proc/sys/vm/drop_caches");
777*288bf522SAndroid Build Coastguard Worker init_work(start_file, num_files);
778*288bf522SAndroid Build Coastguard Worker (void)gettimeofday(&time_for_pass,
779*288bf522SAndroid Build Coastguard Worker (struct timezone *)NULL);
780*288bf522SAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
781*288bf522SAndroid Build Coastguard Worker if (ioshark_pthread_create(&(tid[i]),
782*288bf522SAndroid Build Coastguard Worker create_files_thread)) {
783*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
784*288bf522SAndroid Build Coastguard Worker "%s: Can't create creator thread %d\n",
785*288bf522SAndroid Build Coastguard Worker progname, i);
786*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
787*288bf522SAndroid Build Coastguard Worker }
788*288bf522SAndroid Build Coastguard Worker }
789*288bf522SAndroid Build Coastguard Worker wait_for_threads(num_threads);
790*288bf522SAndroid Build Coastguard Worker update_delta_time(&time_for_pass, &aggregate_file_create_time);
791*288bf522SAndroid Build Coastguard Worker /* Do the IOs N times */
792*288bf522SAndroid Build Coastguard Worker for (i = 0 ; i < num_iterations ; i++) {
793*288bf522SAndroid Build Coastguard Worker (void)system("echo 3 > /proc/sys/vm/drop_caches");
794*288bf522SAndroid Build Coastguard Worker if (!summary_mode) {
795*288bf522SAndroid Build Coastguard Worker if (num_iterations > 1)
796*288bf522SAndroid Build Coastguard Worker printf("Starting Test. Iteration %d...\n",
797*288bf522SAndroid Build Coastguard Worker i);
798*288bf522SAndroid Build Coastguard Worker else
799*288bf522SAndroid Build Coastguard Worker printf("Starting Test...\n");
800*288bf522SAndroid Build Coastguard Worker }
801*288bf522SAndroid Build Coastguard Worker init_work(start_file, num_files);
802*288bf522SAndroid Build Coastguard Worker (void)gettimeofday(&time_for_pass,
803*288bf522SAndroid Build Coastguard Worker (struct timezone *)NULL);
804*288bf522SAndroid Build Coastguard Worker for (c = 0; c < num_threads; c++) {
805*288bf522SAndroid Build Coastguard Worker if (ioshark_pthread_create(&(tid[c]),
806*288bf522SAndroid Build Coastguard Worker io_thread)) {
807*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
808*288bf522SAndroid Build Coastguard Worker "%s: Can't create thread %d\n",
809*288bf522SAndroid Build Coastguard Worker progname, c);
810*288bf522SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
811*288bf522SAndroid Build Coastguard Worker }
812*288bf522SAndroid Build Coastguard Worker }
813*288bf522SAndroid Build Coastguard Worker wait_for_threads(num_threads);
814*288bf522SAndroid Build Coastguard Worker update_delta_time(&time_for_pass,
815*288bf522SAndroid Build Coastguard Worker &aggregate_IO_time);
816*288bf522SAndroid Build Coastguard Worker }
817*288bf522SAndroid Build Coastguard Worker
818*288bf522SAndroid Build Coastguard Worker /*
819*288bf522SAndroid Build Coastguard Worker * We are done with the N iterations of IO.
820*288bf522SAndroid Build Coastguard Worker * Destroy the files we pre-created.
821*288bf522SAndroid Build Coastguard Worker */
822*288bf522SAndroid Build Coastguard Worker init_work(start_file, num_files);
823*288bf522SAndroid Build Coastguard Worker while ((state = get_work())) {
824*288bf522SAndroid Build Coastguard Worker struct timeval start;
825*288bf522SAndroid Build Coastguard Worker
826*288bf522SAndroid Build Coastguard Worker (void)gettimeofday(&start, (struct timezone *)NULL);
827*288bf522SAndroid Build Coastguard Worker files_db_unlink_files(state->db_handle);
828*288bf522SAndroid Build Coastguard Worker update_delta_time(&start, &aggregate_file_remove_time);
829*288bf522SAndroid Build Coastguard Worker files_db_free_memory(state->db_handle);
830*288bf522SAndroid Build Coastguard Worker }
831*288bf522SAndroid Build Coastguard Worker }
832*288bf522SAndroid Build Coastguard Worker if (!summary_mode) {
833*288bf522SAndroid Build Coastguard Worker printf("Total Creation time = %ju.%ju (msecs.usecs)\n",
834*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_file_create_time),
835*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_file_create_time));
836*288bf522SAndroid Build Coastguard Worker printf("Total Remove time = %ju.%ju (msecs.usecs)\n",
837*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_file_remove_time),
838*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_file_remove_time));
839*288bf522SAndroid Build Coastguard Worker if (do_delay)
840*288bf522SAndroid Build Coastguard Worker printf("Total delay time = %ju.%ju (msecs.usecs)\n",
841*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_delay_time),
842*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_delay_time));
843*288bf522SAndroid Build Coastguard Worker printf("Total Test (IO) time = %ju.%ju (msecs.usecs)\n",
844*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_IO_time),
845*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_IO_time));
846*288bf522SAndroid Build Coastguard Worker if (verbose)
847*288bf522SAndroid Build Coastguard Worker print_bytes("Upfront File Creation bytes",
848*288bf522SAndroid Build Coastguard Worker &aggr_create_rw_bytes);
849*288bf522SAndroid Build Coastguard Worker print_bytes("Total Test (IO) bytes", &aggr_io_rw_bytes);
850*288bf522SAndroid Build Coastguard Worker if (verbose)
851*288bf522SAndroid Build Coastguard Worker print_op_stats(aggr_op_counts);
852*288bf522SAndroid Build Coastguard Worker report_cpu_disk_util();
853*288bf522SAndroid Build Coastguard Worker } else {
854*288bf522SAndroid Build Coastguard Worker printf("%ju.%ju ",
855*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_file_create_time),
856*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_file_create_time));
857*288bf522SAndroid Build Coastguard Worker printf("%ju.%ju ",
858*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_file_remove_time),
859*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_file_remove_time));
860*288bf522SAndroid Build Coastguard Worker if (do_delay)
861*288bf522SAndroid Build Coastguard Worker printf("%ju.%ju ",
862*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_delay_time),
863*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_delay_time));
864*288bf522SAndroid Build Coastguard Worker printf("%ju.%ju ",
865*288bf522SAndroid Build Coastguard Worker get_msecs(&aggregate_IO_time),
866*288bf522SAndroid Build Coastguard Worker get_usecs(&aggregate_IO_time));
867*288bf522SAndroid Build Coastguard Worker print_bytes(NULL, &aggr_io_rw_bytes);
868*288bf522SAndroid Build Coastguard Worker report_cpu_disk_util();
869*288bf522SAndroid Build Coastguard Worker printf("\n");
870*288bf522SAndroid Build Coastguard Worker }
871*288bf522SAndroid Build Coastguard Worker if (quick_mode)
872*288bf522SAndroid Build Coastguard Worker free_filename_cache();
873*288bf522SAndroid Build Coastguard Worker }
874