umount2_02.c revision 879d392fa9fe8883e81aac7407c6bb3b021a8905
1/* 2 * Copyright (c) 2015 Fujitsu Ltd. 3 * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License 14 * alone with this program. 15 */ 16 17/* 18 * DESCRIPTION 19 * Test for feature MNT_EXPIRE of umount2(). 20 * "Mark the mount point as expired.If a mount point is not currently 21 * in use, then an initial call to umount2() with this flag fails with 22 * the error EAGAIN, but marks the mount point as expired. The mount 23 * point remains expired as long as it isn't accessed by any process. 24 * A second umount2() call specifying MNT_EXPIRE unmounts an expired 25 * mount point. This flag cannot be specified with either MNT_FORCE or 26 * MNT_DETACH. (fails with the error EINVAL)" 27 */ 28 29#include <errno.h> 30#include <sys/mount.h> 31 32#include "test.h" 33#include "safe_macros.h" 34#include "lapi/mount.h" 35 36#include "umount2.h" 37 38#define DIR_MODE (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) 39#define MNTPOINT "mntpoint" 40 41static void setup(void); 42static void test_umount2(int i); 43static void verify_failure(int i); 44static void verify_success(int i); 45static void cleanup(void); 46 47static const char *device; 48static const char *fs_type; 49 50static int mount_flag; 51 52static struct test_case_t { 53 int flag; 54 int exp_errno; 55 int do_access; 56 const char *desc; 57} test_cases[] = { 58 {MNT_EXPIRE | MNT_FORCE, EINVAL, 0, 59 "umount2(2) with MNT_EXPIRE | MNT_FORCE expected EINVAL"}, 60 {MNT_EXPIRE | MNT_DETACH, EINVAL, 0, 61 "umount2(2) with MNT_EXPIRE | MNT_DETACH expected EINVAL"}, 62 {MNT_EXPIRE, EAGAIN, 0, 63 "initial call to umount2(2) with MNT_EXPIRE expected EAGAIN"}, 64 {MNT_EXPIRE, EAGAIN, 1, 65 "umount2(2) with MNT_EXPIRE after access(2) expected EAGAIN"}, 66 {MNT_EXPIRE, 0, 0, 67 "second call to umount2(2) with MNT_EXPIRE expected success"}, 68}; 69 70char *TCID = "umount2_02"; 71int TST_TOTAL = ARRAY_SIZE(test_cases); 72 73int main(int ac, char **av) 74{ 75 int lc; 76 int tc; 77 78 tst_parse_opts(ac, av, NULL, NULL); 79 80 setup(); 81 82 for (lc = 0; TEST_LOOPING(lc); lc++) { 83 tst_count = 0; 84 85 SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, 0, NULL); 86 mount_flag = 1; 87 88 for (tc = 0; tc < TST_TOTAL; tc++) 89 test_umount2(tc); 90 91 if (mount_flag) { 92 if (tst_umount(MNTPOINT)) 93 tst_brkm(TBROK, cleanup, "umount() failed"); 94 mount_flag = 0; 95 } 96 } 97 98 cleanup(); 99 tst_exit(); 100} 101 102static void setup(void) 103{ 104 tst_require_root(); 105 106 if ((tst_kvercmp(2, 6, 8)) < 0) { 107 tst_brkm(TCONF, NULL, "This test can only run on kernels " 108 "that are 2.6.8 or higher"); 109 } 110 111 tst_sig(NOFORK, DEF_HANDLER, NULL); 112 113 tst_tmpdir(); 114 115 fs_type = tst_dev_fs_type(); 116 device = tst_acquire_device(cleanup); 117 118 if (!device) 119 tst_brkm(TCONF, cleanup, "Failed to obtain block device"); 120 121 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 122 123 SAFE_MKDIR(cleanup, MNTPOINT, DIR_MODE); 124 125 TEST_PAUSE; 126} 127 128static void test_umount2(int i) 129{ 130 /* a new access removes the expired mark of the mount point */ 131 if (test_cases[i].do_access) { 132 if (access(MNTPOINT, F_OK) == -1) 133 tst_brkm(TBROK | TERRNO, cleanup, "access(2) failed"); 134 } 135 136 TEST(umount2_retry(MNTPOINT, test_cases[i].flag)); 137 138 if (test_cases[i].exp_errno != 0) 139 verify_failure(i); 140 else 141 verify_success(i); 142} 143 144static void verify_failure(int i) 145{ 146 if (TEST_RETURN == 0) { 147 tst_resm(TFAIL, "%s passed unexpectedly", test_cases[i].desc); 148 mount_flag = 0; 149 return; 150 } 151 152 if (TEST_ERRNO != test_cases[i].exp_errno) { 153 tst_resm(TFAIL | TTERRNO, "%s failed unexpectedly", 154 test_cases[i].desc); 155 return; 156 } 157 158 tst_resm(TPASS | TTERRNO, "umount2(2) failed as expected"); 159} 160 161static void verify_success(int i) 162{ 163 if (TEST_RETURN != 0) { 164 tst_resm(TFAIL | TTERRNO, "%s failed unexpectedly", 165 test_cases[i].desc); 166 return; 167 } 168 169 tst_resm(TPASS, "umount2(2) succeeded as expected"); 170 mount_flag = 0; 171} 172 173static void cleanup(void) 174{ 175 if (mount_flag && tst_umount(MNTPOINT)) 176 tst_resm(TWARN | TERRNO, "Failed to unmount"); 177 178 if (device) 179 tst_release_device(device); 180 181 tst_rmdir(); 182} 183