xref: /aosp_15_r20/external/ltp/testcases/kernel/io/ltp-aiodio/aio-stress.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-only
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2004 SuSE, Inc.  All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker  *               Written by: Chris Mason <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2022 SUSE LLC Andrea Cervesato <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker  */
7*49cdfc7eSAndroid Build Coastguard Worker 
8*49cdfc7eSAndroid Build Coastguard Worker /*\
9*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
10*49cdfc7eSAndroid Build Coastguard Worker  *
11*49cdfc7eSAndroid Build Coastguard Worker  * Test creates a series of files and start AIO operations on them.
12*49cdfc7eSAndroid Build Coastguard Worker  * AIO is done in a rotating loop: first file1.bin gets 8 requests, then
13*49cdfc7eSAndroid Build Coastguard Worker  * file2.bin, then file3.bin etc. As each file finishes writing, test switches
14*49cdfc7eSAndroid Build Coastguard Worker  * to reads. IO buffers are aligned in case we want to do direct IO.
15*49cdfc7eSAndroid Build Coastguard Worker  */
16*49cdfc7eSAndroid Build Coastguard Worker 
17*49cdfc7eSAndroid Build Coastguard Worker #define _FILE_OFFSET_BITS 64
18*49cdfc7eSAndroid Build Coastguard Worker 
19*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
20*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
21*49cdfc7eSAndroid Build Coastguard Worker 
22*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_LIBAIO
23*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
25*49cdfc7eSAndroid Build Coastguard Worker #include <assert.h>
26*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
29*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
30*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
32*49cdfc7eSAndroid Build Coastguard Worker #include <sys/ipc.h>
33*49cdfc7eSAndroid Build Coastguard Worker #include <sys/shm.h>
34*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
35*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
36*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
37*49cdfc7eSAndroid Build Coastguard Worker #include <libaio.h>
38*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_pthread.h"
39*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_sysv_ipc.h"
40*49cdfc7eSAndroid Build Coastguard Worker 
41*49cdfc7eSAndroid Build Coastguard Worker #define IO_FREE 0
42*49cdfc7eSAndroid Build Coastguard Worker #define IO_PENDING 1
43*49cdfc7eSAndroid Build Coastguard Worker 
44*49cdfc7eSAndroid Build Coastguard Worker enum {
45*49cdfc7eSAndroid Build Coastguard Worker 	WRITE,
46*49cdfc7eSAndroid Build Coastguard Worker 	READ,
47*49cdfc7eSAndroid Build Coastguard Worker 	RWRITE,
48*49cdfc7eSAndroid Build Coastguard Worker 	RREAD,
49*49cdfc7eSAndroid Build Coastguard Worker 	LAST_STAGE,
50*49cdfc7eSAndroid Build Coastguard Worker };
51*49cdfc7eSAndroid Build Coastguard Worker 
52*49cdfc7eSAndroid Build Coastguard Worker #define USE_MALLOC 0
53*49cdfc7eSAndroid Build Coastguard Worker #define USE_SHM 1
54*49cdfc7eSAndroid Build Coastguard Worker #define USE_SHMFS 2
55*49cdfc7eSAndroid Build Coastguard Worker 
56*49cdfc7eSAndroid Build Coastguard Worker static char *str_num_files;
57*49cdfc7eSAndroid Build Coastguard Worker static char *str_max_io_submit;
58*49cdfc7eSAndroid Build Coastguard Worker static char *str_num_contexts;
59*49cdfc7eSAndroid Build Coastguard Worker static char *str_context_offset;
60*49cdfc7eSAndroid Build Coastguard Worker static char *str_file_size;
61*49cdfc7eSAndroid Build Coastguard Worker static char *str_rec_len;
62*49cdfc7eSAndroid Build Coastguard Worker static char *str_depth;
63*49cdfc7eSAndroid Build Coastguard Worker static char *str_io_iter;
64*49cdfc7eSAndroid Build Coastguard Worker static char *str_iterations;
65*49cdfc7eSAndroid Build Coastguard Worker static char *str_o_flag;
66*49cdfc7eSAndroid Build Coastguard Worker static char *str_stages;
67*49cdfc7eSAndroid Build Coastguard Worker static char *str_use_shm;
68*49cdfc7eSAndroid Build Coastguard Worker static char *str_num_threads;
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker static int num_files = 1;
71*49cdfc7eSAndroid Build Coastguard Worker static long long file_size = 1024 * 1024 * 1024;
72*49cdfc7eSAndroid Build Coastguard Worker static long stages;
73*49cdfc7eSAndroid Build Coastguard Worker static unsigned long page_size_mask;
74*49cdfc7eSAndroid Build Coastguard Worker static int o_flag;
75*49cdfc7eSAndroid Build Coastguard Worker static char *latency_stats;
76*49cdfc7eSAndroid Build Coastguard Worker static char *completion_latency_stats;
77*49cdfc7eSAndroid Build Coastguard Worker static int io_iter = 8;
78*49cdfc7eSAndroid Build Coastguard Worker static int iterations = 500;
79*49cdfc7eSAndroid Build Coastguard Worker static int max_io_submit;
80*49cdfc7eSAndroid Build Coastguard Worker static long long rec_len = 64 * 1024;
81*49cdfc7eSAndroid Build Coastguard Worker static int depth = 64;
82*49cdfc7eSAndroid Build Coastguard Worker static int num_threads = 1;
83*49cdfc7eSAndroid Build Coastguard Worker static int num_contexts = 1;
84*49cdfc7eSAndroid Build Coastguard Worker static long long context_offset = 2 * 1024 * 1024;
85*49cdfc7eSAndroid Build Coastguard Worker static char *no_fsync_stages;
86*49cdfc7eSAndroid Build Coastguard Worker static int use_shm;
87*49cdfc7eSAndroid Build Coastguard Worker static int shm_id;
88*49cdfc7eSAndroid Build Coastguard Worker static char *unaligned_buffer;
89*49cdfc7eSAndroid Build Coastguard Worker static char *aligned_buffer;
90*49cdfc7eSAndroid Build Coastguard Worker static int padded_reclen;
91*49cdfc7eSAndroid Build Coastguard Worker static char *verify;
92*49cdfc7eSAndroid Build Coastguard Worker static char *verify_buf;
93*49cdfc7eSAndroid Build Coastguard Worker static char *unlink_files;
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker /*
96*49cdfc7eSAndroid Build Coastguard Worker  * latencies during io_submit are measured, these are the
97*49cdfc7eSAndroid Build Coastguard Worker  * granularities for deviations
98*49cdfc7eSAndroid Build Coastguard Worker  */
99*49cdfc7eSAndroid Build Coastguard Worker #define DEVIATIONS 6
100*49cdfc7eSAndroid Build Coastguard Worker static int deviations[DEVIATIONS] = { 100, 250, 500, 1000, 5000, 10000 };
101*49cdfc7eSAndroid Build Coastguard Worker 
102*49cdfc7eSAndroid Build Coastguard Worker struct io_latency {
103*49cdfc7eSAndroid Build Coastguard Worker 	double max;
104*49cdfc7eSAndroid Build Coastguard Worker 	double min;
105*49cdfc7eSAndroid Build Coastguard Worker 	double total_io;
106*49cdfc7eSAndroid Build Coastguard Worker 	double total_lat;
107*49cdfc7eSAndroid Build Coastguard Worker 	double deviations[DEVIATIONS];
108*49cdfc7eSAndroid Build Coastguard Worker };
109*49cdfc7eSAndroid Build Coastguard Worker 
110*49cdfc7eSAndroid Build Coastguard Worker /* container for a series of operations to a file */
111*49cdfc7eSAndroid Build Coastguard Worker struct io_oper {
112*49cdfc7eSAndroid Build Coastguard Worker 	/* already open file descriptor, valid for whatever operation you want
113*49cdfc7eSAndroid Build Coastguard Worker 	 */
114*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 	/* starting byte of the operation */
117*49cdfc7eSAndroid Build Coastguard Worker 	off_t start;
118*49cdfc7eSAndroid Build Coastguard Worker 
119*49cdfc7eSAndroid Build Coastguard Worker 	/* ending byte of the operation */
120*49cdfc7eSAndroid Build Coastguard Worker 	off_t end;
121*49cdfc7eSAndroid Build Coastguard Worker 
122*49cdfc7eSAndroid Build Coastguard Worker 	/* size of the read/write buffer */
123*49cdfc7eSAndroid Build Coastguard Worker 	int reclen;
124*49cdfc7eSAndroid Build Coastguard Worker 
125*49cdfc7eSAndroid Build Coastguard Worker 	/* max number of pending requests before a wait is triggered */
126*49cdfc7eSAndroid Build Coastguard Worker 	int depth;
127*49cdfc7eSAndroid Build Coastguard Worker 
128*49cdfc7eSAndroid Build Coastguard Worker 	/* current number of pending requests */
129*49cdfc7eSAndroid Build Coastguard Worker 	int num_pending;
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker 	/* last error, zero if there were none */
132*49cdfc7eSAndroid Build Coastguard Worker 	int last_err;
133*49cdfc7eSAndroid Build Coastguard Worker 
134*49cdfc7eSAndroid Build Coastguard Worker 	/* total number of errors hit. */
135*49cdfc7eSAndroid Build Coastguard Worker 	int num_err;
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	/* read,write, random, etc */
138*49cdfc7eSAndroid Build Coastguard Worker 	int rw;
139*49cdfc7eSAndroid Build Coastguard Worker 
140*49cdfc7eSAndroid Build Coastguard Worker 	/* number of I/O that will get sent to aio */
141*49cdfc7eSAndroid Build Coastguard Worker 	int total_ios;
142*49cdfc7eSAndroid Build Coastguard Worker 
143*49cdfc7eSAndroid Build Coastguard Worker 	/* number of I/O we've already sent */
144*49cdfc7eSAndroid Build Coastguard Worker 	int started_ios;
145*49cdfc7eSAndroid Build Coastguard Worker 
146*49cdfc7eSAndroid Build Coastguard Worker 	/* last offset used in an io operation */
147*49cdfc7eSAndroid Build Coastguard Worker 	off_t last_offset;
148*49cdfc7eSAndroid Build Coastguard Worker 
149*49cdfc7eSAndroid Build Coastguard Worker 	/* stonewalled = 1 when we got cut off before submitting all our I/O */
150*49cdfc7eSAndroid Build Coastguard Worker 	int stonewalled;
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker 	/* list management */
153*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *next;
154*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *prev;
155*49cdfc7eSAndroid Build Coastguard Worker 
156*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval start_time;
157*49cdfc7eSAndroid Build Coastguard Worker 
158*49cdfc7eSAndroid Build Coastguard Worker 	char *file_name;
159*49cdfc7eSAndroid Build Coastguard Worker };
160*49cdfc7eSAndroid Build Coastguard Worker 
161*49cdfc7eSAndroid Build Coastguard Worker /* a single io, and all the tracking needed for it */
162*49cdfc7eSAndroid Build Coastguard Worker struct io_unit {
163*49cdfc7eSAndroid Build Coastguard Worker 	/* note, iocb must go first! */
164*49cdfc7eSAndroid Build Coastguard Worker 	struct iocb iocb;
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker 	/* pointer to parent io operation struct */
167*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *io_oper;
168*49cdfc7eSAndroid Build Coastguard Worker 
169*49cdfc7eSAndroid Build Coastguard Worker 	/* aligned buffer */
170*49cdfc7eSAndroid Build Coastguard Worker 	char *buf;
171*49cdfc7eSAndroid Build Coastguard Worker 
172*49cdfc7eSAndroid Build Coastguard Worker 	/* size of the aligned buffer (record size) */
173*49cdfc7eSAndroid Build Coastguard Worker 	int buf_size;
174*49cdfc7eSAndroid Build Coastguard Worker 
175*49cdfc7eSAndroid Build Coastguard Worker 	/* state of this io unit (free, pending, done) */
176*49cdfc7eSAndroid Build Coastguard Worker 	int busy;
177*49cdfc7eSAndroid Build Coastguard Worker 
178*49cdfc7eSAndroid Build Coastguard Worker 	/* result of last operation */
179*49cdfc7eSAndroid Build Coastguard Worker 	long res;
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *next;
182*49cdfc7eSAndroid Build Coastguard Worker 
183*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval io_start_time; /* time of io_submit */
184*49cdfc7eSAndroid Build Coastguard Worker };
185*49cdfc7eSAndroid Build Coastguard Worker 
186*49cdfc7eSAndroid Build Coastguard Worker struct thread_info {
187*49cdfc7eSAndroid Build Coastguard Worker 	io_context_t io_ctx;
188*49cdfc7eSAndroid Build Coastguard Worker 	pthread_t tid;
189*49cdfc7eSAndroid Build Coastguard Worker 
190*49cdfc7eSAndroid Build Coastguard Worker 	/* allocated array of io_unit structs */
191*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *ios;
192*49cdfc7eSAndroid Build Coastguard Worker 
193*49cdfc7eSAndroid Build Coastguard Worker 	/* list of io units available for io */
194*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *free_ious;
195*49cdfc7eSAndroid Build Coastguard Worker 
196*49cdfc7eSAndroid Build Coastguard Worker 	/* number of io units in the I/O array */
197*49cdfc7eSAndroid Build Coastguard Worker 	int num_global_ios;
198*49cdfc7eSAndroid Build Coastguard Worker 
199*49cdfc7eSAndroid Build Coastguard Worker 	/* number of io units in flight */
200*49cdfc7eSAndroid Build Coastguard Worker 	int num_global_pending;
201*49cdfc7eSAndroid Build Coastguard Worker 
202*49cdfc7eSAndroid Build Coastguard Worker 	/* preallocated array of iocb pointers, only used in run_active */
203*49cdfc7eSAndroid Build Coastguard Worker 	struct iocb **iocbs;
204*49cdfc7eSAndroid Build Coastguard Worker 
205*49cdfc7eSAndroid Build Coastguard Worker 	/* preallocated array of events */
206*49cdfc7eSAndroid Build Coastguard Worker 	struct io_event *events;
207*49cdfc7eSAndroid Build Coastguard Worker 
208*49cdfc7eSAndroid Build Coastguard Worker 	/* size of the events array */
209*49cdfc7eSAndroid Build Coastguard Worker 	int num_global_events;
210*49cdfc7eSAndroid Build Coastguard Worker 
211*49cdfc7eSAndroid Build Coastguard Worker 	/* latency stats for io_submit */
212*49cdfc7eSAndroid Build Coastguard Worker 	struct io_latency io_submit_latency;
213*49cdfc7eSAndroid Build Coastguard Worker 
214*49cdfc7eSAndroid Build Coastguard Worker 	/* list of operations still in progress, and of those finished */
215*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *active_opers;
216*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *finished_opers;
217*49cdfc7eSAndroid Build Coastguard Worker 
218*49cdfc7eSAndroid Build Coastguard Worker 	/* number of files this thread is doing io on */
219*49cdfc7eSAndroid Build Coastguard Worker 	int num_files;
220*49cdfc7eSAndroid Build Coastguard Worker 
221*49cdfc7eSAndroid Build Coastguard Worker 	/* how much io this thread did in the last stage */
222*49cdfc7eSAndroid Build Coastguard Worker 	double stage_mb_trans;
223*49cdfc7eSAndroid Build Coastguard Worker 
224*49cdfc7eSAndroid Build Coastguard Worker 	/* latency completion stats i/o time from io_submit until io_getevents */
225*49cdfc7eSAndroid Build Coastguard Worker 	struct io_latency io_completion_latency;
226*49cdfc7eSAndroid Build Coastguard Worker };
227*49cdfc7eSAndroid Build Coastguard Worker 
228*49cdfc7eSAndroid Build Coastguard Worker /* pthread mutexes and other globals for keeping the threads in sync */
229*49cdfc7eSAndroid Build Coastguard Worker static pthread_barrier_t worker_barrier;
230*49cdfc7eSAndroid Build Coastguard Worker static struct timeval global_stage_start_time;
231*49cdfc7eSAndroid Build Coastguard Worker static struct thread_info *global_thread_info;
232*49cdfc7eSAndroid Build Coastguard Worker 
233*49cdfc7eSAndroid Build Coastguard Worker /*
234*49cdfc7eSAndroid Build Coastguard Worker  * return seconds between start_tv and stop_tv in double precision
235*49cdfc7eSAndroid Build Coastguard Worker  */
time_since(struct timeval * start_tv,struct timeval * stop_tv)236*49cdfc7eSAndroid Build Coastguard Worker static double time_since(struct timeval *start_tv, struct timeval *stop_tv)
237*49cdfc7eSAndroid Build Coastguard Worker {
238*49cdfc7eSAndroid Build Coastguard Worker 	double sec, usec;
239*49cdfc7eSAndroid Build Coastguard Worker 	double ret;
240*49cdfc7eSAndroid Build Coastguard Worker 
241*49cdfc7eSAndroid Build Coastguard Worker 	sec = stop_tv->tv_sec - start_tv->tv_sec;
242*49cdfc7eSAndroid Build Coastguard Worker 	usec = stop_tv->tv_usec - start_tv->tv_usec;
243*49cdfc7eSAndroid Build Coastguard Worker 	if (sec > 0 && usec < 0) {
244*49cdfc7eSAndroid Build Coastguard Worker 		sec--;
245*49cdfc7eSAndroid Build Coastguard Worker 		usec += 1000000;
246*49cdfc7eSAndroid Build Coastguard Worker 	}
247*49cdfc7eSAndroid Build Coastguard Worker 
248*49cdfc7eSAndroid Build Coastguard Worker 	ret = sec + usec / (double)1000000;
249*49cdfc7eSAndroid Build Coastguard Worker 	if (ret < 0)
250*49cdfc7eSAndroid Build Coastguard Worker 		ret = 0;
251*49cdfc7eSAndroid Build Coastguard Worker 
252*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
253*49cdfc7eSAndroid Build Coastguard Worker }
254*49cdfc7eSAndroid Build Coastguard Worker 
255*49cdfc7eSAndroid Build Coastguard Worker /*
256*49cdfc7eSAndroid Build Coastguard Worker  * return seconds between start_tv and now in double precision
257*49cdfc7eSAndroid Build Coastguard Worker  */
time_since_now(struct timeval * start_tv)258*49cdfc7eSAndroid Build Coastguard Worker static double time_since_now(struct timeval *start_tv)
259*49cdfc7eSAndroid Build Coastguard Worker {
260*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval stop_time;
261*49cdfc7eSAndroid Build Coastguard Worker 
262*49cdfc7eSAndroid Build Coastguard Worker 	gettimeofday(&stop_time, NULL);
263*49cdfc7eSAndroid Build Coastguard Worker 
264*49cdfc7eSAndroid Build Coastguard Worker 	return time_since(start_tv, &stop_time);
265*49cdfc7eSAndroid Build Coastguard Worker }
266*49cdfc7eSAndroid Build Coastguard Worker 
267*49cdfc7eSAndroid Build Coastguard Worker /*
268*49cdfc7eSAndroid Build Coastguard Worker  * Add latency info to latency struct
269*49cdfc7eSAndroid Build Coastguard Worker  */
calc_latency(struct timeval * start_tv,struct timeval * stop_tv,struct io_latency * lat)270*49cdfc7eSAndroid Build Coastguard Worker static void calc_latency(struct timeval *start_tv, struct timeval *stop_tv,
271*49cdfc7eSAndroid Build Coastguard Worker 			 struct io_latency *lat)
272*49cdfc7eSAndroid Build Coastguard Worker {
273*49cdfc7eSAndroid Build Coastguard Worker 	double delta;
274*49cdfc7eSAndroid Build Coastguard Worker 	int i;
275*49cdfc7eSAndroid Build Coastguard Worker 
276*49cdfc7eSAndroid Build Coastguard Worker 	delta = time_since(start_tv, stop_tv);
277*49cdfc7eSAndroid Build Coastguard Worker 	delta = delta * 1000;
278*49cdfc7eSAndroid Build Coastguard Worker 
279*49cdfc7eSAndroid Build Coastguard Worker 	if (delta > lat->max)
280*49cdfc7eSAndroid Build Coastguard Worker 		lat->max = delta;
281*49cdfc7eSAndroid Build Coastguard Worker 
282*49cdfc7eSAndroid Build Coastguard Worker 	if (!lat->min || delta < lat->min)
283*49cdfc7eSAndroid Build Coastguard Worker 		lat->min = delta;
284*49cdfc7eSAndroid Build Coastguard Worker 
285*49cdfc7eSAndroid Build Coastguard Worker 	lat->total_io++;
286*49cdfc7eSAndroid Build Coastguard Worker 	lat->total_lat += delta;
287*49cdfc7eSAndroid Build Coastguard Worker 
288*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < DEVIATIONS; i++) {
289*49cdfc7eSAndroid Build Coastguard Worker 		if (delta < deviations[i]) {
290*49cdfc7eSAndroid Build Coastguard Worker 			lat->deviations[i]++;
291*49cdfc7eSAndroid Build Coastguard Worker 			break;
292*49cdfc7eSAndroid Build Coastguard Worker 		}
293*49cdfc7eSAndroid Build Coastguard Worker 	}
294*49cdfc7eSAndroid Build Coastguard Worker }
295*49cdfc7eSAndroid Build Coastguard Worker 
oper_list_add(struct io_oper * oper,struct io_oper ** list)296*49cdfc7eSAndroid Build Coastguard Worker static void oper_list_add(struct io_oper *oper, struct io_oper **list)
297*49cdfc7eSAndroid Build Coastguard Worker {
298*49cdfc7eSAndroid Build Coastguard Worker 	if (!*list) {
299*49cdfc7eSAndroid Build Coastguard Worker 		*list = oper;
300*49cdfc7eSAndroid Build Coastguard Worker 		oper->prev = oper->next = oper;
301*49cdfc7eSAndroid Build Coastguard Worker 		return;
302*49cdfc7eSAndroid Build Coastguard Worker 	}
303*49cdfc7eSAndroid Build Coastguard Worker 
304*49cdfc7eSAndroid Build Coastguard Worker 	oper->prev = (*list)->prev;
305*49cdfc7eSAndroid Build Coastguard Worker 	oper->next = *list;
306*49cdfc7eSAndroid Build Coastguard Worker 
307*49cdfc7eSAndroid Build Coastguard Worker 	(*list)->prev->next = oper;
308*49cdfc7eSAndroid Build Coastguard Worker 	(*list)->prev = oper;
309*49cdfc7eSAndroid Build Coastguard Worker }
310*49cdfc7eSAndroid Build Coastguard Worker 
oper_list_del(struct io_oper * oper,struct io_oper ** list)311*49cdfc7eSAndroid Build Coastguard Worker static void oper_list_del(struct io_oper *oper, struct io_oper **list)
312*49cdfc7eSAndroid Build Coastguard Worker {
313*49cdfc7eSAndroid Build Coastguard Worker 	if ((*list)->next == (*list)->prev && *list == (*list)->next) {
314*49cdfc7eSAndroid Build Coastguard Worker 		*list = NULL;
315*49cdfc7eSAndroid Build Coastguard Worker 		return;
316*49cdfc7eSAndroid Build Coastguard Worker 	}
317*49cdfc7eSAndroid Build Coastguard Worker 
318*49cdfc7eSAndroid Build Coastguard Worker 	oper->prev->next = oper->next;
319*49cdfc7eSAndroid Build Coastguard Worker 	oper->next->prev = oper->prev;
320*49cdfc7eSAndroid Build Coastguard Worker 
321*49cdfc7eSAndroid Build Coastguard Worker 	if (*list == oper)
322*49cdfc7eSAndroid Build Coastguard Worker 		*list = oper->next;
323*49cdfc7eSAndroid Build Coastguard Worker }
324*49cdfc7eSAndroid Build Coastguard Worker 
325*49cdfc7eSAndroid Build Coastguard Worker /* worker func to check error fields in the io unit */
check_finished_io(struct io_unit * io)326*49cdfc7eSAndroid Build Coastguard Worker static int check_finished_io(struct io_unit *io)
327*49cdfc7eSAndroid Build Coastguard Worker {
328*49cdfc7eSAndroid Build Coastguard Worker 	int i;
329*49cdfc7eSAndroid Build Coastguard Worker 
330*49cdfc7eSAndroid Build Coastguard Worker 	if (io->res != io->buf_size) {
331*49cdfc7eSAndroid Build Coastguard Worker 		struct stat s;
332*49cdfc7eSAndroid Build Coastguard Worker 
333*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FSTAT(io->io_oper->fd, &s);
334*49cdfc7eSAndroid Build Coastguard Worker 
335*49cdfc7eSAndroid Build Coastguard Worker 		/*
336*49cdfc7eSAndroid Build Coastguard Worker 		 * If file size is large enough for the read, then this short
337*49cdfc7eSAndroid Build Coastguard Worker 		 * read is an error.
338*49cdfc7eSAndroid Build Coastguard Worker 		 */
339*49cdfc7eSAndroid Build Coastguard Worker 		if ((io->io_oper->rw == READ || io->io_oper->rw == RREAD) &&
340*49cdfc7eSAndroid Build Coastguard Worker 		    s.st_size > (io->iocb.u.c.offset + io->res)) {
341*49cdfc7eSAndroid Build Coastguard Worker 
342*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO, "io err %lu (%s) op %d, off %llu size %d",
343*49cdfc7eSAndroid Build Coastguard Worker 				io->res, tst_strerrno(-io->res), io->iocb.aio_lio_opcode,
344*49cdfc7eSAndroid Build Coastguard Worker 				io->iocb.u.c.offset, io->buf_size);
345*49cdfc7eSAndroid Build Coastguard Worker 			io->io_oper->last_err = io->res;
346*49cdfc7eSAndroid Build Coastguard Worker 			io->io_oper->num_err++;
347*49cdfc7eSAndroid Build Coastguard Worker 			return -1;
348*49cdfc7eSAndroid Build Coastguard Worker 		}
349*49cdfc7eSAndroid Build Coastguard Worker 	}
350*49cdfc7eSAndroid Build Coastguard Worker 
351*49cdfc7eSAndroid Build Coastguard Worker 	if (verify && io->io_oper->rw == READ) {
352*49cdfc7eSAndroid Build Coastguard Worker 		if (memcmp(io->buf, verify_buf, io->io_oper->reclen)) {
353*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO, "verify error, file %s offset %llu contents (offset:bad:good):",
354*49cdfc7eSAndroid Build Coastguard Worker 				io->io_oper->file_name, io->iocb.u.c.offset);
355*49cdfc7eSAndroid Build Coastguard Worker 
356*49cdfc7eSAndroid Build Coastguard Worker 			for (i = 0; i < io->io_oper->reclen; i++) {
357*49cdfc7eSAndroid Build Coastguard Worker 				if (io->buf[i] != verify_buf[i]) {
358*49cdfc7eSAndroid Build Coastguard Worker 					tst_res(TINFO, "%d:%c:%c ", i,
359*49cdfc7eSAndroid Build Coastguard Worker 						io->buf[i], verify_buf[i]);
360*49cdfc7eSAndroid Build Coastguard Worker 				}
361*49cdfc7eSAndroid Build Coastguard Worker 			}
362*49cdfc7eSAndroid Build Coastguard Worker 		}
363*49cdfc7eSAndroid Build Coastguard Worker 	}
364*49cdfc7eSAndroid Build Coastguard Worker 
365*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
366*49cdfc7eSAndroid Build Coastguard Worker }
367*49cdfc7eSAndroid Build Coastguard Worker 
368*49cdfc7eSAndroid Build Coastguard Worker /* worker func to check the busy bits and get an io unit ready for use */
grab_iou(struct io_unit * io,struct io_oper * oper)369*49cdfc7eSAndroid Build Coastguard Worker static int grab_iou(struct io_unit *io, struct io_oper *oper)
370*49cdfc7eSAndroid Build Coastguard Worker {
371*49cdfc7eSAndroid Build Coastguard Worker 	if (io->busy == IO_PENDING)
372*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
373*49cdfc7eSAndroid Build Coastguard Worker 
374*49cdfc7eSAndroid Build Coastguard Worker 	io->busy = IO_PENDING;
375*49cdfc7eSAndroid Build Coastguard Worker 	io->res = 0;
376*49cdfc7eSAndroid Build Coastguard Worker 	io->io_oper = oper;
377*49cdfc7eSAndroid Build Coastguard Worker 
378*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
379*49cdfc7eSAndroid Build Coastguard Worker }
380*49cdfc7eSAndroid Build Coastguard Worker 
stage_name(int rw)381*49cdfc7eSAndroid Build Coastguard Worker static char *stage_name(int rw)
382*49cdfc7eSAndroid Build Coastguard Worker {
383*49cdfc7eSAndroid Build Coastguard Worker 	switch (rw) {
384*49cdfc7eSAndroid Build Coastguard Worker 	case WRITE:
385*49cdfc7eSAndroid Build Coastguard Worker 		return "write";
386*49cdfc7eSAndroid Build Coastguard Worker 	case READ:
387*49cdfc7eSAndroid Build Coastguard Worker 		return "read";
388*49cdfc7eSAndroid Build Coastguard Worker 	case RWRITE:
389*49cdfc7eSAndroid Build Coastguard Worker 		return "random write";
390*49cdfc7eSAndroid Build Coastguard Worker 	case RREAD:
391*49cdfc7eSAndroid Build Coastguard Worker 		return "random read";
392*49cdfc7eSAndroid Build Coastguard Worker 	}
393*49cdfc7eSAndroid Build Coastguard Worker 
394*49cdfc7eSAndroid Build Coastguard Worker 	return "unknown";
395*49cdfc7eSAndroid Build Coastguard Worker }
396*49cdfc7eSAndroid Build Coastguard Worker 
oper_mb_trans(struct io_oper * oper)397*49cdfc7eSAndroid Build Coastguard Worker static inline double oper_mb_trans(struct io_oper *oper)
398*49cdfc7eSAndroid Build Coastguard Worker {
399*49cdfc7eSAndroid Build Coastguard Worker 	return ((double)oper->started_ios * (double)oper->reclen) / (double)(1024 * 1024);
400*49cdfc7eSAndroid Build Coastguard Worker }
401*49cdfc7eSAndroid Build Coastguard Worker 
print_time(struct io_oper * oper)402*49cdfc7eSAndroid Build Coastguard Worker static void print_time(struct io_oper *oper)
403*49cdfc7eSAndroid Build Coastguard Worker {
404*49cdfc7eSAndroid Build Coastguard Worker 	double runtime;
405*49cdfc7eSAndroid Build Coastguard Worker 	double tput;
406*49cdfc7eSAndroid Build Coastguard Worker 	double mb;
407*49cdfc7eSAndroid Build Coastguard Worker 
408*49cdfc7eSAndroid Build Coastguard Worker 	runtime = time_since_now(&oper->start_time);
409*49cdfc7eSAndroid Build Coastguard Worker 	mb = oper_mb_trans(oper);
410*49cdfc7eSAndroid Build Coastguard Worker 	tput = mb / runtime;
411*49cdfc7eSAndroid Build Coastguard Worker 
412*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s on %s (%.2f MB/s) %.2f MB in %.2fs",
413*49cdfc7eSAndroid Build Coastguard Worker 		stage_name(oper->rw), oper->file_name, tput, mb, runtime);
414*49cdfc7eSAndroid Build Coastguard Worker }
415*49cdfc7eSAndroid Build Coastguard Worker 
print_lat(char * str,struct io_latency * lat)416*49cdfc7eSAndroid Build Coastguard Worker static void print_lat(char *str, struct io_latency *lat)
417*49cdfc7eSAndroid Build Coastguard Worker {
418*49cdfc7eSAndroid Build Coastguard Worker 	char out[4 * 1024];
419*49cdfc7eSAndroid Build Coastguard Worker 	char *ptr = out;
420*49cdfc7eSAndroid Build Coastguard Worker 	double avg = lat->total_lat / lat->total_io;
421*49cdfc7eSAndroid Build Coastguard Worker 	int i;
422*49cdfc7eSAndroid Build Coastguard Worker 	double total_counted = 0;
423*49cdfc7eSAndroid Build Coastguard Worker 
424*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s min %.2f avg %.2f max %.2f", str, lat->min, avg, lat->max);
425*49cdfc7eSAndroid Build Coastguard Worker 
426*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < DEVIATIONS; i++) {
427*49cdfc7eSAndroid Build Coastguard Worker 		ptr += sprintf(ptr, "%.0f < %d", lat->deviations[i], deviations[i]);
428*49cdfc7eSAndroid Build Coastguard Worker 		total_counted += lat->deviations[i];
429*49cdfc7eSAndroid Build Coastguard Worker 	}
430*49cdfc7eSAndroid Build Coastguard Worker 
431*49cdfc7eSAndroid Build Coastguard Worker 	if (total_counted && lat->total_io - total_counted)
432*49cdfc7eSAndroid Build Coastguard Worker 		ptr += sprintf(ptr, " < %.0f", lat->total_io - total_counted);
433*49cdfc7eSAndroid Build Coastguard Worker 
434*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "%s", out);
435*49cdfc7eSAndroid Build Coastguard Worker 
436*49cdfc7eSAndroid Build Coastguard Worker 	memset(lat, 0, sizeof(*lat));
437*49cdfc7eSAndroid Build Coastguard Worker }
438*49cdfc7eSAndroid Build Coastguard Worker 
print_latency(struct thread_info * t)439*49cdfc7eSAndroid Build Coastguard Worker static void print_latency(struct thread_info *t)
440*49cdfc7eSAndroid Build Coastguard Worker {
441*49cdfc7eSAndroid Build Coastguard Worker 	struct io_latency *lat = &t->io_submit_latency;
442*49cdfc7eSAndroid Build Coastguard Worker 
443*49cdfc7eSAndroid Build Coastguard Worker 	print_lat("latency", lat);
444*49cdfc7eSAndroid Build Coastguard Worker }
445*49cdfc7eSAndroid Build Coastguard Worker 
print_completion_latency(struct thread_info * t)446*49cdfc7eSAndroid Build Coastguard Worker static void print_completion_latency(struct thread_info *t)
447*49cdfc7eSAndroid Build Coastguard Worker {
448*49cdfc7eSAndroid Build Coastguard Worker 	struct io_latency *lat = &t->io_completion_latency;
449*49cdfc7eSAndroid Build Coastguard Worker 
450*49cdfc7eSAndroid Build Coastguard Worker 	print_lat("completion latency", lat);
451*49cdfc7eSAndroid Build Coastguard Worker }
452*49cdfc7eSAndroid Build Coastguard Worker 
453*49cdfc7eSAndroid Build Coastguard Worker /*
454*49cdfc7eSAndroid Build Coastguard Worker  * updates the fields in the io operation struct that belongs to this
455*49cdfc7eSAndroid Build Coastguard Worker  * io unit, and make the io unit reusable again
456*49cdfc7eSAndroid Build Coastguard Worker  */
finish_io(struct thread_info * t,struct io_unit * io,long result,struct timeval * tv_now)457*49cdfc7eSAndroid Build Coastguard Worker static void finish_io(struct thread_info *t, struct io_unit *io, long result,
458*49cdfc7eSAndroid Build Coastguard Worker 		      struct timeval *tv_now)
459*49cdfc7eSAndroid Build Coastguard Worker {
460*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *oper = io->io_oper;
461*49cdfc7eSAndroid Build Coastguard Worker 
462*49cdfc7eSAndroid Build Coastguard Worker 	calc_latency(&io->io_start_time, tv_now, &t->io_completion_latency);
463*49cdfc7eSAndroid Build Coastguard Worker 	io->res = result;
464*49cdfc7eSAndroid Build Coastguard Worker 	io->busy = IO_FREE;
465*49cdfc7eSAndroid Build Coastguard Worker 	io->next = t->free_ious;
466*49cdfc7eSAndroid Build Coastguard Worker 	t->free_ious = io;
467*49cdfc7eSAndroid Build Coastguard Worker 	oper->num_pending--;
468*49cdfc7eSAndroid Build Coastguard Worker 	t->num_global_pending--;
469*49cdfc7eSAndroid Build Coastguard Worker 	check_finished_io(io);
470*49cdfc7eSAndroid Build Coastguard Worker 
471*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->num_pending == 0 &&
472*49cdfc7eSAndroid Build Coastguard Worker 	    (oper->started_ios == oper->total_ios || oper->stonewalled)) {
473*49cdfc7eSAndroid Build Coastguard Worker 		print_time(oper);
474*49cdfc7eSAndroid Build Coastguard Worker 	}
475*49cdfc7eSAndroid Build Coastguard Worker }
476*49cdfc7eSAndroid Build Coastguard Worker 
read_some_events(struct thread_info * t)477*49cdfc7eSAndroid Build Coastguard Worker static int read_some_events(struct thread_info *t)
478*49cdfc7eSAndroid Build Coastguard Worker {
479*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *event_io;
480*49cdfc7eSAndroid Build Coastguard Worker 	struct io_event *event;
481*49cdfc7eSAndroid Build Coastguard Worker 	int nr;
482*49cdfc7eSAndroid Build Coastguard Worker 	int i;
483*49cdfc7eSAndroid Build Coastguard Worker 	int min_nr = io_iter;
484*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval stop_time;
485*49cdfc7eSAndroid Build Coastguard Worker 
486*49cdfc7eSAndroid Build Coastguard Worker 	if (t->num_global_pending < io_iter)
487*49cdfc7eSAndroid Build Coastguard Worker 		min_nr = t->num_global_pending;
488*49cdfc7eSAndroid Build Coastguard Worker 
489*49cdfc7eSAndroid Build Coastguard Worker 	nr = io_getevents(t->io_ctx, min_nr, t->num_global_events, t->events, NULL);
490*49cdfc7eSAndroid Build Coastguard Worker 	if (nr <= 0)
491*49cdfc7eSAndroid Build Coastguard Worker 		return nr;
492*49cdfc7eSAndroid Build Coastguard Worker 
493*49cdfc7eSAndroid Build Coastguard Worker 	gettimeofday(&stop_time, NULL);
494*49cdfc7eSAndroid Build Coastguard Worker 
495*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nr; i++) {
496*49cdfc7eSAndroid Build Coastguard Worker 		event = t->events + i;
497*49cdfc7eSAndroid Build Coastguard Worker 		event_io = (struct io_unit *)((unsigned long)event->obj);
498*49cdfc7eSAndroid Build Coastguard Worker 		finish_io(t, event_io, event->res, &stop_time);
499*49cdfc7eSAndroid Build Coastguard Worker 	}
500*49cdfc7eSAndroid Build Coastguard Worker 
501*49cdfc7eSAndroid Build Coastguard Worker 	return nr;
502*49cdfc7eSAndroid Build Coastguard Worker }
503*49cdfc7eSAndroid Build Coastguard Worker 
504*49cdfc7eSAndroid Build Coastguard Worker /*
505*49cdfc7eSAndroid Build Coastguard Worker  * finds a free io unit, waiting for pending requests if required.  returns
506*49cdfc7eSAndroid Build Coastguard Worker  * null if none could be found
507*49cdfc7eSAndroid Build Coastguard Worker  */
find_iou(struct thread_info * t,struct io_oper * oper)508*49cdfc7eSAndroid Build Coastguard Worker static struct io_unit *find_iou(struct thread_info *t, struct io_oper *oper)
509*49cdfc7eSAndroid Build Coastguard Worker {
510*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *event_io;
511*49cdfc7eSAndroid Build Coastguard Worker 	int nr;
512*49cdfc7eSAndroid Build Coastguard Worker 
513*49cdfc7eSAndroid Build Coastguard Worker retry:
514*49cdfc7eSAndroid Build Coastguard Worker 	if (t->free_ious) {
515*49cdfc7eSAndroid Build Coastguard Worker 		event_io = t->free_ious;
516*49cdfc7eSAndroid Build Coastguard Worker 		t->free_ious = t->free_ious->next;
517*49cdfc7eSAndroid Build Coastguard Worker 
518*49cdfc7eSAndroid Build Coastguard Worker 		if (grab_iou(event_io, oper))
519*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TBROK, "io unit on free list but not free");
520*49cdfc7eSAndroid Build Coastguard Worker 
521*49cdfc7eSAndroid Build Coastguard Worker 		return event_io;
522*49cdfc7eSAndroid Build Coastguard Worker 	}
523*49cdfc7eSAndroid Build Coastguard Worker 
524*49cdfc7eSAndroid Build Coastguard Worker 	nr = read_some_events(t);
525*49cdfc7eSAndroid Build Coastguard Worker 	if (nr > 0)
526*49cdfc7eSAndroid Build Coastguard Worker 		goto retry;
527*49cdfc7eSAndroid Build Coastguard Worker 	else
528*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "no free ious after read_some_events");
529*49cdfc7eSAndroid Build Coastguard Worker 
530*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
531*49cdfc7eSAndroid Build Coastguard Worker }
532*49cdfc7eSAndroid Build Coastguard Worker 
533*49cdfc7eSAndroid Build Coastguard Worker /*
534*49cdfc7eSAndroid Build Coastguard Worker  * wait for all pending requests for this io operation to finish
535*49cdfc7eSAndroid Build Coastguard Worker  */
io_oper_wait(struct thread_info * t,struct io_oper * oper)536*49cdfc7eSAndroid Build Coastguard Worker static int io_oper_wait(struct thread_info *t, struct io_oper *oper)
537*49cdfc7eSAndroid Build Coastguard Worker {
538*49cdfc7eSAndroid Build Coastguard Worker 	struct io_event event;
539*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *event_io;
540*49cdfc7eSAndroid Build Coastguard Worker 
541*49cdfc7eSAndroid Build Coastguard Worker 	if (!oper)
542*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
543*49cdfc7eSAndroid Build Coastguard Worker 
544*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->num_pending == 0)
545*49cdfc7eSAndroid Build Coastguard Worker 		goto done;
546*49cdfc7eSAndroid Build Coastguard Worker 
547*49cdfc7eSAndroid Build Coastguard Worker 		/* this func is not speed sensitive, no need to go wild reading
548*49cdfc7eSAndroid Build Coastguard Worker 		 * more than one event at a time
549*49cdfc7eSAndroid Build Coastguard Worker 		 */
550*49cdfc7eSAndroid Build Coastguard Worker 	while (io_getevents(t->io_ctx, 1, 1, &event, NULL) > 0) {
551*49cdfc7eSAndroid Build Coastguard Worker 		struct timeval tv_now;
552*49cdfc7eSAndroid Build Coastguard Worker 
553*49cdfc7eSAndroid Build Coastguard Worker 		event_io = (struct io_unit *)((unsigned long)event.obj);
554*49cdfc7eSAndroid Build Coastguard Worker 
555*49cdfc7eSAndroid Build Coastguard Worker 		gettimeofday(&tv_now, NULL);
556*49cdfc7eSAndroid Build Coastguard Worker 		finish_io(t, event_io, event.res, &tv_now);
557*49cdfc7eSAndroid Build Coastguard Worker 
558*49cdfc7eSAndroid Build Coastguard Worker 		if (oper->num_pending == 0)
559*49cdfc7eSAndroid Build Coastguard Worker 			break;
560*49cdfc7eSAndroid Build Coastguard Worker 	}
561*49cdfc7eSAndroid Build Coastguard Worker done:
562*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->num_err)
563*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "%u errors on oper, last %u", oper->num_err, oper->last_err);
564*49cdfc7eSAndroid Build Coastguard Worker 
565*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
566*49cdfc7eSAndroid Build Coastguard Worker }
567*49cdfc7eSAndroid Build Coastguard Worker 
random_byte_offset(struct io_oper * oper)568*49cdfc7eSAndroid Build Coastguard Worker static off_t random_byte_offset(struct io_oper *oper)
569*49cdfc7eSAndroid Build Coastguard Worker {
570*49cdfc7eSAndroid Build Coastguard Worker 	off_t num;
571*49cdfc7eSAndroid Build Coastguard Worker 	off_t rand_byte = oper->start;
572*49cdfc7eSAndroid Build Coastguard Worker 	off_t range;
573*49cdfc7eSAndroid Build Coastguard Worker 	off_t offset = 1;
574*49cdfc7eSAndroid Build Coastguard Worker 
575*49cdfc7eSAndroid Build Coastguard Worker 	range = (oper->end - oper->start) / (1024 * 1024);
576*49cdfc7eSAndroid Build Coastguard Worker 
577*49cdfc7eSAndroid Build Coastguard Worker 	if ((page_size_mask + 1) > (1024 * 1024))
578*49cdfc7eSAndroid Build Coastguard Worker 		offset = (page_size_mask + 1) / (1024 * 1024);
579*49cdfc7eSAndroid Build Coastguard Worker 
580*49cdfc7eSAndroid Build Coastguard Worker 	if (range < offset)
581*49cdfc7eSAndroid Build Coastguard Worker 		range = 0;
582*49cdfc7eSAndroid Build Coastguard Worker 	else
583*49cdfc7eSAndroid Build Coastguard Worker 		range -= offset;
584*49cdfc7eSAndroid Build Coastguard Worker 
585*49cdfc7eSAndroid Build Coastguard Worker 	/* find a random mb offset */
586*49cdfc7eSAndroid Build Coastguard Worker 	num = 1 + (int)((double)range * rand() / (RAND_MAX + 1.0));
587*49cdfc7eSAndroid Build Coastguard Worker 	rand_byte += num * 1024 * 1024;
588*49cdfc7eSAndroid Build Coastguard Worker 
589*49cdfc7eSAndroid Build Coastguard Worker 	/* find a random byte offset */
590*49cdfc7eSAndroid Build Coastguard Worker 	num = 1 + (int)((double)(1024 * 1024) * rand() / (RAND_MAX + 1.0));
591*49cdfc7eSAndroid Build Coastguard Worker 
592*49cdfc7eSAndroid Build Coastguard Worker 	/* page align */
593*49cdfc7eSAndroid Build Coastguard Worker 	num = (num + page_size_mask) & ~page_size_mask;
594*49cdfc7eSAndroid Build Coastguard Worker 	rand_byte += num;
595*49cdfc7eSAndroid Build Coastguard Worker 
596*49cdfc7eSAndroid Build Coastguard Worker 	if (rand_byte + oper->reclen > oper->end)
597*49cdfc7eSAndroid Build Coastguard Worker 		rand_byte -= oper->reclen;
598*49cdfc7eSAndroid Build Coastguard Worker 
599*49cdfc7eSAndroid Build Coastguard Worker 	return rand_byte;
600*49cdfc7eSAndroid Build Coastguard Worker }
601*49cdfc7eSAndroid Build Coastguard Worker 
602*49cdfc7eSAndroid Build Coastguard Worker /*
603*49cdfc7eSAndroid Build Coastguard Worker  * build an aio iocb for an operation, based on oper->rw and the
604*49cdfc7eSAndroid Build Coastguard Worker  * last offset used.  This finds the struct io_unit that will be attached
605*49cdfc7eSAndroid Build Coastguard Worker  * to the iocb, and things are ready for submission to aio after this
606*49cdfc7eSAndroid Build Coastguard Worker  * is called.
607*49cdfc7eSAndroid Build Coastguard Worker  *
608*49cdfc7eSAndroid Build Coastguard Worker  * returns null on error
609*49cdfc7eSAndroid Build Coastguard Worker  */
build_iocb(struct thread_info * t,struct io_oper * oper)610*49cdfc7eSAndroid Build Coastguard Worker static struct io_unit *build_iocb(struct thread_info *t, struct io_oper *oper)
611*49cdfc7eSAndroid Build Coastguard Worker {
612*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *io;
613*49cdfc7eSAndroid Build Coastguard Worker 	off_t rand_byte;
614*49cdfc7eSAndroid Build Coastguard Worker 
615*49cdfc7eSAndroid Build Coastguard Worker 	io = find_iou(t, oper);
616*49cdfc7eSAndroid Build Coastguard Worker 	if (!io)
617*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "unable to find io unit");
618*49cdfc7eSAndroid Build Coastguard Worker 
619*49cdfc7eSAndroid Build Coastguard Worker 	switch (oper->rw) {
620*49cdfc7eSAndroid Build Coastguard Worker 	case WRITE:
621*49cdfc7eSAndroid Build Coastguard Worker 		io_prep_pwrite(&io->iocb, oper->fd, io->buf, oper->reclen, oper->last_offset);
622*49cdfc7eSAndroid Build Coastguard Worker 		oper->last_offset += oper->reclen;
623*49cdfc7eSAndroid Build Coastguard Worker 		break;
624*49cdfc7eSAndroid Build Coastguard Worker 	case READ:
625*49cdfc7eSAndroid Build Coastguard Worker 		io_prep_pread(&io->iocb, oper->fd, io->buf, oper->reclen, oper->last_offset);
626*49cdfc7eSAndroid Build Coastguard Worker 		oper->last_offset += oper->reclen;
627*49cdfc7eSAndroid Build Coastguard Worker 		break;
628*49cdfc7eSAndroid Build Coastguard Worker 	case RREAD:
629*49cdfc7eSAndroid Build Coastguard Worker 		rand_byte = random_byte_offset(oper);
630*49cdfc7eSAndroid Build Coastguard Worker 		oper->last_offset = rand_byte;
631*49cdfc7eSAndroid Build Coastguard Worker 		io_prep_pread(&io->iocb, oper->fd, io->buf, oper->reclen, rand_byte);
632*49cdfc7eSAndroid Build Coastguard Worker 		break;
633*49cdfc7eSAndroid Build Coastguard Worker 	case RWRITE:
634*49cdfc7eSAndroid Build Coastguard Worker 		rand_byte = random_byte_offset(oper);
635*49cdfc7eSAndroid Build Coastguard Worker 		oper->last_offset = rand_byte;
636*49cdfc7eSAndroid Build Coastguard Worker 		io_prep_pwrite(&io->iocb, oper->fd, io->buf, oper->reclen, rand_byte);
637*49cdfc7eSAndroid Build Coastguard Worker 
638*49cdfc7eSAndroid Build Coastguard Worker 		break;
639*49cdfc7eSAndroid Build Coastguard Worker 	}
640*49cdfc7eSAndroid Build Coastguard Worker 
641*49cdfc7eSAndroid Build Coastguard Worker 	return io;
642*49cdfc7eSAndroid Build Coastguard Worker }
643*49cdfc7eSAndroid Build Coastguard Worker 
644*49cdfc7eSAndroid Build Coastguard Worker /*
645*49cdfc7eSAndroid Build Coastguard Worker  * wait for any pending requests, and then free all ram associated with
646*49cdfc7eSAndroid Build Coastguard Worker  * an operation.  returns the last error the operation hit (zero means none)
647*49cdfc7eSAndroid Build Coastguard Worker  */
finish_oper(struct thread_info * t,struct io_oper * oper)648*49cdfc7eSAndroid Build Coastguard Worker static int finish_oper(struct thread_info *t, struct io_oper *oper)
649*49cdfc7eSAndroid Build Coastguard Worker {
650*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long last_err;
651*49cdfc7eSAndroid Build Coastguard Worker 
652*49cdfc7eSAndroid Build Coastguard Worker 	io_oper_wait(t, oper);
653*49cdfc7eSAndroid Build Coastguard Worker 
654*49cdfc7eSAndroid Build Coastguard Worker 	last_err = oper->last_err;
655*49cdfc7eSAndroid Build Coastguard Worker 
656*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->num_pending > 0)
657*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "oper num_pending is %d", oper->num_pending);
658*49cdfc7eSAndroid Build Coastguard Worker 
659*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(oper->fd);
660*49cdfc7eSAndroid Build Coastguard Worker 	free(oper);
661*49cdfc7eSAndroid Build Coastguard Worker 
662*49cdfc7eSAndroid Build Coastguard Worker 	return last_err;
663*49cdfc7eSAndroid Build Coastguard Worker }
664*49cdfc7eSAndroid Build Coastguard Worker 
665*49cdfc7eSAndroid Build Coastguard Worker /*
666*49cdfc7eSAndroid Build Coastguard Worker  * allocates an io operation and fills in all the fields.  returns
667*49cdfc7eSAndroid Build Coastguard Worker  * null on error
668*49cdfc7eSAndroid Build Coastguard Worker  */
create_oper(int fd,int rw,off_t start,off_t end,int reclen,int depth,char * file_name)669*49cdfc7eSAndroid Build Coastguard Worker static struct io_oper *create_oper(int fd, int rw, off_t start, off_t end,
670*49cdfc7eSAndroid Build Coastguard Worker 				   int reclen, int depth, char *file_name)
671*49cdfc7eSAndroid Build Coastguard Worker {
672*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *oper;
673*49cdfc7eSAndroid Build Coastguard Worker 
674*49cdfc7eSAndroid Build Coastguard Worker 	oper = SAFE_MALLOC(sizeof(*oper));
675*49cdfc7eSAndroid Build Coastguard Worker 	memset(oper, 0, sizeof(*oper));
676*49cdfc7eSAndroid Build Coastguard Worker 
677*49cdfc7eSAndroid Build Coastguard Worker 	oper->depth = depth;
678*49cdfc7eSAndroid Build Coastguard Worker 	oper->start = start;
679*49cdfc7eSAndroid Build Coastguard Worker 	oper->end = end;
680*49cdfc7eSAndroid Build Coastguard Worker 	oper->last_offset = oper->start;
681*49cdfc7eSAndroid Build Coastguard Worker 	oper->fd = fd;
682*49cdfc7eSAndroid Build Coastguard Worker 	oper->reclen = reclen;
683*49cdfc7eSAndroid Build Coastguard Worker 	oper->rw = rw;
684*49cdfc7eSAndroid Build Coastguard Worker 	oper->total_ios = (oper->end - oper->start) / oper->reclen;
685*49cdfc7eSAndroid Build Coastguard Worker 	oper->file_name = file_name;
686*49cdfc7eSAndroid Build Coastguard Worker 
687*49cdfc7eSAndroid Build Coastguard Worker 	return oper;
688*49cdfc7eSAndroid Build Coastguard Worker }
689*49cdfc7eSAndroid Build Coastguard Worker 
690*49cdfc7eSAndroid Build Coastguard Worker /*
691*49cdfc7eSAndroid Build Coastguard Worker  * does setup on num_ios worth of iocbs, but does not actually
692*49cdfc7eSAndroid Build Coastguard Worker  * start any io
693*49cdfc7eSAndroid Build Coastguard Worker  */
build_oper(struct thread_info * t,struct io_oper * oper,int num_ios,struct iocb ** my_iocbs)694*49cdfc7eSAndroid Build Coastguard Worker static int build_oper(struct thread_info *t, struct io_oper *oper, int num_ios,
695*49cdfc7eSAndroid Build Coastguard Worker 		      struct iocb **my_iocbs)
696*49cdfc7eSAndroid Build Coastguard Worker {
697*49cdfc7eSAndroid Build Coastguard Worker 	int i;
698*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *io;
699*49cdfc7eSAndroid Build Coastguard Worker 
700*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->started_ios == 0)
701*49cdfc7eSAndroid Build Coastguard Worker 		gettimeofday(&oper->start_time, NULL);
702*49cdfc7eSAndroid Build Coastguard Worker 
703*49cdfc7eSAndroid Build Coastguard Worker 	if (num_ios == 0)
704*49cdfc7eSAndroid Build Coastguard Worker 		num_ios = oper->total_ios;
705*49cdfc7eSAndroid Build Coastguard Worker 
706*49cdfc7eSAndroid Build Coastguard Worker 	if ((oper->started_ios + num_ios) > oper->total_ios)
707*49cdfc7eSAndroid Build Coastguard Worker 		num_ios = oper->total_ios - oper->started_ios;
708*49cdfc7eSAndroid Build Coastguard Worker 
709*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_ios; i++) {
710*49cdfc7eSAndroid Build Coastguard Worker 		io = build_iocb(t, oper);
711*49cdfc7eSAndroid Build Coastguard Worker 		if (!io)
712*49cdfc7eSAndroid Build Coastguard Worker 			return -1;
713*49cdfc7eSAndroid Build Coastguard Worker 
714*49cdfc7eSAndroid Build Coastguard Worker 		my_iocbs[i] = &io->iocb;
715*49cdfc7eSAndroid Build Coastguard Worker 	}
716*49cdfc7eSAndroid Build Coastguard Worker 
717*49cdfc7eSAndroid Build Coastguard Worker 	return num_ios;
718*49cdfc7eSAndroid Build Coastguard Worker }
719*49cdfc7eSAndroid Build Coastguard Worker 
720*49cdfc7eSAndroid Build Coastguard Worker /*
721*49cdfc7eSAndroid Build Coastguard Worker  * runs through the iocbs in the array provided and updates
722*49cdfc7eSAndroid Build Coastguard Worker  * counters in the associated oper struct
723*49cdfc7eSAndroid Build Coastguard Worker  */
update_iou_counters(struct iocb ** my_iocbs,int nr,struct timeval * tv_now)724*49cdfc7eSAndroid Build Coastguard Worker static void update_iou_counters(struct iocb **my_iocbs, int nr, struct timeval *tv_now)
725*49cdfc7eSAndroid Build Coastguard Worker {
726*49cdfc7eSAndroid Build Coastguard Worker 	struct io_unit *io;
727*49cdfc7eSAndroid Build Coastguard Worker 	int i;
728*49cdfc7eSAndroid Build Coastguard Worker 
729*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nr; i++) {
730*49cdfc7eSAndroid Build Coastguard Worker 		io = (struct io_unit *)(my_iocbs[i]);
731*49cdfc7eSAndroid Build Coastguard Worker 		io->io_oper->num_pending++;
732*49cdfc7eSAndroid Build Coastguard Worker 		io->io_oper->started_ios++;
733*49cdfc7eSAndroid Build Coastguard Worker 		io->io_start_time = *tv_now; /* set time of io_submit */
734*49cdfc7eSAndroid Build Coastguard Worker 	}
735*49cdfc7eSAndroid Build Coastguard Worker }
736*49cdfc7eSAndroid Build Coastguard Worker 
737*49cdfc7eSAndroid Build Coastguard Worker /* starts some io for a given file, returns zero if all went well */
run_built(struct thread_info * t,int num_ios,struct iocb ** my_iocbs)738*49cdfc7eSAndroid Build Coastguard Worker static int run_built(struct thread_info *t, int num_ios, struct iocb **my_iocbs)
739*49cdfc7eSAndroid Build Coastguard Worker {
740*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
741*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval start_time;
742*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval stop_time;
743*49cdfc7eSAndroid Build Coastguard Worker 
744*49cdfc7eSAndroid Build Coastguard Worker resubmit:
745*49cdfc7eSAndroid Build Coastguard Worker 	gettimeofday(&start_time, NULL);
746*49cdfc7eSAndroid Build Coastguard Worker 	ret = io_submit(t->io_ctx, num_ios, my_iocbs);
747*49cdfc7eSAndroid Build Coastguard Worker 
748*49cdfc7eSAndroid Build Coastguard Worker 	gettimeofday(&stop_time, NULL);
749*49cdfc7eSAndroid Build Coastguard Worker 	calc_latency(&start_time, &stop_time, &t->io_submit_latency);
750*49cdfc7eSAndroid Build Coastguard Worker 
751*49cdfc7eSAndroid Build Coastguard Worker 	if (ret != num_ios) {
752*49cdfc7eSAndroid Build Coastguard Worker 		/* some I/O got through */
753*49cdfc7eSAndroid Build Coastguard Worker 		if (ret > 0) {
754*49cdfc7eSAndroid Build Coastguard Worker 			update_iou_counters(my_iocbs, ret, &stop_time);
755*49cdfc7eSAndroid Build Coastguard Worker 			my_iocbs += ret;
756*49cdfc7eSAndroid Build Coastguard Worker 			t->num_global_pending += ret;
757*49cdfc7eSAndroid Build Coastguard Worker 			num_ios -= ret;
758*49cdfc7eSAndroid Build Coastguard Worker 		}
759*49cdfc7eSAndroid Build Coastguard Worker 		/*
760*49cdfc7eSAndroid Build Coastguard Worker 		 * we've used all the requests allocated in aio_init, wait and
761*49cdfc7eSAndroid Build Coastguard Worker 		 * retry
762*49cdfc7eSAndroid Build Coastguard Worker 		 */
763*49cdfc7eSAndroid Build Coastguard Worker 		if (ret > 0 || ret == -EAGAIN) {
764*49cdfc7eSAndroid Build Coastguard Worker 			int old_ret = ret;
765*49cdfc7eSAndroid Build Coastguard Worker 
766*49cdfc7eSAndroid Build Coastguard Worker 			ret = read_some_events(t);
767*49cdfc7eSAndroid Build Coastguard Worker 			if (ret <= 0)
768*49cdfc7eSAndroid Build Coastguard Worker 				tst_brk(TBROK, "ret was %d and now is %d", ret, old_ret);
769*49cdfc7eSAndroid Build Coastguard Worker 
770*49cdfc7eSAndroid Build Coastguard Worker 			goto resubmit;
771*49cdfc7eSAndroid Build Coastguard Worker 		}
772*49cdfc7eSAndroid Build Coastguard Worker 
773*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "ret %d (%s) on io_submit", ret, tst_strerrno(-ret));
774*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
775*49cdfc7eSAndroid Build Coastguard Worker 	}
776*49cdfc7eSAndroid Build Coastguard Worker 
777*49cdfc7eSAndroid Build Coastguard Worker 	update_iou_counters(my_iocbs, ret, &stop_time);
778*49cdfc7eSAndroid Build Coastguard Worker 	t->num_global_pending += ret;
779*49cdfc7eSAndroid Build Coastguard Worker 
780*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
781*49cdfc7eSAndroid Build Coastguard Worker }
782*49cdfc7eSAndroid Build Coastguard Worker 
783*49cdfc7eSAndroid Build Coastguard Worker /*
784*49cdfc7eSAndroid Build Coastguard Worker  * changes oper->rw to the next in a command sequence, or returns zero
785*49cdfc7eSAndroid Build Coastguard Worker  * to say this operation is really, completely done for
786*49cdfc7eSAndroid Build Coastguard Worker  */
restart_oper(struct io_oper * oper)787*49cdfc7eSAndroid Build Coastguard Worker static int restart_oper(struct io_oper *oper)
788*49cdfc7eSAndroid Build Coastguard Worker {
789*49cdfc7eSAndroid Build Coastguard Worker 	int new_rw = 0;
790*49cdfc7eSAndroid Build Coastguard Worker 
791*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->last_err)
792*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
793*49cdfc7eSAndroid Build Coastguard Worker 
794*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->rw == WRITE && (stages & (1 << READ)))
795*49cdfc7eSAndroid Build Coastguard Worker 		new_rw = READ;
796*49cdfc7eSAndroid Build Coastguard Worker 
797*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->rw == READ && (!new_rw && stages & (1 << RWRITE)))
798*49cdfc7eSAndroid Build Coastguard Worker 		new_rw = RWRITE;
799*49cdfc7eSAndroid Build Coastguard Worker 
800*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->rw == RWRITE && (!new_rw && stages & (1 << RREAD)))
801*49cdfc7eSAndroid Build Coastguard Worker 		new_rw = RREAD;
802*49cdfc7eSAndroid Build Coastguard Worker 
803*49cdfc7eSAndroid Build Coastguard Worker 	if (new_rw) {
804*49cdfc7eSAndroid Build Coastguard Worker 		oper->started_ios = 0;
805*49cdfc7eSAndroid Build Coastguard Worker 		oper->last_offset = oper->start;
806*49cdfc7eSAndroid Build Coastguard Worker 		oper->stonewalled = 0;
807*49cdfc7eSAndroid Build Coastguard Worker 
808*49cdfc7eSAndroid Build Coastguard Worker 		/*
809*49cdfc7eSAndroid Build Coastguard Worker 		 * we're restarting an operation with pending requests, so the
810*49cdfc7eSAndroid Build Coastguard Worker 		 * timing info won't be printed by finish_io.  Printing it here
811*49cdfc7eSAndroid Build Coastguard Worker 		 */
812*49cdfc7eSAndroid Build Coastguard Worker 		if (oper->num_pending)
813*49cdfc7eSAndroid Build Coastguard Worker 			print_time(oper);
814*49cdfc7eSAndroid Build Coastguard Worker 
815*49cdfc7eSAndroid Build Coastguard Worker 		oper->rw = new_rw;
816*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
817*49cdfc7eSAndroid Build Coastguard Worker 	}
818*49cdfc7eSAndroid Build Coastguard Worker 
819*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
820*49cdfc7eSAndroid Build Coastguard Worker }
821*49cdfc7eSAndroid Build Coastguard Worker 
oper_runnable(struct io_oper * oper)822*49cdfc7eSAndroid Build Coastguard Worker static int oper_runnable(struct io_oper *oper)
823*49cdfc7eSAndroid Build Coastguard Worker {
824*49cdfc7eSAndroid Build Coastguard Worker 	struct stat buf;
825*49cdfc7eSAndroid Build Coastguard Worker 
826*49cdfc7eSAndroid Build Coastguard Worker 	/* first context is always runnable, if started_ios > 0, no need to
827*49cdfc7eSAndroid Build Coastguard Worker 	 * redo the calculations
828*49cdfc7eSAndroid Build Coastguard Worker 	 */
829*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->started_ios || oper->start == 0)
830*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
831*49cdfc7eSAndroid Build Coastguard Worker 
832*49cdfc7eSAndroid Build Coastguard Worker 	/* only the sequential phases force delays in starting */
833*49cdfc7eSAndroid Build Coastguard Worker 	if (oper->rw >= RWRITE)
834*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
835*49cdfc7eSAndroid Build Coastguard Worker 
836*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FSTAT(oper->fd, &buf);
837*49cdfc7eSAndroid Build Coastguard Worker 	if (S_ISREG(buf.st_mode) && buf.st_size < oper->start)
838*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
839*49cdfc7eSAndroid Build Coastguard Worker 
840*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
841*49cdfc7eSAndroid Build Coastguard Worker }
842*49cdfc7eSAndroid Build Coastguard Worker 
843*49cdfc7eSAndroid Build Coastguard Worker /*
844*49cdfc7eSAndroid Build Coastguard Worker  * runs through all the io operations on the active list, and starts
845*49cdfc7eSAndroid Build Coastguard Worker  * a chunk of io on each.  If any io operations are completely finished,
846*49cdfc7eSAndroid Build Coastguard Worker  * it either switches them to the next stage or puts them on the
847*49cdfc7eSAndroid Build Coastguard Worker  * finished list.
848*49cdfc7eSAndroid Build Coastguard Worker  *
849*49cdfc7eSAndroid Build Coastguard Worker  * this function stops after max_io_submit iocbs are sent down the
850*49cdfc7eSAndroid Build Coastguard Worker  * pipe, even if it has not yet touched all the operations on the
851*49cdfc7eSAndroid Build Coastguard Worker  * active list.  Any operations that have finished are moved onto
852*49cdfc7eSAndroid Build Coastguard Worker  * the finished_opers list.
853*49cdfc7eSAndroid Build Coastguard Worker  */
run_active_list(struct thread_info * t,int io_iter,int max_io_submit)854*49cdfc7eSAndroid Build Coastguard Worker static int run_active_list(struct thread_info *t, int io_iter, int max_io_submit)
855*49cdfc7eSAndroid Build Coastguard Worker {
856*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *oper;
857*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *built_opers = NULL;
858*49cdfc7eSAndroid Build Coastguard Worker 	struct iocb **my_iocbs = t->iocbs;
859*49cdfc7eSAndroid Build Coastguard Worker 	int ret = 0;
860*49cdfc7eSAndroid Build Coastguard Worker 	int num_built = 0;
861*49cdfc7eSAndroid Build Coastguard Worker 
862*49cdfc7eSAndroid Build Coastguard Worker 	oper = t->active_opers;
863*49cdfc7eSAndroid Build Coastguard Worker 
864*49cdfc7eSAndroid Build Coastguard Worker 	while (oper) {
865*49cdfc7eSAndroid Build Coastguard Worker 		if (!oper_runnable(oper)) {
866*49cdfc7eSAndroid Build Coastguard Worker 			oper = oper->next;
867*49cdfc7eSAndroid Build Coastguard Worker 			if (oper == t->active_opers)
868*49cdfc7eSAndroid Build Coastguard Worker 				break;
869*49cdfc7eSAndroid Build Coastguard Worker 			continue;
870*49cdfc7eSAndroid Build Coastguard Worker 		}
871*49cdfc7eSAndroid Build Coastguard Worker 
872*49cdfc7eSAndroid Build Coastguard Worker 		ret = build_oper(t, oper, io_iter, my_iocbs);
873*49cdfc7eSAndroid Build Coastguard Worker 		if (ret >= 0) {
874*49cdfc7eSAndroid Build Coastguard Worker 			my_iocbs += ret;
875*49cdfc7eSAndroid Build Coastguard Worker 			num_built += ret;
876*49cdfc7eSAndroid Build Coastguard Worker 			oper_list_del(oper, &t->active_opers);
877*49cdfc7eSAndroid Build Coastguard Worker 			oper_list_add(oper, &built_opers);
878*49cdfc7eSAndroid Build Coastguard Worker 			oper = t->active_opers;
879*49cdfc7eSAndroid Build Coastguard Worker 			if (num_built + io_iter > max_io_submit)
880*49cdfc7eSAndroid Build Coastguard Worker 				break;
881*49cdfc7eSAndroid Build Coastguard Worker 		} else
882*49cdfc7eSAndroid Build Coastguard Worker 			break;
883*49cdfc7eSAndroid Build Coastguard Worker 	}
884*49cdfc7eSAndroid Build Coastguard Worker 
885*49cdfc7eSAndroid Build Coastguard Worker 	if (num_built) {
886*49cdfc7eSAndroid Build Coastguard Worker 		ret = run_built(t, num_built, t->iocbs);
887*49cdfc7eSAndroid Build Coastguard Worker 		if (ret < 0)
888*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TBROK, "error %d on run_built", ret);
889*49cdfc7eSAndroid Build Coastguard Worker 
890*49cdfc7eSAndroid Build Coastguard Worker 		while (built_opers) {
891*49cdfc7eSAndroid Build Coastguard Worker 			oper = built_opers;
892*49cdfc7eSAndroid Build Coastguard Worker 			oper_list_del(oper, &built_opers);
893*49cdfc7eSAndroid Build Coastguard Worker 			oper_list_add(oper, &t->active_opers);
894*49cdfc7eSAndroid Build Coastguard Worker 			if (oper->started_ios == oper->total_ios) {
895*49cdfc7eSAndroid Build Coastguard Worker 				oper_list_del(oper, &t->active_opers);
896*49cdfc7eSAndroid Build Coastguard Worker 				oper_list_add(oper, &t->finished_opers);
897*49cdfc7eSAndroid Build Coastguard Worker 			}
898*49cdfc7eSAndroid Build Coastguard Worker 		}
899*49cdfc7eSAndroid Build Coastguard Worker 	}
900*49cdfc7eSAndroid Build Coastguard Worker 
901*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
902*49cdfc7eSAndroid Build Coastguard Worker }
903*49cdfc7eSAndroid Build Coastguard Worker 
aio_setup(io_context_t * io_ctx,int n)904*49cdfc7eSAndroid Build Coastguard Worker static void aio_setup(io_context_t *io_ctx, int n)
905*49cdfc7eSAndroid Build Coastguard Worker {
906*49cdfc7eSAndroid Build Coastguard Worker 	int res = io_queue_init(n, io_ctx);
907*49cdfc7eSAndroid Build Coastguard Worker 
908*49cdfc7eSAndroid Build Coastguard Worker 	if (res != 0)
909*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "io_queue_setup(%d) returned %d (%s)", n, res, tst_strerrno(-res));
910*49cdfc7eSAndroid Build Coastguard Worker }
911*49cdfc7eSAndroid Build Coastguard Worker 
912*49cdfc7eSAndroid Build Coastguard Worker /*
913*49cdfc7eSAndroid Build Coastguard Worker  * allocate io operation and event arrays for a given thread
914*49cdfc7eSAndroid Build Coastguard Worker  */
setup_ious(struct thread_info * t,int num_files,int depth,int reclen,int max_io_submit)915*49cdfc7eSAndroid Build Coastguard Worker static void setup_ious(struct thread_info *t, int num_files, int depth, int reclen, int max_io_submit)
916*49cdfc7eSAndroid Build Coastguard Worker {
917*49cdfc7eSAndroid Build Coastguard Worker 	int i;
918*49cdfc7eSAndroid Build Coastguard Worker 	size_t bytes = num_files * depth * sizeof(*t->ios);
919*49cdfc7eSAndroid Build Coastguard Worker 
920*49cdfc7eSAndroid Build Coastguard Worker 	t->ios = SAFE_MALLOC(bytes);
921*49cdfc7eSAndroid Build Coastguard Worker 
922*49cdfc7eSAndroid Build Coastguard Worker 	memset(t->ios, 0, bytes);
923*49cdfc7eSAndroid Build Coastguard Worker 
924*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < depth * num_files; i++) {
925*49cdfc7eSAndroid Build Coastguard Worker 		t->ios[i].buf = aligned_buffer;
926*49cdfc7eSAndroid Build Coastguard Worker 		aligned_buffer += padded_reclen;
927*49cdfc7eSAndroid Build Coastguard Worker 		t->ios[i].buf_size = reclen;
928*49cdfc7eSAndroid Build Coastguard Worker 		if (verify)
929*49cdfc7eSAndroid Build Coastguard Worker 			memset(t->ios[i].buf, 'b', reclen);
930*49cdfc7eSAndroid Build Coastguard Worker 		else
931*49cdfc7eSAndroid Build Coastguard Worker 			memset(t->ios[i].buf, 0, reclen);
932*49cdfc7eSAndroid Build Coastguard Worker 		t->ios[i].next = t->free_ious;
933*49cdfc7eSAndroid Build Coastguard Worker 		t->free_ious = t->ios + i;
934*49cdfc7eSAndroid Build Coastguard Worker 	}
935*49cdfc7eSAndroid Build Coastguard Worker 
936*49cdfc7eSAndroid Build Coastguard Worker 	if (verify) {
937*49cdfc7eSAndroid Build Coastguard Worker 		verify_buf = aligned_buffer;
938*49cdfc7eSAndroid Build Coastguard Worker 		memset(verify_buf, 'b', reclen);
939*49cdfc7eSAndroid Build Coastguard Worker 	}
940*49cdfc7eSAndroid Build Coastguard Worker 
941*49cdfc7eSAndroid Build Coastguard Worker 	t->iocbs = SAFE_MALLOC(sizeof(struct iocb *) * max_io_submit);
942*49cdfc7eSAndroid Build Coastguard Worker 	memset(t->iocbs, 0, max_io_submit * sizeof(struct iocb *));
943*49cdfc7eSAndroid Build Coastguard Worker 
944*49cdfc7eSAndroid Build Coastguard Worker 	t->events = SAFE_MALLOC(sizeof(struct io_event) * depth * num_files);
945*49cdfc7eSAndroid Build Coastguard Worker 	memset(t->events, 0, num_files * sizeof(struct io_event) * depth);
946*49cdfc7eSAndroid Build Coastguard Worker 
947*49cdfc7eSAndroid Build Coastguard Worker 	t->num_global_ios = num_files * depth;
948*49cdfc7eSAndroid Build Coastguard Worker 	t->num_global_events = t->num_global_ios;
949*49cdfc7eSAndroid Build Coastguard Worker }
950*49cdfc7eSAndroid Build Coastguard Worker 
951*49cdfc7eSAndroid Build Coastguard Worker /*
952*49cdfc7eSAndroid Build Coastguard Worker  * The buffers used for file data are allocated as a single big
953*49cdfc7eSAndroid Build Coastguard Worker  * malloc, and then each thread and operation takes a piece and uses
954*49cdfc7eSAndroid Build Coastguard Worker  * that for file data.  This lets us do a large shm or bigpages alloc
955*49cdfc7eSAndroid Build Coastguard Worker  * and without trying to find a special place in each thread to map the
956*49cdfc7eSAndroid Build Coastguard Worker  * buffers to
957*49cdfc7eSAndroid Build Coastguard Worker  */
setup_shared_mem(int num_threads,int num_files,int depth,int reclen)958*49cdfc7eSAndroid Build Coastguard Worker static int setup_shared_mem(int num_threads, int num_files, int depth, int reclen)
959*49cdfc7eSAndroid Build Coastguard Worker {
960*49cdfc7eSAndroid Build Coastguard Worker 	char *p = NULL;
961*49cdfc7eSAndroid Build Coastguard Worker 	size_t total_ram;
962*49cdfc7eSAndroid Build Coastguard Worker 
963*49cdfc7eSAndroid Build Coastguard Worker 	padded_reclen = (reclen + page_size_mask) / (page_size_mask + 1);
964*49cdfc7eSAndroid Build Coastguard Worker 	padded_reclen = padded_reclen * (page_size_mask + 1);
965*49cdfc7eSAndroid Build Coastguard Worker 	total_ram = num_files * depth * padded_reclen + num_threads;
966*49cdfc7eSAndroid Build Coastguard Worker 
967*49cdfc7eSAndroid Build Coastguard Worker 	if (verify)
968*49cdfc7eSAndroid Build Coastguard Worker 		total_ram += padded_reclen;
969*49cdfc7eSAndroid Build Coastguard Worker 
970*49cdfc7eSAndroid Build Coastguard Worker 	/* for aligning buffer after the allocation */
971*49cdfc7eSAndroid Build Coastguard Worker 	total_ram += page_size_mask;
972*49cdfc7eSAndroid Build Coastguard Worker 
973*49cdfc7eSAndroid Build Coastguard Worker 	if (use_shm == USE_MALLOC) {
974*49cdfc7eSAndroid Build Coastguard Worker 		p = SAFE_MALLOC(total_ram);
975*49cdfc7eSAndroid Build Coastguard Worker 	} else if (use_shm == USE_SHM) {
976*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_SHMGET(IPC_PRIVATE, total_ram, IPC_CREAT | 0700);
977*49cdfc7eSAndroid Build Coastguard Worker 		p = SAFE_SHMAT(shm_id, (char *)0x50000000, 0);
978*49cdfc7eSAndroid Build Coastguard Worker 	} else if (use_shm == USE_SHMFS) {
979*49cdfc7eSAndroid Build Coastguard Worker 		char mmap_name[16]; /* /dev/shm/ + null + XXXXXX */
980*49cdfc7eSAndroid Build Coastguard Worker 		int fd;
981*49cdfc7eSAndroid Build Coastguard Worker 
982*49cdfc7eSAndroid Build Coastguard Worker 		strcpy(mmap_name, "/dev/shm/XXXXXX");
983*49cdfc7eSAndroid Build Coastguard Worker 		fd = mkstemp(mmap_name);
984*49cdfc7eSAndroid Build Coastguard Worker 		if (fd < 0)
985*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TBROK, "mkstemp error");
986*49cdfc7eSAndroid Build Coastguard Worker 
987*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_UNLINK(mmap_name);
988*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FTRUNCATE(fd, total_ram);
989*49cdfc7eSAndroid Build Coastguard Worker 
990*49cdfc7eSAndroid Build Coastguard Worker 		shm_id = fd;
991*49cdfc7eSAndroid Build Coastguard Worker 
992*49cdfc7eSAndroid Build Coastguard Worker 		p = SAFE_MMAP((char *)0x50000000, total_ram,
993*49cdfc7eSAndroid Build Coastguard Worker 			      PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
994*49cdfc7eSAndroid Build Coastguard Worker 	}
995*49cdfc7eSAndroid Build Coastguard Worker 
996*49cdfc7eSAndroid Build Coastguard Worker 	unaligned_buffer = p;
997*49cdfc7eSAndroid Build Coastguard Worker 	p = (char *)((intptr_t)(p + page_size_mask) & ~page_size_mask);
998*49cdfc7eSAndroid Build Coastguard Worker 	aligned_buffer = p;
999*49cdfc7eSAndroid Build Coastguard Worker 
1000*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
1001*49cdfc7eSAndroid Build Coastguard Worker }
1002*49cdfc7eSAndroid Build Coastguard Worker 
1003*49cdfc7eSAndroid Build Coastguard Worker /*
1004*49cdfc7eSAndroid Build Coastguard Worker  * runs through all the thread_info structs and calculates a combined
1005*49cdfc7eSAndroid Build Coastguard Worker  * throughput
1006*49cdfc7eSAndroid Build Coastguard Worker  */
global_thread_throughput(struct thread_info * t,char * this_stage)1007*49cdfc7eSAndroid Build Coastguard Worker static void global_thread_throughput(struct thread_info *t, char *this_stage)
1008*49cdfc7eSAndroid Build Coastguard Worker {
1009*49cdfc7eSAndroid Build Coastguard Worker 	int i;
1010*49cdfc7eSAndroid Build Coastguard Worker 	double runtime = time_since_now(&global_stage_start_time);
1011*49cdfc7eSAndroid Build Coastguard Worker 	double total_mb = 0;
1012*49cdfc7eSAndroid Build Coastguard Worker 	double min_trans = 0;
1013*49cdfc7eSAndroid Build Coastguard Worker 
1014*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_threads; i++) {
1015*49cdfc7eSAndroid Build Coastguard Worker 		total_mb += global_thread_info[i].stage_mb_trans;
1016*49cdfc7eSAndroid Build Coastguard Worker 
1017*49cdfc7eSAndroid Build Coastguard Worker 		if (!min_trans || t->stage_mb_trans < min_trans)
1018*49cdfc7eSAndroid Build Coastguard Worker 			min_trans = t->stage_mb_trans;
1019*49cdfc7eSAndroid Build Coastguard Worker 	}
1020*49cdfc7eSAndroid Build Coastguard Worker 
1021*49cdfc7eSAndroid Build Coastguard Worker 	if (total_mb) {
1022*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "%s throughput (%.2f MB/s)", this_stage, total_mb / runtime);
1023*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "%.2f MB in %.2fs", total_mb, runtime);
1024*49cdfc7eSAndroid Build Coastguard Worker 	}
1025*49cdfc7eSAndroid Build Coastguard Worker }
1026*49cdfc7eSAndroid Build Coastguard Worker 
1027*49cdfc7eSAndroid Build Coastguard Worker /* this is the meat of the state machine.  There is a list of
1028*49cdfc7eSAndroid Build Coastguard Worker  * active operations structs, and as each one finishes the required
1029*49cdfc7eSAndroid Build Coastguard Worker  * io it is moved to a list of finished operations.  Once they have
1030*49cdfc7eSAndroid Build Coastguard Worker  * all finished whatever stage they were in, they are given the chance
1031*49cdfc7eSAndroid Build Coastguard Worker  * to restart and pick a different stage (read/write/random read etc)
1032*49cdfc7eSAndroid Build Coastguard Worker  *
1033*49cdfc7eSAndroid Build Coastguard Worker  * various timings are printed in between the stages, along with
1034*49cdfc7eSAndroid Build Coastguard Worker  * thread synchronization if there are more than one threads.
1035*49cdfc7eSAndroid Build Coastguard Worker  */
worker(struct thread_info * t)1036*49cdfc7eSAndroid Build Coastguard Worker static int *worker(struct thread_info *t)
1037*49cdfc7eSAndroid Build Coastguard Worker {
1038*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *oper;
1039*49cdfc7eSAndroid Build Coastguard Worker 	char *this_stage = NULL;
1040*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval stage_time;
1041*49cdfc7eSAndroid Build Coastguard Worker 	int status = 0;
1042*49cdfc7eSAndroid Build Coastguard Worker 	int cnt;
1043*49cdfc7eSAndroid Build Coastguard Worker 
1044*49cdfc7eSAndroid Build Coastguard Worker 	aio_setup(&t->io_ctx, 512);
1045*49cdfc7eSAndroid Build Coastguard Worker 
1046*49cdfc7eSAndroid Build Coastguard Worker restart:
1047*49cdfc7eSAndroid Build Coastguard Worker 	if (num_threads > 1) {
1048*49cdfc7eSAndroid Build Coastguard Worker 		if (pthread_barrier_wait(&worker_barrier))
1049*49cdfc7eSAndroid Build Coastguard Worker 			gettimeofday(&global_stage_start_time, NULL);
1050*49cdfc7eSAndroid Build Coastguard Worker 	}
1051*49cdfc7eSAndroid Build Coastguard Worker 
1052*49cdfc7eSAndroid Build Coastguard Worker 	if (t->active_opers) {
1053*49cdfc7eSAndroid Build Coastguard Worker 		this_stage = stage_name(t->active_opers->rw);
1054*49cdfc7eSAndroid Build Coastguard Worker 		gettimeofday(&stage_time, NULL);
1055*49cdfc7eSAndroid Build Coastguard Worker 		t->stage_mb_trans = 0;
1056*49cdfc7eSAndroid Build Coastguard Worker 	}
1057*49cdfc7eSAndroid Build Coastguard Worker 
1058*49cdfc7eSAndroid Build Coastguard Worker 	cnt = 0;
1059*49cdfc7eSAndroid Build Coastguard Worker 
1060*49cdfc7eSAndroid Build Coastguard Worker 	/* first we send everything through aio */
1061*49cdfc7eSAndroid Build Coastguard Worker 	while (t->active_opers && cnt < iterations) {
1062*49cdfc7eSAndroid Build Coastguard Worker 		run_active_list(t, io_iter, max_io_submit);
1063*49cdfc7eSAndroid Build Coastguard Worker 		cnt++;
1064*49cdfc7eSAndroid Build Coastguard Worker 	}
1065*49cdfc7eSAndroid Build Coastguard Worker 
1066*49cdfc7eSAndroid Build Coastguard Worker 	if (latency_stats)
1067*49cdfc7eSAndroid Build Coastguard Worker 		print_latency(t);
1068*49cdfc7eSAndroid Build Coastguard Worker 
1069*49cdfc7eSAndroid Build Coastguard Worker 	if (completion_latency_stats)
1070*49cdfc7eSAndroid Build Coastguard Worker 		print_completion_latency(t);
1071*49cdfc7eSAndroid Build Coastguard Worker 
1072*49cdfc7eSAndroid Build Coastguard Worker 	/* then we wait for all the operations to finish */
1073*49cdfc7eSAndroid Build Coastguard Worker 	oper = t->finished_opers;
1074*49cdfc7eSAndroid Build Coastguard Worker 	do {
1075*49cdfc7eSAndroid Build Coastguard Worker 		if (!oper)
1076*49cdfc7eSAndroid Build Coastguard Worker 			break;
1077*49cdfc7eSAndroid Build Coastguard Worker 		io_oper_wait(t, oper);
1078*49cdfc7eSAndroid Build Coastguard Worker 		oper = oper->next;
1079*49cdfc7eSAndroid Build Coastguard Worker 	} while (oper != t->finished_opers);
1080*49cdfc7eSAndroid Build Coastguard Worker 
1081*49cdfc7eSAndroid Build Coastguard Worker 	/* then we do an fsync to get the timing for any future operations
1082*49cdfc7eSAndroid Build Coastguard Worker 	 * right, and check to see if any of these need to get restarted
1083*49cdfc7eSAndroid Build Coastguard Worker 	 */
1084*49cdfc7eSAndroid Build Coastguard Worker 	oper = t->finished_opers;
1085*49cdfc7eSAndroid Build Coastguard Worker 	while (oper) {
1086*49cdfc7eSAndroid Build Coastguard Worker 		if (!no_fsync_stages)
1087*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_FSYNC(oper->fd);
1088*49cdfc7eSAndroid Build Coastguard Worker 
1089*49cdfc7eSAndroid Build Coastguard Worker 		t->stage_mb_trans += oper_mb_trans(oper);
1090*49cdfc7eSAndroid Build Coastguard Worker 
1091*49cdfc7eSAndroid Build Coastguard Worker 		if (restart_oper(oper)) {
1092*49cdfc7eSAndroid Build Coastguard Worker 			oper_list_del(oper, &t->finished_opers);
1093*49cdfc7eSAndroid Build Coastguard Worker 			oper_list_add(oper, &t->active_opers);
1094*49cdfc7eSAndroid Build Coastguard Worker 			oper = t->finished_opers;
1095*49cdfc7eSAndroid Build Coastguard Worker 			continue;
1096*49cdfc7eSAndroid Build Coastguard Worker 		}
1097*49cdfc7eSAndroid Build Coastguard Worker 
1098*49cdfc7eSAndroid Build Coastguard Worker 		oper = oper->next;
1099*49cdfc7eSAndroid Build Coastguard Worker 
1100*49cdfc7eSAndroid Build Coastguard Worker 		if (oper == t->finished_opers)
1101*49cdfc7eSAndroid Build Coastguard Worker 			break;
1102*49cdfc7eSAndroid Build Coastguard Worker 	}
1103*49cdfc7eSAndroid Build Coastguard Worker 
1104*49cdfc7eSAndroid Build Coastguard Worker 	if (t->stage_mb_trans && t->num_files > 0) {
1105*49cdfc7eSAndroid Build Coastguard Worker 		double seconds = time_since_now(&stage_time);
1106*49cdfc7eSAndroid Build Coastguard Worker 
1107*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "thread %td %s totals (%.2f MB/s) %.2f MB in %.2fs",
1108*49cdfc7eSAndroid Build Coastguard Worker 			t - global_thread_info, this_stage,
1109*49cdfc7eSAndroid Build Coastguard Worker 			t->stage_mb_trans / seconds, t->stage_mb_trans, seconds);
1110*49cdfc7eSAndroid Build Coastguard Worker 	}
1111*49cdfc7eSAndroid Build Coastguard Worker 
1112*49cdfc7eSAndroid Build Coastguard Worker 	if (num_threads > 1) {
1113*49cdfc7eSAndroid Build Coastguard Worker 		if (pthread_barrier_wait(&worker_barrier))
1114*49cdfc7eSAndroid Build Coastguard Worker 			global_thread_throughput(t, this_stage);
1115*49cdfc7eSAndroid Build Coastguard Worker 	}
1116*49cdfc7eSAndroid Build Coastguard Worker 
1117*49cdfc7eSAndroid Build Coastguard Worker 	/* someone got restarted, go back to the beginning */
1118*49cdfc7eSAndroid Build Coastguard Worker 	if (t->active_opers && cnt < iterations)
1119*49cdfc7eSAndroid Build Coastguard Worker 		goto restart;
1120*49cdfc7eSAndroid Build Coastguard Worker 
1121*49cdfc7eSAndroid Build Coastguard Worker 	/* finally, free all the ram */
1122*49cdfc7eSAndroid Build Coastguard Worker 	while (t->finished_opers) {
1123*49cdfc7eSAndroid Build Coastguard Worker 		oper = t->finished_opers;
1124*49cdfc7eSAndroid Build Coastguard Worker 		oper_list_del(oper, &t->finished_opers);
1125*49cdfc7eSAndroid Build Coastguard Worker 		status = finish_oper(t, oper);
1126*49cdfc7eSAndroid Build Coastguard Worker 	}
1127*49cdfc7eSAndroid Build Coastguard Worker 
1128*49cdfc7eSAndroid Build Coastguard Worker 	if (t->num_global_pending)
1129*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "global num pending is %d", t->num_global_pending);
1130*49cdfc7eSAndroid Build Coastguard Worker 
1131*49cdfc7eSAndroid Build Coastguard Worker 	io_queue_release(t->io_ctx);
1132*49cdfc7eSAndroid Build Coastguard Worker 
1133*49cdfc7eSAndroid Build Coastguard Worker 	return (void *)(intptr_t)status;
1134*49cdfc7eSAndroid Build Coastguard Worker }
1135*49cdfc7eSAndroid Build Coastguard Worker 
1136*49cdfc7eSAndroid Build Coastguard Worker typedef void *(*start_routine)(void *);
run_workers(struct thread_info * t,int num_threads)1137*49cdfc7eSAndroid Build Coastguard Worker static int run_workers(struct thread_info *t, int num_threads)
1138*49cdfc7eSAndroid Build Coastguard Worker {
1139*49cdfc7eSAndroid Build Coastguard Worker 	void *retval;
1140*49cdfc7eSAndroid Build Coastguard Worker 	int ret = 0;
1141*49cdfc7eSAndroid Build Coastguard Worker 	int i;
1142*49cdfc7eSAndroid Build Coastguard Worker 
1143*49cdfc7eSAndroid Build Coastguard Worker 	pthread_barrier_init(&worker_barrier, NULL, num_threads);
1144*49cdfc7eSAndroid Build Coastguard Worker 
1145*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_threads; i++)
1146*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_PTHREAD_CREATE(&t[i].tid, NULL, (start_routine)worker, t + i);
1147*49cdfc7eSAndroid Build Coastguard Worker 
1148*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_threads; i++) {
1149*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_PTHREAD_JOIN(t[i].tid, &retval);
1150*49cdfc7eSAndroid Build Coastguard Worker 		ret |= (intptr_t)retval;
1151*49cdfc7eSAndroid Build Coastguard Worker 	}
1152*49cdfc7eSAndroid Build Coastguard Worker 
1153*49cdfc7eSAndroid Build Coastguard Worker 	pthread_barrier_destroy(&worker_barrier);
1154*49cdfc7eSAndroid Build Coastguard Worker 
1155*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
1156*49cdfc7eSAndroid Build Coastguard Worker }
1157*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)1158*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
1159*49cdfc7eSAndroid Build Coastguard Worker {
1160*49cdfc7eSAndroid Build Coastguard Worker 	int maxaio;
1161*49cdfc7eSAndroid Build Coastguard Worker 	int stages_i;
1162*49cdfc7eSAndroid Build Coastguard Worker 
1163*49cdfc7eSAndroid Build Coastguard Worker 	page_size_mask = getpagesize() - 1;
1164*49cdfc7eSAndroid Build Coastguard Worker 
1165*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FILE_SCANF("/proc/sys/fs/aio-max-nr", "%d", &maxaio);
1166*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Maximum AIO blocks: %d", maxaio);
1167*49cdfc7eSAndroid Build Coastguard Worker 
1168*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_num_files, &num_files, 1, INT_MAX))
1169*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of files to generate '%s'", str_num_files);
1170*49cdfc7eSAndroid Build Coastguard Worker 
1171*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_max_io_submit, &max_io_submit, 0, INT_MAX))
1172*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of iocbs '%s'", str_max_io_submit);
1173*49cdfc7eSAndroid Build Coastguard Worker 
1174*49cdfc7eSAndroid Build Coastguard Worker 	if (max_io_submit > maxaio)
1175*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TCONF, "Number of async IO blocks passed the maximum (%d)", maxaio);
1176*49cdfc7eSAndroid Build Coastguard Worker 
1177*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_num_contexts, &num_contexts, 1, INT_MAX))
1178*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of contexts per file '%s'", str_num_contexts);
1179*49cdfc7eSAndroid Build Coastguard Worker 
1180*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_filesize(str_context_offset, &context_offset, 1, LLONG_MAX))
1181*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid offset between contexts '%s'", str_context_offset);
1182*49cdfc7eSAndroid Build Coastguard Worker 
1183*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_filesize(str_file_size, &file_size, 1, LLONG_MAX))
1184*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid file size '%s'", str_file_size);
1185*49cdfc7eSAndroid Build Coastguard Worker 
1186*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_filesize(str_rec_len, &rec_len, 1, LONG_MAX))
1187*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid record size '%s'", str_rec_len);
1188*49cdfc7eSAndroid Build Coastguard Worker 
1189*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_depth, &depth, 1, INT_MAX))
1190*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of pending aio requests '%s'", str_depth);
1191*49cdfc7eSAndroid Build Coastguard Worker 
1192*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_io_iter, &io_iter, 1, INT_MAX))
1193*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of I/O per file '%s'", str_io_iter);
1194*49cdfc7eSAndroid Build Coastguard Worker 
1195*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_iterations, &iterations, 1, INT_MAX))
1196*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of total ayncs I/O '%s'", str_iterations);
1197*49cdfc7eSAndroid Build Coastguard Worker 
1198*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_stages, &stages_i, 0, INT_MAX))
1199*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid stage number '%s'", str_stages);
1200*49cdfc7eSAndroid Build Coastguard Worker 
1201*49cdfc7eSAndroid Build Coastguard Worker 	if (stages_i) {
1202*49cdfc7eSAndroid Build Coastguard Worker 		stages |= 1 << stages_i;
1203*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Adding stage %s", stage_name(stages_i));
1204*49cdfc7eSAndroid Build Coastguard Worker 	}
1205*49cdfc7eSAndroid Build Coastguard Worker 
1206*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_num_threads, &num_threads, 1, INT_MAX))
1207*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of threads '%s'", str_num_threads);
1208*49cdfc7eSAndroid Build Coastguard Worker 
1209*49cdfc7eSAndroid Build Coastguard Worker 	if (str_o_flag) {
1210*49cdfc7eSAndroid Build Coastguard Worker 		if (tst_fs_type(".") == TST_TMPFS_MAGIC)
1211*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TCONF, "O_DIRECT not supported on tmpfs");
1212*49cdfc7eSAndroid Build Coastguard Worker 		o_flag = O_DIRECT;
1213*49cdfc7eSAndroid Build Coastguard Worker 	} else {
1214*49cdfc7eSAndroid Build Coastguard Worker 		o_flag = O_SYNC;
1215*49cdfc7eSAndroid Build Coastguard Worker 	}
1216*49cdfc7eSAndroid Build Coastguard Worker 
1217*49cdfc7eSAndroid Build Coastguard Worker 	if (str_use_shm) {
1218*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(str_use_shm, "shm")) {
1219*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO, "using ipc shm");
1220*49cdfc7eSAndroid Build Coastguard Worker 			use_shm = USE_SHM;
1221*49cdfc7eSAndroid Build Coastguard Worker 		} else if (!strcmp(str_use_shm, "shmfs")) {
1222*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO, "using /dev/shm for buffers");
1223*49cdfc7eSAndroid Build Coastguard Worker 			use_shm = USE_SHMFS;
1224*49cdfc7eSAndroid Build Coastguard Worker 		} else {
1225*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TBROK, "Invalid shm option '%s'", str_use_shm);
1226*49cdfc7eSAndroid Build Coastguard Worker 		}
1227*49cdfc7eSAndroid Build Coastguard Worker 	}
1228*49cdfc7eSAndroid Build Coastguard Worker }
1229*49cdfc7eSAndroid Build Coastguard Worker 
run(void)1230*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
1231*49cdfc7eSAndroid Build Coastguard Worker {
1232*49cdfc7eSAndroid Build Coastguard Worker 	char files[num_files][265];
1233*49cdfc7eSAndroid Build Coastguard Worker 	int first_stage = WRITE;
1234*49cdfc7eSAndroid Build Coastguard Worker 	struct io_oper *oper;
1235*49cdfc7eSAndroid Build Coastguard Worker 	int status = 0;
1236*49cdfc7eSAndroid Build Coastguard Worker 	int open_fds = 0;
1237*49cdfc7eSAndroid Build Coastguard Worker 	struct thread_info *t;
1238*49cdfc7eSAndroid Build Coastguard Worker 	int rwfd;
1239*49cdfc7eSAndroid Build Coastguard Worker 	int i;
1240*49cdfc7eSAndroid Build Coastguard Worker 	int j;
1241*49cdfc7eSAndroid Build Coastguard Worker 
1242*49cdfc7eSAndroid Build Coastguard Worker 	/*
1243*49cdfc7eSAndroid Build Coastguard Worker 	 * make sure we don't try to submit more I/O than we have allocated
1244*49cdfc7eSAndroid Build Coastguard Worker 	 * memory for
1245*49cdfc7eSAndroid Build Coastguard Worker 	 */
1246*49cdfc7eSAndroid Build Coastguard Worker 	if (depth < io_iter) {
1247*49cdfc7eSAndroid Build Coastguard Worker 		io_iter = depth;
1248*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "dropping io_iter to %d", io_iter);
1249*49cdfc7eSAndroid Build Coastguard Worker 	}
1250*49cdfc7eSAndroid Build Coastguard Worker 
1251*49cdfc7eSAndroid Build Coastguard Worker 	if (num_threads > (num_files * num_contexts)) {
1252*49cdfc7eSAndroid Build Coastguard Worker 		num_threads = num_files * num_contexts;
1253*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Dropping thread count to the number of contexts %d", num_threads);
1254*49cdfc7eSAndroid Build Coastguard Worker 	}
1255*49cdfc7eSAndroid Build Coastguard Worker 
1256*49cdfc7eSAndroid Build Coastguard Worker 	t = SAFE_MALLOC(num_threads * sizeof(*t));
1257*49cdfc7eSAndroid Build Coastguard Worker 	memset(t, 0, num_threads * sizeof(*t));
1258*49cdfc7eSAndroid Build Coastguard Worker 	global_thread_info = t;
1259*49cdfc7eSAndroid Build Coastguard Worker 
1260*49cdfc7eSAndroid Build Coastguard Worker 	/* by default, allow a huge number of iocbs to be sent towards
1261*49cdfc7eSAndroid Build Coastguard Worker 	 * io_submit
1262*49cdfc7eSAndroid Build Coastguard Worker 	 */
1263*49cdfc7eSAndroid Build Coastguard Worker 	if (!max_io_submit)
1264*49cdfc7eSAndroid Build Coastguard Worker 		max_io_submit = num_files * io_iter * num_contexts;
1265*49cdfc7eSAndroid Build Coastguard Worker 
1266*49cdfc7eSAndroid Build Coastguard Worker 	/*
1267*49cdfc7eSAndroid Build Coastguard Worker 	 * make sure we don't try to submit more I/O than max_io_submit allows
1268*49cdfc7eSAndroid Build Coastguard Worker 	 */
1269*49cdfc7eSAndroid Build Coastguard Worker 	if (max_io_submit < io_iter) {
1270*49cdfc7eSAndroid Build Coastguard Worker 		io_iter = max_io_submit;
1271*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "dropping io_iter to %d", io_iter);
1272*49cdfc7eSAndroid Build Coastguard Worker 	}
1273*49cdfc7eSAndroid Build Coastguard Worker 
1274*49cdfc7eSAndroid Build Coastguard Worker 	if (!stages) {
1275*49cdfc7eSAndroid Build Coastguard Worker 		stages = (1 << WRITE) | (1 << READ) | (1 << RREAD) | (1 << RWRITE);
1276*49cdfc7eSAndroid Build Coastguard Worker 	} else {
1277*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < LAST_STAGE; i++) {
1278*49cdfc7eSAndroid Build Coastguard Worker 			if (stages & (1 << i)) {
1279*49cdfc7eSAndroid Build Coastguard Worker 				first_stage = i;
1280*49cdfc7eSAndroid Build Coastguard Worker 				tst_res(TINFO, "starting with %s", stage_name(i));
1281*49cdfc7eSAndroid Build Coastguard Worker 				break;
1282*49cdfc7eSAndroid Build Coastguard Worker 			}
1283*49cdfc7eSAndroid Build Coastguard Worker 		}
1284*49cdfc7eSAndroid Build Coastguard Worker 	}
1285*49cdfc7eSAndroid Build Coastguard Worker 
1286*49cdfc7eSAndroid Build Coastguard Worker 	if (file_size < num_contexts * context_offset) {
1287*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "file size %ld too small for %d contexts",
1288*49cdfc7eSAndroid Build Coastguard Worker 			(long)file_size, num_contexts);
1289*49cdfc7eSAndroid Build Coastguard Worker 	}
1290*49cdfc7eSAndroid Build Coastguard Worker 
1291*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "file size %ldMB, record size %lldKB, depth %d, I/O per iteration %d",
1292*49cdfc7eSAndroid Build Coastguard Worker 		(long)(file_size / (1024 * 1024)), rec_len / 1024, depth, io_iter);
1293*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "max io_submit %d, buffer alignment set to %luKB",
1294*49cdfc7eSAndroid Build Coastguard Worker 		max_io_submit, (page_size_mask + 1) / 1024);
1295*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "threads %d files %d contexts %d context offset %ldMB verification %s",
1296*49cdfc7eSAndroid Build Coastguard Worker 		num_threads, num_files, num_contexts,
1297*49cdfc7eSAndroid Build Coastguard Worker 		(long)(context_offset / (1024 * 1024)), verify ? "on" : "off");
1298*49cdfc7eSAndroid Build Coastguard Worker 
1299*49cdfc7eSAndroid Build Coastguard Worker 	/* open all the files and do any required setup for them */
1300*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_files; i++) {
1301*49cdfc7eSAndroid Build Coastguard Worker 		int thread_index;
1302*49cdfc7eSAndroid Build Coastguard Worker 
1303*49cdfc7eSAndroid Build Coastguard Worker 		snprintf(files[i], sizeof(files[i]), "file%d.bin", i);
1304*49cdfc7eSAndroid Build Coastguard Worker 
1305*49cdfc7eSAndroid Build Coastguard Worker 		for (j = 0; j < num_contexts; j++) {
1306*49cdfc7eSAndroid Build Coastguard Worker 			thread_index = open_fds % num_threads;
1307*49cdfc7eSAndroid Build Coastguard Worker 			open_fds++;
1308*49cdfc7eSAndroid Build Coastguard Worker 
1309*49cdfc7eSAndroid Build Coastguard Worker 			rwfd = SAFE_OPEN(files[i], O_CREAT | O_RDWR | o_flag, 0600);
1310*49cdfc7eSAndroid Build Coastguard Worker 
1311*49cdfc7eSAndroid Build Coastguard Worker 			oper = create_oper(rwfd, first_stage, j * context_offset,
1312*49cdfc7eSAndroid Build Coastguard Worker 					   file_size - j * context_offset,
1313*49cdfc7eSAndroid Build Coastguard Worker 					   rec_len, depth, files[i]);
1314*49cdfc7eSAndroid Build Coastguard Worker 			if (!oper)
1315*49cdfc7eSAndroid Build Coastguard Worker 				tst_brk(TBROK, "error in create_oper");
1316*49cdfc7eSAndroid Build Coastguard Worker 
1317*49cdfc7eSAndroid Build Coastguard Worker 			oper_list_add(oper, &t[thread_index].active_opers);
1318*49cdfc7eSAndroid Build Coastguard Worker 			t[thread_index].num_files++;
1319*49cdfc7eSAndroid Build Coastguard Worker 		}
1320*49cdfc7eSAndroid Build Coastguard Worker 	}
1321*49cdfc7eSAndroid Build Coastguard Worker 
1322*49cdfc7eSAndroid Build Coastguard Worker 	if (setup_shared_mem(num_threads, num_files * num_contexts, depth, rec_len))
1323*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "error in setup_shared_mem");
1324*49cdfc7eSAndroid Build Coastguard Worker 
1325*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_threads; i++)
1326*49cdfc7eSAndroid Build Coastguard Worker 		setup_ious(&t[i], t[i].num_files, depth, rec_len, max_io_submit);
1327*49cdfc7eSAndroid Build Coastguard Worker 
1328*49cdfc7eSAndroid Build Coastguard Worker 	if (num_threads > 1) {
1329*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Running multi thread version num_threads: %d", num_threads);
1330*49cdfc7eSAndroid Build Coastguard Worker 		status = run_workers(t, num_threads);
1331*49cdfc7eSAndroid Build Coastguard Worker 	} else {
1332*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Running single thread version");
1333*49cdfc7eSAndroid Build Coastguard Worker 		status = (intptr_t)worker(t);
1334*49cdfc7eSAndroid Build Coastguard Worker 	}
1335*49cdfc7eSAndroid Build Coastguard Worker 
1336*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_files; i++)
1337*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_UNLINK(files[i]);
1338*49cdfc7eSAndroid Build Coastguard Worker 
1339*49cdfc7eSAndroid Build Coastguard Worker 	if (status)
1340*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "Test did not pass");
1341*49cdfc7eSAndroid Build Coastguard Worker 	else
1342*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "Test passed");
1343*49cdfc7eSAndroid Build Coastguard Worker }
1344*49cdfc7eSAndroid Build Coastguard Worker 
1345*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
1346*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = run,
1347*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
1348*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
1349*49cdfc7eSAndroid Build Coastguard Worker 	.needs_root = 1,
1350*49cdfc7eSAndroid Build Coastguard Worker 	.max_runtime = 1800,
1351*49cdfc7eSAndroid Build Coastguard Worker 	.options = (struct tst_option[]){
1352*49cdfc7eSAndroid Build Coastguard Worker 		{ "a:", &str_iterations, "Total number of ayncs I/O the program will run (default 500)" },
1353*49cdfc7eSAndroid Build Coastguard Worker 		{ "b:", &str_max_io_submit, "Max number of iocbs to give io_submit at once" },
1354*49cdfc7eSAndroid Build Coastguard Worker 		{ "c:", &str_num_contexts, "Number of io contexts per file" },
1355*49cdfc7eSAndroid Build Coastguard Worker 		{ "d:", &str_depth, "Number of pending aio requests for each file (default 64)" },
1356*49cdfc7eSAndroid Build Coastguard Worker 		{ "e:", &str_io_iter, "Number of I/O per file sent before switching to the next file (default 8)" },
1357*49cdfc7eSAndroid Build Coastguard Worker 		{ "f:", &str_num_files, "Number of files to generate" },
1358*49cdfc7eSAndroid Build Coastguard Worker 		{ "g:", &str_context_offset, "Offset between contexts (default 2M)" },
1359*49cdfc7eSAndroid Build Coastguard Worker 		{ "l", &latency_stats, "Print io_submit latencies after each stage" },
1360*49cdfc7eSAndroid Build Coastguard Worker 		{ "L", &completion_latency_stats, "Print io completion latencies after each stage" },
1361*49cdfc7eSAndroid Build Coastguard Worker 		{ "m", &str_use_shm, "SHM use ipc shared memory for io buffers instead of malloc" },
1362*49cdfc7eSAndroid Build Coastguard Worker 		{ "n", &no_fsync_stages, "No fsyncs between write stage and read stage" },
1363*49cdfc7eSAndroid Build Coastguard Worker 		{ "o:", &str_stages, "Add an operation to the list: write=0, read=1, random write=2, random read=3" },
1364*49cdfc7eSAndroid Build Coastguard Worker 		{ "O", &str_o_flag, "Use O_DIRECT" },
1365*49cdfc7eSAndroid Build Coastguard Worker 		{ "r:", &str_rec_len, "Record size in KB used for each io (default 64K)" },
1366*49cdfc7eSAndroid Build Coastguard Worker 		{ "s:", &str_file_size, "Size in MB of the test file(s) (default 1024M)" },
1367*49cdfc7eSAndroid Build Coastguard Worker 		{ "t:", &str_num_threads, "Number of threads to run" },
1368*49cdfc7eSAndroid Build Coastguard Worker 		{ "u", &unlink_files, "Unlink files after completion" },
1369*49cdfc7eSAndroid Build Coastguard Worker 		{ "v", &verify, "Verification of bytes written" },
1370*49cdfc7eSAndroid Build Coastguard Worker 		{},
1371*49cdfc7eSAndroid Build Coastguard Worker 	},
1372*49cdfc7eSAndroid Build Coastguard Worker };
1373*49cdfc7eSAndroid Build Coastguard Worker #else
1374*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("test requires libaio and its development packages");
1375*49cdfc7eSAndroid Build Coastguard Worker #endif
1376