io: Check at runtime if timestamp supports nanoseconds

Message ID 20210329174323.222990-1-adhemerval.zanella@linaro.org
State Committed
Headers
Series io: Check at runtime if timestamp supports nanoseconds |

Commit Message

Adhemerval Zanella Netto March 29, 2021, 5:43 p.m. UTC
  Now that non-LFS stat function is implemented on to on LFS, it will
use statx when available.  It allows to check for nanosecond timestamp
if the kernel supports __NR_statx.

Checked on s390-linux-gnu with 4.12.14 kernel.
---
 io/tst-stat.c                      |  7 ++++-
 support/support.h                  |  2 +-
 support/support_stat_nanoseconds.c | 41 +++++++++++++++++++++++++-----
 3 files changed, 41 insertions(+), 9 deletions(-)
  

Comments

Stefan Liebler March 31, 2021, 7:17 a.m. UTC | #1
On 29/03/2021 19:43, Adhemerval Zanella wrote:
> Now that non-LFS stat function is implemented on to on LFS, it will
> use statx when available.  It allows to check for nanosecond timestamp
> if the kernel supports __NR_statx.
> 
> Checked on s390-linux-gnu with 4.12.14 kernel.
> ---
>  io/tst-stat.c                      |  7 ++++-
>  support/support.h                  |  2 +-
>  support/support_stat_nanoseconds.c | 41 +++++++++++++++++++++++++-----
>  3 files changed, 41 insertions(+), 9 deletions(-)
> 
> diff --git a/io/tst-stat.c b/io/tst-stat.c
> index 397d480ecc..22b89bb3e7 100644
> --- a/io/tst-stat.c
> +++ b/io/tst-stat.c
> @@ -25,6 +25,7 @@
>  #include <support/xunistd.h>
>  #include <sys/stat.h>
>  #include <sys/sysmacros.h>
> +#include <stdio.h>
>  #include <unistd.h>
>  
>  static void
> @@ -73,6 +74,10 @@ do_test (void)
>  
>    test_t tests[] = { stat_check, lstat_check, fstat_check, fstatat_check };
>  
> +  bool check_ns = support_stat_nanoseconds (path);
> +  if (!check_ns)
> +    printf ("warning: timestamp with nanoseconds not supportted\n");
> +
>    for (int i = 0; i < array_length (tests); i++)
>      {
>        struct stat st;
> @@ -92,7 +97,7 @@ do_test (void)
>  
>        TEST_COMPARE (stx.stx_ctime.tv_sec, st.st_ctim.tv_sec);
>        TEST_COMPARE (stx.stx_mtime.tv_sec, st.st_mtim.tv_sec);
> -      if (support_stat_nanoseconds ())
> +      if (check_ns)
>  	{
>  	  TEST_COMPARE (stx.stx_ctime.tv_nsec, st.st_ctim.tv_nsec);
>  	  TEST_COMPARE (stx.stx_mtime.tv_nsec, st.st_mtim.tv_nsec);
OK

> diff --git a/support/support.h b/support/support.h
> index b0352726bf..e023d00857 100644
> --- a/support/support.h
> +++ b/support/support.h
> @@ -142,7 +142,7 @@ static __inline bool support_path_support_time64 (const char *path)
>  }
>  
>  /* Return true if stat supports nanoseconds resolution.  */
> -extern bool support_stat_nanoseconds (void);
> +extern bool support_stat_nanoseconds (const char *path);
OK
>  
>  __END_DECLS
>  
> diff --git a/support/support_stat_nanoseconds.c b/support/support_stat_nanoseconds.c
> index c0d5b2c3a9..94953c0868 100644
> --- a/support/support_stat_nanoseconds.c
> +++ b/support/support_stat_nanoseconds.c
> @@ -16,16 +16,43 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/timespec.h>
>  #include <stdbool.h>
> +#include <sys/stat.h>
> +#include <sys/syscall.h>
Do we really need syscall.h?
> +#include <sys/types.h>
> +#include <unistd.h>
>  
>  bool
> -support_stat_nanoseconds (void)
> +support_stat_nanoseconds (const char *path)
>  {
> -  /* s390 stat64 compat symbol does not support nanoseconds resolution
> -     and it used on non-LFS [f,l]stat[at] implementations.  */
> -#if defined __linux__ && !defined __s390x__ && defined __s390__
> -  return false;
> -#else
> -  return true;
> +  bool support;
> +#ifdef __linux__
> +  /* Obtain the original timestamp to restore at the end.  */
> +  struct stat ost;
> +  TEST_VERIFY_EXIT (stat (path, &ost) == 0);
> +
> +  const struct timespec tsp[] = { { 0, TIMESPEC_HZ - 1 },
> +				  { 0, TIMESPEC_HZ / 2 } };
> +  TEST_VERIFY_EXIT (utimensat (AT_FDCWD, path, tsp, 0) == 0);
> +
> +  struct stat st;
> +  TEST_VERIFY_EXIT (stat (path, &st) == 0);
> +
> +  support = st.st_atim.tv_nsec == tsp[0].tv_nsec
> +	    && st.st_mtim.tv_nsec == tsp[1].tv_nsec;
> +
> +  /* Reset to original timestamps.  */
> +  const struct timespec otsp[] =
> +  {
> +    { ost.st_atim.tv_sec, ost.st_atim.tv_nsec },
> +    { ost.st_mtim.tv_sec, ost.st_mtim.tv_nsec },
> +  };
> +  TEST_VERIFY_EXIT (utimensat (AT_FDCWD, path, otsp, 0) == 0);
>  #endif
> +  return support;
>  }
> 
OK
  
Adhemerval Zanella Netto March 31, 2021, 8:17 p.m. UTC | #2
On 31/03/2021 04:17, Stefan Liebler wrote:
> On 29/03/2021 19:43, Adhemerval Zanella wrote:
>> Now that non-LFS stat function is implemented on to on LFS, it will
>> use statx when available.  It allows to check for nanosecond timestamp
>> if the kernel supports __NR_statx.
>>
>> Checked on s390-linux-gnu with 4.12.14 kernel.
>> ---
>>  io/tst-stat.c                      |  7 ++++-
>>  support/support.h                  |  2 +-
>>  support/support_stat_nanoseconds.c | 41 +++++++++++++++++++++++++-----
>>  3 files changed, 41 insertions(+), 9 deletions(-)
>>
>> diff --git a/io/tst-stat.c b/io/tst-stat.c
>> index 397d480ecc..22b89bb3e7 100644
>> --- a/io/tst-stat.c
>> +++ b/io/tst-stat.c
>> @@ -25,6 +25,7 @@
>>  #include <support/xunistd.h>
>>  #include <sys/stat.h>
>>  #include <sys/sysmacros.h>
>> +#include <stdio.h>
>>  #include <unistd.h>
>>  
>>  static void
>> @@ -73,6 +74,10 @@ do_test (void)
>>  
>>    test_t tests[] = { stat_check, lstat_check, fstat_check, fstatat_check };
>>  
>> +  bool check_ns = support_stat_nanoseconds (path);
>> +  if (!check_ns)
>> +    printf ("warning: timestamp with nanoseconds not supportted\n");
>> +
>>    for (int i = 0; i < array_length (tests); i++)
>>      {
>>        struct stat st;
>> @@ -92,7 +97,7 @@ do_test (void)
>>  
>>        TEST_COMPARE (stx.stx_ctime.tv_sec, st.st_ctim.tv_sec);
>>        TEST_COMPARE (stx.stx_mtime.tv_sec, st.st_mtim.tv_sec);
>> -      if (support_stat_nanoseconds ())
>> +      if (check_ns)
>>  	{
>>  	  TEST_COMPARE (stx.stx_ctime.tv_nsec, st.st_ctim.tv_nsec);
>>  	  TEST_COMPARE (stx.stx_mtime.tv_nsec, st.st_mtim.tv_nsec);
> OK
> 
>> diff --git a/support/support.h b/support/support.h
>> index b0352726bf..e023d00857 100644
>> --- a/support/support.h
>> +++ b/support/support.h
>> @@ -142,7 +142,7 @@ static __inline bool support_path_support_time64 (const char *path)
>>  }
>>  
>>  /* Return true if stat supports nanoseconds resolution.  */
>> -extern bool support_stat_nanoseconds (void);
>> +extern bool support_stat_nanoseconds (const char *path);
> OK
>>  
>>  __END_DECLS
>>  
>> diff --git a/support/support_stat_nanoseconds.c b/support/support_stat_nanoseconds.c
>> index c0d5b2c3a9..94953c0868 100644
>> --- a/support/support_stat_nanoseconds.c
>> +++ b/support/support_stat_nanoseconds.c
>> @@ -16,16 +16,43 @@
>>     License along with the GNU C Library; if not, see
>>     <https://www.gnu.org/licenses/>.  */
>>  
>> +#include <errno.h>
>> +#include <fcntl.h>
>> +#include <support/check.h>
>> +#include <support/support.h>
>> +#include <support/timespec.h>
>>  #include <stdbool.h>
>> +#include <sys/stat.h>
>> +#include <sys/syscall.h>
> Do we really need syscall.h?

It does not, I will remove it.
  
Paul Eggert March 31, 2021, 9:04 p.m. UTC | #3
On 3/29/21 10:43 AM, Adhemerval Zanella via Libc-alpha wrote:

> +    printf ("warning: timestamp with nanoseconds not supportted\n");

supportted -> supported

I see you installed the patch already, so I took the liberty of 
installing the trivial spelling fix.
  
Adhemerval Zanella Netto April 1, 2021, 11:17 a.m. UTC | #4
On 31/03/2021 18:04, Paul Eggert wrote:
> On 3/29/21 10:43 AM, Adhemerval Zanella via Libc-alpha wrote:
> 
>> +    printf ("warning: timestamp with nanoseconds not supportted\n");
> 
> supportted -> supported
> 
> I see you installed the patch already, so I took the liberty of installing the trivial spelling fix.

Thanks.
  
Joseph Myers April 1, 2021, 4:19 p.m. UTC | #5
This change has broken the build of the testsuite for Hurd.

support_stat_nanoseconds.c: In function 'support_stat_nanoseconds':
support_stat_nanoseconds.c:56:10: error: 'support' is used uninitialized in this function [-Werror=uninitialized]
   56 |   return support;
      |          ^~~~~~~

https://sourceware.org/pipermail/libc-testresults/2021q2/007729.html
  
Adhemerval Zanella Netto April 1, 2021, 4:31 p.m. UTC | #6
> Il giorno 1 apr 2021, alle ore 13:19, Joseph Myers <joseph@codesourcery.com> ha scritto:
> 
> This change has broken the build of the testsuite for Hurd.
> 
> support_stat_nanoseconds.c: In function 'support_stat_nanoseconds':
> support_stat_nanoseconds.c:56:10: error: 'support' is used uninitialized in this function [-Werror=uninitialized]
>   56 |   return support;
>      |          ^~~~~~~

I will fix it.
  

Patch

diff --git a/io/tst-stat.c b/io/tst-stat.c
index 397d480ecc..22b89bb3e7 100644
--- a/io/tst-stat.c
+++ b/io/tst-stat.c
@@ -25,6 +25,7 @@ 
 #include <support/xunistd.h>
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
+#include <stdio.h>
 #include <unistd.h>
 
 static void
@@ -73,6 +74,10 @@  do_test (void)
 
   test_t tests[] = { stat_check, lstat_check, fstat_check, fstatat_check };
 
+  bool check_ns = support_stat_nanoseconds (path);
+  if (!check_ns)
+    printf ("warning: timestamp with nanoseconds not supportted\n");
+
   for (int i = 0; i < array_length (tests); i++)
     {
       struct stat st;
@@ -92,7 +97,7 @@  do_test (void)
 
       TEST_COMPARE (stx.stx_ctime.tv_sec, st.st_ctim.tv_sec);
       TEST_COMPARE (stx.stx_mtime.tv_sec, st.st_mtim.tv_sec);
-      if (support_stat_nanoseconds ())
+      if (check_ns)
 	{
 	  TEST_COMPARE (stx.stx_ctime.tv_nsec, st.st_ctim.tv_nsec);
 	  TEST_COMPARE (stx.stx_mtime.tv_nsec, st.st_mtim.tv_nsec);
diff --git a/support/support.h b/support/support.h
index b0352726bf..e023d00857 100644
--- a/support/support.h
+++ b/support/support.h
@@ -142,7 +142,7 @@  static __inline bool support_path_support_time64 (const char *path)
 }
 
 /* Return true if stat supports nanoseconds resolution.  */
-extern bool support_stat_nanoseconds (void);
+extern bool support_stat_nanoseconds (const char *path);
 
 __END_DECLS
 
diff --git a/support/support_stat_nanoseconds.c b/support/support_stat_nanoseconds.c
index c0d5b2c3a9..94953c0868 100644
--- a/support/support_stat_nanoseconds.c
+++ b/support/support_stat_nanoseconds.c
@@ -16,16 +16,43 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
+#include <fcntl.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/timespec.h>
 #include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 bool
-support_stat_nanoseconds (void)
+support_stat_nanoseconds (const char *path)
 {
-  /* s390 stat64 compat symbol does not support nanoseconds resolution
-     and it used on non-LFS [f,l]stat[at] implementations.  */
-#if defined __linux__ && !defined __s390x__ && defined __s390__
-  return false;
-#else
-  return true;
+  bool support;
+#ifdef __linux__
+  /* Obtain the original timestamp to restore at the end.  */
+  struct stat ost;
+  TEST_VERIFY_EXIT (stat (path, &ost) == 0);
+
+  const struct timespec tsp[] = { { 0, TIMESPEC_HZ - 1 },
+				  { 0, TIMESPEC_HZ / 2 } };
+  TEST_VERIFY_EXIT (utimensat (AT_FDCWD, path, tsp, 0) == 0);
+
+  struct stat st;
+  TEST_VERIFY_EXIT (stat (path, &st) == 0);
+
+  support = st.st_atim.tv_nsec == tsp[0].tv_nsec
+	    && st.st_mtim.tv_nsec == tsp[1].tv_nsec;
+
+  /* Reset to original timestamps.  */
+  const struct timespec otsp[] =
+  {
+    { ost.st_atim.tv_sec, ost.st_atim.tv_nsec },
+    { ost.st_mtim.tv_sec, ost.st_mtim.tv_nsec },
+  };
+  TEST_VERIFY_EXIT (utimensat (AT_FDCWD, path, otsp, 0) == 0);
 #endif
+  return support;
 }