[LTP] [PATCH v3] provide separate functions for getting start and end fs timestamps

Jan Stancek jstancek@redhat.com
Tue Feb 25 12:39:04 CET 2025


Tests using tst_get_fs_timestamp() rarely fail with recent kernels,
for example (after 6.13-rc1):
  tst_test.c:1833: TINFO: === Testing on ext4 ===
  tst_test.c:1170: TINFO: Formatting /dev/loop0 with ext4 opts='' extra opts=''
  mke2fs 1.47.2 (1-Jan-2025)
  tst_test.c:1182: TINFO: Mounting /dev/loop0 to /tmp/LTP_uti42UpHj/mntpoint fstyp=ext4 flags=0
  utime03.c:74: TPASS: utime(TEMP_FILE, NULL) passed
  utime03.c:80: TFAIL: utime() did not set expected atime, mintime: 1738291930, maxtime: 1738291930, st_atime: 1738291931
  utime03.c:85: TFAIL: utime() did not set expected mtime, mintime: 1738291930, maxtime: 1738291930, st_mtime: 1738291931

Since 4e40eff0b573 ("fs: add infrastructure for multigrain timestamps"),
filesystem can use more precise clock to update the inode.

Provide two versions of the function, for collecting start and end
timestamp, where latter one uses more precise clock.

Old function is renamed to tst_clock_get_timestamp() and used as
a helper function.

Signed-off-by: Jan Stancek <jstancek@redhat.com>
---
 include/tst_clocks.h                          | 21 +++++++++++++++++--
 lib/tst_clocks.c                              | 20 ++++++++++++++----
 .../kernel/syscalls/ipc/msgrcv/msgrcv01.c     |  4 ++--
 .../kernel/syscalls/ipc/msgsnd/msgsnd01.c     |  4 ++--
 .../kernel/syscalls/ipc/shmctl/shmctl01.c     |  4 ++--
 testcases/kernel/syscalls/utime/utime01.c     |  6 +++---
 testcases/kernel/syscalls/utime/utime02.c     |  6 +++---
 testcases/kernel/syscalls/utime/utime03.c     |  4 ++--
 8 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/include/tst_clocks.h b/include/tst_clocks.h
index 06d2d03bef33..8b7f33d4f387 100644
--- a/include/tst_clocks.h
+++ b/include/tst_clocks.h
@@ -20,15 +20,32 @@ int tst_clock_settime(clockid_t clk_id, struct timespec *ts);
  */
 const char *tst_clock_name(clockid_t clk_id);
 
+/*
+ * Returns timestamp (seconds passed) for the specified clock.
+ * TBROKs on error.
+ */
+time_t tst_clock_get_timestamp(clockid_t clk_id);
+
 /*
  * Returns current system time for file/IPC operations, which may slightly lag
- * behind time() return values.
+ * behind time() return values. Meant to be used as lower bound in atime/mtime
+ * checks.
  *
  * The reason for this is that the time() syscall reads the nanosecond timer at
  * the time of the call and adds it to the kernel current time, because of that
  * accumulation may cause it jump one second ahead compared to the kernel time
  * stamp that is used for IPC and filesystems.
  */
-time_t tst_get_fs_timestamp(void);
+time_t tst_fs_timestamp_start(void);
+
+/*
+ * Returns current system time for file/IPC operation, using clock
+ * which has higher precision. Meant to be used as higher bound in atime/mtime
+ * checks.
+ *
+ * The reason for separate start/end functions is to cover features like
+ * multigrain timestamps, which update atime/mtime using more precise clock.
+ */
+time_t tst_fs_timestamp_end(void);
 
 #endif /* TST_CLOCKS__ */
diff --git a/lib/tst_clocks.c b/lib/tst_clocks.c
index 29f4b420c373..fba4a4f7ba51 100644
--- a/lib/tst_clocks.c
+++ b/lib/tst_clocks.c
@@ -144,15 +144,27 @@ const char *tst_clock_name(clockid_t clk_id)
 	}
 }
 
-time_t tst_get_fs_timestamp(void)
+time_t tst_clock_get_timestamp(clockid_t clk_id)
 {
 	struct timespec ts;
 	int ret;
 
-	ret = tst_clock_gettime(CLOCK_REALTIME_COARSE, &ts);
+	ret = tst_clock_gettime(clk_id, &ts);
 
-	if (ret < 0)
-		tst_brk(TBROK | TERRNO, "clock_gettime(CLOCK_REALTIME_COARSE)");
+	if (ret < 0) {
+		tst_brk(TBROK | TERRNO, "clock_gettime(%s)",
+			tst_clock_name(clk_id));
+	}
 
 	return ts.tv_sec;
 }
+
+time_t tst_fs_timestamp_start(void)
+{
+	return tst_clock_get_timestamp(CLOCK_REALTIME_COARSE);
+}
+
+time_t tst_fs_timestamp_end(void)
+{
+	return tst_clock_get_timestamp(CLOCK_REALTIME);
+}
diff --git a/testcases/kernel/syscalls/ipc/msgrcv/msgrcv01.c b/testcases/kernel/syscalls/ipc/msgrcv/msgrcv01.c
index 9df20a61e38e..58bfd27716a2 100644
--- a/testcases/kernel/syscalls/ipc/msgrcv/msgrcv01.c
+++ b/testcases/kernel/syscalls/ipc/msgrcv/msgrcv01.c
@@ -26,13 +26,13 @@ static void verify_msgrcv(void)
 
 	SAFE_MSGSND(queue_id, &snd_buf, MSGSIZE, 0);
 
-	before_rcv = tst_get_fs_timestamp();
+	before_rcv = tst_fs_timestamp_start();
 	TEST(msgrcv(queue_id, &rcv_buf, MSGSIZE, 1, 0));
 	if (TST_RET == -1) {
 		tst_res(TFAIL | TTERRNO, "msgrcv failed");
 		return;
 	}
-	after_rcv = tst_get_fs_timestamp();
+	after_rcv = tst_fs_timestamp_end();
 
 	if (strcmp(rcv_buf.mtext, snd_buf.mtext) == 0)
 		tst_res(TPASS, "message received(%s) = message sent(%s)",
diff --git a/testcases/kernel/syscalls/ipc/msgsnd/msgsnd01.c b/testcases/kernel/syscalls/ipc/msgsnd/msgsnd01.c
index 60936be8a355..6d92f3dece11 100644
--- a/testcases/kernel/syscalls/ipc/msgsnd/msgsnd01.c
+++ b/testcases/kernel/syscalls/ipc/msgsnd/msgsnd01.c
@@ -30,13 +30,13 @@ static void verify_msgsnd(void)
 	struct msqid_ds qs_buf;
 	time_t before_snd, after_snd;
 
-	before_snd = tst_get_fs_timestamp();
+	before_snd = tst_fs_timestamp_start();
 	TEST(msgsnd(queue_id, &snd_buf, MSGSIZE, 0));
 	if (TST_RET == -1) {
 		tst_res(TFAIL | TTERRNO, "msgsnd() failed");
 		return;
 	}
-	after_snd = tst_get_fs_timestamp();
+	after_snd = tst_fs_timestamp_end();
 
 	SAFE_MSGCTL(queue_id, IPC_STAT, &qs_buf);
 
diff --git a/testcases/kernel/syscalls/ipc/shmctl/shmctl01.c b/testcases/kernel/syscalls/ipc/shmctl/shmctl01.c
index 1eec0798930f..e86cd71031af 100644
--- a/testcases/kernel/syscalls/ipc/shmctl/shmctl01.c
+++ b/testcases/kernel/syscalls/ipc/shmctl/shmctl01.c
@@ -242,9 +242,9 @@ static int get_shm_idx_from_id(int shm_id)
 
 static void setup(void)
 {
-	ctime_min = tst_get_fs_timestamp();
+	ctime_min = tst_fs_timestamp_start();
 	shm_id = SAFE_SHMGET(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | SHM_RW);
-	ctime_max = tst_get_fs_timestamp();
+	ctime_max = tst_fs_timestamp_end();
 
 	shm_idx = get_shm_idx_from_id(shm_id);
 
diff --git a/testcases/kernel/syscalls/utime/utime01.c b/testcases/kernel/syscalls/utime/utime01.c
index 2a74f8952d64..9e985ec3761d 100644
--- a/testcases/kernel/syscalls/utime/utime01.c
+++ b/testcases/kernel/syscalls/utime/utime01.c
@@ -31,7 +31,7 @@ static void run(void)
 	struct stat stat_buf;
 	time_t pre_time, post_time;
 
-	utbuf.modtime = tst_get_fs_timestamp() - 5;
+	utbuf.modtime = tst_fs_timestamp_start() - 5;
 	utbuf.actime = utbuf.modtime + 1;
 	TST_EXP_PASS_SILENT(utime(TEMP_FILE, &utbuf));
 	SAFE_STAT(TEMP_FILE, &stat_buf);
@@ -39,11 +39,11 @@ static void run(void)
 	TST_EXP_EQ_LI(stat_buf.st_atime, utbuf.actime);
 	TST_EXP_EQ_LI(stat_buf.st_mtime, utbuf.modtime);
 
-	pre_time = tst_get_fs_timestamp();
+	pre_time = tst_fs_timestamp_start();
 	TST_EXP_PASS(utime(TEMP_FILE, NULL), "utime(%s, NULL)", TEMP_FILE);
 	if (!TST_PASS)
 		return;
-	post_time = tst_get_fs_timestamp();
+	post_time = tst_fs_timestamp_end();
 	SAFE_STAT(TEMP_FILE, &stat_buf);
 
 	if (stat_buf.st_mtime < pre_time || stat_buf.st_mtime > post_time)
diff --git a/testcases/kernel/syscalls/utime/utime02.c b/testcases/kernel/syscalls/utime/utime02.c
index 52185d839e65..5ed83298796d 100644
--- a/testcases/kernel/syscalls/utime/utime02.c
+++ b/testcases/kernel/syscalls/utime/utime02.c
@@ -48,7 +48,7 @@ static void run(void)
 	struct stat stat_buf;
 	time_t pre_time, post_time;
 
-	utbuf.modtime = tst_get_fs_timestamp() - 5;
+	utbuf.modtime = tst_fs_timestamp_start() - 5;
 	utbuf.actime = utbuf.modtime + 1;
 	TST_EXP_PASS_SILENT(utime(TEMP_FILE, &utbuf));
 	SAFE_STAT(TEMP_FILE, &stat_buf);
@@ -56,11 +56,11 @@ static void run(void)
 	TST_EXP_EQ_LI(stat_buf.st_atime, utbuf.actime);
 	TST_EXP_EQ_LI(stat_buf.st_mtime, utbuf.modtime);
 
-	pre_time = tst_get_fs_timestamp();
+	pre_time = tst_fs_timestamp_start();
 	TST_EXP_PASS(utime(TEMP_FILE, NULL), "utime(%s, NULL)", TEMP_FILE);
 	if (!TST_PASS)
 		return;
-	post_time = tst_get_fs_timestamp();
+	post_time = tst_fs_timestamp_end();
 	SAFE_STAT(TEMP_FILE, &stat_buf);
 
 	if (stat_buf.st_mtime < pre_time || stat_buf.st_mtime > post_time)
diff --git a/testcases/kernel/syscalls/utime/utime03.c b/testcases/kernel/syscalls/utime/utime03.c
index 564e1de3dd77..aa0dcef250c8 100644
--- a/testcases/kernel/syscalls/utime/utime03.c
+++ b/testcases/kernel/syscalls/utime/utime03.c
@@ -68,9 +68,9 @@ static void run(void)
 	}
 
 	SAFE_SETEUID(user_uid);
-	mintime = tst_get_fs_timestamp();
+	mintime = tst_fs_timestamp_start();
 	TST_EXP_PASS(utime(TEMP_FILE, NULL));
-	maxtime = tst_get_fs_timestamp();
+	maxtime = tst_fs_timestamp_end();
 	SAFE_SETEUID(root_uid);
 	SAFE_STAT(TEMP_FILE, &statbuf);
 
-- 
2.43.0



More information about the ltp mailing list