1/* 2 * Copyright (c) 2013 Fujitsu Ltd. 3 * Author: DAN LI <li.dan@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 along 14 * with this program; if not, write the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 * 17 */ 18 19/* 20 * DESCRIPTION 21 * Test for feature MS_MOVE of mount(2). 22 * "Move an existing mount point to the new location." 23 */ 24 25#include <errno.h> 26#include <sys/mount.h> 27#include <unistd.h> 28#include <fcntl.h> 29 30#include "test.h" 31#include "safe_macros.h" 32 33#ifndef MS_MOVE 34#define MS_MOVE 8192 35#endif 36 37#ifndef MS_PRIVATE 38#define MS_PRIVATE (1 << 18) 39#endif 40 41#define MNTPOINT_SRC "mnt_src" 42#define MNTPOINT_DES "mnt_des" 43#define LINELENGTH 256 44#define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP) 45 46static int ismount(char *mntpoint); 47static void setup(void); 48static void cleanup(void); 49 50char *TCID = "mount06"; 51int TST_TOTAL = 1; 52 53static const char *fs_type; 54static const char *device; 55static char path_name[PATH_MAX]; 56static char mntpoint_src[PATH_MAX]; 57static char mntpoint_des[PATH_MAX]; 58static int mount_flag; 59 60int main(int argc, char *argv[]) 61{ 62 int lc; 63 64 tst_parse_opts(argc, argv, NULL, NULL); 65 66 setup(); 67 68 for (lc = 0; TEST_LOOPING(lc); lc++) { 69 70 tst_count = 0; 71 72 if (mount(device, mntpoint_src, fs_type, 0, NULL) == -1) 73 tst_brkm(TBROK | TERRNO, cleanup, "mount %s failed", 74 mntpoint_src); 75 76 TEST(mount(mntpoint_src, mntpoint_des, fs_type, MS_MOVE, NULL)); 77 78 if (TEST_RETURN != 0) { 79 tst_resm(TFAIL | TTERRNO, "mount(2) failed"); 80 } else { 81 82 if (!ismount(mntpoint_src) && ismount(mntpoint_des)) 83 tst_resm(TPASS, "move mount is ok"); 84 else 85 tst_resm(TFAIL, "move mount does not work"); 86 87 TEST(tst_umount(mntpoint_des)); 88 if (TEST_RETURN != 0) 89 tst_brkm(TBROK | TTERRNO, cleanup, 90 "umount(2) failed"); 91 } 92 } 93 94 cleanup(); 95 tst_exit(); 96} 97 98int ismount(char *mntpoint) 99{ 100 int ret = 0; 101 FILE *file; 102 char line[LINELENGTH]; 103 104 file = fopen("/proc/mounts", "r"); 105 if (file == NULL) 106 tst_brkm(TFAIL | TERRNO, NULL, "Open /proc/mounts failed"); 107 108 while (fgets(line, LINELENGTH, file) != NULL) { 109 if (strstr(line, mntpoint) != NULL) { 110 ret = 1; 111 break; 112 } 113 } 114 fclose(file); 115 return ret; 116} 117 118static void setup(void) 119{ 120 tst_require_root(); 121 122 tst_sig(NOFORK, DEF_HANDLER, cleanup); 123 124 tst_tmpdir(); 125 126 fs_type = tst_dev_fs_type(); 127 device = tst_acquire_device(cleanup); 128 129 if (!device) 130 tst_brkm(TCONF, cleanup, "Failed to obtain block device"); 131 132 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 133 134 if (getcwd(path_name, sizeof(path_name)) == NULL) 135 tst_brkm(TBROK, cleanup, "getcwd failed"); 136 137 /* 138 * Turn current dir into a private mount point being a parent 139 * mount which is required by move mount. 140 */ 141 if (mount(path_name, path_name, "none", MS_BIND, NULL) == -1) 142 tst_brkm(TBROK | TERRNO, cleanup, "bind mount failed"); 143 144 mount_flag = 1; 145 146 if (mount("none", path_name, "none", MS_PRIVATE, NULL) == -1) 147 tst_brkm(TBROK | TERRNO, cleanup, "mount private failed"); 148 149 snprintf(mntpoint_src, PATH_MAX, "%s/%s", path_name, MNTPOINT_SRC); 150 snprintf(mntpoint_des, PATH_MAX, "%s/%s", path_name, MNTPOINT_DES); 151 152 SAFE_MKDIR(cleanup, mntpoint_src, DIR_MODE); 153 SAFE_MKDIR(cleanup, mntpoint_des, DIR_MODE); 154 155 TEST_PAUSE; 156} 157 158static void cleanup(void) 159{ 160 if (mount_flag && tst_umount(path_name) != 0) 161 tst_resm(TWARN | TERRNO, "umount(2) %s failed", path_name); 162 163 if (device) 164 tst_release_device(device); 165 166 tst_rmdir(); 167} 168