xref: /aosp_15_r20/external/ltp/lib/tst_fill_fs.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) 2017 Cyril Hrubis <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  */
5*49cdfc7eSAndroid Build Coastguard Worker 
6*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
7*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
8*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
9*49cdfc7eSAndroid Build Coastguard Worker #include <sys/statvfs.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <sys/uio.h>
11*49cdfc7eSAndroid Build Coastguard Worker 
12*49cdfc7eSAndroid Build Coastguard Worker #define TST_NO_DEFAULT_MAIN
13*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
14*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/fcntl.h"
15*49cdfc7eSAndroid Build Coastguard Worker #include "tst_fs.h"
16*49cdfc7eSAndroid Build Coastguard Worker #include "tst_rand_data.h"
17*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_file_at.h"
18*49cdfc7eSAndroid Build Coastguard Worker 
fill_random(const char * path,int verbose)19*49cdfc7eSAndroid Build Coastguard Worker static void fill_random(const char *path, int verbose)
20*49cdfc7eSAndroid Build Coastguard Worker {
21*49cdfc7eSAndroid Build Coastguard Worker 	int i = 0;
22*49cdfc7eSAndroid Build Coastguard Worker 	char file[PATH_MAX];
23*49cdfc7eSAndroid Build Coastguard Worker 	size_t len;
24*49cdfc7eSAndroid Build Coastguard Worker 	ssize_t ret;
25*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
26*49cdfc7eSAndroid Build Coastguard Worker 	struct statvfs fi;
27*49cdfc7eSAndroid Build Coastguard Worker 
28*49cdfc7eSAndroid Build Coastguard Worker 	statvfs(path, &fi);
29*49cdfc7eSAndroid Build Coastguard Worker 
30*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
31*49cdfc7eSAndroid Build Coastguard Worker 		len = random() % (1024 * 102400);
32*49cdfc7eSAndroid Build Coastguard Worker 
33*49cdfc7eSAndroid Build Coastguard Worker 		snprintf(file, sizeof(file), "%s/file%i", path, i++);
34*49cdfc7eSAndroid Build Coastguard Worker 
35*49cdfc7eSAndroid Build Coastguard Worker 		if (verbose)
36*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO, "Creating file %s size %zu", file, len);
37*49cdfc7eSAndroid Build Coastguard Worker 
38*49cdfc7eSAndroid Build Coastguard Worker 		fd = open(file, O_WRONLY | O_CREAT, 0700);
39*49cdfc7eSAndroid Build Coastguard Worker 		if (fd == -1) {
40*49cdfc7eSAndroid Build Coastguard Worker 			if (errno != ENOSPC)
41*49cdfc7eSAndroid Build Coastguard Worker 				tst_brk(TBROK | TERRNO, "open()");
42*49cdfc7eSAndroid Build Coastguard Worker 
43*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO | TERRNO, "open()");
44*49cdfc7eSAndroid Build Coastguard Worker 			return;
45*49cdfc7eSAndroid Build Coastguard Worker 		}
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker 		while (len) {
48*49cdfc7eSAndroid Build Coastguard Worker 			ret = write(fd, tst_rand_data, MIN(len, tst_rand_data_len));
49*49cdfc7eSAndroid Build Coastguard Worker 
50*49cdfc7eSAndroid Build Coastguard Worker 			if (ret < 0) {
51*49cdfc7eSAndroid Build Coastguard Worker 				/* retry on ENOSPC to make sure filesystem is really full */
52*49cdfc7eSAndroid Build Coastguard Worker 				if (errno == ENOSPC && len >= fi.f_bsize/2) {
53*49cdfc7eSAndroid Build Coastguard Worker 					SAFE_FSYNC(fd);
54*49cdfc7eSAndroid Build Coastguard Worker 					len /= 2;
55*49cdfc7eSAndroid Build Coastguard Worker 					continue;
56*49cdfc7eSAndroid Build Coastguard Worker 				}
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker 				SAFE_CLOSE(fd);
59*49cdfc7eSAndroid Build Coastguard Worker 
60*49cdfc7eSAndroid Build Coastguard Worker 				if (errno != ENOSPC)
61*49cdfc7eSAndroid Build Coastguard Worker 					tst_brk(TBROK | TERRNO, "write()");
62*49cdfc7eSAndroid Build Coastguard Worker 
63*49cdfc7eSAndroid Build Coastguard Worker 				tst_res(TINFO | TERRNO, "write()");
64*49cdfc7eSAndroid Build Coastguard Worker 				return;
65*49cdfc7eSAndroid Build Coastguard Worker 			}
66*49cdfc7eSAndroid Build Coastguard Worker 
67*49cdfc7eSAndroid Build Coastguard Worker 			len -= ret;
68*49cdfc7eSAndroid Build Coastguard Worker 		}
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fd);
71*49cdfc7eSAndroid Build Coastguard Worker 	}
72*49cdfc7eSAndroid Build Coastguard Worker }
73*49cdfc7eSAndroid Build Coastguard Worker 
fill_flat_vec(const char * path,int verbose)74*49cdfc7eSAndroid Build Coastguard Worker static void fill_flat_vec(const char *path, int verbose)
75*49cdfc7eSAndroid Build Coastguard Worker {
76*49cdfc7eSAndroid Build Coastguard Worker 	int dir, fd;
77*49cdfc7eSAndroid Build Coastguard Worker 	struct iovec iov[512];
78*49cdfc7eSAndroid Build Coastguard Worker 	int iovcnt = ARRAY_SIZE(iov);
79*49cdfc7eSAndroid Build Coastguard Worker 	int retries = 3;
80*49cdfc7eSAndroid Build Coastguard Worker 
81*49cdfc7eSAndroid Build Coastguard Worker 	dir = open(path, O_PATH | O_DIRECTORY);
82*49cdfc7eSAndroid Build Coastguard Worker 	if (dir == -1) {
83*49cdfc7eSAndroid Build Coastguard Worker 		if (errno == ENOSPC) {
84*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO | TERRNO, "open()");
85*49cdfc7eSAndroid Build Coastguard Worker 			return;
86*49cdfc7eSAndroid Build Coastguard Worker 		}
87*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "open(%s, %d) failed", path, O_PATH | O_DIRECTORY);
88*49cdfc7eSAndroid Build Coastguard Worker 	}
89*49cdfc7eSAndroid Build Coastguard Worker 
90*49cdfc7eSAndroid Build Coastguard Worker 	fd = openat(dir, "AOF", O_WRONLY | O_CREAT, 0600);
91*49cdfc7eSAndroid Build Coastguard Worker 	if (fd == -1) {
92*49cdfc7eSAndroid Build Coastguard Worker 		if (errno == ENOSPC) {
93*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO | TERRNO, "openat()");
94*49cdfc7eSAndroid Build Coastguard Worker 			return;
95*49cdfc7eSAndroid Build Coastguard Worker 		}
96*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "openat(%d, %d, 0600) failed for path %s",
97*49cdfc7eSAndroid Build Coastguard Worker 			dir, O_PATH | O_DIRECTORY, path);
98*49cdfc7eSAndroid Build Coastguard Worker 	}
99*49cdfc7eSAndroid Build Coastguard Worker 
100*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(dir);
101*49cdfc7eSAndroid Build Coastguard Worker 
102*49cdfc7eSAndroid Build Coastguard Worker 	for (int i = 0; i < iovcnt; i++) {
103*49cdfc7eSAndroid Build Coastguard Worker 		iov[i] = (struct iovec) {
104*49cdfc7eSAndroid Build Coastguard Worker 			(void *)tst_rand_data,
105*49cdfc7eSAndroid Build Coastguard Worker 			tst_rand_data_len
106*49cdfc7eSAndroid Build Coastguard Worker 		};
107*49cdfc7eSAndroid Build Coastguard Worker 	}
108*49cdfc7eSAndroid Build Coastguard Worker 
109*49cdfc7eSAndroid Build Coastguard Worker 	while (retries) {
110*49cdfc7eSAndroid Build Coastguard Worker 		const int ret = writev(fd, iov, iovcnt);
111*49cdfc7eSAndroid Build Coastguard Worker 
112*49cdfc7eSAndroid Build Coastguard Worker 		if (!ret)
113*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TWARN | TERRNO, "writev returned 0; not sure what this means");
114*49cdfc7eSAndroid Build Coastguard Worker 
115*49cdfc7eSAndroid Build Coastguard Worker 		if (ret > -1) {
116*49cdfc7eSAndroid Build Coastguard Worker 			if (verbose && retries < 3)
117*49cdfc7eSAndroid Build Coastguard Worker 				tst_res(TINFO, "writev(\"%s/AOF\", iov, %d) = %d", path, iovcnt, ret);
118*49cdfc7eSAndroid Build Coastguard Worker 
119*49cdfc7eSAndroid Build Coastguard Worker 			retries = 3;
120*49cdfc7eSAndroid Build Coastguard Worker 			continue;
121*49cdfc7eSAndroid Build Coastguard Worker 		}
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 		if (errno != ENOSPC)
124*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TBROK | TERRNO, "writev(\"%s/AOF\", iov, %d)", path, iovcnt);
125*49cdfc7eSAndroid Build Coastguard Worker 
126*49cdfc7eSAndroid Build Coastguard Worker 		if (verbose)
127*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO, "writev(\"%s/AOF\", iov, %d): ENOSPC", path, iovcnt);
128*49cdfc7eSAndroid Build Coastguard Worker 
129*49cdfc7eSAndroid Build Coastguard Worker 		retries--;
130*49cdfc7eSAndroid Build Coastguard Worker 	}
131*49cdfc7eSAndroid Build Coastguard Worker 
132*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(fd);
133*49cdfc7eSAndroid Build Coastguard Worker }
134*49cdfc7eSAndroid Build Coastguard Worker 
tst_fill_fs(const char * path,int verbose,enum tst_fill_access_pattern pattern)135*49cdfc7eSAndroid Build Coastguard Worker void tst_fill_fs(const char *path, int verbose, enum tst_fill_access_pattern pattern)
136*49cdfc7eSAndroid Build Coastguard Worker {
137*49cdfc7eSAndroid Build Coastguard Worker 
138*49cdfc7eSAndroid Build Coastguard Worker 	switch (pattern) {
139*49cdfc7eSAndroid Build Coastguard Worker 	case TST_FILL_BLOCKS:
140*49cdfc7eSAndroid Build Coastguard Worker 		return fill_flat_vec(path, verbose);
141*49cdfc7eSAndroid Build Coastguard Worker 	case TST_FILL_RANDOM:
142*49cdfc7eSAndroid Build Coastguard Worker 		return fill_random(path, verbose);
143*49cdfc7eSAndroid Build Coastguard Worker 	}
144*49cdfc7eSAndroid Build Coastguard Worker }
145