[LTP] [PATCH v2 3/3] tst_fill_fs: Add alternate access pattern "flat"

Richard Palethorpe rpalethorpe@suse.com
Mon Dec 12 14:55:24 CET 2022


Depending on the workload, the way in which a file system is filled
will be different. The system calls will also be different.

This adds a fill mode which uses writev with uniform batches of
data. This simulates when the FS is filled by a program which batches
writes.

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
---
 include/tst_fs.h                              |  7 ++-
 lib/tst_fill_fs.c                             | 59 ++++++++++++++++++-
 testcases/kernel/fs/fs_fill/fs_fill.c         | 18 ++++--
 .../kernel/syscalls/fallocate/fallocate05.c   |  2 +-
 .../kernel/syscalls/fallocate/fallocate06.c   |  2 +-
 5 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/include/tst_fs.h b/include/tst_fs.h
index cc6d9b547..43ead32a2 100644
--- a/include/tst_fs.h
+++ b/include/tst_fs.h
@@ -34,6 +34,11 @@
 #define TST_VFAT_MAGIC     0x4d44 /* AKA MSDOS */
 #define TST_EXFAT_MAGIC    0x2011BAB0UL
 
+enum tst_fill_access_pattern {
+	TST_FILL_FLAT_VEC,
+	TST_FILL_RANDOM
+};
+
 enum {
 	TST_BYTES = 1,
 	TST_KB = 1024,
@@ -201,7 +206,7 @@ int tst_fs_in_skiplist(const char *fs_type, const char *const *skiplist);
 /*
  * Creates and writes to files on given path until write fails with ENOSPC
  */
-void tst_fill_fs(const char *path, int verbose);
+void tst_fill_fs(const char *path, int verbose, enum tst_fill_access_pattern pattern);
 
 /*
  * test if FIBMAP ioctl is supported
diff --git a/lib/tst_fill_fs.c b/lib/tst_fill_fs.c
index 1d6d76abd..e7d5d73b7 100644
--- a/lib/tst_fill_fs.c
+++ b/lib/tst_fill_fs.c
@@ -7,13 +7,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/statvfs.h>
+#include <sys/uio.h>
 
 #define TST_NO_DEFAULT_MAIN
 #include "tst_test.h"
+#include "lapi/fcntl.h"
 #include "tst_fs.h"
 #include "tst_rand_data.h"
+#include "tst_safe_file_at.h"
 
-void tst_fill_fs(const char *path, int verbose)
+void fill_random(const char *path, int verbose)
 {
 	int i = 0;
 	char file[PATH_MAX];
@@ -67,3 +70,57 @@ void tst_fill_fs(const char *path, int verbose)
 		SAFE_CLOSE(fd);
 	}
 }
+
+void fill_flat_vec(const char *path, int verbose)
+{
+	int dir = SAFE_OPEN(path, O_PATH | O_DIRECTORY | O_FSYNC);
+	int fd = SAFE_OPENAT(dir, "AOF", O_WRONLY | O_CREAT, 0600);
+	struct iovec iov[512];
+	int iovcnt = ARRAY_SIZE(iov);
+	int retries = 3;
+
+	SAFE_CLOSE(dir);
+
+	for (int i = 0; i < iovcnt; i++) {
+		iov[i] = (struct iovec) {
+			(void *)tst_rand_data,
+			tst_rand_data_len
+		};
+	}
+
+	while (retries) {
+		const int ret = writev(fd, iov, iovcnt);
+
+		if (!ret)
+			tst_res(TWARN | TERRNO, "writev returned 0; not sure what this means");
+
+		if (ret > -1) {
+			if (verbose && retries < 3)
+				tst_res(TINFO, "writev(\"%s/AOF\", iov, %d) = %d", path, iovcnt, ret);
+
+			retries = 3;
+			continue;
+		}
+
+		if (errno != ENOSPC)
+			tst_brk(TBROK | TERRNO, "writev(\"%s/AOF\", iov, %d)", path, iovcnt);
+
+		if (verbose)
+			tst_res(TINFO, "writev(\"%s/AOF\", iov, %d): ENOSPC", path, iovcnt);
+
+		retries--;
+	}
+
+	SAFE_CLOSE(fd);
+}
+
+void tst_fill_fs(const char *path, int verbose, enum tst_fill_access_pattern pattern)
+{
+
+	switch (pattern) {
+	case TST_FILL_FLAT_VEC:
+		return fill_flat_vec(path, verbose);
+	case TST_FILL_RANDOM:
+		return fill_random(path, verbose);
+	}
+}
diff --git a/testcases/kernel/fs/fs_fill/fs_fill.c b/testcases/kernel/fs/fs_fill/fs_fill.c
index 95dfc2cb6..2027b6df1 100644
--- a/testcases/kernel/fs/fs_fill/fs_fill.c
+++ b/testcases/kernel/fs/fs_fill/fs_fill.c
@@ -25,6 +25,7 @@ static int enospc_cnt;
 static struct worker *workers;
 
 struct worker {
+	enum tst_fill_access_pattern pattern;
 	char dir[PATH_MAX];
 };
 
@@ -36,7 +37,7 @@ static void *worker(void *p)
 	char file[PATH_MAX];
 
 	while (run) {
-		tst_fill_fs(w->dir, 0);
+		tst_fill_fs(w->dir, 1, w->pattern);
 
 		tst_atomic_inc(&enospc_cnt);
 
@@ -61,22 +62,26 @@ static void *worker(void *p)
 	return NULL;
 }
 
-static void testrun(void)
+static void testrun(unsigned int n)
 {
 	pthread_t threads[nthreads];
 	unsigned int i, ms;
 
+	tst_atomic_store(0, &enospc_cnt);
+
 	run = 1;
-	for (i = 0; i < nthreads; i++)
+	for (i = 0; i < nthreads; i++) {
+		workers[i].pattern = n;
 		SAFE_PTHREAD_CREATE(&threads[i], NULL, worker, &workers[i]);
+	}
 
 	for (ms = 0; ; ms++) {
 		usleep(1000);
 
-		if (ms >= 1000 && enospc_cnt)
+		if (ms >= 1000 && tst_atomic_load(&enospc_cnt))
 			break;
 
-		if (enospc_cnt > 100)
+		if (tst_atomic_load(&enospc_cnt) > 100)
 			break;
 	}
 
@@ -116,5 +121,6 @@ static struct tst_test test = {
 	.all_filesystems = 1,
 	.setup = setup,
 	.cleanup = cleanup,
-	.test_all = testrun,
+	.test = testrun,
+	.tcnt = 2
 };
diff --git a/testcases/kernel/syscalls/fallocate/fallocate05.c b/testcases/kernel/syscalls/fallocate/fallocate05.c
index d67c6cf5b..af6bf9e8c 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate05.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate05.c
@@ -68,7 +68,7 @@ static void run(void)
 		tst_brk(TBROK | TTERRNO, "fallocate(fd, 0, 0, %ld)", bufsize);
 	}
 
-	tst_fill_fs(MNTPOINT, 1);
+	tst_fill_fs(MNTPOINT, 1, TST_FILL_RANDOM);
 
 	TEST(write(fd, buf, bufsize));
 
diff --git a/testcases/kernel/syscalls/fallocate/fallocate06.c b/testcases/kernel/syscalls/fallocate/fallocate06.c
index 16f9db066..124fb7eae 100644
--- a/testcases/kernel/syscalls/fallocate/fallocate06.c
+++ b/testcases/kernel/syscalls/fallocate/fallocate06.c
@@ -202,7 +202,7 @@ static void run(unsigned int n)
 	}
 
 	if (tc->fill_fs)
-		tst_fill_fs(MNTPOINT, 1);
+		tst_fill_fs(MNTPOINT, 1, TST_FILL_RANDOM);
 
 	SAFE_LSEEK(fd, offset, SEEK_SET);
 	TEST(write(fd, wbuf, size));
-- 
2.38.1



More information about the ltp mailing list