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