Skip to contentSkip to conversation

lib/tst_mkfs: Clear first 512k of the device

PATCH New Cyril Hrubis 4 participants 27 messages Oct 11, 2017 – Nov 9, 2017 Library code

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/16 lib/tst_mkfs: Clear first 512k of the device

If we cal tst_mkfs() from a test more than once we end up with the very same bug we already fixed by clearing the device in tst_acquire_device(), i.e. some mkfs programs will not format it when there is a valid FS signature there. But we have to clear the device for the shell tests as well.

So this commit adds tst_clear_device() function that is both called from the tst_mkfs() and from the shell tst_device helper to clear up the first 512k of the device.

---
 include/tst_device.h       | 10 ++++++++++
 lib/tst_device.c           | 19 +++++++++++--------
 lib/tst_mkfs.c             |  4 ++++
 testcases/lib/tst_device.c |  5 +++++
 4 files changed, 30 insertions(+), 8 deletions(-)
include/tst_device.h +10 -0
index 897696dd9..7ac288368 100644
@@ -34,4 +34,14 @@ extern struct tst_device *tst_device;
  */
 int tst_umount(const char *path);
 
+/*
+ * Clears a first few blocks of the device. This is needed when device has
+ * already been formatted with a filesystems, subset of mkfs.foo utils aborts
+ * the operation if it finds a filesystem signature there.
+ *
+ * Note that this is called from tst_mkfs() automatically, so you probably will
+ * not need to use this from the test yourself.
+ */
+int tst_clear_device(const char *dev);
+
 #endif	/* TST_DEVICE_H__ */
lib/tst_device.c +11 -8
index 67432caf6..6ad6c47f6 100644
@@ -245,15 +245,8 @@ const char *tst_acquire_device__(unsigned int size)
 
 		ltp_dev_size = ltp_dev_size/1024/1024;
 
-		if (acq_dev_size <= ltp_dev_size) {
-			if (tst_fill_file(dev, 0, 1024, 512)) {
-				tst_resm(TWARN | TERRNO,
-					 "Failed to clear the first 512k of %s",
-					 dev);
-			}
-
+		if (acq_dev_size <= ltp_dev_size)
 			return dev;
-		}
 
 		tst_resm(TINFO, "Skipping $LTP_DEV size %"PRIu64"MB, requested size %uMB",
 				ltp_dev_size, acq_dev_size);
@@ -319,6 +312,16 @@ int tst_release_device(const char *dev)
 	return ret;
 }
 
+int tst_clear_device(const char *dev)
+{
+	if (tst_fill_file(dev, 0, 1024, 512)) {
+		tst_resm(TWARN, "Failed to clear 512k block on %s", dev);
+		return 1;
+	}
+
+	return 0;
+}
+
 int tst_umount(const char *path)
 {
 	int err, ret, i;
lib/tst_mkfs.c +4 -0
index f2e40ecd6..7385a939f 100644
@@ -18,6 +18,7 @@
 #include "test.h"
 #include "ltp_priv.h"
 #include "tst_mkfs.h"
+#include "tst_device.h"
 
 #define OPTS_MAX 32
 
@@ -75,6 +76,9 @@ void tst_mkfs_(const char *file, const int lineno, void (cleanup_fn)(void),
 
 	argv[pos] = NULL;
 
+	if (tst_clear_device(dev))
+		tst_brkm(TBROK, cleanup_fn, "tst_clear_device() failed");
+
 	tst_resm(TINFO, "Formatting %s with %s opts='%s' extra opts='%s'",
 	         dev, fs_type, fs_opts_str, extra_opt ? extra_opt : "");
 	ret = tst_run_cmd(cleanup_fn, argv, "/dev/null", NULL, 1);
testcases/lib/tst_device.c +5 -0
index d33cac613..9afaeb1ef 100644
@@ -59,6 +59,11 @@ static int acquire_device(int argc, char *argv[])
 	if (!device)
 		return 1;
 
+	if (tst_clear_device(device)) {
+		tst_release_device(device);
+		return 1;
+	}
+
 	printf("%s", device);
 
 	return 0;
Signature · 1 line
2.13.5
#3 lore raw

PATCH v3 1/16 lib/tst_mkfs: Clear first 512k of the device

Hi!

Quoted 2 lines

The only changes against v2 are in last 2 patches we discussed, so no objections from me.

Rebased and pushed, thanks for the review.

Signature · 2 lines
Cyril Hrubis
[email protected]
#4 lore raw

PATCH v3 2/16 lib: Add interface to list supported filesystems

In reply to Cyril Hrubis

A filesystem is supported if kernel can mount it (we do not get ENODEV when we attempt to mount it) and if there is mkfs installed so that we can format a test device.

The function starts with a whitelist of filesystems to use and loops over them filtering out unsupported ones, then finally returns a list of filesystem that could be used for the testing.

---
 include/tst_fs.h             |   4 ++
 lib/tst_supported_fs_types.c | 118 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)
 create mode 100644 lib/tst_supported_fs_types.c
include/tst_fs.h +4 -0
index 52befbec9..1f6d2bab5 100644
@@ -146,6 +146,10 @@ int tst_get_path(const char *prog_name, char *buf, size_t buf_len);
  */
 int tst_fill_file(const char *path, char pattern, size_t bs, size_t bcount);
 
+/*
+ * Returns NULL-terminated array of kernel-supported filesystems.
+ */
+const char **tst_get_supported_fs_types(void);
 
 #ifdef TST_TEST_H__
 static inline long tst_fs_type(const char *path)
lib/tst_supported_fs_types.c new file +118 -0

118 lines not on this page · raw message

Signature · 1 line
2.13.5
#5 lore raw

PATCH v3 2/16 lib: Add interface to list supported filesystems

Quoted 132 lines · Cyril Hrubis

A filesystem is supported if kernel can mount it (we do not get ENODEV when we attempt to mount it) and if there is mkfs installed so that we can format a test device.

The function starts with a whitelist of filesystems to use and loops over them filtering out unsupported ones, then finally returns a list of filesystem that could be used for the testing.

---
 include/tst_fs.h             |   4 ++
 lib/tst_supported_fs_types.c | 118 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)
 create mode 100644 lib/tst_supported_fs_types.c
include/tst_fs.h +4 -0
index 52befbec9..1f6d2bab5 100644
@@ -146,6 +146,10 @@ int tst_get_path(const char *prog_name, char *buf, size_t buf_len);
  */
 int tst_fill_file(const char *path, char pattern, size_t bs, size_t bcount);
 
+/*
+ * Returns NULL-terminated array of kernel-supported filesystems.
+ */
+const char **tst_get_supported_fs_types(void);
 
 #ifdef TST_TEST_H__
 static inline long tst_fs_type(const char *path)
lib/tst_supported_fs_types.c new file +96 -0
new file mode 100644
index 000000000..a23b1ed52
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017 Cyril Hrubis <[email protected]>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_fs.h"
+
+static const char *const fs_type_whitelist[] = {
+	"ext2",
+	"ext3",
+	"ext4",
+	"xfs",
+	"btrfs",
+	"vfat",
+	"exfat",
+	"ntfs",
+	NULL
+};
+
+static const char *fs_types[ARRAY_SIZE(fs_type_whitelist)];
+
+static int has_mkfs(const char *fs_type)
+{
+	char buf[128];
+	int ret;
+
+	sprintf(buf, "mkfs.%s >/dev/null 2>&1", fs_type);
+
+	ret = tst_system(buf);
+
+	if (WEXITSTATUS(ret) == 127) {
+		tst_res(TINFO, "mkfs.%s does not exist", fs_type);
+		return 0;
+	}
+
+	tst_res(TINFO, "mkfs.%s does exist", fs_type);
+	return 1;
+}
+
+static int has_kernel_support(const char *fs_type)
+{
+	static int fuse_supported = -1;
+	const char *tmpdir = getenv("TMPDIR");
+	char buf[128];
+	int ret;
+
+	if (!tmpdir)
+		tmpdir = "/tmp";
+
+	mount("/dev/zero", tmpdir, fs_type, 0, NULL);
+	if (errno != ENODEV) {
+		tst_res(TINFO, "Kernel supports %s", fs_type);
+		return 1;
+	}
+
+	/* Is FUSE supported by kernel? */
+	if (fuse_supported == -1) {
+		ret = open("/dev/fuse", O_RDWR);
+		if (ret < 0) {
+			fuse_supported = 0;
+		} else {
+			fuse_supported = 1;
+			SAFE_CLOSE(ret);
+		}
+	}
+
+	if (!fuse_supported)
+		return 0;
+
+	/* Is FUSE implementation installed? */
+	sprintf(buf, "mount.%s >/dev/null 2>&1", fs_type);
+
+	ret = tst_system(buf);
+	if (WEXITSTATUS(ret) == 127) {
+		tst_res(TINFO, "Filesystem %s is not supported", fs_type);
+		return 0;

lib/tst_supported_fs_types.c line 106

Quoted 10 lines
lib/tst_supported_fs_types.c new file +10 -0
+	}
+
+	tst_res(TINFO, "FUSE does support %s", fs_type);
+	return 1;
+}
+
+static int is_supported(const char *fs_type)
+{
+	return has_kernel_support(fs_type) && has_mkfs(fs_type);
+}

It will be nice if this was an exported API as well.

Other than that, this is very useful for a bunch of tests that rely on formatting + mounting devices for error checks.

#6 lore raw

PATCH v3 3/16 SAFE_MOUNT: Handle FUSE mounts as well

In reply to Cyril Hrubis

FUSE mounts can be only mounted by the corresponding mount.$fs_type handler.

---
 lib/safe_macros.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
lib/safe_macros.c +39 -0
index 7ca1849fa..c4aed0b30 100644
@@ -699,6 +699,23 @@ int safe_rename(const char *file, const int lineno, void (*cleanup_fn)(void),
 	return rval;
 }
 
+static const char *const fuse_fs_types[] = {
+	"exfat",
+	"ntfs",
+};
+
+static int is_fuse(const char *fs_type)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(fuse_fs_types); i++) {
+		if (!strcmp(fuse_fs_types[i], fs_type))
+			return 1;
+	}
+
+	return 0;
+}
+
 int safe_mount(const char *file, const int lineno, void (*cleanup_fn)(void),
 	       const char *source, const char *target,
 	       const char *filesystemtype, unsigned long mountflags,
@@ -708,6 +725,28 @@ int safe_mount(const char *file, const int lineno, void (*cleanup_fn)(void),
 
 	rval = mount(source, target, filesystemtype, mountflags, data);
 
+	/*
+	 * The FUSE filesystem executes mount.fuse helper, which tries to
+	 * execute corresponding binary name which is encoded@the start of
+	 * the source string and separated by # from the device name.
+         *
+	 * The mount helpers are called mount.$fs_type.
+	 */
+	if (rval == -1 && errno == ENODEV && is_fuse(filesystemtype)) {
+		char buf[1024];
+		int ret;
+
+		tst_resm(TINFO, "Trying FUSE...");
+		snprintf(buf, sizeof(buf), "mount.%s '%s' '%s'",
+			 filesystemtype, source, target);
+
+		ret = tst_system(buf);
+		if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0)
+			return 0;
+
+		errno = ENODEV;
+	}
+
 	if (rval == -1) {
 		tst_brkm(TBROK | TERRNO, cleanup_fn,
 			 "%s:%d: mount(%s, %s, %s, %lu, %p) failed",
Signature · 1 line
2.13.5
#7 lore raw

PATCH v3 4/16 lib/tst_test: Add .all_filesystems flag

In reply to Cyril Hrubis

This commit adds a support for re-runing a test on all available filesystems simply by turning on .all_filesystems flag in the tst_test structure.

The .all_filesystems flag implies .needs_device, the .format_filesystem and .mount_filesystem works as usuall but the device is formatted and mounted for each filesystem before we run the test function. The .setup and .cleanup functions are executed for each filesystem. The currently tested filesystem type is stored in the tst_device->fs_type.

This allows us to easily run a test that tests filesystem specific syscall for all supported filesystems without a need to hardcode all fs types into a runtest file and with a minimal changes to the test code.

---
 include/tst_test.h |   9 +++++
 lib/tst_test.c     | 117 ++++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 97 insertions(+), 29 deletions(-)
include/tst_test.h +9 -0
index ad468e8cf..e0dd12708 100644
@@ -125,6 +125,15 @@ struct tst_test {
 	int format_device:1;
 	int mount_device:1;
 	int needs_rofs:1;
+	/*
+	 * If set the test function will be executed for all available
+	 * filesystems and the current filesytem type would be set in the
+	 * tst_device->fs_type.
+	 *
+	 * The test setup and cleanup are executed before/after __EACH__ call
+	 * to the test function.
+	 */
+	int all_filesystems:1;
 
 	/* Minimal device size in megabytes */
 	unsigned int dev_min_size;
lib/tst_test.c +88 -29

174 lines not on this page · raw message

Signature · 1 line
2.13.5
#8 lore raw

PATCH v3 5/16 lib/tst_fs: Add tst_fill_fs()

In reply to Cyril Hrubis

Adds a simple helper to fill a filesystem.

All the funciton does is to create and write to files in a given directory until write() fails with ENOSPC.

This is intended to be used in various filesystem related tests such as fallocate and stress tests.

---
 include/tst_fs.h  |  5 +++++
 lib/tst_fill_fs.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 lib/tst_fill_fs.c
include/tst_fs.h +5 -0
index 1f6d2bab5..0ad535c2b 100644
@@ -151,6 +151,11 @@ int tst_fill_file(const char *path, char pattern, size_t bs, size_t bcount);
  */
 const char **tst_get_supported_fs_types(void);
 
+/*
+ * Creates and writes to files on given path until write fails with ENOSPC
+ */
+void tst_fill_fs(const char *path, int verbose);
+
 #ifdef TST_TEST_H__
 static inline long tst_fs_type(const char *path)
 {
lib/tst_fill_fs.c new file +63 -0

63 lines not on this page · raw message

Signature · 1 line
2.13.5
#9 lore raw

PATCH v3 5/16 lib/tst_fs: Add tst_fill_fs()

Quoted 3 lines · Cyril Hrubis

Adds a simple helper to fill a filesystem.

All the funciton does is to create and write to files in a given

s/funciton/function

Quoted 4 lines

directory until write() fails with ENOSPC.

This is intended to be used in various filesystem related tests such as fallocate and stress tests.

Couple of other use cases
- To fill a filesystem would be to create nested directories for EMLINK testing in order to test file system limit(s) (e.g. syscalls/mkdir)
- Filling a filesystem with empty files (e.g syscalls/rename etc )

That said, the function can be expanded to do this at a later time as well based on the function parameters.

Quoted 83 lines
---
 include/tst_fs.h  |  5 +++++
 lib/tst_fill_fs.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 lib/tst_fill_fs.c
include/tst_fs.h +5 -0
index 1f6d2bab5..0ad535c2b 100644
@@ -151,6 +151,11 @@ int tst_fill_file(const char *path, char pattern, size_t bs, size_t bcount);
  */
 const char **tst_get_supported_fs_types(void);
 
+/*
+ * Creates and writes to files on given path until write fails with ENOSPC
+ */
+void tst_fill_fs(const char *path, int verbose);
+
 #ifdef TST_TEST_H__
 static inline long tst_fs_type(const char *path)
 {
lib/tst_fill_fs.c new file +53 -0
new file mode 100644
index 000000000..6b2bbbcd7
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Cyril Hrubis <[email protected]>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_fs.h"
+
+void tst_fill_fs(const char *path, int verbose)
+{
+	int i = 0;
+	char file[PATH_MAX];
+	char buf[4096];
+	size_t len;
+	ssize_t ret;
+	int fd;
+
+	for (;;) {
+		len = random() % (1024 * 102400);
+
+		snprintf(file, sizeof(file), "%s/file%i", path, i++);
+
+		if (verbose)
+			tst_res(TINFO, "Creating file %s size %zu", file, len);
+
+		fd = SAFE_OPEN(file, O_WRONLY | O_CREAT, 0700);
+
+		while (len) {
+			ret = write(fd, buf, MIN(len, sizeof(buf)));
+
+			if (ret < 0) {
+				SAFE_CLOSE(fd);
+
+				if (errno != ENOSPC)
+					tst_brk(TBROK | TERRNO, "write()");
+

lib/tst_fill_fs.c line 63

Quoted 10 lines
lib/tst_fill_fs.c new file +10 -0
+				tst_res(TINFO | TERRNO, "write()");
+				return;
+			}
+
+			len -= ret;
+		}
+
+		SAFE_CLOSE(fd);
+	}
+}
Quoted 6 lines
Signature · 5 lines
2.13.5


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp
#10 lore raw

PATCH v3 6/16 syscalls/fallocate05: New test

In reply to Cyril Hrubis

Tests that fallocate() works fine when filesystem is full.

---
 runtest/syscalls                                  |   1 +
 testcases/kernel/syscalls/.gitignore              |   1 +
 testcases/kernel/syscalls/fallocate/fallocate05.c | 104 ++++++++++++++++++++++
 3 files changed, 106 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fallocate/fallocate05.c
runtest/syscalls +1 -0
index 2362a231d..a31d15da6 100644
@@ -160,6 +160,7 @@ fallocate01 fallocate01
 fallocate02 fallocate02
 fallocate03 fallocate03
 fallocate04 fallocate04
+fallocate05 fallocate05
 
 #posix_fadvise test cases
 posix_fadvise01                      posix_fadvise01
testcases/kernel/syscalls/.gitignore +1 -0
index 930f3f999..a91abd9f0 100644
@@ -141,6 +141,7 @@
 /fallocate/fallocate02
 /fallocate/fallocate03
 /fallocate/fallocate04
+/fallocate/fallocate05
 /fchdir/fchdir01
 /fchdir/fchdir02
 /fchdir/fchdir03
testcases/kernel/syscalls/fallocate/fallocate05.c new file +104 -0

104 lines not on this page · raw message

Signature · 1 line
2.13.5
#11 lore raw

PATCH v3 7/16 syscalls/msync04: Run test for all filesystems

In reply to Cyril Hrubis
---
 testcases/kernel/syscalls/msync/msync04.c | 1 +
 1 file changed, 1 insertion(+)
testcases/kernel/syscalls/msync/msync04.c +1 -0
index 4f70ca1ef..9dec3c1d9 100644
@@ -109,5 +109,6 @@ static struct tst_test test = {
 	.needs_root = 1,
 	.mntpoint = "msync04",
 	.mount_device = 1,
+	.all_filesystems = 1,
 	.min_kver = "2.6.25",
 };
Signature · 1 line
2.13.5
#12 lore raw

PATCH v3 8/16 syscalls/fallocate04: Convert to the new library

In reply to Cyril Hrubis
---
 testcases/kernel/syscalls/fallocate/fallocate04.c | 169 ++++++++++------------
 1 file changed, 77 insertions(+), 92 deletions(-)
testcases/kernel/syscalls/fallocate/fallocate04.c +77 -92
index a6729161c..4916c8b47 100644
@@ -30,13 +30,9 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_test.h"
 #include "lapi/fallocate.h"
 
-char *TCID = "fallocate04";
-int TST_TOTAL = 5;
-
 static int fd;
 static const char fname[] = "fallocate04.txt";
 static size_t block_size;
@@ -44,28 +40,18 @@ static size_t buf_size;
 
 #define NUM_OF_BLOCKS	3
 
-static int verbose;
-static const option_t options[] = {
-	{"v", &verbose, NULL},
-	{NULL, NULL, NULL}
-};
-
-static void help(void)
-{
-	printf("  -v      Verbose\n");
-}
+static char *verbose;
 
 static void cleanup(void)
 {
-	close(fd);
-	tst_rmdir();
+	SAFE_CLOSE(fd);
 }
 
 static void get_blocksize(void)
 {
 	struct stat file_stat;
 
-	SAFE_FSTAT(cleanup, fd, &file_stat);
+	SAFE_FSTAT(fd, &file_stat);
 
 	block_size = file_stat.st_blksize;
 	buf_size = NUM_OF_BLOCKS * block_size;
@@ -77,7 +63,7 @@ static size_t get_allocsize(void)
 
 	fsync(fd);
 
-	SAFE_FSTAT(cleanup, fd, &file_stat);
+	SAFE_FSTAT(fd, &file_stat);
 
 	return file_stat.st_blocks * 512;
 }
@@ -93,9 +79,7 @@ static void fill_tst_buf(char buf[])
 
 static void setup(void)
 {
-	tst_tmpdir();
-
-	fd = SAFE_OPEN(cleanup, fname, O_RDWR | O_CREAT, 0700);
+	fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
 
 	get_blocksize();
 }
@@ -104,86 +88,86 @@ static void check_file_data(const char exp_buf[], size_t size)
 {
 	char rbuf[size];
 
-	tst_resm(TINFO, "reading the file, compare with expected buffer");
+	tst_res(TINFO, "reading the file, compare with expected buffer");
 
-	SAFE_LSEEK(cleanup, fd, 0, SEEK_SET);
-	SAFE_READ(cleanup, 1, fd, rbuf, size);
+	SAFE_LSEEK(fd, 0, SEEK_SET);
+	SAFE_READ(1, fd, rbuf, size);
 
 	if (memcmp(exp_buf, rbuf, size)) {
 		if (verbose) {
-			tst_resm_hexd(TINFO, exp_buf, size, "expected:");
-			tst_resm_hexd(TINFO, rbuf, size, "but read:");
+			tst_res_hexd(TINFO, exp_buf, size, "expected:");
+			tst_res_hexd(TINFO, rbuf, size, "but read:");
 		}
-		tst_brkm(TFAIL, cleanup, "not expected file data");
+		tst_brk(TFAIL, "not expected file data");
 	}
 }
 
 static void test01(void)
 {
-	tst_resm(TINFO, "allocate '%zu' bytes", buf_size);
+	tst_res(TINFO, "allocate '%zu' bytes", buf_size);
 
 	if (fallocate(fd, 0, 0, buf_size) == -1) {
 		if (errno == ENOSYS || errno == EOPNOTSUPP)
-			tst_brkm(TCONF, cleanup, "fallocate() not supported");
-		tst_brkm(TFAIL | TERRNO, cleanup, "fallocate() failed");
+			tst_brk(TCONF, "fallocate() not supported");
+		tst_brk(TFAIL | TERRNO, "fallocate() failed");
 	}
 
 	char buf[buf_size];
 
 	fill_tst_buf(buf);
 
-	SAFE_WRITE(cleanup, 1, fd, buf, buf_size);
+	SAFE_WRITE(1, fd, buf, buf_size);
 
-	tst_resm(TPASS, "test-case succeeded");
+	tst_res(TPASS, "test-case succeeded");
 }
 
 static void test02(void)
 {
 	size_t alloc_size0 = get_allocsize();
 
-	tst_resm(TINFO, "read allocated file size '%zu'", alloc_size0);
-	tst_resm(TINFO, "make a hole with FALLOC_FL_PUNCH_HOLE");
+	tst_res(TINFO, "read allocated file size '%zu'", alloc_size0);
+	tst_res(TINFO, "make a hole with FALLOC_FL_PUNCH_HOLE");
 
 	if (tst_kvercmp(2, 6, 38) < 0) {
-		tst_brkm(TCONF, cleanup,
-			 "FALLOC_FL_PUNCH_HOLE needs Linux 2.6.38 or newer");
+		tst_brk(TCONF,
+			"FALLOC_FL_PUNCH_HOLE needs Linux 2.6.38 or newer");
 	}
 
 	if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
 	    block_size, block_size) == -1) {
 		if (errno == EOPNOTSUPP) {
-			tst_brkm(TCONF, cleanup,
-			         "FALLOC_FL_PUNCH_HOLE not supported");
+			tst_brk(TCONF,
+			        "FALLOC_FL_PUNCH_HOLE not supported");
 		}
-		tst_brkm(TFAIL | TERRNO, cleanup, "fallocate() failed");
+		tst_brk(TFAIL | TERRNO, "fallocate() failed");
 	}
 
-	tst_resm(TINFO, "check that file has a hole with lseek(,,SEEK_HOLE)");
+	tst_res(TINFO, "check that file has a hole with lseek(,,SEEK_HOLE)");
 	off_t ret = lseek(fd, 0, SEEK_HOLE);
 
 	if (ret != (ssize_t)block_size) {
 		/* exclude error when kernel doesn't have SEEK_HOLE support */
 		if (errno != EINVAL) {
-			tst_brkm(TFAIL | TERRNO, cleanup,
+			tst_brk(TFAIL | TERRNO,
 				 "fallocate() or lseek() failed");
 		}
 		if (tst_kvercmp(3, 1, 0) < 0) {
-			tst_resm(TINFO, "lseek() doesn't support SEEK_HOLE, "
+			tst_res(TINFO, "lseek() doesn't support SEEK_HOLE, "
 				 "this is expected for < 3.1 kernels");
 		} else {
-			tst_brkm(TBROK | TERRNO, cleanup,
+			tst_brk(TBROK | TERRNO,
 				 "lseek() doesn't support SEEK_HOLE");
 		}
 	} else {
-		tst_resm(TINFO, "found a hole at '%ld' offset", ret);
+		tst_res(TINFO, "found a hole@'%ld' offset", ret);
 	}
 
 	size_t alloc_size1 = get_allocsize();
 
-	tst_resm(TINFO, "allocated file size before '%zu' and after '%zu'",
+	tst_res(TINFO, "allocated file size before '%zu' and after '%zu'",
 		 alloc_size0, alloc_size1);
 	if ((alloc_size0 - block_size) != alloc_size1)
-		tst_brkm(TFAIL, cleanup, "not expected allocated size");
+		tst_brk(TFAIL, "not expected allocated size");
 
 	char exp_buf[buf_size];
 
@@ -192,29 +176,29 @@ static void test02(void)
 
 	check_file_data(exp_buf, buf_size);
 
-	tst_resm(TPASS, "test-case succeeded");
+	tst_res(TPASS, "test-case succeeded");
 }
 
 static void test03(void)
 {
-	tst_resm(TINFO, "zeroing file space with FALLOC_FL_ZERO_RANGE");
+	tst_res(TINFO, "zeroing file space with FALLOC_FL_ZERO_RANGE");
 
 	if (tst_kvercmp(3, 15, 0) < 0) {
-		tst_brkm(TCONF, cleanup,
-			 "FALLOC_FL_ZERO_RANGE needs Linux 3.15 or newer");
+		tst_brk(TCONF,
+			"FALLOC_FL_ZERO_RANGE needs Linux 3.15 or newer");
 	}
 
 	size_t alloc_size0 = get_allocsize();
 
-	tst_resm(TINFO, "read current allocated file size '%zu'", alloc_size0);
+	tst_res(TINFO, "read current allocated file size '%zu'", alloc_size0);
 
 	if (fallocate(fd, FALLOC_FL_ZERO_RANGE, block_size - 1,
 	    block_size + 2) == -1) {
 		if (errno == EOPNOTSUPP) {
-			tst_brkm(TCONF, cleanup,
-			         "FALLOC_FL_ZERO_RANGE not supported");
+			tst_brk(TCONF,
+			        "FALLOC_FL_ZERO_RANGE not supported");
 		}
-		tst_brkm(TFAIL | TERRNO, cleanup, "fallocate failed");
+		tst_brk(TFAIL | TERRNO, "fallocate failed");
 	}
 
 	/* The file hole in the specified range must be allocated and
@@ -222,10 +206,10 @@ static void test03(void)
 	 */
 	size_t alloc_size1 = get_allocsize();
 
-	tst_resm(TINFO, "allocated file size before '%zu' and after '%zu'",
+	tst_res(TINFO, "allocated file size before '%zu' and after '%zu'",
 		 alloc_size0, alloc_size1);
 	if ((alloc_size0 + block_size) != alloc_size1)
-		tst_brkm(TFAIL, cleanup, "not expected allocated size");
+		tst_brk(TFAIL, "not expected allocated size");
 
 	char exp_buf[buf_size];
 
@@ -234,32 +218,32 @@ static void test03(void)
 
 	check_file_data(exp_buf, buf_size);
 
-	tst_resm(TPASS, "test-case succeeded");
+	tst_res(TPASS, "test-case succeeded");
 }
 
 static void test04(void)
 {
-	tst_resm(TINFO, "collapsing file space with FALLOC_FL_COLLAPSE_RANGE");
+	tst_res(TINFO, "collapsing file space with FALLOC_FL_COLLAPSE_RANGE");
 
 	size_t alloc_size0 = get_allocsize();
 
-	tst_resm(TINFO, "read current allocated file size '%zu'", alloc_size0);
+	tst_res(TINFO, "read current allocated file size '%zu'", alloc_size0);
 
 	if (fallocate(fd, FALLOC_FL_COLLAPSE_RANGE, block_size,
 	    block_size) == -1) {
 		if (errno == EOPNOTSUPP) {
-			tst_brkm(TCONF, cleanup,
-			         "FALLOC_FL_COLLAPSE_RANGE not supported");
+			tst_brk(TCONF,
+			        "FALLOC_FL_COLLAPSE_RANGE not supported");
 		}
-		tst_brkm(TFAIL | TERRNO, cleanup, "fallocate failed");
+		tst_brk(TFAIL | TERRNO, "fallocate failed");
 	}
 
 	size_t alloc_size1 = get_allocsize();
 
-	tst_resm(TINFO, "allocated file size before '%zu' and after '%zu'",
+	tst_res(TINFO, "allocated file size before '%zu' and after '%zu'",
 		 alloc_size0, alloc_size1);
 	if ((alloc_size0 - block_size) != alloc_size1)
-		tst_brkm(TFAIL, cleanup, "not expected allocated size");
+		tst_brk(TFAIL, "not expected allocated size");
 
 	size_t size = buf_size - block_size;
 	char tmp_buf[buf_size];
@@ -274,36 +258,36 @@ static void test04(void)
 	exp_buf[block_size - 1] = exp_buf[block_size] = '\0';
 	check_file_data(exp_buf, size);
 
-	tst_resm(TPASS, "test-case succeeded");
+	tst_res(TPASS, "test-case succeeded");
 }
 
 static void test05(void)
 {
-	tst_resm(TINFO, "inserting space with FALLOC_FL_INSERT_RANGE");
+	tst_res(TINFO, "inserting space with FALLOC_FL_INSERT_RANGE");
 
 	size_t alloc_size0 = get_allocsize();
 
-	tst_resm(TINFO, "read current allocated file size '%zu'", alloc_size0);
+	tst_res(TINFO, "read current allocated file size '%zu'", alloc_size0);
 
 	if (fallocate(fd, FALLOC_FL_INSERT_RANGE, block_size,
 	    block_size) == -1) {
 		if (errno == EOPNOTSUPP) {
-			tst_brkm(TCONF, cleanup,
-				 "FALLOC_FL_INSERT_RANGE not supported");
+			tst_brk(TCONF,
+				"FALLOC_FL_INSERT_RANGE not supported");
 		}
-		tst_brkm(TFAIL | TERRNO, cleanup, "fallocate failed");
+		tst_brk(TFAIL | TERRNO, "fallocate failed");
 	}
 
 	/* allocate space and ensure that it filled with zeroes */
 	if (fallocate(fd, FALLOC_FL_ZERO_RANGE, block_size, block_size) == -1)
-		tst_brkm(TFAIL | TERRNO, cleanup, "fallocate failed");
+		tst_brk(TFAIL | TERRNO, "fallocate failed");
 
 	size_t alloc_size1 = get_allocsize();
 
-	tst_resm(TINFO, "allocated file size before '%zu' and after '%zu'",
+	tst_res(TINFO, "allocated file size before '%zu' and after '%zu'",
 		 alloc_size0, alloc_size1);
 	if ((alloc_size0 + block_size) != alloc_size1)
-		tst_brkm(TFAIL, cleanup, "not expected allocated size");
+		tst_brk(TFAIL, "not expected allocated size");
 
 	char exp_buf[buf_size];
 
@@ -312,26 +296,27 @@ static void test05(void)
 
 	check_file_data(exp_buf, buf_size);
 
-	tst_resm(TPASS, "test-case succeeded");
+	tst_res(TPASS, "test-case succeeded");
 }
 
-int main(int argc, char *argv[])
+static void run(void)
 {
-	int lc;
-
-	tst_parse_opts(argc, argv, options, help);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); ++lc) {
-		test01();
-		test02();
-		test03();
-		test04();
-		test05();
-	}
+	test01();
+	test02();
+	test03();
+	test04();
+	test05();
+}
 
-	cleanup();
+static struct tst_option opts[] = {
+	{"v", &verbose, "-v       Turns on verbose mode"},
+	{NULL, NULL, NULL}
+};
 
-	tst_exit();
-}
+static struct tst_test test = {
+	.options = opts,
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run,
+	.needs_tmpdir = 1,
+};
Signature · 1 line
2.13.5
#13 lore raw

PATCH v3 9/16 syscalls/fallocate04: Run test for all filesystems

In reply to Cyril Hrubis
---
 testcases/kernel/syscalls/fallocate/fallocate04.c | 49 +++++++++++++----------
 1 file changed, 28 insertions(+), 21 deletions(-)
testcases/kernel/syscalls/fallocate/fallocate04.c +28 -21
index 4916c8b47..e576d728d 100644
@@ -34,19 +34,15 @@
 #include "lapi/fallocate.h"
 
 static int fd;
-static const char fname[] = "fallocate04.txt";
 static size_t block_size;
 static size_t buf_size;
 
+#define MNTPOINT "fallocate"
+#define FNAME MNTPOINT "/fallocate.txt"
 #define NUM_OF_BLOCKS	3
 
 static char *verbose;
 
-static void cleanup(void)
-{
-	SAFE_CLOSE(fd);
-}
-
 static void get_blocksize(void)
 {
 	struct stat file_stat;
@@ -77,13 +73,6 @@ static void fill_tst_buf(char buf[])
 		memset(buf + i * block_size, 'a' + i, block_size);
 }
 
-static void setup(void)
-{
-	fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
-
-	get_blocksize();
-}
-
 static void check_file_data(const char exp_buf[], size_t size)
 {
 	char rbuf[size];
@@ -299,13 +288,26 @@ static void test05(void)
 	tst_res(TPASS, "test-case succeeded");
 }
 
-static void run(void)
+static void (*tcases[])(void) = {
+	test01, test02, test03, test04, test05
+};
+
+static void run(unsigned int i)
+{
+	tcases[i]();
+}
+
+static void setup(void)
+{
+	fd = SAFE_OPEN(FNAME, O_RDWR | O_CREAT, 0700);
+
+	get_blocksize();
+}
+
+static void cleanup(void)
 {
-	test01();
-	test02();
-	test03();
-	test04();
-	test05();
+	if (fd > 0)
+		SAFE_CLOSE(fd);
 }
 
 static struct tst_option opts[] = {
@@ -315,8 +317,13 @@ static struct tst_option opts[] = {
 
 static struct tst_test test = {
 	.options = opts,
-	.setup = setup,
 	.cleanup = cleanup,
-	.test_all = run,
+	.setup = setup,
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.mount_device = 1,
+	.mntpoint = MNTPOINT,
+	.all_filesystems = 1,
 	.needs_tmpdir = 1,
+	.needs_root = 1,
 };
Signature · 1 line
2.13.5
#14 lore raw

PATCH v3 10/16 syscalls/setxattr01: Convert to the new library.

In reply to Cyril Hrubis
---
 testcases/kernel/syscalls/setxattr/setxattr01.c | 138 +++++++++---------------
 1 file changed, 51 insertions(+), 87 deletions(-)
testcases/kernel/syscalls/setxattr/setxattr01.c +51 -87
index 359991e3f..86df7ba73 100644
@@ -57,10 +57,7 @@
 #ifdef HAVE_SYS_XATTR_H
 # include <sys/xattr.h>
 #endif
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "setxattr01";
+#include "tst_test.h"
 
 #ifdef HAVE_SYS_XATTR_H
 #define XATTR_NAME_MAX 255
@@ -69,157 +66,124 @@ char *TCID = "setxattr01";
 #define XATTR_TEST_KEY "user.testkey"
 #define XATTR_TEST_VALUE "this is a test value"
 #define XATTR_TEST_VALUE_SIZE 20
+#define FNAME "setxattr01testfile"
 
-static void setup(void);
-static void cleanup(void);
-
-char filename[BUFSIZ];
-char long_key[XATTR_NAME_LEN];
-char *long_value;
+static char long_key[XATTR_NAME_LEN];
+static char *long_value;
+static char *xattr_value = XATTR_TEST_VALUE;
 
 struct test_case {
-	char *fname;
 	char *key;
-	char *value;
+	char **value;
 	size_t size;
 	int flags;
 	int exp_err;
 };
 struct test_case tc[] = {
 	{			/* case 00, invalid flags */
-	 .fname = filename,
-	 .key = XATTR_TEST_KEY,
-	 .value = XATTR_TEST_VALUE,
+	 .key = long_key,
+	 .value = &xattr_value,
 	 .size = XATTR_TEST_VALUE_SIZE,
 	 .flags = ~0,
 	 .exp_err = EINVAL,
 	 },
 	{			/* case 01, replace non-existing attribute */
-	 .fname = filename,
 	 .key = XATTR_TEST_KEY,
-	 .value = XATTR_TEST_VALUE,
+	 .value = &xattr_value,
 	 .size = XATTR_TEST_VALUE_SIZE,
 	 .flags = XATTR_REPLACE,
 	 .exp_err = ENODATA,
 	 },
-	{			/* case 02, long key name, key will be set in setup() */
-	 .fname = filename,
-	 .key = NULL,
-	 .value = XATTR_TEST_VALUE,
+	{			/* case 02, long key name */
+	 .key = long_key,
+	 .value = &xattr_value,
 	 .size = XATTR_TEST_VALUE_SIZE,
 	 .flags = XATTR_CREATE,
 	 .exp_err = ERANGE,
 	 },
-	{			/* case 03, long value, value will be set in setup() */
-	 .fname = filename,
+	{			/* case 03, long value */
 	 .key = XATTR_TEST_KEY,
-	 .value = NULL,
+	 .value = &long_value,
 	 .size = XATTR_SIZE_MAX + 1,
 	 .flags = XATTR_CREATE,
 	 .exp_err = E2BIG,
 	 },
 	{			/* case 04, zero length value */
-	 .fname = filename,
 	 .key = XATTR_TEST_KEY,
-	 .value = XATTR_TEST_VALUE,
+	 .value = &xattr_value,
 	 .size = 0,
 	 .flags = XATTR_CREATE,
 	 .exp_err = 0,
 	 },
 	{			/* case 05, create existing attribute */
-	 .fname = filename,
 	 .key = XATTR_TEST_KEY,
-	 .value = XATTR_TEST_VALUE,
+	 .value = &xattr_value,
 	 .size = XATTR_TEST_VALUE_SIZE,
 	 .flags = XATTR_CREATE,
 	 .exp_err = EEXIST,
 	 },
 	{			/* case 06, replace existing attribute */
-	 .fname = filename,
 	 .key = XATTR_TEST_KEY,
-	 .value = XATTR_TEST_VALUE,
+	 .value = &xattr_value,
 	 .size = XATTR_TEST_VALUE_SIZE,
 	 .flags = XATTR_REPLACE,
 	 .exp_err = 0,
-	 },
+	},
 };
 
-int TST_TOTAL = sizeof(tc) / sizeof(tc[0]);
-
-int main(int argc, char *argv[])
+static void verify_setxattr(unsigned int i)
 {
-	int lc;
-	int i;
+	TEST(setxattr(FNAME, tc[i].key, *tc[i].value, tc[i].size, tc[i].flags));
 
-	tst_parse_opts(argc, argv, NULL, NULL);
+	if (TEST_RETURN == -1 && TEST_ERRNO == EOPNOTSUPP)
+		tst_brk(TCONF, "setxattr() not supported");
 
-	setup();
+	if (!tc[i].exp_err) {
+		if (TEST_RETURN) {
+			tst_res(TFAIL | TTERRNO,
+				"setxattr() failed with %li", TEST_RETURN);
+			return;
+		}
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
+		tst_res(TPASS, "setxattr() passed");
+		return;
+	}
 
-		for (i = 0; i < TST_TOTAL; i++) {
-			TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value,
-				      tc[i].size, tc[i].flags));
+	if (TEST_RETURN == 0) {
+		tst_res(TFAIL, "setxattr() passed unexpectedly");
+		return;
+	}
 
-			if (TEST_ERRNO == tc[i].exp_err) {
-				tst_resm(TPASS | TTERRNO, "expected behavior");
-			} else {
-				tst_resm(TFAIL | TTERRNO, "unexpected behavior "
-					 "- expected errno %d - Got",
-					 tc[i].exp_err);
-			}
-		}
+	if (TEST_ERRNO != tc[i].exp_err) {
+		tst_res(TFAIL | TTERRNO, "setxattr() should fail with %s",
+			tst_strerrno(tc[i].exp_err));
+		return;
 	}
 
-	cleanup();
-	tst_exit();
+	tst_res(TPASS | TTERRNO, "setxattr() failed");
 }
 
 static void setup(void)
 {
-	int fd;
-
-	tst_require_root();
+	SAFE_TOUCH(FNAME, 0644, NULL);
 
-	tst_tmpdir();
-
-	/* Test for xattr support */
-	fd = SAFE_CREAT(cleanup, "testfile", 0644);
-	close(fd);
-	if (setxattr("testfile", "user.test", "test", 4, XATTR_CREATE) == -1)
-		if (errno == ENOTSUP)
-			tst_brkm(TCONF, cleanup, "No xattr support in fs or "
-				 "mount without user_xattr option");
-
-	/* Create test file */
-	snprintf(filename, BUFSIZ, "setxattr01testfile");
-	fd = SAFE_CREAT(cleanup, filename, 0644);
-	close(fd);
-
-	/* Prepare test cases */
 	snprintf(long_key, 6, "%s", "user.");
 	memset(long_key + 5, 'k', XATTR_NAME_LEN - 5);
 	long_key[XATTR_NAME_LEN - 1] = '\0';
-	tc[2].key = long_key;
 
-	long_value = malloc(XATTR_SIZE_MAX + 2);
-	if (!long_value)
-		tst_brkm(TBROK | TERRNO, cleanup, "malloc failed");
+	long_value = SAFE_MALLOC(XATTR_SIZE_MAX + 2);
 	memset(long_value, 'v', XATTR_SIZE_MAX + 2);
 	long_value[XATTR_SIZE_MAX + 1] = '\0';
-	tc[3].value = long_value;
-
-	TEST_PAUSE;
 }
 
-static void cleanup(void)
-{
-	tst_rmdir();
-}
+static struct tst_test test = {
+	.setup = setup,
+	.test = verify_setxattr,
+	.tcnt = ARRAY_SIZE(tc),
+	.needs_tmpdir = 1,
+	.needs_root = 1,
+};
+
 #else /* HAVE_SYS_XATTR_H */
-int main(int argc, char *argv[])
-{
-	tst_brkm(TCONF, NULL, "<sys/xattr.h> does not exist.");
-}
+TST_TEST_TCONF("<sys/xattr.h> does not exist");
 #endif
Signature · 1 line
2.13.5
#15 lore raw

PATCH v3 11/16 syscalls/setxattr01: Run test for all filesystems

In reply to Cyril Hrubis
---
 testcases/kernel/syscalls/setxattr/setxattr01.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
testcases/kernel/syscalls/setxattr/setxattr01.c +7 -3
index 86df7ba73..4db56123a 100644
@@ -66,7 +66,8 @@
 #define XATTR_TEST_KEY "user.testkey"
 #define XATTR_TEST_VALUE "this is a test value"
 #define XATTR_TEST_VALUE_SIZE 20
-#define FNAME "setxattr01testfile"
+#define MNTPOINT "mntpoint"
+#define FNAME MNTPOINT"/setxattr01testfile"
 
 static char long_key[XATTR_NAME_LEN];
 static char *long_value;
@@ -165,8 +166,6 @@ static void verify_setxattr(unsigned int i)
 
 static void setup(void)
 {
-	SAFE_TOUCH(FNAME, 0644, NULL);
-
 	snprintf(long_key, 6, "%s", "user.");
 	memset(long_key + 5, 'k', XATTR_NAME_LEN - 5);
 	long_key[XATTR_NAME_LEN - 1] = '\0';
@@ -174,12 +173,17 @@ static void setup(void)
 	long_value = SAFE_MALLOC(XATTR_SIZE_MAX + 2);
 	memset(long_value, 'v', XATTR_SIZE_MAX + 2);
 	long_value[XATTR_SIZE_MAX + 1] = '\0';
+
+	SAFE_TOUCH(FNAME, 0644, NULL);
 }
 
 static struct tst_test test = {
 	.setup = setup,
 	.test = verify_setxattr,
 	.tcnt = ARRAY_SIZE(tc),
+	.mntpoint = MNTPOINT,
+	.mount_device = 1,
+	.all_filesystems = 1,
 	.needs_tmpdir = 1,
 	.needs_root = 1,
 };
Signature · 1 line
2.13.5
#16 lore raw

PATCH v3 12/16 syscallse/setxattr02: Convert to the new library

In reply to Cyril Hrubis
---
 testcases/kernel/syscalls/setxattr/setxattr02.c | 120 ++++++++----------------
 1 file changed, 41 insertions(+), 79 deletions(-)
testcases/kernel/syscalls/setxattr/setxattr02.c +41 -79
index 6d39236a3..0b6ecb3fa 100644
@@ -57,10 +57,7 @@
 #ifdef HAVE_SYS_XATTR_H
 # include <sys/xattr.h>
 #endif
-#include "test.h"
-#include "safe_macros.h"
-
-char *TCID = "setxattr02";
+#include "tst_test.h"
 
 #ifdef HAVE_SYS_XATTR_H
 #define XATTR_TEST_KEY "user.testkey"
@@ -75,9 +72,6 @@ char *TCID = "setxattr02";
 #define BLK      "setxattr02blk"
 #define SOCK     "setxattr02sock"
 
-static void setup(void);
-static void cleanup(void);
-
 struct test_case {
 	char *fname;
 	char *key;
@@ -145,91 +139,59 @@ static struct test_case tc[] = {
 	 },
 };
 
-int TST_TOTAL = sizeof(tc) / sizeof(tc[0]);
-
-int main(int argc, char *argv[])
+static void verify_setxattr(unsigned int i)
 {
-	int lc;
-	int i;
+	TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, tc[i].size, tc[i].flags));
 
-	tst_parse_opts(argc, argv, NULL, NULL);
+	if (TEST_RETURN == -1 && TEST_ERRNO == EOPNOTSUPP)
+		tst_brk(TCONF, "setxattr() not supported");
 
-	setup();
+	if (!tc[i].exp_err) {
+		if (TEST_RETURN) {
+			tst_res(TFAIL | TTERRNO,
+				"setxattr() failed with %li", TEST_RETURN);
+			return;
+		}
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
+		tst_res(TPASS, "setxattr() passed");
+		return;
+	}
 
-		for (i = 0; i < TST_TOTAL; i++) {
-			TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value,
-				      tc[i].size, tc[i].flags));
+	if (TEST_RETURN == 0) {
+		tst_res(TFAIL, "setxattr() passed unexpectedly");
+		return;
+	}
 
-			if (TEST_ERRNO == tc[i].exp_err) {
-				tst_resm(TPASS | TTERRNO, "expected behavior");
-			} else {
-				tst_resm(TFAIL | TTERRNO, "unexpected behavior "
-					 "- expected errno %d - Got",
-					 tc[i].exp_err);
-			}
-		}
+	if (TEST_ERRNO != tc[i].exp_err) {
+		tst_res(TFAIL | TTERRNO, "setxattr() should fail with %s",
+			tst_strerrno(tc[i].exp_err));
+		return;
 	}
 
-	cleanup();
-	tst_exit();
+	tst_res(TPASS | TTERRNO, "setxattr() failed");
 }
 
 static void setup(void)
 {
-	int fd;
-	dev_t dev;
-
-	tst_require_root();
-
-	tst_tmpdir();
-
-	/* Test for xattr support */
-	fd = SAFE_CREAT(cleanup, "testfile", 0644);
-	close(fd);
-	if (setxattr("testfile", "user.test", "test", 4, XATTR_CREATE) == -1)
-		if (errno == ENOTSUP)
-			tst_brkm(TCONF, cleanup, "No xattr support in fs or "
-				 "mount without user_xattr option");
-	unlink("testfile");
-
-	/* Create test files */
-	fd = SAFE_CREAT(cleanup, FILENAME, 0644);
-	close(fd);
-
-	SAFE_MKDIR(cleanup, DIRNAME, 0644);
-
-	SAFE_SYMLINK(cleanup, FILENAME, SYMLINK);
-
-	if (mknod(FIFO, S_IFIFO | 0777, 0) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "Create FIFO(%s) failed",
-			 FIFO);
-
-	dev = makedev(1, 3);
-	if (mknod(CHR, S_IFCHR | 0777, dev) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "Create char special(%s)"
-			 " failed", CHR);
-
-	if (mknod(BLK, S_IFBLK | 0777, 0) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "Create block special(%s)"
-			 " failed", BLK);
-
-	if (mknod(SOCK, S_IFSOCK | 0777, 0) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "Create socket(%s) failed",
-			 SOCK);
-
-	TEST_PAUSE;
+	dev_t dev = makedev(1, 3);
+
+	SAFE_TOUCH(FILENAME, 0644, NULL);
+	SAFE_MKDIR(DIRNAME, 0644);
+	SAFE_SYMLINK(FILENAME, SYMLINK);
+	SAFE_MKNOD(FIFO, S_IFIFO | 0777, 0);
+	SAFE_MKNOD(CHR, S_IFCHR | 0777, dev);
+	SAFE_MKNOD(BLK, S_IFBLK | 0777, 0);
+	SAFE_MKNOD(SOCK, S_IFSOCK | 0777, 0);
 }
 
-static void cleanup(void)
-{
-	tst_rmdir();
-}
+static struct tst_test test = {
+	.setup = setup,
+	.test = verify_setxattr,
+	.tcnt = ARRAY_SIZE(tc),
+	.needs_tmpdir = 1,
+	.needs_root = 1,
+};
+
 #else /* HAVE_SYS_XATTR_H */
-int main(int argc, char *argv[])
-{
-	tst_brkm(TCONF, NULL, "<sys/xattr.h> does not exist.");
-}
+TST_TEST_TCONF("<sys/xattr.h> does not exist");
 #endif
Signature · 1 line
2.13.5
#17 lore raw

PATCH v3 13/16 syscalls/fsync01: Convert to the new library.

In reply to Cyril Hrubis
---
 testcases/kernel/syscalls/fsync/fsync01.c | 157 +++++-------------------------
 1 file changed, 27 insertions(+), 130 deletions(-)
testcases/kernel/syscalls/fsync/fsync01.c +27 -130
index d7cc4f0a4..af35902bd 100644
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ *    AUTHOR		: William Roske
+ *    CO-PILOT		: Dave Fenner
  *
  * 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
@@ -30,149 +32,44 @@
  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
  *
  */
-/* $Id: fsync01.c,v 1.6 2009/10/26 14:55:47 subrata_modak Exp $ */
-/**********************************************************
- *
- *    OS Test - Silicon Graphics, Inc.
- *
- *    TEST IDENTIFIER	: fsync01
- *
- *    EXECUTED BY	: anyone
- *
- *    TEST TITLE	: Basic test for fsync(2)
- *
- *    PARENT DOCUMENT	: usctpl01
- *
- *    TEST CASE TOTAL	: 1
- *
- *    WALL CLOCK TIME	: 1
- *
- *    CPU TYPES		: ALL
- *
- *    AUTHOR		: William Roske
- *
- *    CO-PILOT		: Dave Fenner
- *
- *    DATE STARTED	: 03/30/92
- *
- *    INITIAL RELEASE	: UNICOS 7.0
- *
- *    TEST CASES
- *
- * 	1.) fsync(2) returns...(See Description)
- *
- *    INPUT SPECIFICATIONS
- * 	The standard options for system call tests are accepted.
- *	(See the parse_opts(3) man page).
- *
- *    OUTPUT SPECIFICATIONS
- *$
- *    DURATION
- * 	Terminates - with frequency and infinite modes.
- *
- *    SIGNALS
- * 	Uses SIGUSR1 to pause before test if option set.
- * 	(See the parse_opts(3) man page).
- *
- *    RESOURCES
- * 	None
- *
- *    ENVIRONMENTAL NEEDS
- *      No run-time environmental needs.
- *
- *    SPECIAL PROCEDURAL REQUIREMENTS
- * 	None
- *
- *    INTERCASE DEPENDENCIES
- * 	None
- *
- *    DETAILED DESCRIPTION
- *	This is a Phase I test for the fsync(2) system call.  It is intended
- *	to provide a limited exposure of the system call, for now.  It
- *	should/will be extended when full functional tests are written for
- *	fsync(2).
- *
- * 	Setup:
- * 	  Setup signal handling.
- *	  Pause for SIGUSR1 if option specified.
- *
- * 	Test:
- *	 Loop if the proper options are given.
- * 	  Execute system call
- *	  Check return code, if system call failed (return=-1)
- *		Log the errno and Issue a FAIL message.
- *	  Otherwise, Issue a PASS message.
- *
- * 	Cleanup:
- * 	  Print errno log and/or timing stats if options given
- *
- *
- *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
 
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/statfs.h>
+#include <unistd.h>
 #include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include "test.h"
-
-void setup();
-void cleanup();
+#include <stdio.h>
 
-char *TCID = "fsync01";
-int TST_TOTAL = 1;
+#include "tst_test.h"
 
-char fname[255];
-int fd;
-char *buf = "davef";
+static char fname[255];
+static int fd;
+#define BUF "davef"
 
-int main(int ac, char **av)
+static void verify_fsync(void)
 {
-	int lc;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-	setup();
+	SAFE_WRITE(1, fd, BUF, sizeof(BUF));
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
+	TEST(fsync(fd));
 
-		tst_count = 0;
-
-		if (write(fd, buf, strlen(buf)) == -1)
-			tst_brkm(TBROK | TERRNO, cleanup, "write failed");
-		TEST(fsync(fd));
-
-		if (TEST_RETURN == -1)
-			tst_resm(TFAIL | TTERRNO, "fsync failed");
-		else
-			tst_resm(TPASS, "fsync returned %ld", TEST_RETURN);
-
-	}
-
-	cleanup();
-	tst_exit();
+	if (TEST_RETURN == -1)
+		tst_res(TFAIL | TTERRNO, "fsync failed");
+	else
+		tst_res(TPASS, "fsync() returned %ld", TEST_RETURN);
 }
 
-void setup(void)
+static void setup(void)
 {
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
 	sprintf(fname, "tfile_%d", getpid());
-	if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "open failed");
+	fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
 }
 
-void cleanup(void)
+static void cleanup(void)
 {
-	if (close(fd) == -1)
-		tst_resm(TWARN, "close failed");
-
-	tst_rmdir();
-
+	if (fd > 0)
+		SAFE_CLOSE(fd);
 }
+
+static struct tst_test test = {
+	.cleanup = cleanup,
+	.setup = setup,
+	.test_all = verify_fsync,
+	.needs_tmpdir = 1,
+};
Signature · 1 line
2.13.5
#18 lore raw

PATCH v3 14/16 syscalls/fsync01: Run test for all filesystems.

In reply to Cyril Hrubis

+ do write() + fsync() 10 times

---
 testcases/kernel/syscalls/fsync/fsync01.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)
testcases/kernel/syscalls/fsync/fsync01.c +15 -7
index af35902bd..c93b131f2 100644
@@ -45,19 +45,23 @@ static int fd;
 
 static void verify_fsync(void)
 {
-	SAFE_WRITE(1, fd, BUF, sizeof(BUF));
+	unsigned int i;
 
-	TEST(fsync(fd));
+	for (i = 0; i < 10; i++) {
+		SAFE_WRITE(1, fd, BUF, sizeof(BUF));
 
-	if (TEST_RETURN == -1)
-		tst_res(TFAIL | TTERRNO, "fsync failed");
-	else
-		tst_res(TPASS, "fsync() returned %ld", TEST_RETURN);
+		TEST(fsync(fd));
+
+		if (TEST_RETURN == -1)
+			tst_res(TFAIL | TTERRNO, "fsync failed");
+		else
+			tst_res(TPASS, "fsync() returned %ld", TEST_RETURN);
+	}
 }
 
 static void setup(void)
 {
-	sprintf(fname, "tfile_%d", getpid());
+	sprintf(fname, "mntpoint/tfile_%d", getpid());
 	fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
 }
 
@@ -72,4 +76,8 @@ static struct tst_test test = {
 	.setup = setup,
 	.test_all = verify_fsync,
 	.needs_tmpdir = 1,
+	.needs_root = 1,
+	.mount_device = 1,
+	.mntpoint = "mntpoint",
+	.all_filesystems = 1,
 };
Signature · 1 line
2.13.5
#19 lore raw

PATCH v3 15/16 fs/fs_fill: Add a test to fill a FS in a few threads

In reply to Cyril Hrubis

Runs CPU+2 threads that write into FS until they got ENOSPC, then delete a file and continue.

Older exfat fails with EIO instead of ENOSPC, it has been fixed in:

commit ca112f07b115a419250b6526e71345dcd29e4d67

Author: relan <[email protected]>
Date:   Tue Dec 27 17:22:12 2016 +0300

Propagate ENOSPC on write.

at:

https://github.com/relan/exfat/

---
 runtest/fs                             |   2 +
 testcases/kernel/fs/fs_fill/.gitignore |   1 +
 testcases/kernel/fs/fs_fill/Makefile   |  22 ++++++
 testcases/kernel/fs/fs_fill/fs_fill.c  | 122 +++++++++++++++++++++++++++++++++
 4 files changed, 147 insertions(+)
 create mode 100644 testcases/kernel/fs/fs_fill/.gitignore
 create mode 100644 testcases/kernel/fs/fs_fill/Makefile
 create mode 100644 testcases/kernel/fs/fs_fill/fs_fill.c
runtest/fs +2 -0
index 33a8412fd..3fa210a9f 100644
@@ -76,3 +76,5 @@ fs_racer fs_racer.sh -t 5
 quota_remount_test01 quota_remount_test01.sh
 
 isofs isofs.sh
+
+fs_fill fs_fill
testcases/kernel/fs/fs_fill/.gitignore new file +1 -0
new file mode 100644
index 000000000..ebdfb439f
@@ -0,0 +1 @@
+fs_fill
testcases/kernel/fs/fs_fill/Makefile new file +22 -0
new file mode 100644
index 000000000..f0e092b13
@@ -0,0 +1,22 @@
+# Copyright (c) 2017 Linux Test Project
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# 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.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+top_srcdir              ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+CFLAGS += -pthread
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
testcases/kernel/fs/fs_fill/fs_fill.c new file +122 -0

122 lines not on this page · raw message

Signature · 1 line
2.13.5
#20 lore raw

PATCH v3 15/16 fs/fs_fill: Add a test to fill a FS in a few threads

Hi Cyril,

This case always broken in SAFE_* operations, seems the reason is no space left on the device,
so I wonder if is it necessary to create so many thread "CPUs + 2" to run the test?

What about just creating half of CPU number thread (nthreads = tst_ncpus_conf()/2 + 1) there?

$ git diff
(quoted diff) +0 -0

b/testcases/kernel/fs/fs_fill/fs_fill.c
index a50a22f..13207c4 100644

testcases/kernel/fs/fs_fill/fs_fill.c +1 -1
@@ -106,7 +106,7 @@ static void testrun(void)
 
 static void setup(void)
 {
-       nthreads = tst_ncpus_conf() + 2;
+       nthreads = tst_ncpus_conf()/2 + 1;
 
        tst_res(TINFO, "Running %i writer threads", nthreads);
 }

Broken message:
==============
fs_fill.c:104: PASS: Got 73 ENOSPC runtime 1000ms tst_mkfs.c:83: INFO: Formatting /dev/loop1 with xfs opts='' extra opts='' tst_test.c:970: INFO: Timeout per run is 0h 05m 00s fs_fill.c:111: INFO: Running 66 writer threads safe_macros.c:225: BROK: tst_fill_fs.c:43:
open(mntpoint/thread48/file0,65,0700) failed: ENOSPC

Signature · 2 lines
Li Wang
[email protected]
#21 lore raw

PATCH v3 15/16 fs/fs_fill: Add a test to fill a FS in a few threads

Hi!

Quoted 15 lines

This case always broken in SAFE_* operations, seems the reason is no space left on the device,
so I wonder if is it necessary to create so many thread "CPUs + 2" to run the test?

What about just creating half of CPU number thread (nthreads = tst_ncpus_conf()/2 + 1) there?

$ git diff
testcases/kernel/fs/fs_fill/fs_fill.c +0 -0
index a50a22f..13207c4 100644

testcases/kernel/fs/fs_fill/fs_fill.c static void testrun(void) · line 112

Quoted 8 lines
testcases/kernel/fs/fs_fill/fs_fill.c +1 -1
@@ -106,7 +106,7 @@ static void testrun(void)
 
 static void setup(void)
 {
-       nthreads = tst_ncpus_conf() + 2;
+       nthreads = tst_ncpus_conf()/2 + 1;
 
        tst_res(TINFO, "Running %i writer threads", nthreads);
 }

This does not fix the problem, only makes it less likely.

The correct fix is to use open() instead of SAFE_OPEN() in the tst_fill_fs() and just return from the function when we get ENOSPC. I can fix that, or you can send the patch. Either way thanks for pointing out the mistake.

Signature · 2 lines
Cyril Hrubis
[email protected]
#22 lore raw

PATCH v3 15/16 fs/fs_fill: Add a test to fill a FS in a few threads

Quoted 22 lines · Cyril Hrubis

Hi!

Quoted 21 lines

This case always broken in SAFE_* operations, seems the reason is no space left on the device,
so I wonder if is it necessary to create so many thread "CPUs + 2" to run the test?

What about just creating half of CPU number thread (nthreads = tst_ncpus_conf()/2 + 1) there?

$ git diff
testcases/kernel/fs/fs_fill/fs_fill.c +1 -1
index a50a22f..13207c4 100644
@@ -106,7 +106,7 @@ static void testrun(void)
 
 static void setup(void)
 {
-       nthreads = tst_ncpus_conf() + 2;
+       nthreads = tst_ncpus_conf()/2 + 1;
 
Quoted 4 lines

testcases/kernel/fs/fs_fill/fs_fill.c static void testrun(void) · line 112

Quoted 2 lines
testcases/kernel/fs/fs_fill/fs_fill.c +0 -0
        tst_res(TINFO, "Running %i writer threads", nthreads);
 }

This does not fix the problem, only makes it less likely.

Actually yes. Retest and failed again.

Quoted 5 lines

The correct fix is to use open() instead of SAFE_OPEN() in the tst_fill_fs() and just return from the function when we get ENOSPC. I can fix that, or you can send the patch. Either way thanks for pointing out the mistake.

The broken are not only in tst_fills_fs() function but also come from SAFE_MKDIR(w->dir, 0700),
SAFE_OPENDIR(w->dir) and SAFE_UNLINK(file).

safe_macros.c:169: BROK: fs_fill.c:49:
mkdir(mntpoint/thread21,0700) failed: ENOSPC

If we just handle the 'ENOSPC' in tst_fill_fs(), I doubt that test will be broken as well.

Signature · 2 lines
Li Wang
[email protected]
#23 lore raw

PATCH v3 15/16 fs/fs_fill: Add a test to fill a FS in a few threads

Hi!

Quoted 7 lines
Quoted 4 lines

The correct fix is to use open() instead of SAFE_OPEN() in the tst_fill_fs() and just return from the function when we get ENOSPC. I can fix that, or you can send the patch. Either way thanks for pointing out the mistake.

The broken are not only in tst_fills_fs() function but also come from SAFE_MKDIR(w->dir, 0700),

Ok, we have to create the directories in the testrun() function before we attempt to run the threads, that should fix this particular problem.

Quoted 1 line

SAFE_OPENDIR(w->dir) and SAFE_UNLINK(file).

The opendir() should not fail with ENOSPC since that only reads the directory content.

And the unlink() should not fail with ENOSPC as well. Since unlink() actually deletes a file, if that breaks because filesystem is full you lost since you cannot free any space by removing files...

So fixing the tst_fill_fs() and doing the mkdir() before we start these threads should IMHO fix the test.

Signature · 2 lines
Cyril Hrubis
[email protected]
#24 lore raw

PATCH v3 15/16 fs/fs_fill: Add a test to fill a FS in a few threads

Quoted 17 lines · Cyril Hrubis

Hi!

Quoted 7 lines
Quoted 4 lines

The correct fix is to use open() instead of SAFE_OPEN() in the tst_fill_fs() and just return from the function when we get ENOSPC. I can fix that, or you can send the patch. Either way thanks for pointing out the mistake.

The broken are not only in tst_fills_fs() function but also come from SAFE_MKDIR(w->dir, 0700),

Ok, we have to create the directories in the testrun() function before we attempt to run the threads, that should fix this particular problem.

Quoted 1 line

SAFE_OPENDIR(w->dir) and SAFE_UNLINK(file).

The opendir() should not fail with ENOSPC since that only reads the directory content.

Quoted 6 lines

And the unlink() should not fail with ENOSPC as well. Since unlink() actually deletes a file, if that breaks because filesystem is full you lost since you cannot free any space by removing files...

So fixing the tst_fill_fs() and doing the mkdir() before we start these threads should IMHO fix the test.

OK, Thanks for your analysis. Let me try to fix the mistake and test on my system.

Will send a new patch if I can confirm the issue being fully fixed like this.

Signature · 2 lines
Li Wang
[email protected]
#25 lore raw

PATCH v3 16/16 doc: Update device flags in test-writing-guidelines

In reply to Cyril Hrubis
---
 doc/test-writing-guidelines.txt | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)
doc/test-writing-guidelines.txt +17 -2
index 15d418954..133cb9372 100644
@@ -914,12 +914,27 @@ then.
 If '.format_device' flag is set the device is formatted with a filesystem as
 well. You can use '.dev_fs_type' to override the default filesystem type if
 needed and pass additional options to mkfs via '.dev_fs_opts' and
-'.dev_extra_opt' pointers.
+'.dev_extra_opt' pointers. Note that '.format_device' implies '.needs_device'
+there is no need to set both.
 
 If '.mount_device' is set, the device is mounted at '.mntpoint' which is used
 to pass a directory name that will be created and used as mount destination.
 You can pass additional flags and data to the mount command via '.mnt_flags'
-and '.mnt_data' pointers.
+and '.mnt_data' pointers. Note that '.mount_device' implies '.needs_device'
+and '.format_device' so there is no need to set the later two.
+
+If '.needs_rofs' is set, read-only filesystem is mounted at '.mntpoint' this
+one is supposed to be used for 'EROFS' tests.
+
+If '.all_filesystems' is set the test function is executed for all supported
+filesystems. Supported filesystems are detected based on existence of the
+'mkfs.$fs' helper and on kernel support to mount it. For each supported
+filesystem the 'tst_device.fs_type' is set to the currently tested fs type, if
+'.format_device' is set the device is formatted as well, if '.mount_device' is
+set it's mounted at '.mntpoint'. Also the test timeout is reset for each
+execution of the test fuction. This flag is expected to be used for filesystem
+related syscalls that are at least partly implemented in the filesystem
+specific code e.g. fallocate().
 
 [source,c]
 -------------------------------------------------------------------------------
Signature · 1 line
2.13.5
#26 lore raw

PATCH v3 16/16 doc: Update device flags in test-writing-guidelines

Quoted 16 lines · Cyril Hrubis
---
 doc/test-writing-guidelines.txt | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)
doc/test-writing-guidelines.txt +2 -1
index 15d418954..133cb9372 100644
@@ -914,12 +914,27 @@ then.
 If '.format_device' flag is set the device is formatted with a filesystem as
 well. You can use '.dev_fs_type' to override the default filesystem type if
 needed and pass additional options to mkfs via '.dev_fs_opts' and
-'.dev_extra_opt' pointers.
+'.dev_extra_opt' pointers. Note that '.format_device' implies '.needs_device'
+there is no need to set both.

doc/test-writing-guidelines.txt then. · line 927

Quoted 10 lines
doc/test-writing-guidelines.txt +5 -1
 
 If '.mount_device' is set, the device is mounted at '.mntpoint' which is used
 to pass a directory name that will be created and used as mount destination.
 You can pass additional flags and data to the mount command via '.mnt_flags'
-and '.mnt_data' pointers.
+and '.mnt_data' pointers. Note that '.mount_device' implies '.needs_device'
+and '.format_device' so there is no need to set the later two.
+
+If '.needs_rofs' is set, read-only filesystem is mounted at '.mntpoint' this
+one is supposed to be used for 'EROFS' tests.

I probably should have done this with the patches. :(

<snip>