1 /* SPDX-License-Identifier: GPL-2.0-or-later
2 * Copyright (c) 2015-2017 Cyril Hrubis <chrubis@suse.cz>
3 * Copyright (c) Linux Test Project, 2017-2022
4 */
5
6 #ifndef TST_FS_H__
7 #define TST_FS_H__
8
9 /* man 2 statfs or kernel-source/include/linux/magic.h */
10 #define TST_BTRFS_MAGIC 0x9123683E
11 #define TST_NFS_MAGIC 0x6969
12 #define TST_RAMFS_MAGIC 0x858458f6
13 #define TST_TMPFS_MAGIC 0x01021994
14 #define TST_V9FS_MAGIC 0x01021997
15 #define TST_XFS_MAGIC 0x58465342
16 #define TST_EXT2_OLD_MAGIC 0xEF51
17 /* ext2, ext3, ext4 have the same magic number */
18 #define TST_EXT234_MAGIC 0xEF53
19 #define TST_MINIX_MAGIC 0x137F
20 #define TST_MINIX_MAGIC2 0x138F
21 #define TST_MINIX2_MAGIC 0x2468
22 #define TST_MINIX2_MAGIC2 0x2478
23 #define TST_MINIX3_MAGIC 0x4D5A
24 #define TST_UDF_MAGIC 0x15013346
25 #define TST_SYSV2_MAGIC 0x012FF7B6
26 #define TST_SYSV4_MAGIC 0x012FF7B5
27 #define TST_UFS_MAGIC 0x00011954
28 #define TST_UFS2_MAGIC 0x19540119
29 #define TST_F2FS_MAGIC 0xF2F52010
30 #define TST_NILFS_MAGIC 0x3434
31 #define TST_EXOFS_MAGIC 0x5DF5
32 #define TST_OVERLAYFS_MAGIC 0x794c7630
33 #define TST_FUSE_MAGIC 0x65735546
34 #define TST_VFAT_MAGIC 0x4d44 /* AKA MSDOS */
35 #define TST_EXFAT_MAGIC 0x2011BAB0UL
36
37 enum tst_fill_access_pattern {
38 TST_FILL_BLOCKS,
39 TST_FILL_RANDOM
40 };
41
42 enum {
43 TST_BYTES = 1,
44 TST_KB = 1024,
45 TST_MB = 1048576,
46 TST_GB = 1073741824,
47 };
48
49 #define OVL_BASE_MNTPOINT "mntpoint"
50 #define OVL_LOWER OVL_BASE_MNTPOINT"/lower"
51 #define OVL_UPPER OVL_BASE_MNTPOINT"/upper"
52 #define OVL_WORK OVL_BASE_MNTPOINT"/work"
53 #define OVL_MNT OVL_BASE_MNTPOINT"/ovl"
54
55 /*
56 * @path: path is the pathname of any file within the mounted file system
57 * @mult: mult should be TST_KB, TST_MB or TST_GB
58 * the required free space is calculated by @size * @mult
59 */
60 int tst_fs_has_free_(void (*cleanup)(void), const char *path, unsigned int size,
61 unsigned int mult);
62
63 /*
64 * Returns filesystem magick for a given path.
65 *
66 * The expected usage is:
67 *
68 * if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) {
69 * tst_brkm(TCONF, cleanup,
70 * "Test not supported on NFS filesystem");
71 * }
72 *
73 * Or:
74 *
75 * long type;
76 *
77 * swtich ((type = tst_fs_type(cleanup, "."))) {
78 * case TST_NFS_MAGIC:
79 * case TST_TMPFS_MAGIC:
80 * case TST_RAMFS_MAGIC:
81 * tst_brkm(TCONF, cleanup, "Test not supported on %s filesystem",
82 * tst_fs_type_name(type));
83 * break;
84 * }
85 */
86 long tst_fs_type_(void (*cleanup)(void), const char *path);
87
88 /*
89 * Returns filesystem name given magic.
90 */
91 const char *tst_fs_type_name(long f_type);
92
93 /*
94 * Try to get maximum number of hard links to a regular file inside the @dir.
95 *
96 * Note: This number depends on the filesystem @dir is on.
97 *
98 * The code uses link(2) to create hard links to a single file until it gets
99 * EMLINK or creates 65535 links.
100 *
101 * If limit is hit maximal number of hardlinks is returned and the @dir is
102 * filled with hardlinks in format "testfile%i" where i belongs to [0, limit)
103 * interval.
104 *
105 * If no limit is hit (succed to create 65535 without error) or if link()
106 * failed with ENOSPC or EDQUOT zero is returned previously created files are
107 * removed.
108 */
109 int tst_fs_fill_hardlinks_(void (*cleanup) (void), const char *dir);
110
111 /*
112 * Try to get maximum number of subdirectories in directory.
113 *
114 * Note: This number depends on the filesystem @dir is on.
115 *
116 * The code uses mkdir(2) to create directories in @dir until it gets EMLINK
117 * or creates 65535 directories.
118 *
119 * If limit is hit the maximal number of subdirectories is returned and the
120 * @dir is filled with subdirectories in format "testdir%i" where i belongs to
121 * [0, limit - 2) interval (because each newly created dir has two links
122 * already the '.' and link from parent dir).
123 *
124 * If no limit is hit or mkdir() failed with ENOSPC or EDQUOT zero is returned
125 * previously created directories are removed.
126 *
127 */
128 int tst_fs_fill_subdirs_(void (*cleanup) (void), const char *dir);
129
130 /*
131 * Checks if a given directory contains any entities,
132 * returns 1 if directory is empty, 0 otherwise
133 */
134 int tst_dir_is_empty_(void (*cleanup)(void), const char *name, int verbose);
135
136 /*
137 * Search $PATH for prog_name and fills buf with absolute path if found.
138 *
139 * Returns -1 on failure, either command was not found or buffer was too small.
140 */
141 int tst_get_path(const char *prog_name, char *buf, size_t buf_len);
142
143 /*
144 * Fill a file with specified pattern
145 * @fd: file descriptor
146 * @pattern: pattern
147 * @bs: block size
148 * @bcount: blocks count
149 */
150 int tst_fill_fd(int fd, char pattern, size_t bs, size_t bcount);
151
152 /*
153 * Preallocate space in open file. If fallocate() fails, falls back to
154 * using tst_fill_fd().
155 * @fd: file descriptor
156 * @bs: block size
157 * @bcount: blocks count
158 */
159 int tst_prealloc_size_fd(int fd, size_t bs, size_t bcount);
160
161 /*
162 * Creates/ovewrites a file with specified pattern
163 * @path: path to file
164 * @pattern: pattern
165 * @bs: block size
166 * @bcount: blocks amount
167 */
168 int tst_fill_file(const char *path, char pattern, size_t bs, size_t bcount);
169
170 /*
171 * Creates file of specified size. Space will be only preallocated if possible.
172 * @path: path to file
173 * @bs: block size
174 * @bcount: blocks amount
175 */
176 int tst_prealloc_file(const char *path, size_t bs, size_t bcount);
177
178 enum tst_fs_impl {
179 TST_FS_UNSUPPORTED = 0,
180 TST_FS_KERNEL = 1,
181 TST_FS_FUSE = 2,
182 };
183
184 /*
185 * Returns if filesystem is supported and if driver is in kernel or FUSE.
186 *
187 * @fs_type A filesystem name to check the support for.
188 */
189 enum tst_fs_impl tst_fs_is_supported(const char *fs_type);
190
191 /*
192 * Returns NULL-terminated array of kernel-supported filesystems.
193 *
194 * @skiplist A NULL terminated array of filesystems to skip.
195 */
196 const char **tst_get_supported_fs_types(const char *const *skiplist);
197
198 /*
199 * Returns 1 if filesystem is in skiplist 0 otherwise.
200 *
201 * @fs_type A filesystem type to lookup.
202 * @skiplist A NULL terminated array of filesystems to skip.
203 */
204 int tst_fs_in_skiplist(const char *fs_type, const char *const *skiplist);
205
206 /*
207 * Creates and writes to files on given path until write fails with ENOSPC
208 */
209 void tst_fill_fs(const char *path, int verbose, enum tst_fill_access_pattern pattern);
210
211 /*
212 * test if FIBMAP ioctl is supported
213 */
214 int tst_fibmap(const char *filename);
215
216 #ifdef TST_TEST_H__
tst_fs_type(const char * path)217 static inline long tst_fs_type(const char *path)
218 {
219 return tst_fs_type_(NULL, path);
220 }
221
tst_fs_has_free(const char * path,unsigned int size,unsigned int mult)222 static inline int tst_fs_has_free(const char *path, unsigned int size,
223 unsigned int mult)
224 {
225 return tst_fs_has_free_(NULL, path, size, mult);
226 }
227
tst_fs_fill_hardlinks(const char * dir)228 static inline int tst_fs_fill_hardlinks(const char *dir)
229 {
230 return tst_fs_fill_hardlinks_(NULL, dir);
231 }
232
tst_fs_fill_subdirs(const char * dir)233 static inline int tst_fs_fill_subdirs(const char *dir)
234 {
235 return tst_fs_fill_subdirs_(NULL, dir);
236 }
237
tst_dir_is_empty(const char * name,int verbose)238 static inline int tst_dir_is_empty(const char *name, int verbose)
239 {
240 return tst_dir_is_empty_(NULL, name, verbose);
241 }
242 #else
tst_fs_type(void (* cleanup)(void),const char * path)243 static inline long tst_fs_type(void (*cleanup)(void), const char *path)
244 {
245 return tst_fs_type_(cleanup, path);
246 }
247
tst_fs_has_free(void (* cleanup)(void),const char * path,unsigned int size,unsigned int mult)248 static inline int tst_fs_has_free(void (*cleanup)(void), const char *path,
249 unsigned int size, unsigned int mult)
250 {
251 return tst_fs_has_free_(cleanup, path, size, mult);
252 }
253
tst_fs_fill_hardlinks(void (* cleanup)(void),const char * dir)254 static inline int tst_fs_fill_hardlinks(void (*cleanup)(void), const char *dir)
255 {
256 return tst_fs_fill_hardlinks_(cleanup, dir);
257 }
258
tst_fs_fill_subdirs(void (* cleanup)(void),const char * dir)259 static inline int tst_fs_fill_subdirs(void (*cleanup)(void), const char *dir)
260 {
261 return tst_fs_fill_subdirs_(cleanup, dir);
262 }
263
tst_dir_is_empty(void (* cleanup)(void),const char * name,int verbose)264 static inline int tst_dir_is_empty(void (*cleanup)(void), const char *name, int verbose)
265 {
266 return tst_dir_is_empty_(cleanup, name, verbose);
267 }
268 #endif
269
270 #endif /* TST_FS_H__ */
271