xref: /aosp_15_r20/external/ltp/testcases/kernel/fs/fsx-linux/fsx-linux.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 1991, NeXT Computer, Inc.  All Rights Reserverd.
4*49cdfc7eSAndroid Build Coastguard Worker  *	Author:	Avadis Tevanian, Jr.
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
7*49cdfc7eSAndroid Build Coastguard Worker  *	Conrad Minshall <[email protected]>
8*49cdfc7eSAndroid Build Coastguard Worker  *	Dave Jones <[email protected]>
9*49cdfc7eSAndroid Build Coastguard Worker  *	Zach Brown <[email protected]>
10*49cdfc7eSAndroid Build Coastguard Worker  *	Joe Sokol, Pat Dirks, Clark Warner, Guy Harris
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2023 SUSE LLC Andrea Cervesato <[email protected]>
13*49cdfc7eSAndroid Build Coastguard Worker  */
14*49cdfc7eSAndroid Build Coastguard Worker 
15*49cdfc7eSAndroid Build Coastguard Worker /*\
16*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
17*49cdfc7eSAndroid Build Coastguard Worker  *
18*49cdfc7eSAndroid Build Coastguard Worker  * This is a complete rewrite of the old fsx-linux tool, created by
19*49cdfc7eSAndroid Build Coastguard Worker  * NeXT Computer, Inc. and Apple Computer, Inc. between 1991 and 2001,
20*49cdfc7eSAndroid Build Coastguard Worker  * then adapted for LTP. Test is actually a file system exerciser: we bring a
21*49cdfc7eSAndroid Build Coastguard Worker  * file and randomly write operations like read/write/map read/map write and
22*49cdfc7eSAndroid Build Coastguard Worker  * truncate, according with input parameters. Then we check if all of them
23*49cdfc7eSAndroid Build Coastguard Worker  * have been completed.
24*49cdfc7eSAndroid Build Coastguard Worker  */
25*49cdfc7eSAndroid Build Coastguard Worker 
26*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
28*49cdfc7eSAndroid Build Coastguard Worker 
29*49cdfc7eSAndroid Build Coastguard Worker #define FNAME "ltp-file.bin"
30*49cdfc7eSAndroid Build Coastguard Worker 
31*49cdfc7eSAndroid Build Coastguard Worker enum {
32*49cdfc7eSAndroid Build Coastguard Worker 	OP_READ = 0,
33*49cdfc7eSAndroid Build Coastguard Worker 	OP_WRITE,
34*49cdfc7eSAndroid Build Coastguard Worker 	OP_TRUNCATE,
35*49cdfc7eSAndroid Build Coastguard Worker 	OP_MAPREAD,
36*49cdfc7eSAndroid Build Coastguard Worker 	OP_MAPWRITE,
37*49cdfc7eSAndroid Build Coastguard Worker 	/* keep counter here */
38*49cdfc7eSAndroid Build Coastguard Worker 	OP_TOTAL,
39*49cdfc7eSAndroid Build Coastguard Worker };
40*49cdfc7eSAndroid Build Coastguard Worker 
41*49cdfc7eSAndroid Build Coastguard Worker static char *str_file_max_size;
42*49cdfc7eSAndroid Build Coastguard Worker static char *str_op_max_size;
43*49cdfc7eSAndroid Build Coastguard Worker static char *str_op_nums;
44*49cdfc7eSAndroid Build Coastguard Worker static char *str_op_write_align;
45*49cdfc7eSAndroid Build Coastguard Worker static char *str_op_read_align;
46*49cdfc7eSAndroid Build Coastguard Worker static char *str_op_trunc_align;
47*49cdfc7eSAndroid Build Coastguard Worker 
48*49cdfc7eSAndroid Build Coastguard Worker static int file_desc;
49*49cdfc7eSAndroid Build Coastguard Worker static long long file_max_size = 256 * 1024;
50*49cdfc7eSAndroid Build Coastguard Worker static long long op_max_size = 64 * 1024;
51*49cdfc7eSAndroid Build Coastguard Worker static long long file_size;
52*49cdfc7eSAndroid Build Coastguard Worker static int op_write_align = 1;
53*49cdfc7eSAndroid Build Coastguard Worker static int op_read_align = 1;
54*49cdfc7eSAndroid Build Coastguard Worker static int op_trunc_align = 1;
55*49cdfc7eSAndroid Build Coastguard Worker static int op_nums = 1000;
56*49cdfc7eSAndroid Build Coastguard Worker static int page_size;
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker static char *file_buff;
59*49cdfc7eSAndroid Build Coastguard Worker static char *temp_buff;
60*49cdfc7eSAndroid Build Coastguard Worker 
61*49cdfc7eSAndroid Build Coastguard Worker struct file_pos_t {
62*49cdfc7eSAndroid Build Coastguard Worker 	long long offset;
63*49cdfc7eSAndroid Build Coastguard Worker 	long long size;
64*49cdfc7eSAndroid Build Coastguard Worker };
65*49cdfc7eSAndroid Build Coastguard Worker 
op_align_pages(struct file_pos_t * pos)66*49cdfc7eSAndroid Build Coastguard Worker static void op_align_pages(struct file_pos_t *pos)
67*49cdfc7eSAndroid Build Coastguard Worker {
68*49cdfc7eSAndroid Build Coastguard Worker 	long long pg_offset;
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker 	pg_offset = pos->offset % page_size;
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker 	pos->offset -= pg_offset;
73*49cdfc7eSAndroid Build Coastguard Worker 	pos->size += pg_offset;
74*49cdfc7eSAndroid Build Coastguard Worker }
75*49cdfc7eSAndroid Build Coastguard Worker 
op_file_position(const long long fsize,const int align,struct file_pos_t * pos)76*49cdfc7eSAndroid Build Coastguard Worker static void op_file_position(
77*49cdfc7eSAndroid Build Coastguard Worker 	const long long fsize,
78*49cdfc7eSAndroid Build Coastguard Worker 	const int align,
79*49cdfc7eSAndroid Build Coastguard Worker 	struct file_pos_t *pos)
80*49cdfc7eSAndroid Build Coastguard Worker {
81*49cdfc7eSAndroid Build Coastguard Worker 	long long diff;
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 	pos->offset = random() % fsize;
84*49cdfc7eSAndroid Build Coastguard Worker 	pos->size = random() % (fsize - pos->offset);
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker 	diff = pos->offset % align;
87*49cdfc7eSAndroid Build Coastguard Worker 
88*49cdfc7eSAndroid Build Coastguard Worker 	if (diff) {
89*49cdfc7eSAndroid Build Coastguard Worker 		pos->offset -= diff;
90*49cdfc7eSAndroid Build Coastguard Worker 		pos->size += diff;
91*49cdfc7eSAndroid Build Coastguard Worker 	}
92*49cdfc7eSAndroid Build Coastguard Worker 
93*49cdfc7eSAndroid Build Coastguard Worker 	if (!pos->size)
94*49cdfc7eSAndroid Build Coastguard Worker 		pos->size = 1;
95*49cdfc7eSAndroid Build Coastguard Worker }
96*49cdfc7eSAndroid Build Coastguard Worker 
update_file_size(struct file_pos_t const * pos)97*49cdfc7eSAndroid Build Coastguard Worker static void update_file_size(struct file_pos_t const *pos)
98*49cdfc7eSAndroid Build Coastguard Worker {
99*49cdfc7eSAndroid Build Coastguard Worker 	if (pos->offset + pos->size > file_size) {
100*49cdfc7eSAndroid Build Coastguard Worker 		file_size = pos->offset + pos->size;
101*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TDEBUG, "File size changed: %llu", file_size);
102*49cdfc7eSAndroid Build Coastguard Worker 	}
103*49cdfc7eSAndroid Build Coastguard Worker }
104*49cdfc7eSAndroid Build Coastguard Worker 
memory_compare(const char * a,const char * b,const long long offset,const long long size)105*49cdfc7eSAndroid Build Coastguard Worker static int memory_compare(
106*49cdfc7eSAndroid Build Coastguard Worker 	const char *a,
107*49cdfc7eSAndroid Build Coastguard Worker 	const char *b,
108*49cdfc7eSAndroid Build Coastguard Worker 	const long long offset,
109*49cdfc7eSAndroid Build Coastguard Worker 	const long long size)
110*49cdfc7eSAndroid Build Coastguard Worker {
111*49cdfc7eSAndroid Build Coastguard Worker 	int diff;
112*49cdfc7eSAndroid Build Coastguard Worker 
113*49cdfc7eSAndroid Build Coastguard Worker 	for (long long i = 0; i < size; i++) {
114*49cdfc7eSAndroid Build Coastguard Worker 		diff = a[i] - b[i];
115*49cdfc7eSAndroid Build Coastguard Worker 		if (diff) {
116*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TDEBUG, "File memory differs at offset=%llu ('%c' != '%c')",
117*49cdfc7eSAndroid Build Coastguard Worker 				offset + i, a[i], b[i]);
118*49cdfc7eSAndroid Build Coastguard Worker 			break;
119*49cdfc7eSAndroid Build Coastguard Worker 		}
120*49cdfc7eSAndroid Build Coastguard Worker 	}
121*49cdfc7eSAndroid Build Coastguard Worker 
122*49cdfc7eSAndroid Build Coastguard Worker 	return diff;
123*49cdfc7eSAndroid Build Coastguard Worker }
124*49cdfc7eSAndroid Build Coastguard Worker 
op_read(void)125*49cdfc7eSAndroid Build Coastguard Worker static int op_read(void)
126*49cdfc7eSAndroid Build Coastguard Worker {
127*49cdfc7eSAndroid Build Coastguard Worker 	if (!file_size) {
128*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Skipping zero size read");
129*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
130*49cdfc7eSAndroid Build Coastguard Worker 	}
131*49cdfc7eSAndroid Build Coastguard Worker 
132*49cdfc7eSAndroid Build Coastguard Worker 	struct file_pos_t pos;
133*49cdfc7eSAndroid Build Coastguard Worker 
134*49cdfc7eSAndroid Build Coastguard Worker 	op_file_position(file_size, op_read_align, &pos);
135*49cdfc7eSAndroid Build Coastguard Worker 
136*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TDEBUG, "Reading at offset=%llu, size=%llu",
137*49cdfc7eSAndroid Build Coastguard Worker 		pos.offset, pos.size);
138*49cdfc7eSAndroid Build Coastguard Worker 
139*49cdfc7eSAndroid Build Coastguard Worker 	memset(temp_buff, 0, file_max_size);
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_LSEEK(file_desc, (off_t)pos.offset, SEEK_SET);
142*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_READ(0, file_desc, temp_buff, pos.size);
143*49cdfc7eSAndroid Build Coastguard Worker 
144*49cdfc7eSAndroid Build Coastguard Worker 	int ret = memory_compare(
145*49cdfc7eSAndroid Build Coastguard Worker 		file_buff + pos.offset,
146*49cdfc7eSAndroid Build Coastguard Worker 		temp_buff,
147*49cdfc7eSAndroid Build Coastguard Worker 		pos.offset,
148*49cdfc7eSAndroid Build Coastguard Worker 		pos.size);
149*49cdfc7eSAndroid Build Coastguard Worker 
150*49cdfc7eSAndroid Build Coastguard Worker 	if (ret)
151*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
152*49cdfc7eSAndroid Build Coastguard Worker 
153*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
154*49cdfc7eSAndroid Build Coastguard Worker }
155*49cdfc7eSAndroid Build Coastguard Worker 
op_write(void)156*49cdfc7eSAndroid Build Coastguard Worker static int op_write(void)
157*49cdfc7eSAndroid Build Coastguard Worker {
158*49cdfc7eSAndroid Build Coastguard Worker 	if (file_size >= file_max_size) {
159*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Skipping max size write");
160*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
161*49cdfc7eSAndroid Build Coastguard Worker 	}
162*49cdfc7eSAndroid Build Coastguard Worker 
163*49cdfc7eSAndroid Build Coastguard Worker 	struct file_pos_t pos;
164*49cdfc7eSAndroid Build Coastguard Worker 	char data;
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker 	op_file_position(file_max_size, op_write_align, &pos);
167*49cdfc7eSAndroid Build Coastguard Worker 
168*49cdfc7eSAndroid Build Coastguard Worker 	for (long long i = 0; i < pos.size; i++) {
169*49cdfc7eSAndroid Build Coastguard Worker 		data = random() % 10 + 'a';
170*49cdfc7eSAndroid Build Coastguard Worker 
171*49cdfc7eSAndroid Build Coastguard Worker 		file_buff[pos.offset + i] = data;
172*49cdfc7eSAndroid Build Coastguard Worker 		temp_buff[i] = data;
173*49cdfc7eSAndroid Build Coastguard Worker 	}
174*49cdfc7eSAndroid Build Coastguard Worker 
175*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TDEBUG, "Writing at offset=%llu, size=%llu",
176*49cdfc7eSAndroid Build Coastguard Worker 		pos.offset, pos.size);
177*49cdfc7eSAndroid Build Coastguard Worker 
178*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_LSEEK(file_desc, (off_t)pos.offset, SEEK_SET);
179*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_WRITE(SAFE_WRITE_ALL, file_desc, temp_buff, pos.size);
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker 	update_file_size(&pos);
182*49cdfc7eSAndroid Build Coastguard Worker 
183*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
184*49cdfc7eSAndroid Build Coastguard Worker }
185*49cdfc7eSAndroid Build Coastguard Worker 
op_truncate(void)186*49cdfc7eSAndroid Build Coastguard Worker static int op_truncate(void)
187*49cdfc7eSAndroid Build Coastguard Worker {
188*49cdfc7eSAndroid Build Coastguard Worker 	struct file_pos_t pos;
189*49cdfc7eSAndroid Build Coastguard Worker 
190*49cdfc7eSAndroid Build Coastguard Worker 	op_file_position(file_max_size, op_trunc_align, &pos);
191*49cdfc7eSAndroid Build Coastguard Worker 	file_size = pos.offset + pos.size;
192*49cdfc7eSAndroid Build Coastguard Worker 
193*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TDEBUG, "Truncating to %llu", file_size);
194*49cdfc7eSAndroid Build Coastguard Worker 
195*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FTRUNCATE(file_desc, file_size);
196*49cdfc7eSAndroid Build Coastguard Worker 	memset(file_buff + file_size, 0, file_max_size - file_size);
197*49cdfc7eSAndroid Build Coastguard Worker 
198*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
199*49cdfc7eSAndroid Build Coastguard Worker }
200*49cdfc7eSAndroid Build Coastguard Worker 
op_map_read(void)201*49cdfc7eSAndroid Build Coastguard Worker static int op_map_read(void)
202*49cdfc7eSAndroid Build Coastguard Worker {
203*49cdfc7eSAndroid Build Coastguard Worker 	if (!file_size) {
204*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Skipping zero size read");
205*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
206*49cdfc7eSAndroid Build Coastguard Worker 	}
207*49cdfc7eSAndroid Build Coastguard Worker 
208*49cdfc7eSAndroid Build Coastguard Worker 	struct file_pos_t pos;
209*49cdfc7eSAndroid Build Coastguard Worker 	char *addr;
210*49cdfc7eSAndroid Build Coastguard Worker 
211*49cdfc7eSAndroid Build Coastguard Worker 	op_file_position(file_size, op_read_align, &pos);
212*49cdfc7eSAndroid Build Coastguard Worker 	op_align_pages(&pos);
213*49cdfc7eSAndroid Build Coastguard Worker 
214*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TDEBUG, "Map reading at offset=%llu, size=%llu",
215*49cdfc7eSAndroid Build Coastguard Worker 		pos.offset, pos.size);
216*49cdfc7eSAndroid Build Coastguard Worker 
217*49cdfc7eSAndroid Build Coastguard Worker 	addr = SAFE_MMAP(
218*49cdfc7eSAndroid Build Coastguard Worker 		0, pos.size,
219*49cdfc7eSAndroid Build Coastguard Worker 		PROT_READ,
220*49cdfc7eSAndroid Build Coastguard Worker 		MAP_FILE | MAP_SHARED,
221*49cdfc7eSAndroid Build Coastguard Worker 		file_desc,
222*49cdfc7eSAndroid Build Coastguard Worker 		(off_t)pos.offset);
223*49cdfc7eSAndroid Build Coastguard Worker 
224*49cdfc7eSAndroid Build Coastguard Worker 	memcpy(file_buff + pos.offset, addr, pos.size);
225*49cdfc7eSAndroid Build Coastguard Worker 
226*49cdfc7eSAndroid Build Coastguard Worker 	int ret = memory_compare(
227*49cdfc7eSAndroid Build Coastguard Worker 		addr,
228*49cdfc7eSAndroid Build Coastguard Worker 		file_buff + pos.offset,
229*49cdfc7eSAndroid Build Coastguard Worker 		pos.offset,
230*49cdfc7eSAndroid Build Coastguard Worker 		pos.size);
231*49cdfc7eSAndroid Build Coastguard Worker 
232*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_MUNMAP(addr, pos.size);
233*49cdfc7eSAndroid Build Coastguard Worker 	if (ret)
234*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
235*49cdfc7eSAndroid Build Coastguard Worker 
236*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
237*49cdfc7eSAndroid Build Coastguard Worker }
238*49cdfc7eSAndroid Build Coastguard Worker 
op_map_write(void)239*49cdfc7eSAndroid Build Coastguard Worker static int op_map_write(void)
240*49cdfc7eSAndroid Build Coastguard Worker {
241*49cdfc7eSAndroid Build Coastguard Worker 	if (file_size >= file_max_size) {
242*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Skipping max size write");
243*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
244*49cdfc7eSAndroid Build Coastguard Worker 	}
245*49cdfc7eSAndroid Build Coastguard Worker 
246*49cdfc7eSAndroid Build Coastguard Worker 	struct file_pos_t pos;
247*49cdfc7eSAndroid Build Coastguard Worker 	char *addr;
248*49cdfc7eSAndroid Build Coastguard Worker 
249*49cdfc7eSAndroid Build Coastguard Worker 	op_file_position(file_max_size, op_write_align, &pos);
250*49cdfc7eSAndroid Build Coastguard Worker 	op_align_pages(&pos);
251*49cdfc7eSAndroid Build Coastguard Worker 
252*49cdfc7eSAndroid Build Coastguard Worker 	if (file_size < pos.offset + pos.size)
253*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_FTRUNCATE(file_desc, pos.offset + pos.size);
254*49cdfc7eSAndroid Build Coastguard Worker 
255*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TDEBUG, "Map writing at offset=%llu, size=%llu",
256*49cdfc7eSAndroid Build Coastguard Worker 		pos.offset, pos.size);
257*49cdfc7eSAndroid Build Coastguard Worker 
258*49cdfc7eSAndroid Build Coastguard Worker 	for (long long i = 0; i < pos.size; i++)
259*49cdfc7eSAndroid Build Coastguard Worker 		file_buff[pos.offset + i] = random() % 10 + 'l';
260*49cdfc7eSAndroid Build Coastguard Worker 
261*49cdfc7eSAndroid Build Coastguard Worker 	addr = SAFE_MMAP(
262*49cdfc7eSAndroid Build Coastguard Worker 		0, pos.size,
263*49cdfc7eSAndroid Build Coastguard Worker 		PROT_READ | PROT_WRITE,
264*49cdfc7eSAndroid Build Coastguard Worker 		MAP_FILE | MAP_SHARED,
265*49cdfc7eSAndroid Build Coastguard Worker 		file_desc,
266*49cdfc7eSAndroid Build Coastguard Worker 		(off_t)pos.offset);
267*49cdfc7eSAndroid Build Coastguard Worker 
268*49cdfc7eSAndroid Build Coastguard Worker 	memcpy(addr, file_buff + pos.offset, pos.size);
269*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_MSYNC(addr, pos.size, MS_SYNC);
270*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_MUNMAP(addr, pos.size);
271*49cdfc7eSAndroid Build Coastguard Worker 	update_file_size(&pos);
272*49cdfc7eSAndroid Build Coastguard Worker 
273*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
274*49cdfc7eSAndroid Build Coastguard Worker }
275*49cdfc7eSAndroid Build Coastguard Worker 
run(void)276*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
277*49cdfc7eSAndroid Build Coastguard Worker {
278*49cdfc7eSAndroid Build Coastguard Worker 	int op;
279*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
280*49cdfc7eSAndroid Build Coastguard Worker 	int counter = 0;
281*49cdfc7eSAndroid Build Coastguard Worker 
282*49cdfc7eSAndroid Build Coastguard Worker 	file_size = 0;
283*49cdfc7eSAndroid Build Coastguard Worker 
284*49cdfc7eSAndroid Build Coastguard Worker 	memset(file_buff, 0, file_max_size);
285*49cdfc7eSAndroid Build Coastguard Worker 	memset(temp_buff, 0, file_max_size);
286*49cdfc7eSAndroid Build Coastguard Worker 
287*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FTRUNCATE(file_desc, 0);
288*49cdfc7eSAndroid Build Coastguard Worker 
289*49cdfc7eSAndroid Build Coastguard Worker 	while (counter < op_nums) {
290*49cdfc7eSAndroid Build Coastguard Worker 		op = random() % OP_TOTAL;
291*49cdfc7eSAndroid Build Coastguard Worker 
292*49cdfc7eSAndroid Build Coastguard Worker 		switch (op) {
293*49cdfc7eSAndroid Build Coastguard Worker 		case OP_WRITE:
294*49cdfc7eSAndroid Build Coastguard Worker 			ret = op_write();
295*49cdfc7eSAndroid Build Coastguard Worker 			break;
296*49cdfc7eSAndroid Build Coastguard Worker 		case OP_MAPREAD:
297*49cdfc7eSAndroid Build Coastguard Worker 			ret = op_map_read();
298*49cdfc7eSAndroid Build Coastguard Worker 			break;
299*49cdfc7eSAndroid Build Coastguard Worker 		case OP_MAPWRITE:
300*49cdfc7eSAndroid Build Coastguard Worker 			ret = op_map_write();
301*49cdfc7eSAndroid Build Coastguard Worker 			break;
302*49cdfc7eSAndroid Build Coastguard Worker 		case OP_TRUNCATE:
303*49cdfc7eSAndroid Build Coastguard Worker 			ret = op_truncate();
304*49cdfc7eSAndroid Build Coastguard Worker 			break;
305*49cdfc7eSAndroid Build Coastguard Worker 		case OP_READ:
306*49cdfc7eSAndroid Build Coastguard Worker 		default:
307*49cdfc7eSAndroid Build Coastguard Worker 			ret = op_read();
308*49cdfc7eSAndroid Build Coastguard Worker 			break;
309*49cdfc7eSAndroid Build Coastguard Worker 		};
310*49cdfc7eSAndroid Build Coastguard Worker 
311*49cdfc7eSAndroid Build Coastguard Worker 		if (ret == -1)
312*49cdfc7eSAndroid Build Coastguard Worker 			break;
313*49cdfc7eSAndroid Build Coastguard Worker 
314*49cdfc7eSAndroid Build Coastguard Worker 		counter += ret;
315*49cdfc7eSAndroid Build Coastguard Worker 	}
316*49cdfc7eSAndroid Build Coastguard Worker 
317*49cdfc7eSAndroid Build Coastguard Worker 	if (counter != op_nums)
318*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TFAIL, "Some file operations failed");
319*49cdfc7eSAndroid Build Coastguard Worker 	else
320*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "All file operations succeed");
321*49cdfc7eSAndroid Build Coastguard Worker }
322*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)323*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
324*49cdfc7eSAndroid Build Coastguard Worker {
325*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_filesize(str_file_max_size, &file_max_size, 1, LLONG_MAX))
326*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid file size '%s'", str_file_max_size);
327*49cdfc7eSAndroid Build Coastguard Worker 
328*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_filesize(str_op_max_size, &op_max_size, 1, LLONG_MAX))
329*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid maximum size for single operation '%s'", str_op_max_size);
330*49cdfc7eSAndroid Build Coastguard Worker 
331*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_op_nums, &op_nums, 1, INT_MAX))
332*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of operations '%s'", str_op_nums);
333*49cdfc7eSAndroid Build Coastguard Worker 
334*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_op_write_align, &op_write_align, 1, INT_MAX))
335*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid memory write alignment factor '%s'", str_op_write_align);
336*49cdfc7eSAndroid Build Coastguard Worker 
337*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_op_read_align, &op_read_align, 1, INT_MAX))
338*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid memory read alignment factor '%s'", str_op_read_align);
339*49cdfc7eSAndroid Build Coastguard Worker 
340*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_op_trunc_align, &op_trunc_align, 1, INT_MAX))
341*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid memory truncate alignment factor '%s'", str_op_trunc_align);
342*49cdfc7eSAndroid Build Coastguard Worker 
343*49cdfc7eSAndroid Build Coastguard Worker 	page_size = (int)sysconf(_SC_PAGESIZE);
344*49cdfc7eSAndroid Build Coastguard Worker 
345*49cdfc7eSAndroid Build Coastguard Worker 	srandom(time(NULL));
346*49cdfc7eSAndroid Build Coastguard Worker 
347*49cdfc7eSAndroid Build Coastguard Worker 	file_desc = SAFE_OPEN(FNAME, O_RDWR | O_CREAT, 0666);
348*49cdfc7eSAndroid Build Coastguard Worker 
349*49cdfc7eSAndroid Build Coastguard Worker 	file_buff = SAFE_MALLOC(file_max_size);
350*49cdfc7eSAndroid Build Coastguard Worker 	temp_buff = SAFE_MALLOC(file_max_size);
351*49cdfc7eSAndroid Build Coastguard Worker }
352*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)353*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
354*49cdfc7eSAndroid Build Coastguard Worker {
355*49cdfc7eSAndroid Build Coastguard Worker 	if (file_buff)
356*49cdfc7eSAndroid Build Coastguard Worker 		free(file_buff);
357*49cdfc7eSAndroid Build Coastguard Worker 
358*49cdfc7eSAndroid Build Coastguard Worker 	if (temp_buff)
359*49cdfc7eSAndroid Build Coastguard Worker 		free(temp_buff);
360*49cdfc7eSAndroid Build Coastguard Worker 
361*49cdfc7eSAndroid Build Coastguard Worker 	if (file_desc)
362*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(file_desc);
363*49cdfc7eSAndroid Build Coastguard Worker }
364*49cdfc7eSAndroid Build Coastguard Worker 
365*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
366*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
367*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
368*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
369*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = run,
370*49cdfc7eSAndroid Build Coastguard Worker 	.max_runtime = 1800,
371*49cdfc7eSAndroid Build Coastguard Worker 	.options = (struct tst_option[]) {
372*49cdfc7eSAndroid Build Coastguard Worker 		{ "l:", &str_file_max_size, "Maximum size in MB of the test file(s) (default 262144)" },
373*49cdfc7eSAndroid Build Coastguard Worker 		{ "o:", &str_op_max_size, "Maximum size for single operation (default 65536)" },
374*49cdfc7eSAndroid Build Coastguard Worker 		{ "N:", &str_op_nums, "Total # operations to do (default 1000)" },
375*49cdfc7eSAndroid Build Coastguard Worker 		{ "w:", &str_op_write_align, "Write memory page alignment (default 1)" },
376*49cdfc7eSAndroid Build Coastguard Worker 		{ "r:", &str_op_read_align, "Read memory page alignment (default 1)" },
377*49cdfc7eSAndroid Build Coastguard Worker 		{ "t:", &str_op_trunc_align, "Truncate memory page alignment (default 1)" },
378*49cdfc7eSAndroid Build Coastguard Worker 		{},
379*49cdfc7eSAndroid Build Coastguard Worker 	},
380*49cdfc7eSAndroid Build Coastguard Worker };
381