public inbox for ltp@lists.linux.it
 help / color / mirror / Atom feed
* [LTP] [PATCH v1] cachestat01.c: Add cachestat() testcheck
@ 2023-09-08  7:29 Wei Gao via ltp
  2023-09-19  8:29 ` [LTP] [PATCH v2] " Wei Gao via ltp
  0 siblings, 1 reply; 3+ messages in thread
From: Wei Gao via ltp @ 2023-09-08  7:29 UTC (permalink / raw)
  To: ltp

Signed-off-by: Wei Gao <wegao@suse.com>
---
 configure.ac                                  |   1 +
 include/lapi/syscalls/aarch64.in              |   1 +
 include/lapi/syscalls/arc.in                  |   1 +
 include/lapi/syscalls/arm.in                  |   1 +
 include/lapi/syscalls/hppa.in                 |   1 +
 include/lapi/syscalls/i386.in                 |   1 +
 include/lapi/syscalls/ia64.in                 |   1 +
 include/lapi/syscalls/powerpc.in              |   1 +
 include/lapi/syscalls/powerpc64.in            |   1 +
 include/lapi/syscalls/s390.in                 |   1 +
 include/lapi/syscalls/s390x.in                |   1 +
 include/lapi/syscalls/sh.in                   |   1 +
 include/lapi/syscalls/sparc.in                |   1 +
 include/lapi/syscalls/sparc64.in              |   1 +
 include/lapi/syscalls/x86_64.in               |   1 +
 runtest/syscalls                              |   2 +
 .../kernel/syscalls/cachestat/.gitignore      |   1 +
 testcases/kernel/syscalls/cachestat/Makefile  |   8 +
 .../kernel/syscalls/cachestat/cachestat01.c   | 260 ++++++++++++++++++
 19 files changed, 286 insertions(+)
 create mode 100644 testcases/kernel/syscalls/cachestat/.gitignore
 create mode 100644 testcases/kernel/syscalls/cachestat/Makefile
 create mode 100644 testcases/kernel/syscalls/cachestat/cachestat01.c

diff --git a/configure.ac b/configure.ac
index 662c4c058..4b5547b5b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,6 +93,7 @@ AC_CHECK_FUNCS_ONCE([ \
     epoll_pwait2 \
     execveat \
     faccessat2 \
+    cachestat \
     fallocate \
     fchownat \
     fsconfig \
diff --git a/include/lapi/syscalls/aarch64.in b/include/lapi/syscalls/aarch64.in
index 2cb6c2d87..1c0218eae 100644
--- a/include/lapi/syscalls/aarch64.in
+++ b/include/lapi/syscalls/aarch64.in
@@ -297,4 +297,5 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
 _sysctl 1078
diff --git a/include/lapi/syscalls/arc.in b/include/lapi/syscalls/arc.in
index 3e2ee9061..5d7cd6ca4 100644
--- a/include/lapi/syscalls/arc.in
+++ b/include/lapi/syscalls/arc.in
@@ -317,3 +317,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
index 7bdbca533..e41a7e576 100644
--- a/include/lapi/syscalls/arm.in
+++ b/include/lapi/syscalls/arm.in
@@ -395,3 +395,4 @@ faccessat2 (__NR_SYSCALL_BASE+439)
 epoll_pwait2 (__NR_SYSCALL_BASE+441)
 quotactl_fd (__NR_SYSCALL_BASE+443)
 futex_waitv (__NR_SYSCALL_BASE+449)
+cachestat (__NR_SYSCALL_BASE+451)
diff --git a/include/lapi/syscalls/hppa.in b/include/lapi/syscalls/hppa.in
index 8ebdafafb..2772e7334 100644
--- a/include/lapi/syscalls/hppa.in
+++ b/include/lapi/syscalls/hppa.in
@@ -44,3 +44,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in
index 1472631c4..2d341182e 100644
--- a/include/lapi/syscalls/i386.in
+++ b/include/lapi/syscalls/i386.in
@@ -431,3 +431,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/ia64.in
index 0ea6e9722..141c6be51 100644
--- a/include/lapi/syscalls/ia64.in
+++ b/include/lapi/syscalls/ia64.in
@@ -344,3 +344,4 @@ faccessat2 1463
 epoll_pwait2 1465
 quotactl_fd 1467
 futex_waitv 1473
+cachestat 1475
diff --git a/include/lapi/syscalls/powerpc.in b/include/lapi/syscalls/powerpc.in
index 545d9d3d6..67e928951 100644
--- a/include/lapi/syscalls/powerpc.in
+++ b/include/lapi/syscalls/powerpc.in
@@ -424,3 +424,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in
index 545d9d3d6..67e928951 100644
--- a/include/lapi/syscalls/powerpc64.in
+++ b/include/lapi/syscalls/powerpc64.in
@@ -424,3 +424,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in
index 7213ac5f8..b456ea408 100644
--- a/include/lapi/syscalls/s390.in
+++ b/include/lapi/syscalls/s390.in
@@ -411,3 +411,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
index 879012e2b..2c57eacdf 100644
--- a/include/lapi/syscalls/s390x.in
+++ b/include/lapi/syscalls/s390x.in
@@ -359,3 +359,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
index 7d5192a27..25eb9bb26 100644
--- a/include/lapi/syscalls/sh.in
+++ b/include/lapi/syscalls/sh.in
@@ -405,3 +405,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in
index 91d2fb1c2..e934591dd 100644
--- a/include/lapi/syscalls/sparc.in
+++ b/include/lapi/syscalls/sparc.in
@@ -410,3 +410,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/sparc64.in b/include/lapi/syscalls/sparc64.in
index 1f2fc59b7..4c489e38d 100644
--- a/include/lapi/syscalls/sparc64.in
+++ b/include/lapi/syscalls/sparc64.in
@@ -375,3 +375,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in
index dc61aa56e..4afea6019 100644
--- a/include/lapi/syscalls/x86_64.in
+++ b/include/lapi/syscalls/x86_64.in
@@ -352,6 +352,7 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
 rt_sigaction 512
 rt_sigreturn 513
 ioctl 514
diff --git a/runtest/syscalls b/runtest/syscalls
index 4fb76584f..b84b2d2ce 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -59,6 +59,8 @@ capset04 capset04
 
 cacheflush01 cacheflush01
 
+cachestat01 cachestat01
+
 chdir01 chdir01
 chdir01A symlink01 -T chdir01
 chdir04 chdir04
diff --git a/testcases/kernel/syscalls/cachestat/.gitignore b/testcases/kernel/syscalls/cachestat/.gitignore
new file mode 100644
index 000000000..870bceae4
--- /dev/null
+++ b/testcases/kernel/syscalls/cachestat/.gitignore
@@ -0,0 +1 @@
+/cachestat01
diff --git a/testcases/kernel/syscalls/cachestat/Makefile b/testcases/kernel/syscalls/cachestat/Makefile
new file mode 100644
index 000000000..49238eee0
--- /dev/null
+++ b/testcases/kernel/syscalls/cachestat/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright (c) 2023 Wei Gao <wegao@suse.com>
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/cachestat/cachestat01.c b/testcases/kernel/syscalls/cachestat/cachestat01.c
new file mode 100644
index 000000000..9ad432b59
--- /dev/null
+++ b/testcases/kernel/syscalls/cachestat/cachestat01.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Andre Przywara <andre.przywara@arm.com>
+ * Copyright (c) 2023 Wei Gao <wegao@suse.com>
+ *
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that cachestat() executes successfully
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <unistd.h> /* _SC_PAGESIZE */
+#include <stdbool.h>
+#include <stdlib.h>
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+#include "lapi/cachestat.h"
+
+#define SAFE_FREE(p) { if (p) { free(p); (p) = NULL; } }
+#define TMPFS_MAGIC 0x01021994
+#define TEST_NORMAL_FILE "tmpfilecachestat"
+#define SHM_FILE "tmpshmcstat"
+#define NUM_PAGES 4
+
+static int fd;
+static int fd_shm;
+static size_t PS;
+static size_t filesize;
+static char *data;
+static int random_fd;
+
+/*
+ * fsync() is implemented via noop_fsync() on tmpfs. This makes the fsync()
+ * test fail below, so we need to check for test file living on a tmpfs.
+ */
+static bool is_on_tmpfs(int fd)
+{
+	struct statfs statfs_buf;
+
+	if (fstatfs(fd, &statfs_buf))
+		return false;
+
+	return statfs_buf.f_type == TMPFS_MAGIC;
+}
+
+static void print_cachestat(struct cachestat *cs)
+{
+	tst_res(TINFO,
+			"Using cachestat: Cached: %llu, Dirty: %llu, Writeback: %llu, Evicted: %llu, Recently Evicted: %llu",
+			cs->nr_cache, cs->nr_dirty, cs->nr_writeback,
+			cs->nr_evicted, cs->nr_recently_evicted);
+}
+
+static const char * const dev_files[] = {
+	"/dev/zero", "/dev/null", "/dev/urandom",
+	"/proc/version", "/proc"
+};
+
+static bool write_exactly(int write_fd)
+{
+	char *cursor;
+	int remained;
+
+	remained = filesize;
+	cursor = data;
+	while (remained) {
+		ssize_t read_len = SAFE_READ(1, random_fd, cursor, remained);
+
+		if (read_len <= 0)
+			tst_brk(TBROK | TERRNO, "Unable to read from urandom.");
+
+		remained -= read_len;
+		cursor += read_len;
+	}
+
+	remained = filesize;
+	cursor = data;
+	while (remained) {
+		ssize_t write_len = SAFE_WRITE(1, write_fd, cursor, remained);
+
+		if (write_len <= 0)
+			tst_brk(TBROK | TERRNO, "Unable write random data to file.");
+
+		remained -= write_len;
+		cursor += write_len;
+	}
+
+	return true;
+}
+
+/*
+ * Open/create the file at filename, (optionally) write random data to it
+ * (exactly num_pages), then test the cachestat syscall on this file.
+ *
+ * If test_fsync == true, fsync the file, then check the number of dirty
+ * pages.
+ */
+static void test_cachestat(const char *filename, bool write_random, bool create,
+		bool test_fsync, int open_flags, mode_t open_mode)
+{
+	struct cachestat cs;
+	struct cachestat_range cs_range = { 0, filesize };
+
+	if (!fcntl(fd, F_GETFD))
+		SAFE_CLOSE(fd);
+	fd = SAFE_OPEN(filename, open_flags, open_mode);
+
+	if (write_random) {
+		if (!write_exactly(fd))
+			tst_brk(TBROK | TERRNO, "Unable to access urandom.");
+	}
+
+	TST_EXP_PASS(cachestat(fd, &cs_range, &cs, 0));
+
+	print_cachestat(&cs);
+
+	if (write_random) {
+		if (cs.nr_cache + cs.nr_evicted != NUM_PAGES) {
+			tst_brk(TBROK | TERRNO,
+					"Total number of cached and evicted pages is off.");
+		}
+	}
+
+	if (test_fsync) {
+		if (is_on_tmpfs(fd)) {
+			tst_res(TCONF, "skip fsync check on tmpfs");
+		} else if (fsync(fd)) {
+			tst_brk(TBROK | TERRNO, "fsync fails.");
+		} else {
+			TST_EXP_PASS(cachestat(fd, &cs_range, &cs, 0));
+			print_cachestat(&cs);
+			if (cs.nr_dirty) {
+				tst_brk(TBROK | TERRNO,
+						"Number of dirty should be zero after fsync.");
+			} else {
+				tst_res(TPASS, "Cachestat (after fsync) pass.");
+			}
+		}
+	}
+
+	close(fd);
+
+	if (create)
+		remove(filename);
+
+	tst_res(TPASS, "cachestat works with file %s", filename);
+}
+
+static void test_incorrect_file(void)
+{
+	TST_EXP_FAIL(cachestat(-1, NULL, NULL, 0), EBADF);
+}
+
+static void test_virtual_file(void)
+{
+	for (unsigned long i = 0; i < sizeof(dev_files) / sizeof(*dev_files); i++) {
+		const char *dev_filename = dev_files[i];
+
+		test_cachestat(dev_filename, false, false, false, O_RDONLY, 0400);
+	}
+}
+
+static void test_normal_file(void)
+{
+	test_cachestat(TEST_NORMAL_FILE, true, true, false, O_CREAT | O_RDWR, 0600);
+	test_cachestat(TEST_NORMAL_FILE, true, true, true, O_CREAT | O_RDWR, 0600);
+}
+
+static void check_cachestat_range(struct cachestat_range *ptr_cs_range, __u64 expect_num_pages)
+{
+	struct cachestat cs;
+
+	TST_EXP_PASS(cachestat(fd_shm, ptr_cs_range, &cs, 0));
+	print_cachestat(&cs);
+	if (cs.nr_cache + cs.nr_evicted != expect_num_pages) {
+		tst_brk(TFAIL | TERRNO,
+				"Total number of cached and evicted pages is off.");
+	} else {
+		tst_res(TPASS,
+				"Cachestat range check pass.");
+	}
+}
+
+static void test_share_memory(void)
+{
+
+	struct cachestat_range cs_range = { 0, filesize};
+
+	if (ftruncate(fd_shm, filesize))
+		tst_brk(TFAIL | TERRNO, "Unable to truncate shmem file.");
+
+	if (!write_exactly(fd_shm))
+		tst_brk(TFAIL | TERRNO, "Unable to write to shmem file.");
+
+	check_cachestat_range(&cs_range, NUM_PAGES);
+
+	size_t compute_len = PS * NUM_PAGES / 2;
+	unsigned long num_pages = ceil((double)NUM_PAGES / 2);
+
+	cs_range.off = PS;
+	cs_range.len = compute_len;
+	check_cachestat_range(&cs_range, num_pages);
+}
+
+static struct tcase {
+	void (*tfunc)(void);
+} tcases[] = {
+	{&test_incorrect_file},
+	{&test_virtual_file},
+	{&test_normal_file},
+	{&test_share_memory}
+};
+
+static void run(unsigned int i)
+{
+	tcases[i].tfunc();
+}
+
+
+static void setup(void)
+{
+
+	PS = sysconf(_SC_PAGESIZE);
+	filesize = NUM_PAGES * PS;
+	data = tst_alloc(filesize);
+	random_fd = SAFE_OPEN("/dev/urandom", O_RDONLY);
+
+	/* setup for test_share_memory case */
+	fd_shm = shm_open(SHM_FILE, O_CREAT | O_RDWR, 0700);
+	if (fd_shm < 0)
+		tst_brk(TFAIL | TERRNO, "Unable to create shmem file.");
+}
+
+static void cleanup(void)
+{
+	SAFE_CLOSE(random_fd);
+
+	/* cleanup for test_normal_file case*/
+	if (!fcntl(fd, F_GETFD))
+		SAFE_CLOSE(fd);
+	remove(TEST_NORMAL_FILE);
+
+	/* cleanup for test_share_memory case */
+	SAFE_CLOSE(fd_shm);
+	shm_unlink(SHM_FILE);
+}
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.min_kver = "6.5.0"
+};
-- 
2.35.3


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [LTP] [PATCH v2] cachestat01.c: Add cachestat() testcheck
  2023-09-08  7:29 [LTP] [PATCH v1] cachestat01.c: Add cachestat() testcheck Wei Gao via ltp
@ 2023-09-19  8:29 ` Wei Gao via ltp
  2023-11-20 11:25   ` Richard Palethorpe
  0 siblings, 1 reply; 3+ messages in thread
From: Wei Gao via ltp @ 2023-09-19  8:29 UTC (permalink / raw)
  To: ltp

Signed-off-by: Wei Gao <wegao@suse.com>
---
 configure.ac                                  |   1 +
 include/lapi/cachestat.h                      |  36 +++
 include/lapi/syscalls/aarch64.in              |   1 +
 include/lapi/syscalls/arc.in                  |   1 +
 include/lapi/syscalls/arm.in                  |   1 +
 include/lapi/syscalls/hppa.in                 |   1 +
 include/lapi/syscalls/i386.in                 |   1 +
 include/lapi/syscalls/ia64.in                 |   1 +
 include/lapi/syscalls/powerpc.in              |   1 +
 include/lapi/syscalls/powerpc64.in            |   1 +
 include/lapi/syscalls/s390.in                 |   1 +
 include/lapi/syscalls/s390x.in                |   1 +
 include/lapi/syscalls/sh.in                   |   1 +
 include/lapi/syscalls/sparc.in                |   1 +
 include/lapi/syscalls/sparc64.in              |   1 +
 include/lapi/syscalls/x86_64.in               |   1 +
 runtest/syscalls                              |   2 +
 .../kernel/syscalls/cachestat/.gitignore      |   1 +
 testcases/kernel/syscalls/cachestat/Makefile  |   8 +
 .../kernel/syscalls/cachestat/cachestat01.c   | 260 ++++++++++++++++++
 20 files changed, 322 insertions(+)
 create mode 100644 include/lapi/cachestat.h
 create mode 100644 testcases/kernel/syscalls/cachestat/.gitignore
 create mode 100644 testcases/kernel/syscalls/cachestat/Makefile
 create mode 100644 testcases/kernel/syscalls/cachestat/cachestat01.c

diff --git a/configure.ac b/configure.ac
index 662c4c058..4b5547b5b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,6 +93,7 @@ AC_CHECK_FUNCS_ONCE([ \
     epoll_pwait2 \
     execveat \
     faccessat2 \
+    cachestat \
     fallocate \
     fchownat \
     fsconfig \
diff --git a/include/lapi/cachestat.h b/include/lapi/cachestat.h
new file mode 100644
index 000000000..fea390849
--- /dev/null
+++ b/include/lapi/cachestat.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Linux Test Project, 2003-2023
+ * Author: Wei Gao <wegao@suse.com>
+ */
+
+#ifndef CACHESTAT_H
+#define CACHESTAT_H
+
+#include "tst_test.h"
+#include "config.h"
+#include "lapi/syscalls.h"
+
+#ifndef HAVE_CACHESTAT
+struct cachestat_range {
+	__u64 off;
+	__u64 len;
+};
+
+struct cachestat {
+	__u64 nr_cache;
+	__u64 nr_dirty;
+	__u64 nr_writeback;
+	__u64 nr_evicted;
+	__u64 nr_recently_evicted;
+};
+
+int cachestat(unsigned int fd,
+                struct cachestat_range *cstat_range,
+                struct cachestat *cstat, unsigned int flags)
+{
+	return tst_syscall(__NR_cachestat, fd, cstat_range, cstat, flags);
+}
+#endif
+
+#endif /* CACHESTAT_H */
diff --git a/include/lapi/syscalls/aarch64.in b/include/lapi/syscalls/aarch64.in
index 2cb6c2d87..1c0218eae 100644
--- a/include/lapi/syscalls/aarch64.in
+++ b/include/lapi/syscalls/aarch64.in
@@ -297,4 +297,5 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
 _sysctl 1078
diff --git a/include/lapi/syscalls/arc.in b/include/lapi/syscalls/arc.in
index 3e2ee9061..5d7cd6ca4 100644
--- a/include/lapi/syscalls/arc.in
+++ b/include/lapi/syscalls/arc.in
@@ -317,3 +317,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
index 7bdbca533..e41a7e576 100644
--- a/include/lapi/syscalls/arm.in
+++ b/include/lapi/syscalls/arm.in
@@ -395,3 +395,4 @@ faccessat2 (__NR_SYSCALL_BASE+439)
 epoll_pwait2 (__NR_SYSCALL_BASE+441)
 quotactl_fd (__NR_SYSCALL_BASE+443)
 futex_waitv (__NR_SYSCALL_BASE+449)
+cachestat (__NR_SYSCALL_BASE+451)
diff --git a/include/lapi/syscalls/hppa.in b/include/lapi/syscalls/hppa.in
index 8ebdafafb..2772e7334 100644
--- a/include/lapi/syscalls/hppa.in
+++ b/include/lapi/syscalls/hppa.in
@@ -44,3 +44,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in
index 1472631c4..2d341182e 100644
--- a/include/lapi/syscalls/i386.in
+++ b/include/lapi/syscalls/i386.in
@@ -431,3 +431,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/ia64.in
index 0ea6e9722..141c6be51 100644
--- a/include/lapi/syscalls/ia64.in
+++ b/include/lapi/syscalls/ia64.in
@@ -344,3 +344,4 @@ faccessat2 1463
 epoll_pwait2 1465
 quotactl_fd 1467
 futex_waitv 1473
+cachestat 1475
diff --git a/include/lapi/syscalls/powerpc.in b/include/lapi/syscalls/powerpc.in
index 545d9d3d6..67e928951 100644
--- a/include/lapi/syscalls/powerpc.in
+++ b/include/lapi/syscalls/powerpc.in
@@ -424,3 +424,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in
index 545d9d3d6..67e928951 100644
--- a/include/lapi/syscalls/powerpc64.in
+++ b/include/lapi/syscalls/powerpc64.in
@@ -424,3 +424,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in
index 7213ac5f8..b456ea408 100644
--- a/include/lapi/syscalls/s390.in
+++ b/include/lapi/syscalls/s390.in
@@ -411,3 +411,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
index 879012e2b..2c57eacdf 100644
--- a/include/lapi/syscalls/s390x.in
+++ b/include/lapi/syscalls/s390x.in
@@ -359,3 +359,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
index 7d5192a27..25eb9bb26 100644
--- a/include/lapi/syscalls/sh.in
+++ b/include/lapi/syscalls/sh.in
@@ -405,3 +405,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in
index 91d2fb1c2..e934591dd 100644
--- a/include/lapi/syscalls/sparc.in
+++ b/include/lapi/syscalls/sparc.in
@@ -410,3 +410,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/sparc64.in b/include/lapi/syscalls/sparc64.in
index 1f2fc59b7..4c489e38d 100644
--- a/include/lapi/syscalls/sparc64.in
+++ b/include/lapi/syscalls/sparc64.in
@@ -375,3 +375,4 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in
index dc61aa56e..4afea6019 100644
--- a/include/lapi/syscalls/x86_64.in
+++ b/include/lapi/syscalls/x86_64.in
@@ -352,6 +352,7 @@ faccessat2 439
 epoll_pwait2 441
 quotactl_fd 443
 futex_waitv 449
+cachestat 451
 rt_sigaction 512
 rt_sigreturn 513
 ioctl 514
diff --git a/runtest/syscalls b/runtest/syscalls
index 4fb76584f..b84b2d2ce 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -59,6 +59,8 @@ capset04 capset04
 
 cacheflush01 cacheflush01
 
+cachestat01 cachestat01
+
 chdir01 chdir01
 chdir01A symlink01 -T chdir01
 chdir04 chdir04
diff --git a/testcases/kernel/syscalls/cachestat/.gitignore b/testcases/kernel/syscalls/cachestat/.gitignore
new file mode 100644
index 000000000..870bceae4
--- /dev/null
+++ b/testcases/kernel/syscalls/cachestat/.gitignore
@@ -0,0 +1 @@
+/cachestat01
diff --git a/testcases/kernel/syscalls/cachestat/Makefile b/testcases/kernel/syscalls/cachestat/Makefile
new file mode 100644
index 000000000..49238eee0
--- /dev/null
+++ b/testcases/kernel/syscalls/cachestat/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright (c) 2023 Wei Gao <wegao@suse.com>
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/cachestat/cachestat01.c b/testcases/kernel/syscalls/cachestat/cachestat01.c
new file mode 100644
index 000000000..9ad432b59
--- /dev/null
+++ b/testcases/kernel/syscalls/cachestat/cachestat01.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Andre Przywara <andre.przywara@arm.com>
+ * Copyright (c) 2023 Wei Gao <wegao@suse.com>
+ *
+ */
+
+/*\
+ * [Description]
+ *
+ * Verify that cachestat() executes successfully
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <unistd.h> /* _SC_PAGESIZE */
+#include <stdbool.h>
+#include <stdlib.h>
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+#include "lapi/cachestat.h"
+
+#define SAFE_FREE(p) { if (p) { free(p); (p) = NULL; } }
+#define TMPFS_MAGIC 0x01021994
+#define TEST_NORMAL_FILE "tmpfilecachestat"
+#define SHM_FILE "tmpshmcstat"
+#define NUM_PAGES 4
+
+static int fd;
+static int fd_shm;
+static size_t PS;
+static size_t filesize;
+static char *data;
+static int random_fd;
+
+/*
+ * fsync() is implemented via noop_fsync() on tmpfs. This makes the fsync()
+ * test fail below, so we need to check for test file living on a tmpfs.
+ */
+static bool is_on_tmpfs(int fd)
+{
+	struct statfs statfs_buf;
+
+	if (fstatfs(fd, &statfs_buf))
+		return false;
+
+	return statfs_buf.f_type == TMPFS_MAGIC;
+}
+
+static void print_cachestat(struct cachestat *cs)
+{
+	tst_res(TINFO,
+			"Using cachestat: Cached: %llu, Dirty: %llu, Writeback: %llu, Evicted: %llu, Recently Evicted: %llu",
+			cs->nr_cache, cs->nr_dirty, cs->nr_writeback,
+			cs->nr_evicted, cs->nr_recently_evicted);
+}
+
+static const char * const dev_files[] = {
+	"/dev/zero", "/dev/null", "/dev/urandom",
+	"/proc/version", "/proc"
+};
+
+static bool write_exactly(int write_fd)
+{
+	char *cursor;
+	int remained;
+
+	remained = filesize;
+	cursor = data;
+	while (remained) {
+		ssize_t read_len = SAFE_READ(1, random_fd, cursor, remained);
+
+		if (read_len <= 0)
+			tst_brk(TBROK | TERRNO, "Unable to read from urandom.");
+
+		remained -= read_len;
+		cursor += read_len;
+	}
+
+	remained = filesize;
+	cursor = data;
+	while (remained) {
+		ssize_t write_len = SAFE_WRITE(1, write_fd, cursor, remained);
+
+		if (write_len <= 0)
+			tst_brk(TBROK | TERRNO, "Unable write random data to file.");
+
+		remained -= write_len;
+		cursor += write_len;
+	}
+
+	return true;
+}
+
+/*
+ * Open/create the file at filename, (optionally) write random data to it
+ * (exactly num_pages), then test the cachestat syscall on this file.
+ *
+ * If test_fsync == true, fsync the file, then check the number of dirty
+ * pages.
+ */
+static void test_cachestat(const char *filename, bool write_random, bool create,
+		bool test_fsync, int open_flags, mode_t open_mode)
+{
+	struct cachestat cs;
+	struct cachestat_range cs_range = { 0, filesize };
+
+	if (!fcntl(fd, F_GETFD))
+		SAFE_CLOSE(fd);
+	fd = SAFE_OPEN(filename, open_flags, open_mode);
+
+	if (write_random) {
+		if (!write_exactly(fd))
+			tst_brk(TBROK | TERRNO, "Unable to access urandom.");
+	}
+
+	TST_EXP_PASS(cachestat(fd, &cs_range, &cs, 0));
+
+	print_cachestat(&cs);
+
+	if (write_random) {
+		if (cs.nr_cache + cs.nr_evicted != NUM_PAGES) {
+			tst_brk(TBROK | TERRNO,
+					"Total number of cached and evicted pages is off.");
+		}
+	}
+
+	if (test_fsync) {
+		if (is_on_tmpfs(fd)) {
+			tst_res(TCONF, "skip fsync check on tmpfs");
+		} else if (fsync(fd)) {
+			tst_brk(TBROK | TERRNO, "fsync fails.");
+		} else {
+			TST_EXP_PASS(cachestat(fd, &cs_range, &cs, 0));
+			print_cachestat(&cs);
+			if (cs.nr_dirty) {
+				tst_brk(TBROK | TERRNO,
+						"Number of dirty should be zero after fsync.");
+			} else {
+				tst_res(TPASS, "Cachestat (after fsync) pass.");
+			}
+		}
+	}
+
+	close(fd);
+
+	if (create)
+		remove(filename);
+
+	tst_res(TPASS, "cachestat works with file %s", filename);
+}
+
+static void test_incorrect_file(void)
+{
+	TST_EXP_FAIL(cachestat(-1, NULL, NULL, 0), EBADF);
+}
+
+static void test_virtual_file(void)
+{
+	for (unsigned long i = 0; i < sizeof(dev_files) / sizeof(*dev_files); i++) {
+		const char *dev_filename = dev_files[i];
+
+		test_cachestat(dev_filename, false, false, false, O_RDONLY, 0400);
+	}
+}
+
+static void test_normal_file(void)
+{
+	test_cachestat(TEST_NORMAL_FILE, true, true, false, O_CREAT | O_RDWR, 0600);
+	test_cachestat(TEST_NORMAL_FILE, true, true, true, O_CREAT | O_RDWR, 0600);
+}
+
+static void check_cachestat_range(struct cachestat_range *ptr_cs_range, __u64 expect_num_pages)
+{
+	struct cachestat cs;
+
+	TST_EXP_PASS(cachestat(fd_shm, ptr_cs_range, &cs, 0));
+	print_cachestat(&cs);
+	if (cs.nr_cache + cs.nr_evicted != expect_num_pages) {
+		tst_brk(TFAIL | TERRNO,
+				"Total number of cached and evicted pages is off.");
+	} else {
+		tst_res(TPASS,
+				"Cachestat range check pass.");
+	}
+}
+
+static void test_share_memory(void)
+{
+
+	struct cachestat_range cs_range = { 0, filesize};
+
+	if (ftruncate(fd_shm, filesize))
+		tst_brk(TFAIL | TERRNO, "Unable to truncate shmem file.");
+
+	if (!write_exactly(fd_shm))
+		tst_brk(TFAIL | TERRNO, "Unable to write to shmem file.");
+
+	check_cachestat_range(&cs_range, NUM_PAGES);
+
+	size_t compute_len = PS * NUM_PAGES / 2;
+	unsigned long num_pages = ceil((double)NUM_PAGES / 2);
+
+	cs_range.off = PS;
+	cs_range.len = compute_len;
+	check_cachestat_range(&cs_range, num_pages);
+}
+
+static struct tcase {
+	void (*tfunc)(void);
+} tcases[] = {
+	{&test_incorrect_file},
+	{&test_virtual_file},
+	{&test_normal_file},
+	{&test_share_memory}
+};
+
+static void run(unsigned int i)
+{
+	tcases[i].tfunc();
+}
+
+
+static void setup(void)
+{
+
+	PS = sysconf(_SC_PAGESIZE);
+	filesize = NUM_PAGES * PS;
+	data = tst_alloc(filesize);
+	random_fd = SAFE_OPEN("/dev/urandom", O_RDONLY);
+
+	/* setup for test_share_memory case */
+	fd_shm = shm_open(SHM_FILE, O_CREAT | O_RDWR, 0700);
+	if (fd_shm < 0)
+		tst_brk(TFAIL | TERRNO, "Unable to create shmem file.");
+}
+
+static void cleanup(void)
+{
+	SAFE_CLOSE(random_fd);
+
+	/* cleanup for test_normal_file case*/
+	if (!fcntl(fd, F_GETFD))
+		SAFE_CLOSE(fd);
+	remove(TEST_NORMAL_FILE);
+
+	/* cleanup for test_share_memory case */
+	SAFE_CLOSE(fd_shm);
+	shm_unlink(SHM_FILE);
+}
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.min_kver = "6.5.0"
+};
-- 
2.35.3


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [LTP] [PATCH v2] cachestat01.c: Add cachestat() testcheck
  2023-09-19  8:29 ` [LTP] [PATCH v2] " Wei Gao via ltp
@ 2023-11-20 11:25   ` Richard Palethorpe
  0 siblings, 0 replies; 3+ messages in thread
From: Richard Palethorpe @ 2023-11-20 11:25 UTC (permalink / raw)
  To: Wei Gao; +Cc: ltp

Hello,

Wei Gao via ltp <ltp@lists.linux.it> writes:

> Signed-off-by: Wei Gao <wegao@suse.com>
> ---
>  configure.ac                                  |   1 +
>  include/lapi/cachestat.h                      |  36 +++
>  include/lapi/syscalls/aarch64.in              |   1 +
>  include/lapi/syscalls/arc.in                  |   1 +
>  include/lapi/syscalls/arm.in                  |   1 +
>  include/lapi/syscalls/hppa.in                 |   1 +
>  include/lapi/syscalls/i386.in                 |   1 +
>  include/lapi/syscalls/ia64.in                 |   1 +
>  include/lapi/syscalls/powerpc.in              |   1 +
>  include/lapi/syscalls/powerpc64.in            |   1 +
>  include/lapi/syscalls/s390.in                 |   1 +
>  include/lapi/syscalls/s390x.in                |   1 +
>  include/lapi/syscalls/sh.in                   |   1 +
>  include/lapi/syscalls/sparc.in                |   1 +
>  include/lapi/syscalls/sparc64.in              |   1 +
>  include/lapi/syscalls/x86_64.in               |   1 +
>  runtest/syscalls                              |   2 +
>  .../kernel/syscalls/cachestat/.gitignore      |   1 +
>  testcases/kernel/syscalls/cachestat/Makefile  |   8 +
>  .../kernel/syscalls/cachestat/cachestat01.c   | 260 ++++++++++++++++++
>  20 files changed, 322 insertions(+)
>  create mode 100644 include/lapi/cachestat.h
>  create mode 100644 testcases/kernel/syscalls/cachestat/.gitignore
>  create mode 100644 testcases/kernel/syscalls/cachestat/Makefile
>  create mode 100644 testcases/kernel/syscalls/cachestat/cachestat01.c
>
> diff --git a/configure.ac b/configure.ac
> index 662c4c058..4b5547b5b 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -93,6 +93,7 @@ AC_CHECK_FUNCS_ONCE([ \
>      epoll_pwait2 \
>      execveat \
>      faccessat2 \
> +    cachestat \
>      fallocate \
>      fchownat \
>      fsconfig \
> diff --git a/include/lapi/cachestat.h b/include/lapi/cachestat.h
> new file mode 100644
> index 000000000..fea390849
> --- /dev/null
> +++ b/include/lapi/cachestat.h
> @@ -0,0 +1,36 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) Linux Test Project, 2003-2023
> + * Author: Wei Gao <wegao@suse.com>
> + */
> +
> +#ifndef CACHESTAT_H
> +#define CACHESTAT_H
> +
> +#include "tst_test.h"
> +#include "config.h"
> +#include "lapi/syscalls.h"
> +
> +#ifndef HAVE_CACHESTAT
> +struct cachestat_range {
> +	__u64 off;
> +	__u64 len;
> +};
> +
> +struct cachestat {
> +	__u64 nr_cache;
> +	__u64 nr_dirty;
> +	__u64 nr_writeback;
> +	__u64 nr_evicted;
> +	__u64 nr_recently_evicted;
> +};
> +
> +int cachestat(unsigned int fd,
> +                struct cachestat_range *cstat_range,
> +                struct cachestat *cstat, unsigned int flags)
> +{
> +	return tst_syscall(__NR_cachestat, fd, cstat_range, cstat, flags);
> +}
> +#endif
> +
> +#endif /* CACHESTAT_H */
> diff --git a/include/lapi/syscalls/aarch64.in b/include/lapi/syscalls/aarch64.in
> index 2cb6c2d87..1c0218eae 100644
> --- a/include/lapi/syscalls/aarch64.in
> +++ b/include/lapi/syscalls/aarch64.in
> @@ -297,4 +297,5 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
>  _sysctl 1078
> diff --git a/include/lapi/syscalls/arc.in b/include/lapi/syscalls/arc.in
> index 3e2ee9061..5d7cd6ca4 100644
> --- a/include/lapi/syscalls/arc.in
> +++ b/include/lapi/syscalls/arc.in
> @@ -317,3 +317,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
> index 7bdbca533..e41a7e576 100644
> --- a/include/lapi/syscalls/arm.in
> +++ b/include/lapi/syscalls/arm.in
> @@ -395,3 +395,4 @@ faccessat2 (__NR_SYSCALL_BASE+439)
>  epoll_pwait2 (__NR_SYSCALL_BASE+441)
>  quotactl_fd (__NR_SYSCALL_BASE+443)
>  futex_waitv (__NR_SYSCALL_BASE+449)
> +cachestat (__NR_SYSCALL_BASE+451)
> diff --git a/include/lapi/syscalls/hppa.in b/include/lapi/syscalls/hppa.in
> index 8ebdafafb..2772e7334 100644
> --- a/include/lapi/syscalls/hppa.in
> +++ b/include/lapi/syscalls/hppa.in
> @@ -44,3 +44,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in
> index 1472631c4..2d341182e 100644
> --- a/include/lapi/syscalls/i386.in
> +++ b/include/lapi/syscalls/i386.in
> @@ -431,3 +431,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/ia64.in
> index 0ea6e9722..141c6be51 100644
> --- a/include/lapi/syscalls/ia64.in
> +++ b/include/lapi/syscalls/ia64.in
> @@ -344,3 +344,4 @@ faccessat2 1463
>  epoll_pwait2 1465
>  quotactl_fd 1467
>  futex_waitv 1473
> +cachestat 1475
> diff --git a/include/lapi/syscalls/powerpc.in b/include/lapi/syscalls/powerpc.in
> index 545d9d3d6..67e928951 100644
> --- a/include/lapi/syscalls/powerpc.in
> +++ b/include/lapi/syscalls/powerpc.in
> @@ -424,3 +424,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in
> index 545d9d3d6..67e928951 100644
> --- a/include/lapi/syscalls/powerpc64.in
> +++ b/include/lapi/syscalls/powerpc64.in
> @@ -424,3 +424,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in
> index 7213ac5f8..b456ea408 100644
> --- a/include/lapi/syscalls/s390.in
> +++ b/include/lapi/syscalls/s390.in
> @@ -411,3 +411,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
> index 879012e2b..2c57eacdf 100644
> --- a/include/lapi/syscalls/s390x.in
> +++ b/include/lapi/syscalls/s390x.in
> @@ -359,3 +359,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
> index 7d5192a27..25eb9bb26 100644
> --- a/include/lapi/syscalls/sh.in
> +++ b/include/lapi/syscalls/sh.in
> @@ -405,3 +405,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in
> index 91d2fb1c2..e934591dd 100644
> --- a/include/lapi/syscalls/sparc.in
> +++ b/include/lapi/syscalls/sparc.in
> @@ -410,3 +410,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/sparc64.in b/include/lapi/syscalls/sparc64.in
> index 1f2fc59b7..4c489e38d 100644
> --- a/include/lapi/syscalls/sparc64.in
> +++ b/include/lapi/syscalls/sparc64.in
> @@ -375,3 +375,4 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
> diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in
> index dc61aa56e..4afea6019 100644
> --- a/include/lapi/syscalls/x86_64.in
> +++ b/include/lapi/syscalls/x86_64.in
> @@ -352,6 +352,7 @@ faccessat2 439
>  epoll_pwait2 441
>  quotactl_fd 443
>  futex_waitv 449
> +cachestat 451
>  rt_sigaction 512
>  rt_sigreturn 513
>  ioctl 514
> diff --git a/runtest/syscalls b/runtest/syscalls
> index 4fb76584f..b84b2d2ce 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -59,6 +59,8 @@ capset04 capset04
>  
>  cacheflush01 cacheflush01
>  
> +cachestat01 cachestat01
> +
>  chdir01 chdir01
>  chdir01A symlink01 -T chdir01
>  chdir04 chdir04
> diff --git a/testcases/kernel/syscalls/cachestat/.gitignore b/testcases/kernel/syscalls/cachestat/.gitignore
> new file mode 100644
> index 000000000..870bceae4
> --- /dev/null
> +++ b/testcases/kernel/syscalls/cachestat/.gitignore
> @@ -0,0 +1 @@
> +/cachestat01
> diff --git a/testcases/kernel/syscalls/cachestat/Makefile b/testcases/kernel/syscalls/cachestat/Makefile
> new file mode 100644
> index 000000000..49238eee0
> --- /dev/null
> +++ b/testcases/kernel/syscalls/cachestat/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +# Copyright (c) 2023 Wei Gao <wegao@suse.com>
> +
> +top_srcdir		?= ../../../..
> +
> +include $(top_srcdir)/include/mk/testcases.mk
> +
> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/syscalls/cachestat/cachestat01.c b/testcases/kernel/syscalls/cachestat/cachestat01.c
> new file mode 100644
> index 000000000..9ad432b59
> --- /dev/null
> +++ b/testcases/kernel/syscalls/cachestat/cachestat01.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2023 Andre Przywara <andre.przywara@arm.com>
> + * Copyright (c) 2023 Wei Gao <wegao@suse.com>
> + *
> + */
> +
> +/*\
> + * [Description]
> + *
> + * Verify that cachestat() executes successfully
> + *
> + */
> +
> +#include <stdio.h>
> +#include <math.h>
> +#include <unistd.h> /* _SC_PAGESIZE */
> +#include <stdbool.h>
> +#include <stdlib.h>
> +#include "tst_test.h"
> +#include "lapi/syscalls.h"
> +#include "lapi/cachestat.h"
> +
> +#define SAFE_FREE(p) { if (p) { free(p); (p) = NULL; } }
> +#define TMPFS_MAGIC 0x01021994

This is already defined as TST_TMPFS_MAGIC

> +#define TEST_NORMAL_FILE "tmpfilecachestat"
> +#define SHM_FILE "tmpshmcstat"
> +#define NUM_PAGES 4
> +
> +static int fd;
> +static int fd_shm;
> +static size_t PS;
> +static size_t filesize;
> +static char *data;
> +static int random_fd;
> +
> +/*
> + * fsync() is implemented via noop_fsync() on tmpfs. This makes the fsync()
> + * test fail below, so we need to check for test file living on a tmpfs.
> + */
> +static bool is_on_tmpfs(int fd)
> +{
> +	struct statfs statfs_buf;
> +
> +	if (fstatfs(fd, &statfs_buf))

fstatfs01 expects fstatfs to succeed on all file systems. So we should
here too.

> +		return false;
> +
> +	return statfs_buf.f_type == TMPFS_MAGIC;
> +}
> +
> +static void print_cachestat(struct cachestat *cs)
> +{
> +	tst_res(TINFO,
> +			"Using cachestat: Cached: %llu, Dirty: %llu, Writeback: %llu, Evicted: %llu, Recently Evicted: %llu",
> +			cs->nr_cache, cs->nr_dirty, cs->nr_writeback,
> +			cs->nr_evicted, cs->nr_recently_evicted);
> +}
> +
> +static const char * const dev_files[] = {
> +	"/dev/zero", "/dev/null", "/dev/urandom",
> +	"/proc/version", "/proc"
> +};
> +
> +static bool write_exactly(int write_fd)
> +{
> +	char *cursor;
> +	int remained;
> +
> +	remained = filesize;
> +	cursor = data;
> +	while (remained) {
> +		ssize_t read_len = SAFE_READ(1, random_fd, cursor,
> remained);

If len_strict is set then there is no point having a loop.

> +
> +		if (read_len <= 0)
> +			tst_brk(TBROK | TERRNO, "Unable to read from urandom.");
> +

read_len can't be negative.

> +		remained -= read_len;
> +		cursor += read_len;
> +	}
> +
> +	remained = filesize;
> +	cursor = data;
> +	while (remained) {
> +		ssize_t write_len = SAFE_WRITE(1, write_fd, cursor, remained);
> +
> +		if (write_len <= 0)
> +			tst_brk(TBROK | TERRNO, "Unable write random
> data to file.");

Same issues again.

Probably 4 pages is too many to rely on being read atomically. I don't
know about FS like btrfs and xfs, but only a single page is used for
buffering sequence files (IIRC).

Why not just use tst_fill_file?

Generally I don't like using random data anyway. If it has any effect at
all, it could make bug reproduction more difficult.

> +
> +		remained -= write_len;
> +		cursor += write_len;
> +	}
> +
> +	return true;
> +}
> +
> +/*
> + * Open/create the file at filename, (optionally) write random data to it
> + * (exactly num_pages), then test the cachestat syscall on this file.
> + *
> + * If test_fsync == true, fsync the file, then check the number of dirty
> + * pages.
> + */
> +static void test_cachestat(const char *filename, bool write_random, bool create,
> +		bool test_fsync, int open_flags, mode_t open_mode)
> +{
> +	struct cachestat cs;
> +	struct cachestat_range cs_range = { 0, filesize };
> +
> +	if (!fcntl(fd, F_GETFD))
> +		SAFE_CLOSE(fd);
> +	fd = SAFE_OPEN(filename, open_flags, open_mode);
> +
> +	if (write_random) {
> +		if (!write_exactly(fd))
> +			tst_brk(TBROK | TERRNO, "Unable to access
> urandom.");

How can write_exactly return false?

> +	}
> +
> +	TST_EXP_PASS(cachestat(fd, &cs_range, &cs, 0));
> +
> +	print_cachestat(&cs);
> +
> +	if (write_random) {
> +		if (cs.nr_cache + cs.nr_evicted != NUM_PAGES) {
> +			tst_brk(TBROK | TERRNO,
> +					"Total number of cached and
> evicted pages is off.");

I suppose this was in the selftest, so we can trust that these counters
are updated synchronously.

We probably should print the number of cached and evicted pages though.

> +		}
> +	}
> +
> +	if (test_fsync) {
> +		if (is_on_tmpfs(fd)) {
> +			tst_res(TCONF, "skip fsync check on tmpfs");
> +		} else if (fsync(fd)) {
> +			tst_brk(TBROK | TERRNO, "fsync fails.");
> +		} else {
> +			TST_EXP_PASS(cachestat(fd, &cs_range, &cs, 0));
> +			print_cachestat(&cs);
> +			if (cs.nr_dirty) {
> +				tst_brk(TBROK | TERRNO,
> +						"Number of dirty should be zero after fsync.");
> +			} else {
> +				tst_res(TPASS, "Cachestat (after fsync) pass.");
> +			}
> +		}
> +	}
> +
> +	close(fd);
> +
> +	if (create)
> +		remove(filename);
> +
> +	tst_res(TPASS, "cachestat works with file %s", filename);
> +}
> +
> +static void test_incorrect_file(void)
> +{
> +	TST_EXP_FAIL(cachestat(-1, NULL, NULL, 0), EBADF);
> +}
> +
> +static void test_virtual_file(void)
> +{
> +	for (unsigned long i = 0; i < sizeof(dev_files) / sizeof(*dev_files); i++) {
> +		const char *dev_filename = dev_files[i];
> +
> +		test_cachestat(dev_filename, false, false, false, O_RDONLY, 0400);
> +	}
> +}
> +
> +static void test_normal_file(void)
> +{
> +	test_cachestat(TEST_NORMAL_FILE, true, true, false, O_CREAT | O_RDWR, 0600);
> +	test_cachestat(TEST_NORMAL_FILE, true, true, true, O_CREAT | O_RDWR, 0600);
> +}
> +
> +static void check_cachestat_range(struct cachestat_range *ptr_cs_range, __u64 expect_num_pages)
> +{
> +	struct cachestat cs;
> +
> +	TST_EXP_PASS(cachestat(fd_shm, ptr_cs_range, &cs, 0));
> +	print_cachestat(&cs);
> +	if (cs.nr_cache + cs.nr_evicted != expect_num_pages) {
> +		tst_brk(TFAIL | TERRNO,
> +				"Total number of cached and evicted pages is off.");
> +	} else {
> +		tst_res(TPASS,
> +				"Cachestat range check pass.");
> +	}
> +}
> +
> +static void test_share_memory(void)
> +{
> +
> +	struct cachestat_range cs_range = { 0, filesize};
> +
> +	if (ftruncate(fd_shm, filesize))
> +		tst_brk(TFAIL | TERRNO, "Unable to truncate shmem file.");
> +
> +	if (!write_exactly(fd_shm))
> +		tst_brk(TFAIL | TERRNO, "Unable to write to shmem file.");
> +
> +	check_cachestat_range(&cs_range, NUM_PAGES);
> +
> +	size_t compute_len = PS * NUM_PAGES / 2;
> +	unsigned long num_pages = ceil((double)NUM_PAGES / 2);
> +
> +	cs_range.off = PS;
> +	cs_range.len = compute_len;
> +	check_cachestat_range(&cs_range, num_pages);
> +}
> +
> +static struct tcase {
> +	void (*tfunc)(void);
> +} tcases[] = {
> +	{&test_incorrect_file},
> +	{&test_virtual_file},
> +	{&test_normal_file},
> +	{&test_share_memory}
> +};
> +
> +static void run(unsigned int i)
> +{
> +	tcases[i].tfunc();
> +}
> +
> +
> +static void setup(void)
> +{
> +
> +	PS = sysconf(_SC_PAGESIZE);
> +	filesize = NUM_PAGES * PS;
> +	data = tst_alloc(filesize);

This can be allocated using test.bufs which will also handle cleanup.

> +	random_fd = SAFE_OPEN("/dev/urandom", O_RDONLY);
> +
> +	/* setup for test_share_memory case */
> +	fd_shm = shm_open(SHM_FILE, O_CREAT | O_RDWR, 0700);
> +	if (fd_shm < 0)
> +		tst_brk(TFAIL | TERRNO, "Unable to create shmem file.");
> +}
> +
> +static void cleanup(void)
> +{
> +	SAFE_CLOSE(random_fd);
> +
> +	/* cleanup for test_normal_file case*/
> +	if (!fcntl(fd, F_GETFD))
> +		SAFE_CLOSE(fd);
> +	remove(TEST_NORMAL_FILE);
> +
> +	/* cleanup for test_share_memory case */
> +	SAFE_CLOSE(fd_shm);
> +	shm_unlink(SHM_FILE);
> +}
> +
> +static struct tst_test test = {
> +	.test = run,
> +	.tcnt = ARRAY_SIZE(tcases),
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.needs_tmpdir = 1,
> +	.min_kver = "6.5.0"

This would benefit from being run on all filesystems!

> +};
> -- 
> 2.35.3


-- 
Thank you,
Richard.

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-11-20 13:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-08  7:29 [LTP] [PATCH v1] cachestat01.c: Add cachestat() testcheck Wei Gao via ltp
2023-09-19  8:29 ` [LTP] [PATCH v2] " Wei Gao via ltp
2023-11-20 11:25   ` Richard Palethorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox