aboutsummaryrefslogtreecommitdiff
path: root/tests/fs-tests/integrity
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fs-tests/integrity')
-rw-r--r--tests/fs-tests/integrity/integck.c167
1 files changed, 165 insertions, 2 deletions
diff --git a/tests/fs-tests/integrity/integck.c b/tests/fs-tests/integrity/integck.c
index 7a4bcdc..9bf42af 100644
--- a/tests/fs-tests/integrity/integck.c
+++ b/tests/fs-tests/integrity/integck.c
@@ -67,6 +67,11 @@ static struct {
* can_mmap: file-system supports share writable 'mmap()' operation
* is_rootfs: the tested file-system the root file-system
* fstype: file-system type (e.g., "ubifs")
+ * fsdev: the underlying device mounted by the tested file-system
+ * mount_opts: non-standard mount options of the tested file-system (non-standard
+ * options are stored in string form as a comma-separated list)
+ * mount_flags: standard mount options of the tested file-system (standard
+ * options as stored as a set of flags)
* mount_point: tested file-system mount point path
* test_dir: the directory on the tested file-system where we test
*/
@@ -78,6 +83,9 @@ static struct {
unsigned int can_mmap:1;
unsigned int is_rootfs:1;
const char *fstype;
+ const char *fsdev;
+ const char *mount_opts;
+ unsigned long mount_flags;
const char *mount_point;
const char *test_dir;
} fsinfo = {
@@ -2011,6 +2019,98 @@ static void update_test_data(void)
do_an_operation();
}
+/**
+ * Re-mount the test file-system. This function randomly select how to
+ * re-mount.
+ */
+void remount_tested_fs(void)
+{
+ char *wd_save;
+ int ret;
+ unsigned long flags;
+ unsigned int rorw1, um, um_ro, um_rorw, rorw2;
+
+ /* Save current working directory */
+ wd_save = malloc(PATH_MAX + 1);
+ CHECK(wd_save != NULL);
+ CHECK(getcwd(wd_save, PATH_MAX + 1) != NULL);
+
+ /* Temporarily change working directory to '/' */
+ CHECK(chdir("/") == 0);
+
+ /* Choose what to do */
+ rorw1 = rand() & 1;
+ um = rand() & 1;
+ um_ro = rand() & 1;
+ um_rorw = rand() & 1;
+ rorw2 = rand() & 1;
+
+ if (rorw1 + um + rorw2 == 0)
+ um = 1;
+
+ if (rorw1) {
+ flags = fsinfo.mount_flags | MS_RDONLY | MS_REMOUNT;
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
+ flags, fsinfo.mount_opts);
+ CHECK(ret == 0);
+
+ flags = fsinfo.mount_flags | MS_REMOUNT;
+ flags &= ~((unsigned long)MS_RDONLY);
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
+ flags, fsinfo.mount_opts);
+ CHECK(ret == 0);
+ }
+
+ if (um) {
+ if (um_ro) {
+ flags = fsinfo.mount_flags | MS_RDONLY | MS_REMOUNT;
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point,
+ fsinfo.fstype, flags, fsinfo.mount_opts);
+ CHECK(ret == 0);
+ }
+
+ CHECK(umount(fsinfo.mount_point) != -1);
+
+ if (!um_rorw) {
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point,
+ fsinfo.fstype, fsinfo.mount_flags,
+ fsinfo.mount_opts);
+ CHECK(ret == 0);
+ } else {
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point,
+ fsinfo.fstype, fsinfo.mount_flags | MS_RDONLY,
+ fsinfo.mount_opts);
+ CHECK(ret == 0);
+
+ flags = fsinfo.mount_flags | MS_REMOUNT;
+ flags &= ~((unsigned long)MS_RDONLY);
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point,
+ fsinfo.fstype, flags, fsinfo.mount_opts);
+ CHECK(ret == 0);
+ }
+ }
+
+ if (rorw2) {
+ flags = fsinfo.mount_flags | MS_RDONLY | MS_REMOUNT;
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
+ flags, fsinfo.mount_opts);
+ CHECK(ret == 0);
+
+ flags = fsinfo.mount_flags | MS_REMOUNT;
+ flags &= ~((unsigned long)MS_RDONLY);
+ ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
+ flags, fsinfo.mount_opts);
+ CHECK(ret == 0);
+ }
+
+ /* Restore the previous working directory */
+ CHECK(chdir(wd_save) == 0);
+ free(wd_save);
+}
+
+/*
+ * Perform the test. Returns zero on success and -1 on failure.
+ */
static int integck(void)
{
int64_t rpt;
@@ -2030,7 +2130,7 @@ static int integck(void)
if (fsinfo.is_rootfs) {
close_open_files();
- tests_remount(); /* Requires root access */
+ remount_tested_fs();
}
/* Check everything */
@@ -2043,7 +2143,7 @@ static int integck(void)
if (!fsinfo.is_rootfs) {
close_open_files();
- tests_remount(); /* Requires root access */
+ remount_tested_fs();
}
/* Check everything */
@@ -2060,6 +2160,67 @@ static int integck(void)
}
/*
+ * This is a helper function for 'get_tested_fs_info()'. It parses file-system
+ * mount options string, extracts standard mount options from there, and saves
+ * them in the 'fsinfo.mount_flags' variable, and non-standard mount options
+ * are saved in the 'fsinfo.mount_opts' variable. The reason for this is that
+ * we want to preserve mount options when unmounting the file-system and
+ * mounting it again. This is because we cannot pass standard mount optins
+ * (like sync, ro, etc) as a string to the 'mount()' function, because it
+ * fails. It accepts standard mount options only as flags. And only the
+ * FS-specific mount options are accepted in form of a string.
+ */
+static void parse_mount_options(const char *mount_opts)
+{
+ char *tmp, *opts, *p;
+ const char *opt;
+
+ /*
+ * We are going to use 'strtok()' which modifies the original string,
+ * so duplicate it.
+ */
+ tmp = dup_string(mount_opts);
+ p = opts = calloc(1, strlen(mount_opts) + 1);
+ CHECK(opts != NULL);
+
+ opt = strtok(tmp, ",");
+ while (opt) {
+ if (!strcmp(opt, "rw"))
+ ;
+ else if (!strcmp(opt, "ro"))
+ fsinfo.mount_flags |= MS_RDONLY;
+ else if (!strcmp(opt, "dirsync"))
+ fsinfo.mount_flags |= MS_DIRSYNC;
+ else if (!strcmp(opt, "noatime"))
+ fsinfo.mount_flags |= MS_NOATIME;
+ else if (!strcmp(opt, "nodiratime"))
+ fsinfo.mount_flags |= MS_NODIRATIME;
+ else if (!strcmp(opt, "noexec"))
+ fsinfo.mount_flags |= MS_NOEXEC;
+ else if (!strcmp(opt, "nosuid"))
+ fsinfo.mount_flags |= MS_NOSUID;
+ else if (!strcmp(opt, "relatime"))
+ fsinfo.mount_flags |= MS_RELATIME;
+ else if (!strcmp(opt, "sync"))
+ fsinfo.mount_flags |= MS_SYNCHRONOUS;
+ else {
+ int len = strlen(opt);
+
+ if (p != opts)
+ *p++ = ',';
+ memcpy(p, opt, len);
+ p += len;
+ *p = '\0';
+ }
+
+ opt = strtok(NULL, ",");
+ }
+
+ free(tmp);
+ fsinfo.mount_opts = opts;
+}
+
+/*
* Fill 'fsinfo' with information about the tested file-system.
*/
static void get_tested_fs_info(void)
@@ -2104,6 +2265,8 @@ static void get_tested_fs_info(void)
fclose(f);
fsinfo.fstype = dup_string(mntent->mnt_type);
+ fsinfo.fsdev = strdup(mntent->mnt_fsname);
+ parse_mount_options(mntent->mnt_opts);
/* Get memory page size for 'mmap()' */
fsinfo.page_size = sysconf(_SC_PAGE_SIZE);