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