[fstests PATCH] generic: add a test for multigrain timestamps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ensure that the mtime and ctime apparently change, even when there are
multiple writes in quick succession. Older kernels didn't do this, but
there are patches in flight that should help ensure it in the future.

Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
 src/Makefile          |   2 +-
 src/mgctime.c         | 107 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/730     |  25 ++++++++++
 tests/generic/730.out |   1 +
 4 files changed, 134 insertions(+), 1 deletion(-)
 create mode 100644 src/mgctime.c
 create mode 100755 tests/generic/730
 create mode 100644 tests/generic/730.out

This patchset is intended to test the new multigrain timestamp feature:

    https://lore.kernel.org/linux-fsdevel/20230713-mgctime-v5-0-9eb795d2ae37@xxxxxxxxxx/T/#t

I had originally attempted to write this as a shell script, but it was
too slow, which made it falsely pass on unpatched kernels.

All current filesystems will fail this, so we may want to wait until
we are closer to merging the kernel series.

diff --git a/src/Makefile b/src/Makefile
index 24cd47479140..aff7d07466f0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -33,7 +33,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	attr_replace_test swapon mkswap t_attr_corruption t_open_tmpfiles \
 	fscrypt-crypt-util bulkstat_null_ocount splice-test chprojid_fail \
 	detached_mounts_propagation ext4_resize t_readdir_3 splice2pipe \
-	uuid_ioctl
+	uuid_ioctl mgctime
 
 EXTRA_EXECS = dmerror fill2attr fill2fs fill2fs_check scaleread.sh \
 	      btrfs_crc32c_forged_name.py popdir.pl popattr.py
diff --git a/src/mgctime.c b/src/mgctime.c
new file mode 100644
index 000000000000..38e22a8613ff
--- /dev/null
+++ b/src/mgctime.c
@@ -0,0 +1,107 @@
+/*
+ * Older Linux kernels always use coarse-grained timestamps, with a
+ * resolution of around 1 jiffy. Writes that are done in quick succession
+ * on those kernels apparent change to the ctime or mtime.
+ *
+ * Newer kernels attempt to ensure that fine-grained timestamps are used
+ * when the mtime or ctime are queried from userland.
+ *
+ * Open a file and do a 1 byte write to it and then statx the mtime and ctime.
+ * Do that in a loop 1000 times and ensure that the value is different from
+ * the last.
+ *
+ * Copyright (c) 2023: Jeff Layton <jlayton@xxxxxxxxxx>
+ */
+#define _GNU_SOURCE 1
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdbool.h>
+
+#define NUM_WRITES 1000
+
+static int64_t statx_ts_cmp(struct statx_timestamp *ts1, struct statx_timestamp *ts2)
+{
+	int64_t ret = ts2->tv_sec - ts1->tv_sec;
+
+	if (ret)
+		return ret;
+
+	ret = ts2->tv_nsec;
+	ret -= ts1->tv_nsec;
+
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	int ret, fd, i;
+	struct statx stx = { };
+	struct statx_timestamp ctime, mtime;
+	bool verbose = false;
+
+	while ((i = getopt(argc, argv, "v")) != -1) {
+		switch (i) {
+		case 'v':
+			verbose = true;
+			break;
+		}
+	}
+
+	if (argc < 2) {
+		errno = -EINVAL;
+		perror("usage");
+	}
+
+	fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644);
+	if (fd < 0) {
+		perror("open");
+		return 1;
+	}
+
+	ret = statx(fd, "", AT_EMPTY_PATH, STATX_MTIME|STATX_CTIME, &stx);
+	if (ret < 0) {
+		perror("stat");
+		return 1;
+	}
+
+	ctime = stx.stx_ctime;
+	mtime = stx.stx_mtime;
+
+	for (i = 0; i < NUM_WRITES; ++i) {
+		ssize_t written;
+
+		written = write(fd, "a", 1);
+		if (written < 0) {
+			perror("write");
+			return 1;
+		}
+
+		ret = statx(fd, "", AT_EMPTY_PATH, STATX_MTIME|STATX_CTIME, &stx);
+		if (ret < 0) {
+			perror("stat");
+			return 1;
+		}
+
+		if (verbose)
+			printf("%d: %llu.%u\n", i, stx.stx_ctime.tv_sec, stx.stx_ctime.tv_nsec);
+
+		if (!statx_ts_cmp(&ctime, &stx.stx_ctime)) {
+			printf("Duplicate ctime after write!\n");
+			return 1;
+		}
+
+		if (!statx_ts_cmp(&mtime, &stx.stx_mtime)) {
+			printf("Duplicate mtime after write!\n");
+			return 1;
+		}
+
+		ctime = stx.stx_ctime;
+		mtime = stx.stx_mtime;
+	}
+	return 0;
+}
diff --git a/tests/generic/730 b/tests/generic/730
new file mode 100755
index 000000000000..c3f24aeb8534
--- /dev/null
+++ b/tests/generic/730
@@ -0,0 +1,25 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2023, Jeff Layton <jlayton@xxxxxxxxxx>
+#
+# FS QA Test No. 730
+#
+# Multigrain time test
+#
+# Open a file, and do 1 byte writes to it, and statx the file for
+# the ctime and mtime after each write. Ensure that they have changed
+# since the previous write.
+#
+. ./common/preamble
+_begin_fstest auto quick
+
+# Override the default cleanup function.
+_require_test_program mgctime
+
+testfile="$TEST_DIR/test_mgtime_file.$$"
+
+$here/src/mgctime $testfile
+
+# success, all done
+status=0
+exit
diff --git a/tests/generic/730.out b/tests/generic/730.out
new file mode 100644
index 000000000000..5dbea532d60f
--- /dev/null
+++ b/tests/generic/730.out
@@ -0,0 +1 @@
+QA output created by 730
-- 
2.41.0




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux