1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) International Business Machines Corp., 2007
4 * Created by <[email protected]>
5 *
6 */
7
8 /*\
9 * [Description]
10 *
11 * This test case checks whether swapon(2) system call returns:
12 *
13 * - EPERM when there are more than MAX_SWAPFILES already in use.
14 */
15
16 #include <stdio.h>
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <sys/wait.h>
20 #include <sys/swap.h>
21 #include "tst_test.h"
22 #include "lapi/syscalls.h"
23 #include "libswap.h"
24
25 #define MNTPOINT "mntpoint"
26 #define TEST_FILE MNTPOINT"/testswap"
27
28 static int swapfiles;
29
setup_swap(void)30 static int setup_swap(void)
31 {
32 pid_t pid;
33 int status;
34 int j, max_swapfiles, used_swapfiles;
35 char filename[FILENAME_MAX];
36
37 SAFE_SETEUID(0);
38
39 /* Determine how many more files are to be created */
40 max_swapfiles = tst_max_swapfiles();
41 used_swapfiles = tst_count_swaps();
42 swapfiles = max_swapfiles - used_swapfiles;
43 if (swapfiles > max_swapfiles)
44 swapfiles = max_swapfiles;
45
46 pid = SAFE_FORK();
47 if (pid == 0) {
48 /*create and turn on remaining swapfiles */
49 for (j = 0; j < swapfiles; j++) {
50
51 /* Create the swapfile */
52 snprintf(filename, sizeof(filename), "%s%02d", TEST_FILE, j + 2);
53 MAKE_SMALL_SWAPFILE(filename);
54
55 /* turn on the swap file */
56 TST_EXP_PASS_SILENT(swapon(filename, 0));
57 }
58 exit(0);
59 } else
60 waitpid(pid, &status, 0);
61
62 if (WEXITSTATUS(status))
63 tst_brk(TFAIL, "Failed to setup swap files");
64
65 tst_res(TINFO, "Successfully created %d swap files", swapfiles);
66 MAKE_SMALL_SWAPFILE(TEST_FILE);
67
68 return 0;
69 }
70
71 /*
72 * Check if the file is at /proc/swaps and remove it giving swapoff
73 */
check_and_swapoff(const char * filename)74 static int check_and_swapoff(const char *filename)
75 {
76 char cmd_buffer[256];
77 int rc = -1;
78
79 snprintf(cmd_buffer, sizeof(cmd_buffer), "grep -q '%s.*file' /proc/swaps", filename);
80
81 if (system(cmd_buffer) == 0 && swapoff(filename) != 0) {
82 tst_res(TWARN, "Failed to swapoff %s", filename);
83 rc = -1;
84 }
85
86 return rc;
87 }
88
89 /*
90 * Turn off all swapfiles previously turned on
91 */
clean_swap(void)92 static void clean_swap(void)
93 {
94 int j;
95 char filename[FILENAME_MAX];
96
97 for (j = 0; j < swapfiles; j++) {
98 snprintf(filename, sizeof(filename), "%s%02d", TEST_FILE, j + 2);
99 check_and_swapoff(filename);
100 }
101
102 check_and_swapoff("testfile");
103 }
104
verify_swapon(void)105 static void verify_swapon(void)
106 {
107 TST_EXP_FAIL(swapon(TEST_FILE, 0), EPERM, "swapon(%s, 0)", TEST_FILE);
108 }
109
setup(void)110 static void setup(void)
111 {
112 if (access("/proc/swaps", F_OK))
113 tst_brk(TCONF, "swap not supported by kernel");
114
115 is_swap_supported(TEST_FILE);
116 if (setup_swap() < 0) {
117 clean_swap();
118 tst_brk(TBROK, "Setup failed, quitting the test");
119 }
120 }
121
cleanup(void)122 static void cleanup(void)
123 {
124 clean_swap();
125 }
126
127 static struct tst_test test = {
128 .mntpoint = MNTPOINT,
129 .mount_device = 1,
130 .all_filesystems = 1,
131 .needs_root = 1,
132 .forks_child = 1,
133 .test_all = verify_swapon,
134 .setup = setup,
135 .cleanup = cleanup
136 };
137