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