The current test in nap.h tries to gauge the minimum delay that results in a timestamp change when successively writing to a file.
There are some proposed changes [1] to track finer-grained timestamps in the Linux kernel that will break the assumptions that nap() uses to gauge the delay. In particular, writing to a file will almost always show a change in the timestamp now, so usually this method will settle on a delay of 1ns. Switch this code over to use file creation of two files to gauge the delay. Since that is operating on two different files, it should still be possible to gauge the coarse-grained timer tick from that. [1]: https://lore.kernel.org/linux-fsdevel/20240626-mgtime-v1-0-a189352d0...@kernel.org/ Signed-off-by: Jeff Layton <jlay...@kernel.org> --- Failure of the test-stat-time test is what triggered us to revert the multigrain timestamp series from the Linux kernel last October. With that failure, we'd sometimes see timestamps showing files being modified in reverse order (if one got a fine-grained and another got a coarse-grained timestamp). That problem has now been addressed, but test-stat-time still fails without this change. --- ChangeLog | 5 ++++ tests/nap.h | 84 +++++++++++++++++++++---------------------------------------- 2 files changed, 33 insertions(+), 56 deletions(-) diff --git a/ChangeLog b/ChangeLog index a9453b0b4513..6524d717cf7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2024-06-28 Jeff Layton <jlay...@kernel.org> + * tests/nap.h: change the method used to gauge the coarse-grained + timestamp to use creation of two files instead of writes to a + single file. + 2024-06-28 Bruno Haible <br...@clisp.org> time: Fix test failure on FreeBSD. diff --git a/tests/nap.h b/tests/nap.h index cf7d998b800e..323df6264a02 100644 --- a/tests/nap.h +++ b/tests/nap.h @@ -31,10 +31,8 @@ # endif /* Name of the witness file. */ -#define TEMPFILE BASE "nap.tmp" - -/* File descriptor used for the witness file. */ -static int nap_fd = -1; +#define TEMPFILE1 BASE "nap1.tmp" +#define TEMPFILE2 BASE "nap2.tmp" /* Return A - B, in ns. Return 0 if the true result would be negative. @@ -62,56 +60,46 @@ diff_timespec (struct timespec a, struct timespec b) return sdiff; } -/* If DO_WRITE, bump the modification time of the file designated by NAP_FD. - Then fetch the new STAT information of NAP_FD. */ -static void -nap_get_stat (struct stat *st, int do_write) +void clear_tempfiles(void) { - if (do_write) - { - ASSERT (write (nap_fd, "\n", 1) == 1); -#if defined _WIN32 || defined __CYGWIN__ - /* On Windows, the modification times are not changed until NAP_FD - is closed. See - <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-writefile> */ - close (nap_fd); - nap_fd = open (TEMPFILE, O_RDWR, 0600); - ASSERT (nap_fd != -1); - lseek (nap_fd, 0, SEEK_END); -#endif - } - ASSERT (fstat (nap_fd, st) == 0); + unlink(TEMPFILE1); + unlink(TEMPFILE2); } /* Given a file whose descriptor is FD, see whether delaying by DELAY nanoseconds causes a change in a file's mtime. OLD_ST is the file's status, recently gotten. */ static bool -nap_works (int delay, struct stat old_st) +nap_works (int delay) { - struct stat st; + struct stat st1, st2; struct timespec delay_spec; + int fd1, fd2; + int ret; + + ret = unlink (TEMPFILE1); + ASSERT(ret == 0 || errno == ENOENT); + ret = unlink (TEMPFILE2); + ASSERT(ret == 0 || errno == ENOENT); + delay_spec.tv_sec = delay / 1000000000; delay_spec.tv_nsec = delay % 1000000000; - ASSERT (nanosleep (&delay_spec, 0) == 0); - nap_get_stat (&st, 1); - if (diff_timespec (get_stat_mtime (&st), get_stat_mtime (&old_st))) + ASSERT ((fd1 = creat (TEMPFILE1, 0600)) != -1); + close(fd1); + ASSERT (nanosleep (&delay_spec, 0) == 0); + ASSERT ((fd2 = creat (TEMPFILE2, 0600)) != -1); + close(fd2); + ASSERT (stat (TEMPFILE1, &st1) != -1); + ASSERT (stat (TEMPFILE2, &st2) != -1); + ASSERT (unlink (TEMPFILE1) == 0); + ASSERT (unlink (TEMPFILE2) == 0); + + if (diff_timespec (get_stat_mtime (&st2), get_stat_mtime (&st1))) return true; - return false; } -static void -clear_temp_file (void) -{ - if (0 <= nap_fd) - { - ASSERT (close (nap_fd) != -1); - ASSERT (unlink (TEMPFILE) != -1); - } -} - /* Sleep long enough to notice a timestamp difference on the file system in the current directory. Use an adaptive approach, trying to find the smallest delay which works on the current file system @@ -122,28 +110,12 @@ clear_temp_file (void) static void nap (void) { - struct stat old_st; static int delay = 1; - if (-1 == nap_fd) - { - atexit (clear_temp_file); - ASSERT ((nap_fd = creat (TEMPFILE, 0600)) != -1); - nap_get_stat (&old_st, 0); - } - else - { - ASSERT (0 <= nap_fd); - nap_get_stat (&old_st, 1); - } - - if (1 < delay) - delay = delay / 2; /* Try half of the previous delay. */ - ASSERT (0 < delay); - + atexit(clear_tempfiles); for (;;) { - if (nap_works (delay, old_st)) + if (nap_works (delay)) return; if (delay <= (2147483647 - 1) / 2) { --- base-commit: 1066dc9c0bc4ffa65fe117cf055a346482f03b1e change-id: 20240612-master-432eef551152 Best regards, -- Jeff Layton <jlay...@kernel.org>