xref: /aosp_15_r20/external/ltp/libs/libltpswap/libswap.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) 2013 Oracle and/or its affiliates. All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) Linux Test Project, 2014-2024
5*49cdfc7eSAndroid Build Coastguard Worker  * Author: Stanislav Kholmanskikh <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker  */
7*49cdfc7eSAndroid Build Coastguard Worker 
8*49cdfc7eSAndroid Build Coastguard Worker #include <sys/statvfs.h>
9*49cdfc7eSAndroid Build Coastguard Worker #include <linux/fs.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <linux/fiemap.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <stdbool.h>
14*49cdfc7eSAndroid Build Coastguard Worker 
15*49cdfc7eSAndroid Build Coastguard Worker #define TST_NO_DEFAULT_MAIN
16*49cdfc7eSAndroid Build Coastguard Worker #define DEFAULT_MAX_SWAPFILE 32
17*49cdfc7eSAndroid Build Coastguard Worker #define BUFSIZE 200
18*49cdfc7eSAndroid Build Coastguard Worker 
19*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
20*49cdfc7eSAndroid Build Coastguard Worker #include "libswap.h"
21*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/syscalls.h"
22*49cdfc7eSAndroid Build Coastguard Worker #include "tst_kconfig.h"
23*49cdfc7eSAndroid Build Coastguard Worker #include "tst_kvercmp.h"
24*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_stdio.h"
25*49cdfc7eSAndroid Build Coastguard Worker 
26*49cdfc7eSAndroid Build Coastguard Worker static const char *const swap_supported_fs[] = {
27*49cdfc7eSAndroid Build Coastguard Worker 	"btrfs",
28*49cdfc7eSAndroid Build Coastguard Worker 	"ext2",
29*49cdfc7eSAndroid Build Coastguard Worker 	"ext3",
30*49cdfc7eSAndroid Build Coastguard Worker 	"ext4",
31*49cdfc7eSAndroid Build Coastguard Worker 	"xfs",
32*49cdfc7eSAndroid Build Coastguard Worker 	"vfat",
33*49cdfc7eSAndroid Build Coastguard Worker 	"exfat",
34*49cdfc7eSAndroid Build Coastguard Worker 	"ntfs",
35*49cdfc7eSAndroid Build Coastguard Worker 	NULL
36*49cdfc7eSAndroid Build Coastguard Worker };
37*49cdfc7eSAndroid Build Coastguard Worker 
set_nocow_attr(const char * filename)38*49cdfc7eSAndroid Build Coastguard Worker static void set_nocow_attr(const char *filename)
39*49cdfc7eSAndroid Build Coastguard Worker {
40*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
41*49cdfc7eSAndroid Build Coastguard Worker 	int attrs;
42*49cdfc7eSAndroid Build Coastguard Worker 
43*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "FS_NOCOW_FL attribute set on %s", filename);
44*49cdfc7eSAndroid Build Coastguard Worker 
45*49cdfc7eSAndroid Build Coastguard Worker 	fd = SAFE_OPEN(filename, O_RDONLY);
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(fd, FS_IOC_GETFLAGS, &attrs);
48*49cdfc7eSAndroid Build Coastguard Worker 
49*49cdfc7eSAndroid Build Coastguard Worker 	attrs |= FS_NOCOW_FL;
50*49cdfc7eSAndroid Build Coastguard Worker 
51*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(fd, FS_IOC_SETFLAGS, &attrs);
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(fd);
54*49cdfc7eSAndroid Build Coastguard Worker }
55*49cdfc7eSAndroid Build Coastguard Worker 
prealloc_contiguous_file(const char * path,size_t bs,size_t bcount)56*49cdfc7eSAndroid Build Coastguard Worker static int prealloc_contiguous_file(const char *path, size_t bs, size_t bcount)
57*49cdfc7eSAndroid Build Coastguard Worker {
58*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
59*49cdfc7eSAndroid Build Coastguard Worker 
60*49cdfc7eSAndroid Build Coastguard Worker 	fd = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0600);
61*49cdfc7eSAndroid Build Coastguard Worker 	if (fd < 0)
62*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
63*49cdfc7eSAndroid Build Coastguard Worker 
64*49cdfc7eSAndroid Build Coastguard Worker 	/* Btrfs file need set 'nocow' attribute */
65*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_fs_type(path) == TST_BTRFS_MAGIC)
66*49cdfc7eSAndroid Build Coastguard Worker 		set_nocow_attr(path);
67*49cdfc7eSAndroid Build Coastguard Worker 
68*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_prealloc_size_fd(fd, bs, bcount)) {
69*49cdfc7eSAndroid Build Coastguard Worker 		close(fd);
70*49cdfc7eSAndroid Build Coastguard Worker 		unlink(path);
71*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
72*49cdfc7eSAndroid Build Coastguard Worker 	}
73*49cdfc7eSAndroid Build Coastguard Worker 
74*49cdfc7eSAndroid Build Coastguard Worker 	if (close(fd) < 0) {
75*49cdfc7eSAndroid Build Coastguard Worker 		unlink(path);
76*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
77*49cdfc7eSAndroid Build Coastguard Worker 	}
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
80*49cdfc7eSAndroid Build Coastguard Worker }
81*49cdfc7eSAndroid Build Coastguard Worker 
file_is_contiguous(const char * filename)82*49cdfc7eSAndroid Build Coastguard Worker static int file_is_contiguous(const char *filename)
83*49cdfc7eSAndroid Build Coastguard Worker {
84*49cdfc7eSAndroid Build Coastguard Worker 	int fd, contiguous = 0;
85*49cdfc7eSAndroid Build Coastguard Worker 	struct fiemap *fiemap;
86*49cdfc7eSAndroid Build Coastguard Worker 
87*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_fibmap(filename) == 0) {
88*49cdfc7eSAndroid Build Coastguard Worker 		contiguous = 1;
89*49cdfc7eSAndroid Build Coastguard Worker 		goto out;
90*49cdfc7eSAndroid Build Coastguard Worker 	}
91*49cdfc7eSAndroid Build Coastguard Worker 
92*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_fs_type(filename) == TST_TMPFS_MAGIC)
93*49cdfc7eSAndroid Build Coastguard Worker 		goto out;
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker 	fd = SAFE_OPEN(filename, O_RDONLY);
96*49cdfc7eSAndroid Build Coastguard Worker 
97*49cdfc7eSAndroid Build Coastguard Worker 	fiemap = (struct fiemap *)SAFE_MALLOC(sizeof(struct fiemap)
98*49cdfc7eSAndroid Build Coastguard Worker 					      + sizeof(struct fiemap_extent));
99*49cdfc7eSAndroid Build Coastguard Worker 
100*49cdfc7eSAndroid Build Coastguard Worker 	memset(fiemap, 0, sizeof(struct fiemap) + sizeof(struct fiemap_extent));
101*49cdfc7eSAndroid Build Coastguard Worker 
102*49cdfc7eSAndroid Build Coastguard Worker 	fiemap->fm_start = 0;
103*49cdfc7eSAndroid Build Coastguard Worker 	fiemap->fm_length = ~0;
104*49cdfc7eSAndroid Build Coastguard Worker 	fiemap->fm_flags = 0;
105*49cdfc7eSAndroid Build Coastguard Worker 	fiemap->fm_extent_count = 1;
106*49cdfc7eSAndroid Build Coastguard Worker 
107*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(fd, FS_IOC_FIEMAP, fiemap);
108*49cdfc7eSAndroid Build Coastguard Worker 
109*49cdfc7eSAndroid Build Coastguard Worker 	/*
110*49cdfc7eSAndroid Build Coastguard Worker 	 * fiemap->fm_mapped_extents != 1:
111*49cdfc7eSAndroid Build Coastguard Worker 	 *   This checks if the file does not have exactly one extent. If there are more
112*49cdfc7eSAndroid Build Coastguard Worker 	 *   or zero extents, the file is not stored in a single contiguous block.
113*49cdfc7eSAndroid Build Coastguard Worker 	 *
114*49cdfc7eSAndroid Build Coastguard Worker 	 * fiemap->fm_extents[0].fe_logical != 0:
115*49cdfc7eSAndroid Build Coastguard Worker 	 *   This checks if the first extent does not start at the logical offset 0 of
116*49cdfc7eSAndroid Build Coastguard Worker 	 *   the file. If it doesn't, it indicates that the file's first block of data
117*49cdfc7eSAndroid Build Coastguard Worker 	 *   is not at the beginning of the file, which implies non-contiguity.
118*49cdfc7eSAndroid Build Coastguard Worker 	 *
119*49cdfc7eSAndroid Build Coastguard Worker 	 * (fiemap->fm_extents[0].fe_flags & FIEMAP_EXTENT_LAST) != FIEMAP_EXTENT_LAST:
120*49cdfc7eSAndroid Build Coastguard Worker 	 *   This checks if the first extent does not have the FIEMAP_EXTENT_LAST flag set.
121*49cdfc7eSAndroid Build Coastguard Worker 	 *   If the flag isn't set, it means that this extent is not the last one, suggesting
122*49cdfc7eSAndroid Build Coastguard Worker 	 *   that there are more extents and the file is not contiguous.
123*49cdfc7eSAndroid Build Coastguard Worker 	 */
124*49cdfc7eSAndroid Build Coastguard Worker 	if (fiemap->fm_mapped_extents != 1 ||
125*49cdfc7eSAndroid Build Coastguard Worker 		fiemap->fm_extents[0].fe_logical != 0 ||
126*49cdfc7eSAndroid Build Coastguard Worker 		(fiemap->fm_extents[0].fe_flags & FIEMAP_EXTENT_LAST) != FIEMAP_EXTENT_LAST) {
127*49cdfc7eSAndroid Build Coastguard Worker 
128*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "File '%s' is not contiguous", filename);
129*49cdfc7eSAndroid Build Coastguard Worker 		contiguous = 0;
130*49cdfc7eSAndroid Build Coastguard Worker 	}
131*49cdfc7eSAndroid Build Coastguard Worker 
132*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(fd);
133*49cdfc7eSAndroid Build Coastguard Worker 	free(fiemap);
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker out:
136*49cdfc7eSAndroid Build Coastguard Worker 	return contiguous;
137*49cdfc7eSAndroid Build Coastguard Worker }
138*49cdfc7eSAndroid Build Coastguard Worker 
make_swapfile(const char * file,const int lineno,const char * swapfile,unsigned int num,int safe,enum swapfile_method method)139*49cdfc7eSAndroid Build Coastguard Worker int make_swapfile(const char *file, const int lineno,
140*49cdfc7eSAndroid Build Coastguard Worker 			const char *swapfile, unsigned int num,
141*49cdfc7eSAndroid Build Coastguard Worker 			int safe, enum swapfile_method method)
142*49cdfc7eSAndroid Build Coastguard Worker {
143*49cdfc7eSAndroid Build Coastguard Worker 	struct statvfs fs_info;
144*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long blk_size;
145*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int blocks = 0;
146*49cdfc7eSAndroid Build Coastguard Worker 	size_t pg_size = sysconf(_SC_PAGESIZE);
147*49cdfc7eSAndroid Build Coastguard Worker 	char mnt_path[PATH_MAX];
148*49cdfc7eSAndroid Build Coastguard Worker 
149*49cdfc7eSAndroid Build Coastguard Worker 	if (statvfs(".", &fs_info) == -1)
150*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK, "statvfs failed");
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker 	blk_size = fs_info.f_bsize;
153*49cdfc7eSAndroid Build Coastguard Worker 
154*49cdfc7eSAndroid Build Coastguard Worker 	if (method == SWAPFILE_BY_SIZE) {
155*49cdfc7eSAndroid Build Coastguard Worker 		tst_res_(file, lineno, TINFO, "create a swapfile size of %u megabytes (MB)", num);
156*49cdfc7eSAndroid Build Coastguard Worker 		blocks = num * 1024 * 1024 / blk_size;
157*49cdfc7eSAndroid Build Coastguard Worker 	} else if (method == SWAPFILE_BY_BLKS) {
158*49cdfc7eSAndroid Build Coastguard Worker 		blocks = num;
159*49cdfc7eSAndroid Build Coastguard Worker 		tst_res_(file, lineno, TINFO, "create a swapfile with %u block numbers", blocks);
160*49cdfc7eSAndroid Build Coastguard Worker 	} else {
161*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK, "Invalid method, please see include/libswap.h");
162*49cdfc7eSAndroid Build Coastguard Worker 	}
163*49cdfc7eSAndroid Build Coastguard Worker 
164*49cdfc7eSAndroid Build Coastguard Worker 	/* To guarantee at least one page can be swapped out */
165*49cdfc7eSAndroid Build Coastguard Worker 	if (blk_size * blocks < pg_size) {
166*49cdfc7eSAndroid Build Coastguard Worker 		tst_res_(file, lineno, TWARN, "Swapfile size is less than the system page size. "
167*49cdfc7eSAndroid Build Coastguard Worker 			"Using page size (%lu bytes) instead of block size (%lu bytes).",
168*49cdfc7eSAndroid Build Coastguard Worker 			(unsigned long)pg_size, blk_size);
169*49cdfc7eSAndroid Build Coastguard Worker 		blk_size = pg_size;
170*49cdfc7eSAndroid Build Coastguard Worker 	}
171*49cdfc7eSAndroid Build Coastguard Worker 
172*49cdfc7eSAndroid Build Coastguard Worker 	if (sscanf(swapfile, "%[^/]", mnt_path) != 1)
173*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK, "sscanf failed");
174*49cdfc7eSAndroid Build Coastguard Worker 
175*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_fs_has_free(mnt_path, blk_size * blocks, TST_BYTES))
176*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TCONF, "Insufficient disk space to create swap file");
177*49cdfc7eSAndroid Build Coastguard Worker 
178*49cdfc7eSAndroid Build Coastguard Worker 	/* create file */
179*49cdfc7eSAndroid Build Coastguard Worker 	if (prealloc_contiguous_file(swapfile, blk_size, blocks) != 0)
180*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK, "Failed to create swapfile");
181*49cdfc7eSAndroid Build Coastguard Worker 
182*49cdfc7eSAndroid Build Coastguard Worker 	/* Fill the file if needed (specific to old xfs filesystems) */
183*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_fs_type(swapfile) == TST_XFS_MAGIC) {
184*49cdfc7eSAndroid Build Coastguard Worker 		if (tst_fill_file(swapfile, 0, blk_size, blocks) != 0)
185*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk_(file, lineno, TBROK, "Failed to fill swapfile");
186*49cdfc7eSAndroid Build Coastguard Worker 	}
187*49cdfc7eSAndroid Build Coastguard Worker 
188*49cdfc7eSAndroid Build Coastguard Worker 	/* make the file swapfile */
189*49cdfc7eSAndroid Build Coastguard Worker 	const char *const argv[] = {"mkswap", swapfile, NULL};
190*49cdfc7eSAndroid Build Coastguard Worker 
191*49cdfc7eSAndroid Build Coastguard Worker 	return tst_cmd(argv, "/dev/null", "/dev/null", safe ?
192*49cdfc7eSAndroid Build Coastguard Worker 			TST_CMD_PASS_RETVAL | TST_CMD_TCONF_ON_MISSING : 0);
193*49cdfc7eSAndroid Build Coastguard Worker }
194*49cdfc7eSAndroid Build Coastguard Worker 
is_swap_supported(const char * filename)195*49cdfc7eSAndroid Build Coastguard Worker bool is_swap_supported(const char *filename)
196*49cdfc7eSAndroid Build Coastguard Worker {
197*49cdfc7eSAndroid Build Coastguard Worker 	int i, sw_support = 0;
198*49cdfc7eSAndroid Build Coastguard Worker 	int ret = SAFE_MAKE_SMALL_SWAPFILE(filename);
199*49cdfc7eSAndroid Build Coastguard Worker 	int fi_contiguous = file_is_contiguous(filename);
200*49cdfc7eSAndroid Build Coastguard Worker 	long fs_type = tst_fs_type(filename);
201*49cdfc7eSAndroid Build Coastguard Worker 	const char *fstype = tst_fs_type_name(fs_type);
202*49cdfc7eSAndroid Build Coastguard Worker 
203*49cdfc7eSAndroid Build Coastguard Worker 	if (fs_type == TST_BTRFS_MAGIC &&
204*49cdfc7eSAndroid Build Coastguard Worker 			tst_kvercmp(5, 0, 0) < 0)
205*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF, "Swapfile on Btrfs (kernel < 5.0) not implemented");
206*49cdfc7eSAndroid Build Coastguard Worker 
207*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; swap_supported_fs[i]; i++) {
208*49cdfc7eSAndroid Build Coastguard Worker 		if (strstr(fstype, swap_supported_fs[i])) {
209*49cdfc7eSAndroid Build Coastguard Worker 			sw_support = 1;
210*49cdfc7eSAndroid Build Coastguard Worker 			break;
211*49cdfc7eSAndroid Build Coastguard Worker 		}
212*49cdfc7eSAndroid Build Coastguard Worker 	}
213*49cdfc7eSAndroid Build Coastguard Worker 
214*49cdfc7eSAndroid Build Coastguard Worker 	if (ret != 0) {
215*49cdfc7eSAndroid Build Coastguard Worker 		if (fi_contiguous == 0 && sw_support == 0) {
216*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TCONF, "mkswap on %s not supported", fstype);
217*49cdfc7eSAndroid Build Coastguard Worker 		} else {
218*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "mkswap on %s failed", fstype);
219*49cdfc7eSAndroid Build Coastguard Worker 			return false;
220*49cdfc7eSAndroid Build Coastguard Worker 		}
221*49cdfc7eSAndroid Build Coastguard Worker 	}
222*49cdfc7eSAndroid Build Coastguard Worker 
223*49cdfc7eSAndroid Build Coastguard Worker 	TEST(tst_syscall(__NR_swapon, filename, 0));
224*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET == -1) {
225*49cdfc7eSAndroid Build Coastguard Worker 		if (errno == EPERM) {
226*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TCONF, "Permission denied for swapon()");
227*49cdfc7eSAndroid Build Coastguard Worker 		} else if (errno == EINVAL && fi_contiguous == 0 && sw_support == 0) {
228*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk(TCONF, "Swapfile on %s not implemented", fstype);
229*49cdfc7eSAndroid Build Coastguard Worker 		} else {
230*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL | TTERRNO, "swapon() on %s failed", fstype);
231*49cdfc7eSAndroid Build Coastguard Worker 			return false;
232*49cdfc7eSAndroid Build Coastguard Worker 		}
233*49cdfc7eSAndroid Build Coastguard Worker 	}
234*49cdfc7eSAndroid Build Coastguard Worker 
235*49cdfc7eSAndroid Build Coastguard Worker 	TEST(tst_syscall(__NR_swapoff, filename, 0));
236*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET == -1) {
237*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TTERRNO, "swapoff on %s failed", fstype);
238*49cdfc7eSAndroid Build Coastguard Worker 		return false;
239*49cdfc7eSAndroid Build Coastguard Worker 	}
240*49cdfc7eSAndroid Build Coastguard Worker 
241*49cdfc7eSAndroid Build Coastguard Worker 	return true;
242*49cdfc7eSAndroid Build Coastguard Worker }
243*49cdfc7eSAndroid Build Coastguard Worker 
tst_max_swapfiles(void)244*49cdfc7eSAndroid Build Coastguard Worker int tst_max_swapfiles(void)
245*49cdfc7eSAndroid Build Coastguard Worker {
246*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int swp_migration_num = 0, swp_hwpoison_num = 0,
247*49cdfc7eSAndroid Build Coastguard Worker 		     swp_device_num = 0, swp_pte_marker_num = 0,
248*49cdfc7eSAndroid Build Coastguard Worker 		     swp_swapin_error_num = 0;
249*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_kconfig_var migration = TST_KCONFIG_INIT("CONFIG_MIGRATION");
250*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_kconfig_var memory = TST_KCONFIG_INIT("CONFIG_MEMORY_FAILURE");
251*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_kconfig_var device = TST_KCONFIG_INIT("CONFIG_DEVICE_PRIVATE");
252*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_kconfig_var marker = TST_KCONFIG_INIT("CONFIG_PTE_MARKER");
253*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_kern_exv kvers_marker_migration[] = {
254*49cdfc7eSAndroid Build Coastguard Worker 		/* RHEL9 kernel has patch 6c287605f and 679d10331 since 5.14.0-179 */
255*49cdfc7eSAndroid Build Coastguard Worker 		{ "RHEL9", "5.14.0-179" },
256*49cdfc7eSAndroid Build Coastguard Worker 		{ NULL, NULL},
257*49cdfc7eSAndroid Build Coastguard Worker 	};
258*49cdfc7eSAndroid Build Coastguard Worker 
259*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_kern_exv kvers_device[] = {
260*49cdfc7eSAndroid Build Coastguard Worker 		/* SLES12-SP4 has patch 5042db43cc26 since 4.12.14-5.5 */
261*49cdfc7eSAndroid Build Coastguard Worker 		{ "SLES", "4.12.14-5.5" },
262*49cdfc7eSAndroid Build Coastguard Worker 		{ NULL, NULL},
263*49cdfc7eSAndroid Build Coastguard Worker 	};
264*49cdfc7eSAndroid Build Coastguard Worker 
265*49cdfc7eSAndroid Build Coastguard Worker 	tst_kconfig_read(&migration, 1);
266*49cdfc7eSAndroid Build Coastguard Worker 	tst_kconfig_read(&memory, 1);
267*49cdfc7eSAndroid Build Coastguard Worker 	tst_kconfig_read(&device, 1);
268*49cdfc7eSAndroid Build Coastguard Worker 	tst_kconfig_read(&marker, 1);
269*49cdfc7eSAndroid Build Coastguard Worker 
270*49cdfc7eSAndroid Build Coastguard Worker 	if (migration.choice == 'y') {
271*49cdfc7eSAndroid Build Coastguard Worker 		if (tst_kvercmp2(5, 19, 0, kvers_marker_migration) < 0)
272*49cdfc7eSAndroid Build Coastguard Worker 			swp_migration_num = 2;
273*49cdfc7eSAndroid Build Coastguard Worker 		else
274*49cdfc7eSAndroid Build Coastguard Worker 			swp_migration_num = 3;
275*49cdfc7eSAndroid Build Coastguard Worker 	}
276*49cdfc7eSAndroid Build Coastguard Worker 
277*49cdfc7eSAndroid Build Coastguard Worker 	if (memory.choice == 'y')
278*49cdfc7eSAndroid Build Coastguard Worker 		swp_hwpoison_num = 1;
279*49cdfc7eSAndroid Build Coastguard Worker 
280*49cdfc7eSAndroid Build Coastguard Worker 	if (device.choice == 'y') {
281*49cdfc7eSAndroid Build Coastguard Worker 		if (tst_kvercmp2(4, 14, 0, kvers_device) >= 0)
282*49cdfc7eSAndroid Build Coastguard Worker 			swp_device_num = 2;
283*49cdfc7eSAndroid Build Coastguard Worker 		if (tst_kvercmp(5, 14, 0) >= 0)
284*49cdfc7eSAndroid Build Coastguard Worker 			swp_device_num = 4;
285*49cdfc7eSAndroid Build Coastguard Worker 	}
286*49cdfc7eSAndroid Build Coastguard Worker 
287*49cdfc7eSAndroid Build Coastguard Worker 	if ((marker.choice == 'y' &&
288*49cdfc7eSAndroid Build Coastguard Worker 	     tst_kvercmp2(5, 19, 0, kvers_marker_migration) >= 0)
289*49cdfc7eSAndroid Build Coastguard Worker 	    || tst_kvercmp(6, 2, 0) >= 0) {
290*49cdfc7eSAndroid Build Coastguard Worker 		swp_pte_marker_num = 1;
291*49cdfc7eSAndroid Build Coastguard Worker 	}
292*49cdfc7eSAndroid Build Coastguard Worker 
293*49cdfc7eSAndroid Build Coastguard Worker 	if ((tst_kvercmp(5, 19, 0) >= 0) && (tst_kvercmp(6, 2, 0) < 0))
294*49cdfc7eSAndroid Build Coastguard Worker 		swp_swapin_error_num = 1;
295*49cdfc7eSAndroid Build Coastguard Worker 
296*49cdfc7eSAndroid Build Coastguard Worker 	return DEFAULT_MAX_SWAPFILE - swp_migration_num - swp_hwpoison_num
297*49cdfc7eSAndroid Build Coastguard Worker 		- swp_device_num - swp_pte_marker_num - swp_swapin_error_num;
298*49cdfc7eSAndroid Build Coastguard Worker }
299*49cdfc7eSAndroid Build Coastguard Worker 
tst_count_swaps(void)300*49cdfc7eSAndroid Build Coastguard Worker int tst_count_swaps(void)
301*49cdfc7eSAndroid Build Coastguard Worker {
302*49cdfc7eSAndroid Build Coastguard Worker 	FILE *fp;
303*49cdfc7eSAndroid Build Coastguard Worker 	int used = -1;
304*49cdfc7eSAndroid Build Coastguard Worker 	char buf[BUFSIZE];
305*49cdfc7eSAndroid Build Coastguard Worker 
306*49cdfc7eSAndroid Build Coastguard Worker 	fp = SAFE_FOPEN("/proc/swaps", "r");
307*49cdfc7eSAndroid Build Coastguard Worker 	if (fp == NULL)
308*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
309*49cdfc7eSAndroid Build Coastguard Worker 
310*49cdfc7eSAndroid Build Coastguard Worker 	while (fgets(buf, BUFSIZE, fp) != NULL)
311*49cdfc7eSAndroid Build Coastguard Worker 		used++;
312*49cdfc7eSAndroid Build Coastguard Worker 
313*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FCLOSE(fp);
314*49cdfc7eSAndroid Build Coastguard Worker 	if (used < 0)
315*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "can't read /proc/swaps to get used swapfiles resource total");
316*49cdfc7eSAndroid Build Coastguard Worker 
317*49cdfc7eSAndroid Build Coastguard Worker 	return used;
318*49cdfc7eSAndroid Build Coastguard Worker }
319