umount2_02.c revision 2df37ec39d153598ae7f4262c8422d50a2e3359b
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#define DIR_MODE (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) 37#define MNTPOINT "mntpoint" 38 39static void setup(void); 40static void test_umount2(int i); 41static void verify_failure(int i); 42static void verify_success(int i); 43static void cleanup(void); 44 45static const char *device; 46static const char *fs_type; 47 48static int mount_flag; 49 50static struct test_case_t { 51 int flag; 52 int exp_errno; 53 int do_access; 54 const char *desc; 55} test_cases[] = { 56 {MNT_EXPIRE | MNT_FORCE, EINVAL, 0, 57 "umount2(2) with MNT_EXPIRE | MNT_FORCE expected EINVAL"}, 58 {MNT_EXPIRE | MNT_DETACH, EINVAL, 0, 59 "umount2(2) with MNT_EXPIRE | MNT_DETACH expected EINVAL"}, 60 {MNT_EXPIRE, EAGAIN, 0, 61 "initial call to umount2(2) with MNT_EXPIRE expected EAGAIN"}, 62 {MNT_EXPIRE, EAGAIN, 1, 63 "umount2(2) with MNT_EXPIRE after access(2) expected EAGAIN"}, 64 {MNT_EXPIRE, 0, 0, 65 "second call to umount2(2) with MNT_EXPIRE expected success"}, 66}; 67 68char *TCID = "umount2_02"; 69int TST_TOTAL = ARRAY_SIZE(test_cases); 70 71int main(int ac, char **av) 72{ 73 int lc; 74 int tc; 75 76 tst_parse_opts(ac, av, NULL, NULL); 77 78 setup(); 79 80 for (lc = 0; TEST_LOOPING(lc); lc++) { 81 tst_count = 0; 82 83 SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, 0, NULL); 84 mount_flag = 1; 85 86 for (tc = 0; tc < TST_TOTAL; tc++) 87 test_umount2(tc); 88 89 if (mount_flag) { 90 SAFE_UMOUNT(cleanup, MNTPOINT); 91 mount_flag = 0; 92 } 93 } 94 95 cleanup(); 96 tst_exit(); 97} 98 99static void setup(void) 100{ 101 tst_require_root(); 102 103 if ((tst_kvercmp(2, 6, 8)) < 0) { 104 tst_brkm(TCONF, NULL, "This test can only run on kernels " 105 "that are 2.6.8 or higher"); 106 } 107 108 tst_sig(NOFORK, DEF_HANDLER, NULL); 109 110 tst_tmpdir(); 111 112 fs_type = tst_dev_fs_type(); 113 device = tst_acquire_device(cleanup); 114 115 if (!device) 116 tst_brkm(TCONF, cleanup, "Failed to obtain block device"); 117 118 tst_mkfs(cleanup, device, fs_type, NULL); 119 120 SAFE_MKDIR(cleanup, MNTPOINT, DIR_MODE); 121 122 TEST_PAUSE; 123} 124 125static void test_umount2(int i) 126{ 127 /* a new access removes the expired mark of the mount point */ 128 if (test_cases[i].do_access) { 129 if (access(MNTPOINT, F_OK) == -1) 130 tst_brkm(TBROK | TERRNO, cleanup, "access(2) failed"); 131 } 132 133 TEST(umount2(MNTPOINT, test_cases[i].flag)); 134 135 if (test_cases[i].exp_errno != 0) 136 verify_failure(i); 137 else 138 verify_success(i); 139} 140 141static void verify_failure(int i) 142{ 143 if (TEST_RETURN == 0) { 144 tst_resm(TFAIL, "%s passed unexpectedly", test_cases[i].desc); 145 mount_flag = 0; 146 return; 147 } 148 149 if (TEST_ERRNO != test_cases[i].exp_errno) { 150 tst_resm(TFAIL | TTERRNO, "%s failed unexpectedly", 151 test_cases[i].desc); 152 return; 153 } 154 155 tst_resm(TPASS | TTERRNO, "umount2(2) failed as expected"); 156} 157 158static void verify_success(int i) 159{ 160 if (TEST_RETURN != 0) { 161 tst_resm(TFAIL | TTERRNO, "%s failed unexpectedly", 162 test_cases[i].desc); 163 return; 164 } 165 166 tst_resm(TPASS, "umount2(2) succeeded as expected"); 167 mount_flag = 0; 168} 169 170static void cleanup(void) 171{ 172 if (mount_flag && tst_umount(MNTPOINT)) 173 tst_resm(TWARN | TERRNO, "Failed to unmount"); 174 175 if (device) 176 tst_release_device(NULL, device); 177 178 tst_rmdir(); 179} 180