Patchwork [22/27] fs-tests: integck: do not use tests_remount

login
register
mail settings
Submitter Artem Bityutskiy
Date April 13, 2011, 3:19 p.m.
Message ID <1302707947-6143-23-git-send-email-dedekind1@gmail.com>
Download mbox | patch
Permalink /patch/91051/
State New
Headers show

Comments

Artem Bityutskiy - April 13, 2011, 3:19 p.m.
From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>

Implement our own version of 'tests_remount()' instead of depending
on the common implementation.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
---
 tests/fs-tests/integrity/integck.c |  167 +++++++++++++++++++++++++++++++++++-
 1 files changed, 165 insertions(+), 2 deletions(-)

Patch

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);