166 lines
3.3 KiB
C
166 lines
3.3 KiB
C
/*
|
|
* Copyright (c) 2015 Fujitsu Ltd.
|
|
* Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* alone with this program.
|
|
*/
|
|
|
|
/*
|
|
* DESCRIPTION
|
|
* Test for feature MNT_DETACH of umount2().
|
|
* "Perform a lazy unmount: make the mount point unavailable for
|
|
* new accesses, and actually perform the unmount when the mount
|
|
* point ceases to be busy."
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <sys/mount.h>
|
|
|
|
#include "test.h"
|
|
#include "safe_macros.h"
|
|
#include "lapi/mount.h"
|
|
|
|
static void setup(void);
|
|
static void umount2_verify(void);
|
|
static void cleanup(void);
|
|
|
|
char *TCID = "umount2_01";
|
|
int TST_TOTAL = 1;
|
|
|
|
#define DIR_MODE (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
|
|
#define FILE_MODE (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID)
|
|
#define MNTPOINT "mntpoint"
|
|
|
|
static int fd;
|
|
static int mount_flag;
|
|
|
|
static const char *device;
|
|
static const char *fs_type;
|
|
|
|
int main(int ac, char **av)
|
|
{
|
|
int lc;
|
|
|
|
tst_parse_opts(ac, av, NULL, NULL);
|
|
|
|
setup();
|
|
|
|
for (lc = 0; TEST_LOOPING(lc); lc++) {
|
|
tst_count = 0;
|
|
|
|
umount2_verify();
|
|
}
|
|
|
|
cleanup();
|
|
tst_exit();
|
|
}
|
|
|
|
static void setup(void)
|
|
{
|
|
tst_require_root();
|
|
|
|
tst_sig(NOFORK, DEF_HANDLER, NULL);
|
|
|
|
tst_tmpdir();
|
|
|
|
fs_type = tst_dev_fs_type();
|
|
device = tst_acquire_device(cleanup);
|
|
|
|
if (!device)
|
|
tst_brkm(TCONF, cleanup, "Failed to obtain block device");
|
|
|
|
tst_mkfs(cleanup, device, fs_type, NULL, NULL);
|
|
|
|
SAFE_MKDIR(cleanup, MNTPOINT, DIR_MODE);
|
|
|
|
TEST_PAUSE;
|
|
}
|
|
|
|
static void umount2_verify(void)
|
|
{
|
|
int ret;
|
|
char buf[256];
|
|
const char *str = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, 0, NULL);
|
|
mount_flag = 1;
|
|
|
|
fd = SAFE_CREAT(cleanup, MNTPOINT "/file", FILE_MODE);
|
|
|
|
TEST(umount2(MNTPOINT, MNT_DETACH));
|
|
|
|
if (TEST_RETURN != 0) {
|
|
tst_resm(TFAIL | TTERRNO, "umount2(2) Failed");
|
|
goto EXIT;
|
|
}
|
|
|
|
mount_flag = 0;
|
|
|
|
/* check the unavailability for new access */
|
|
ret = access(MNTPOINT "/file", F_OK);
|
|
|
|
if (ret != -1) {
|
|
tst_resm(TFAIL, "umount2(2) MNT_DETACH flag "
|
|
"performed abnormally");
|
|
goto EXIT;
|
|
}
|
|
|
|
/*
|
|
* check the old fd still points to the file
|
|
* in previous mount point and is available
|
|
*/
|
|
SAFE_WRITE(cleanup, 1, fd, str, strlen(str));
|
|
|
|
SAFE_CLOSE(cleanup, fd);
|
|
|
|
SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, 0, NULL);
|
|
mount_flag = 1;
|
|
|
|
fd = SAFE_OPEN(cleanup, MNTPOINT "/file", O_RDONLY);
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
SAFE_READ(cleanup, 1, fd, buf, strlen(str));
|
|
|
|
if (strcmp(str, buf)) {
|
|
tst_resm(TFAIL, "umount2(2) MNT_DETACH flag "
|
|
"performed abnormally");
|
|
goto EXIT;
|
|
}
|
|
|
|
tst_resm(TPASS, "umount2(2) Passed");
|
|
|
|
EXIT:
|
|
SAFE_CLOSE(cleanup, fd);
|
|
fd = 0;
|
|
|
|
if (mount_flag) {
|
|
if (tst_umount(MNTPOINT))
|
|
tst_brkm(TBROK, cleanup, "umount() failed");
|
|
mount_flag = 0;
|
|
}
|
|
}
|
|
|
|
static void cleanup(void)
|
|
{
|
|
if (fd > 0 && close(fd))
|
|
tst_resm(TWARN | TERRNO, "Failed to close file");
|
|
|
|
if (mount_flag && tst_umount(MNTPOINT))
|
|
tst_resm(TWARN | TERRNO, "Failed to unmount");
|
|
|
|
if (device)
|
|
tst_release_device(device);
|
|
|
|
tst_rmdir();
|
|
}
|