1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2007 4f08c3bdfSopenharmony_ci * Created by <rsalveti@linux.vnet.ibm.com> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/*\ 9f08c3bdfSopenharmony_ci * [Description] 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * This test case checks whether swapon(2) system call returns: 12f08c3bdfSopenharmony_ci * - EPERM when there are more than MAX_SWAPFILES already in use. 13f08c3bdfSopenharmony_ci */ 14f08c3bdfSopenharmony_ci 15f08c3bdfSopenharmony_ci#include <stdio.h> 16f08c3bdfSopenharmony_ci#include <errno.h> 17f08c3bdfSopenharmony_ci#include <stdlib.h> 18f08c3bdfSopenharmony_ci#include <sys/wait.h> 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#include "tst_test.h" 21f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 22f08c3bdfSopenharmony_ci#include "swaponoff.h" 23f08c3bdfSopenharmony_ci#include "libswap.h" 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_cistatic int setup_swap(void); 26f08c3bdfSopenharmony_cistatic int clean_swap(void); 27f08c3bdfSopenharmony_cistatic int check_and_swapoff(const char *filename); 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_cistatic int swapfiles; 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ciint testfiles = 3; 32f08c3bdfSopenharmony_cistatic struct swap_testfile_t { 33f08c3bdfSopenharmony_ci char *filename; 34f08c3bdfSopenharmony_ci} swap_testfiles[] = { 35f08c3bdfSopenharmony_ci {"firstswapfile"}, 36f08c3bdfSopenharmony_ci {"secondswapfile"}, 37f08c3bdfSopenharmony_ci {"thirdswapfile"} 38f08c3bdfSopenharmony_ci}; 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ciint expected_errno = EPERM; 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_cistatic void verify_swapon(void) 43f08c3bdfSopenharmony_ci{ 44f08c3bdfSopenharmony_ci if (setup_swap() < 0) { 45f08c3bdfSopenharmony_ci clean_swap(); 46f08c3bdfSopenharmony_ci tst_brk(TBROK, "Setup failed, quitting the test"); 47f08c3bdfSopenharmony_ci } 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ci TEST(tst_syscall(__NR_swapon, swap_testfiles[0].filename, 0)); 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci if ((TST_RET == -1) && (TST_ERR == expected_errno)) { 52f08c3bdfSopenharmony_ci tst_res(TPASS, "swapon(2) got expected failure (%d),", 53f08c3bdfSopenharmony_ci expected_errno); 54f08c3bdfSopenharmony_ci } else if (TST_RET < 0) { 55f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 56f08c3bdfSopenharmony_ci "swapon(2) failed to produce expected error " 57f08c3bdfSopenharmony_ci "(%d). System reboot recommended.", 58f08c3bdfSopenharmony_ci expected_errno); 59f08c3bdfSopenharmony_ci } else { 60f08c3bdfSopenharmony_ci /* Probably the system supports MAX_SWAPFILES > 30, 61f08c3bdfSopenharmony_ci * let's try with MAX_SWAPFILES == 32 */ 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci /* Call swapon sys call once again for 32 64f08c3bdfSopenharmony_ci * now we can't receive an error */ 65f08c3bdfSopenharmony_ci TEST(tst_syscall(__NR_swapon, swap_testfiles[1].filename, 0)); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci /* Check return code (now we're expecting success) */ 68f08c3bdfSopenharmony_ci if (TST_RET < 0) { 69f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 70f08c3bdfSopenharmony_ci "swapon(2) got an unexpected failure"); 71f08c3bdfSopenharmony_ci } else { 72f08c3bdfSopenharmony_ci /* Call swapon sys call once again for 33 73f08c3bdfSopenharmony_ci * now we have to receive an error */ 74f08c3bdfSopenharmony_ci TEST(tst_syscall(__NR_swapon, swap_testfiles[2].filename, 0)); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci /* Check return code (should be an error) */ 77f08c3bdfSopenharmony_ci if ((TST_RET == -1) && (TST_ERR == expected_errno)) { 78f08c3bdfSopenharmony_ci tst_res(TPASS, 79f08c3bdfSopenharmony_ci "swapon(2) got expected failure;" 80f08c3bdfSopenharmony_ci " Got errno = %d, probably your" 81f08c3bdfSopenharmony_ci " MAX_SWAPFILES is 32", 82f08c3bdfSopenharmony_ci expected_errno); 83f08c3bdfSopenharmony_ci } else { 84f08c3bdfSopenharmony_ci tst_res(TFAIL, 85f08c3bdfSopenharmony_ci "swapon(2) failed to produce" 86f08c3bdfSopenharmony_ci " expected error: %d, got %s." 87f08c3bdfSopenharmony_ci " System reboot after execution of LTP" 88f08c3bdfSopenharmony_ci " test suite is recommended.", 89f08c3bdfSopenharmony_ci expected_errno, strerror(TST_ERR)); 90f08c3bdfSopenharmony_ci } 91f08c3bdfSopenharmony_ci } 92f08c3bdfSopenharmony_ci } 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci if (clean_swap() < 0) 95f08c3bdfSopenharmony_ci tst_brk(TBROK, "Cleanup failed, quitting the test"); 96f08c3bdfSopenharmony_ci} 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci/* 99f08c3bdfSopenharmony_ci * Create 33 and activate 30 swapfiles. 100f08c3bdfSopenharmony_ci */ 101f08c3bdfSopenharmony_cistatic int setup_swap(void) 102f08c3bdfSopenharmony_ci{ 103f08c3bdfSopenharmony_ci pid_t pid; 104f08c3bdfSopenharmony_ci int j, fd; 105f08c3bdfSopenharmony_ci int status; 106f08c3bdfSopenharmony_ci int res = 0; 107f08c3bdfSopenharmony_ci char filename[FILENAME_MAX]; 108f08c3bdfSopenharmony_ci char buf[BUFSIZ + 1]; 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci /* Find out how many swapfiles (1 line per entry) already exist */ 111f08c3bdfSopenharmony_ci swapfiles = 0; 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci if (seteuid(0) < 0) 114f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, "Failed to call seteuid"); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci /* This includes the first (header) line */ 117f08c3bdfSopenharmony_ci if ((fd = open("/proc/swaps", O_RDONLY)) == -1) { 118f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, 119f08c3bdfSopenharmony_ci "Failed to find out existing number of swap files"); 120f08c3bdfSopenharmony_ci } 121f08c3bdfSopenharmony_ci do { 122f08c3bdfSopenharmony_ci char *p = buf; 123f08c3bdfSopenharmony_ci res = read(fd, buf, BUFSIZ); 124f08c3bdfSopenharmony_ci if (res < 0) { 125f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, 126f08c3bdfSopenharmony_ci "Failed to find out existing number of swap files"); 127f08c3bdfSopenharmony_ci } 128f08c3bdfSopenharmony_ci buf[res] = '\0'; 129f08c3bdfSopenharmony_ci while ((p = strchr(p, '\n'))) { 130f08c3bdfSopenharmony_ci p++; 131f08c3bdfSopenharmony_ci swapfiles++; 132f08c3bdfSopenharmony_ci } 133f08c3bdfSopenharmony_ci } while (BUFSIZ <= res); 134f08c3bdfSopenharmony_ci close(fd); 135f08c3bdfSopenharmony_ci if (swapfiles) 136f08c3bdfSopenharmony_ci swapfiles--; /* don't count the /proc/swaps header */ 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci if (swapfiles < 0) 139f08c3bdfSopenharmony_ci tst_brk(TFAIL, "Failed to find existing number of swapfiles"); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci /* Determine how many more files are to be created */ 142f08c3bdfSopenharmony_ci swapfiles = MAX_SWAPFILES - swapfiles; 143f08c3bdfSopenharmony_ci if (swapfiles > MAX_SWAPFILES) 144f08c3bdfSopenharmony_ci swapfiles = MAX_SWAPFILES; 145f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 146f08c3bdfSopenharmony_ci if (pid == 0) { 147f08c3bdfSopenharmony_ci /*create and turn on remaining swapfiles */ 148f08c3bdfSopenharmony_ci for (j = 0; j < swapfiles; j++) { 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci /* prepare filename for the iteration */ 151f08c3bdfSopenharmony_ci if (sprintf(filename, "swapfile%02d", j + 2) < 0) { 152f08c3bdfSopenharmony_ci printf("sprintf() failed to create " 153f08c3bdfSopenharmony_ci "filename"); 154f08c3bdfSopenharmony_ci exit(1); 155f08c3bdfSopenharmony_ci } 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci /* Create the swapfile */ 158f08c3bdfSopenharmony_ci make_swapfile(filename, 0); 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_ci /* turn on the swap file */ 161f08c3bdfSopenharmony_ci res = tst_syscall(__NR_swapon, filename, 0); 162f08c3bdfSopenharmony_ci if (res != 0) { 163f08c3bdfSopenharmony_ci if (errno == EPERM) { 164f08c3bdfSopenharmony_ci printf("Successfully created %d swapfiles\n", j); 165f08c3bdfSopenharmony_ci break; 166f08c3bdfSopenharmony_ci } else { 167f08c3bdfSopenharmony_ci printf("Failed to create swapfile: %s\n", filename); 168f08c3bdfSopenharmony_ci exit(1); 169f08c3bdfSopenharmony_ci } 170f08c3bdfSopenharmony_ci } 171f08c3bdfSopenharmony_ci } 172f08c3bdfSopenharmony_ci exit(0); 173f08c3bdfSopenharmony_ci } else 174f08c3bdfSopenharmony_ci waitpid(pid, &status, 0); 175f08c3bdfSopenharmony_ci 176f08c3bdfSopenharmony_ci if (WEXITSTATUS(status)) 177f08c3bdfSopenharmony_ci tst_brk(TFAIL, "Failed to setup swaps"); 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ci /* Create all needed extra swapfiles for testing */ 180f08c3bdfSopenharmony_ci for (j = 0; j < testfiles; j++) 181f08c3bdfSopenharmony_ci make_swapfile(swap_testfiles[j].filename, 0); 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_ci return 0; 184f08c3bdfSopenharmony_ci} 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci/* 187f08c3bdfSopenharmony_ci * Turn off all swapfiles previously turned on 188f08c3bdfSopenharmony_ci */ 189f08c3bdfSopenharmony_cistatic int clean_swap(void) 190f08c3bdfSopenharmony_ci{ 191f08c3bdfSopenharmony_ci int j; 192f08c3bdfSopenharmony_ci char filename[FILENAME_MAX]; 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci for (j = 0; j < swapfiles; j++) { 195f08c3bdfSopenharmony_ci if (snprintf(filename, sizeof(filename), 196f08c3bdfSopenharmony_ci "swapfile%02d", j + 2) < 0) { 197f08c3bdfSopenharmony_ci tst_res(TWARN, "sprintf() failed to create filename"); 198f08c3bdfSopenharmony_ci tst_res(TWARN, "Failed to turn off swap files. System" 199f08c3bdfSopenharmony_ci " reboot after execution of LTP test" 200f08c3bdfSopenharmony_ci " suite is recommended"); 201f08c3bdfSopenharmony_ci return -1; 202f08c3bdfSopenharmony_ci } 203f08c3bdfSopenharmony_ci if (check_and_swapoff(filename) != 0) { 204f08c3bdfSopenharmony_ci tst_res(TWARN, "Failed to turn off swap file %s.", filename); 205f08c3bdfSopenharmony_ci return -1; 206f08c3bdfSopenharmony_ci } 207f08c3bdfSopenharmony_ci } 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci for (j = 0; j < testfiles; j++) { 210f08c3bdfSopenharmony_ci if (check_and_swapoff(swap_testfiles[j].filename) != 0) { 211f08c3bdfSopenharmony_ci tst_res(TWARN, "Failed to turn off swap file %s.", 212f08c3bdfSopenharmony_ci swap_testfiles[j].filename); 213f08c3bdfSopenharmony_ci return -1; 214f08c3bdfSopenharmony_ci } 215f08c3bdfSopenharmony_ci } 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci return 0; 218f08c3bdfSopenharmony_ci} 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci/* 221f08c3bdfSopenharmony_ci * Check if the file is at /proc/swaps and remove it giving swapoff 222f08c3bdfSopenharmony_ci */ 223f08c3bdfSopenharmony_cistatic int check_and_swapoff(const char *filename) 224f08c3bdfSopenharmony_ci{ 225f08c3bdfSopenharmony_ci char cmd_buffer[256]; 226f08c3bdfSopenharmony_ci int rc = -1; 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci if (snprintf(cmd_buffer, sizeof(cmd_buffer), 229f08c3bdfSopenharmony_ci "grep -q '%s.*file' /proc/swaps", filename) < 0) { 230f08c3bdfSopenharmony_ci tst_res(TWARN, "sprintf() failed to create the command string"); 231f08c3bdfSopenharmony_ci } else { 232f08c3bdfSopenharmony_ci 233f08c3bdfSopenharmony_ci rc = 0; 234f08c3bdfSopenharmony_ci 235f08c3bdfSopenharmony_ci if (system(cmd_buffer) == 0) { 236f08c3bdfSopenharmony_ci 237f08c3bdfSopenharmony_ci /* now we need to swapoff the file */ 238f08c3bdfSopenharmony_ci if (tst_syscall(__NR_swapoff, filename) != 0) { 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_ci tst_res(TWARN, "Failed to turn off swap " 241f08c3bdfSopenharmony_ci "file. system reboot after " 242f08c3bdfSopenharmony_ci "execution of LTP test suite " 243f08c3bdfSopenharmony_ci "is recommended"); 244f08c3bdfSopenharmony_ci rc = -1; 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci } 247f08c3bdfSopenharmony_ci 248f08c3bdfSopenharmony_ci } 249f08c3bdfSopenharmony_ci } 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci return rc; 252f08c3bdfSopenharmony_ci} 253f08c3bdfSopenharmony_ci 254f08c3bdfSopenharmony_cistatic void setup(void) 255f08c3bdfSopenharmony_ci{ 256f08c3bdfSopenharmony_ci if (access("/proc/swaps", F_OK)) 257f08c3bdfSopenharmony_ci tst_brk(TCONF, "swap not supported by kernel"); 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_ci is_swap_supported("./tstswap"); 260f08c3bdfSopenharmony_ci} 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_cistatic void cleanup(void) 263f08c3bdfSopenharmony_ci{ 264f08c3bdfSopenharmony_ci clean_swap(); 265f08c3bdfSopenharmony_ci} 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_cistatic struct tst_test test = { 268f08c3bdfSopenharmony_ci .needs_root = 1, 269f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 270f08c3bdfSopenharmony_ci .forks_child = 1, 271f08c3bdfSopenharmony_ci .test_all = verify_swapon, 272f08c3bdfSopenharmony_ci .setup = setup, 273f08c3bdfSopenharmony_ci .cleanup = cleanup 274f08c3bdfSopenharmony_ci}; 275