* [RFC] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps @ 2021-03-11 12:35 Adhemerval Zanella 2021-03-11 15:08 ` Christoph Hellwig 2021-03-11 15:32 ` [RFC] " Lukasz Majewski 0 siblings, 2 replies; 6+ messages in thread From: Adhemerval Zanella @ 2021-03-11 12:35 UTC (permalink / raw) To: libc-alpha Cc: Florian Weimer, Mike Frysinger, DJ Delorie, Arjun Shankar, Lukasz Majewski Some Linux filesystems might not fully support 64 bit timestamps [1], which make some Linux specific tests to fail when they check for the functionality. This patch make them return as 'unsupported' is the target file is created on a buggy filesystem: $ dd if=/dev/zero of=loopbackfile.img bs=100M count=1 1+0 records in 1+0 records out 104857600 bytes (105 MB, 100 MiB) copied, 0,0589568 s, 1,8 GB/s $ sudo losetup -fP loopbackfile.img $ mkfs.xfs loopbackfile.img meta-data=loopbackfile.img isize=512 agcount=4, agsize=6400 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 data = bsize=4096 blocks=25600, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=1368, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 $ mkdir loopfs $ sudo mount -o loop /dev/loop0 loopfs/ $ sudo chown -R azanella:azanella loopfs $ TMPDIR=loopfs/ ./testrun.sh misc/tst-utimes error: ../sysdeps/unix/sysv/linux/tst-utimes.c:55: File loopfs//utimesfECsK1 does not support 64-bit timestamps [1] https://bugzilla.redhat.com/show_bug.cgi?id=1795576 --- support/Makefile | 1 + support/support.h | 5 ++++ support/support_path_support_time64.c | 38 ++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/tst-futimens.c | 8 +++++- sysdeps/unix/sysv/linux/tst-utime.c | 7 ++++- sysdeps/unix/sysv/linux/tst-utimes.c | 7 ++++- 6 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 support/support_path_support_time64.c diff --git a/support/Makefile b/support/Makefile index 8d63fbd5da..5904cdd412 100644 --- a/support/Makefile +++ b/support/Makefile @@ -59,6 +59,7 @@ libsupport-routines = \ support_format_hostent \ support_format_netent \ support_isolate_in_subprocess \ + support_path_support_time64 \ support_process_state \ support_ptrace \ support_openpty \ diff --git a/support/support.h b/support/support.h index 9cbc455720..2e477c9e7c 100644 --- a/support/support.h +++ b/support/support.h @@ -23,6 +23,7 @@ #ifndef SUPPORT_H #define SUPPORT_H +#include <stdbool.h> #include <stddef.h> #include <sys/cdefs.h> /* For mode_t. */ @@ -129,6 +130,10 @@ extern void support_copy_file (const char *from, const char *to); extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, size_t, unsigned int); +/* Return true is PATH supports 64-bit time_t interfaces for file + operations (such as fstatat or utimensat). */ +extern bool support_path_support_time64 (const char *path); + __END_DECLS #endif /* SUPPORT_H */ diff --git a/support/support_path_support_time64.c b/support/support_path_support_time64.c new file mode 100644 index 0000000000..c780dcd4aa --- /dev/null +++ b/support/support_path_support_time64.c @@ -0,0 +1,38 @@ +/* Check if path supports 64-bit time interfaces. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <support/check.h> +#include <support/support.h> +#include <sys/vfs.h> +#ifdef __linux +#include <linux_fsinfo.h> +#endif + +bool +support_path_support_time64 (const char *path) +{ +#ifdef __linux__ + struct statfs64 fs; + if (statfs64 (path, &fs) < 0) + FAIL_EXIT1 ("statfs64 (\"%s\"): %m", path); + /* Kernel silent truncate metadata timestamps on some version. */ + return ! (fs.f_type == XFS_SUPER_MAGIC); +#else + return true; +#endif +} diff --git a/sysdeps/unix/sysv/linux/tst-futimens.c b/sysdeps/unix/sysv/linux/tst-futimens.c index 8f48cfee63..785cd87557 100644 --- a/sysdeps/unix/sysv/linux/tst-futimens.c +++ b/sysdeps/unix/sysv/linux/tst-futimens.c @@ -21,10 +21,12 @@ #include <stdlib.h> #include <sys/stat.h> #include <support/check.h> +#include <support/support.h> #include <support/xunistd.h> #include <support/temp_file.h> static int temp_fd = -1; +static char *testfile; /* struct timespec array with Y2038 threshold minus 2 and 1 seconds. */ const struct timespec t1[2] = { { 0x7FFFFFFE, 0 }, { 0x7FFFFFFF, 0 } }; @@ -39,13 +41,17 @@ const struct timespec t3[2] = { { 0x7FFFFFFE, 0 }, { 0x80000002ULL, 0 } }; static void do_prepare (int argc, char *argv[]) { - temp_fd = create_temp_file ("futimensat", NULL); + temp_fd = create_temp_file ("futimensat", &testfile); TEST_VERIFY_EXIT (temp_fd > 0); } static int test_futimens_helper (const struct timespec *ts) { + if (!support_path_support_time64 (testfile)) + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", + testfile); + struct stat64 st; int result; time_t t; diff --git a/sysdeps/unix/sysv/linux/tst-utime.c b/sysdeps/unix/sysv/linux/tst-utime.c index 6735421657..21e4e41dea 100644 --- a/sysdeps/unix/sysv/linux/tst-utime.c +++ b/sysdeps/unix/sysv/linux/tst-utime.c @@ -23,11 +23,12 @@ #include <sys/types.h> #include <utime.h> #include <support/check.h> +#include <support/support.h> #include <support/xunistd.h> #include <support/temp_file.h> static int temp_fd = -1; -char *testfile; +static char *testfile; /* struct utimbuf with Y2038 threshold minus 2 and 1 seconds. */ const static struct utimbuf t1 = { 0x7FFFFFFE, 0x7FFFFFFF }; @@ -49,6 +50,10 @@ do_prepare (int argc, char *argv[]) static int test_utime_helper (const struct utimbuf *ut) { + if (!support_path_support_time64 (testfile)) + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", + testfile); + struct stat64 st; int result; time_t t; diff --git a/sysdeps/unix/sysv/linux/tst-utimes.c b/sysdeps/unix/sysv/linux/tst-utimes.c index 8c7b006a22..0f23e44897 100644 --- a/sysdeps/unix/sysv/linux/tst-utimes.c +++ b/sysdeps/unix/sysv/linux/tst-utimes.c @@ -22,11 +22,12 @@ #include <sys/stat.h> #include <sys/time.h> #include <support/check.h> +#include <support/support.h> #include <support/xunistd.h> #include <support/temp_file.h> static int temp_fd = -1; -char *testfile; +static char *testfile; /* struct timeval array with Y2038 threshold minus 2 and 1 seconds. */ const static struct timeval t1[2] = { { 0x7FFFFFFE, 0 }, { 0x7FFFFFFF, 0 } }; @@ -50,6 +51,10 @@ do_prepare (int argc, char *argv[]) static int test_utime_helper (const struct timeval *tv) { + if (!support_path_support_time64 (testfile)) + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", + testfile); + struct stat64 st; int result; time_t t; -- 2.25.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps 2021-03-11 12:35 [RFC] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps Adhemerval Zanella @ 2021-03-11 15:08 ` Christoph Hellwig 2021-03-11 17:20 ` Adhemerval Zanella 2021-03-11 15:32 ` [RFC] " Lukasz Majewski 1 sibling, 1 reply; 6+ messages in thread From: Christoph Hellwig @ 2021-03-11 15:08 UTC (permalink / raw) To: Adhemerval Zanella; +Cc: libc-alpha, Florian Weimer On Thu, Mar 11, 2021 at 09:35:57AM -0300, Adhemerval Zanella via Libc-alpha wrote: > +bool > +support_path_support_time64 (const char *path) > +{ > +#ifdef __linux__ > + struct statfs64 fs; > + if (statfs64 (path, &fs) < 0) > + FAIL_EXIT1 ("statfs64 (\"%s\"): %m", path); > + /* Kernel silent truncate metadata timestamps on some version. */ > + return ! (fs.f_type == XFS_SUPER_MAGIC); Please check for the actual truncation, as XFS does not always do this based on the exact on-disk format revision. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps 2021-03-11 15:08 ` Christoph Hellwig @ 2021-03-11 17:20 ` Adhemerval Zanella 2021-03-11 19:29 ` [RFC v2] " Adhemerval Zanella 0 siblings, 1 reply; 6+ messages in thread From: Adhemerval Zanella @ 2021-03-11 17:20 UTC (permalink / raw) To: Christoph Hellwig; +Cc: libc-alpha, Florian Weimer On 11/03/2021 12:08, Christoph Hellwig wrote: > On Thu, Mar 11, 2021 at 09:35:57AM -0300, Adhemerval Zanella via Libc-alpha wrote: >> +bool >> +support_path_support_time64 (const char *path) >> +{ >> +#ifdef __linux__ >> + struct statfs64 fs; >> + if (statfs64 (path, &fs) < 0) >> + FAIL_EXIT1 ("statfs64 (\"%s\"): %m", path); >> + /* Kernel silent truncate metadata timestamps on some version. */ >> + return ! (fs.f_type == XFS_SUPER_MAGIC); > > Please check for the actual truncation, as XFS does not always do > this based on the exact on-disk format revision. > It would require to emulate a syscall that sets/reset some timestamp on the filsystem without using the glibc interfaces (since we are working on providing y2038 support for old ABI with 32-bit time as default). I will check out a better to way to do it, but this ad-hoc solution is just to be more friendly on system with buggy filesystem. My preferred personal solution is let the tests fail and warn the tests something is wrong. ^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC v2] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps 2021-03-11 17:20 ` Adhemerval Zanella @ 2021-03-11 19:29 ` Adhemerval Zanella 2021-03-11 23:06 ` Carlos O'Donell 0 siblings, 1 reply; 6+ messages in thread From: Adhemerval Zanella @ 2021-03-11 19:29 UTC (permalink / raw) To: libc-alpha Some Linux filesystems might not fully support 64 bit timestamps [1], which make some Linux specific tests to fail when they check for the functionality. This patch adds a new libsupport functions, support_path_support_time64, that returns whether the target file supports or not 64 bit timestamps. The support is checked by issuing a utimensat and verifying both the last access and last modification time against a statx call. The tests that might fail are also adjusted to check the file support as well: $ dd if=/dev/zero of=loopbackfile.img bs=100M count=1 1+0 records in 1+0 records out 104857600 bytes (105 MB, 100 MiB) copied, 0,0589568 s, 1,8 GB/s $ sudo losetup -fP loopbackfile.img $ mkfs.xfs loopbackfile.img meta-data=loopbackfile.img isize=512 agcount=4, agsize=6400 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 data = bsize=4096 blocks=25600, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=1368, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 $ mkdir loopfs $ sudo mount -o loop /dev/loop0 loopfs/ $ sudo chown -R azanella:azanella loopfs $ TMPDIR=loopfs/ ./testrun.sh misc/tst-utimes error: ../sysdeps/unix/sysv/linux/tst-utimes.c:55: File loopfs//utimesfECsK1 does not support 64-bit timestamps [1] https://bugzilla.redhat.com/show_bug.cgi?id=1795576 --- support/Makefile | 1 + support/support.h | 5 ++ support/support_path_support_time64.c | 76 ++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/tst-futimens.c | 8 ++- sysdeps/unix/sysv/linux/tst-utime.c | 7 ++- sysdeps/unix/sysv/linux/tst-utimes.c | 7 ++- 6 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 support/support_path_support_time64.c diff --git a/support/Makefile b/support/Makefile index 8d63fbd5da..5904cdd412 100644 --- a/support/Makefile +++ b/support/Makefile @@ -59,6 +59,7 @@ libsupport-routines = \ support_format_hostent \ support_format_netent \ support_isolate_in_subprocess \ + support_path_support_time64 \ support_process_state \ support_ptrace \ support_openpty \ diff --git a/support/support.h b/support/support.h index 9cbc455720..2e477c9e7c 100644 --- a/support/support.h +++ b/support/support.h @@ -23,6 +23,7 @@ #ifndef SUPPORT_H #define SUPPORT_H +#include <stdbool.h> #include <stddef.h> #include <sys/cdefs.h> /* For mode_t. */ @@ -129,6 +130,10 @@ extern void support_copy_file (const char *from, const char *to); extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, size_t, unsigned int); +/* Return true is PATH supports 64-bit time_t interfaces for file + operations (such as fstatat or utimensat). */ +extern bool support_path_support_time64 (const char *path); + __END_DECLS #endif /* SUPPORT_H */ diff --git a/support/support_path_support_time64.c b/support/support_path_support_time64.c new file mode 100644 index 0000000000..74af7d4973 --- /dev/null +++ b/support/support_path_support_time64.c @@ -0,0 +1,76 @@ +/* Check if path supports 64-bit time interfaces. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <fcntl.h> +#include <support/check.h> +#include <support/support.h> +#include <sys/stat.h> +#ifdef __linux__ +#include <sysdep.h> +#endif + +#ifdef __linux__ +static int +utimesat_call (const char *path, const struct __timespec64 tsp[2]) +{ +# ifndef __NR_utimensat_time64 +# define __NR_utimensat_time64 __NR_utimensat +# endif + return INLINE_SYSCALL_CALL (utimensat_time64, AT_FDCWD, path, &tsp[0], 0); +} +#endif + +bool +support_path_support_time64 (const char *path) +{ +#ifdef __linux__ + /* Obtain the original timestamps to restore at the end. */ + struct statx ostx; + TEST_VERIFY_EXIT (statx (AT_FDCWD, path, 0, STATX_BASIC_STATS, &ostx) == 0); + + const struct __timespec64 tsp[] = + { + /* 1s and 2s after y2038 limit. */ + { 0x80000001ULL, 0 }, + { 0x80000002ULL, 0 } + }; + /* Return is kernel does not support __NR_utimensat_time64. */ + if (utimesat_call (path, tsp) == -1) + return false; + + /* Verify if the last access and last modification time match the ones + obtained with statx. */ + struct statx stx; + TEST_VERIFY_EXIT (statx (AT_FDCWD, path, 0, STATX_BASIC_STATS, &stx) == 0); + + bool support = stx.stx_atime.tv_sec == tsp[0].tv_sec + && stx.stx_mtime.tv_sec == tsp[1].tv_sec; + + /* Reset to original timestamps. */ + const struct __timespec64 otsp[] = + { + { ostx.stx_atime.tv_sec, ostx.stx_atime.tv_nsec }, + { ostx.stx_mtime.tv_sec, ostx.stx_mtime.tv_nsec }, + }; + TEST_VERIFY_EXIT (utimesat_call (path, otsp) == 0); + + return support; +#else + return true; +#endif +} diff --git a/sysdeps/unix/sysv/linux/tst-futimens.c b/sysdeps/unix/sysv/linux/tst-futimens.c index 8f48cfee63..785cd87557 100644 --- a/sysdeps/unix/sysv/linux/tst-futimens.c +++ b/sysdeps/unix/sysv/linux/tst-futimens.c @@ -21,10 +21,12 @@ #include <stdlib.h> #include <sys/stat.h> #include <support/check.h> +#include <support/support.h> #include <support/xunistd.h> #include <support/temp_file.h> static int temp_fd = -1; +static char *testfile; /* struct timespec array with Y2038 threshold minus 2 and 1 seconds. */ const struct timespec t1[2] = { { 0x7FFFFFFE, 0 }, { 0x7FFFFFFF, 0 } }; @@ -39,13 +41,17 @@ const struct timespec t3[2] = { { 0x7FFFFFFE, 0 }, { 0x80000002ULL, 0 } }; static void do_prepare (int argc, char *argv[]) { - temp_fd = create_temp_file ("futimensat", NULL); + temp_fd = create_temp_file ("futimensat", &testfile); TEST_VERIFY_EXIT (temp_fd > 0); } static int test_futimens_helper (const struct timespec *ts) { + if (!support_path_support_time64 (testfile)) + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", + testfile); + struct stat64 st; int result; time_t t; diff --git a/sysdeps/unix/sysv/linux/tst-utime.c b/sysdeps/unix/sysv/linux/tst-utime.c index 6735421657..21e4e41dea 100644 --- a/sysdeps/unix/sysv/linux/tst-utime.c +++ b/sysdeps/unix/sysv/linux/tst-utime.c @@ -23,11 +23,12 @@ #include <sys/types.h> #include <utime.h> #include <support/check.h> +#include <support/support.h> #include <support/xunistd.h> #include <support/temp_file.h> static int temp_fd = -1; -char *testfile; +static char *testfile; /* struct utimbuf with Y2038 threshold minus 2 and 1 seconds. */ const static struct utimbuf t1 = { 0x7FFFFFFE, 0x7FFFFFFF }; @@ -49,6 +50,10 @@ do_prepare (int argc, char *argv[]) static int test_utime_helper (const struct utimbuf *ut) { + if (!support_path_support_time64 (testfile)) + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", + testfile); + struct stat64 st; int result; time_t t; diff --git a/sysdeps/unix/sysv/linux/tst-utimes.c b/sysdeps/unix/sysv/linux/tst-utimes.c index 8c7b006a22..0f23e44897 100644 --- a/sysdeps/unix/sysv/linux/tst-utimes.c +++ b/sysdeps/unix/sysv/linux/tst-utimes.c @@ -22,11 +22,12 @@ #include <sys/stat.h> #include <sys/time.h> #include <support/check.h> +#include <support/support.h> #include <support/xunistd.h> #include <support/temp_file.h> static int temp_fd = -1; -char *testfile; +static char *testfile; /* struct timeval array with Y2038 threshold minus 2 and 1 seconds. */ const static struct timeval t1[2] = { { 0x7FFFFFFE, 0 }, { 0x7FFFFFFF, 0 } }; @@ -50,6 +51,10 @@ do_prepare (int argc, char *argv[]) static int test_utime_helper (const struct timeval *tv) { + if (!support_path_support_time64 (testfile)) + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", + testfile); + struct stat64 st; int result; time_t t; -- 2.25.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC v2] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps 2021-03-11 19:29 ` [RFC v2] " Adhemerval Zanella @ 2021-03-11 23:06 ` Carlos O'Donell 0 siblings, 0 replies; 6+ messages in thread From: Carlos O'Donell @ 2021-03-11 23:06 UTC (permalink / raw) To: Adhemerval Zanella, libc-alpha On 3/11/21 2:29 PM, Adhemerval Zanella via Libc-alpha wrote: > Some Linux filesystems might not fully support 64 bit timestamps [1], > which make some Linux specific tests to fail when they check for the > functionality. LGTM. Reviewed-by: Carlos O'Donell <carlos@redhat.com> > This patch adds a new libsupport functions, support_path_support_time64, > that returns whether the target file supports or not 64 bit timestamps. > The support is checked by issuing a utimensat and verifying both the > last access and last modification time against a statx call. > > The tests that might fail are also adjusted to check the file support > as well: > > $ dd if=/dev/zero of=loopbackfile.img bs=100M count=1 > 1+0 records in > 1+0 records out > 104857600 bytes (105 MB, 100 MiB) copied, 0,0589568 s, 1,8 GB/s > $ sudo losetup -fP loopbackfile.img > $ mkfs.xfs loopbackfile.img > meta-data=loopbackfile.img isize=512 agcount=4, agsize=6400 blks > = sectsz=512 attr=2, projid32bit=1 > = crc=1 finobt=1, sparse=1, rmapbt=0 > = reflink=1 > data = bsize=4096 blocks=25600, imaxpct=25 > = sunit=0 swidth=0 blks > naming =version 2 bsize=4096 ascii-ci=0, ftype=1 > log =internal log bsize=4096 blocks=1368, version=2 > = sectsz=512 sunit=0 blks, lazy-count=1 > realtime =none extsz=4096 blocks=0, rtextents=0 > $ mkdir loopfs > $ sudo mount -o loop /dev/loop0 loopfs/ > $ sudo chown -R azanella:azanella loopfs > $ TMPDIR=loopfs/ ./testrun.sh misc/tst-utimes > error: ../sysdeps/unix/sysv/linux/tst-utimes.c:55: File loopfs//utimesfECsK1 does not support 64-bit timestamps > > [1] https://bugzilla.redhat.com/show_bug.cgi?id=1795576 > --- > support/Makefile | 1 + > support/support.h | 5 ++ > support/support_path_support_time64.c | 76 ++++++++++++++++++++++++++ > sysdeps/unix/sysv/linux/tst-futimens.c | 8 ++- > sysdeps/unix/sysv/linux/tst-utime.c | 7 ++- > sysdeps/unix/sysv/linux/tst-utimes.c | 7 ++- > 6 files changed, 101 insertions(+), 3 deletions(-) > create mode 100644 support/support_path_support_time64.c > > diff --git a/support/Makefile b/support/Makefile > index 8d63fbd5da..5904cdd412 100644 > --- a/support/Makefile > +++ b/support/Makefile > @@ -59,6 +59,7 @@ libsupport-routines = \ > support_format_hostent \ > support_format_netent \ > support_isolate_in_subprocess \ > + support_path_support_time64 \ > support_process_state \ > support_ptrace \ > support_openpty \ > diff --git a/support/support.h b/support/support.h > index 9cbc455720..2e477c9e7c 100644 > --- a/support/support.h > +++ b/support/support.h > @@ -23,6 +23,7 @@ > #ifndef SUPPORT_H > #define SUPPORT_H > > +#include <stdbool.h> > #include <stddef.h> > #include <sys/cdefs.h> > /* For mode_t. */ > @@ -129,6 +130,10 @@ extern void support_copy_file (const char *from, const char *to); > extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, > size_t, unsigned int); > > +/* Return true is PATH supports 64-bit time_t interfaces for file > + operations (such as fstatat or utimensat). */ > +extern bool support_path_support_time64 (const char *path); > + > __END_DECLS > > #endif /* SUPPORT_H */ > diff --git a/support/support_path_support_time64.c b/support/support_path_support_time64.c > new file mode 100644 > index 0000000000..74af7d4973 > --- /dev/null > +++ b/support/support_path_support_time64.c > @@ -0,0 +1,76 @@ > +/* Check if path supports 64-bit time interfaces. > + Copyright (C) 2021 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <fcntl.h> > +#include <support/check.h> > +#include <support/support.h> > +#include <sys/stat.h> > +#ifdef __linux__ > +#include <sysdep.h> > +#endif > + > +#ifdef __linux__ > +static int > +utimesat_call (const char *path, const struct __timespec64 tsp[2]) > +{ > +# ifndef __NR_utimensat_time64 > +# define __NR_utimensat_time64 __NR_utimensat > +# endif > + return INLINE_SYSCALL_CALL (utimensat_time64, AT_FDCWD, path, &tsp[0], 0); > +} > +#endif > + > +bool > +support_path_support_time64 (const char *path) > +{ > +#ifdef __linux__ > + /* Obtain the original timestamps to restore at the end. */ > + struct statx ostx; > + TEST_VERIFY_EXIT (statx (AT_FDCWD, path, 0, STATX_BASIC_STATS, &ostx) == 0); > + > + const struct __timespec64 tsp[] = > + { > + /* 1s and 2s after y2038 limit. */ > + { 0x80000001ULL, 0 }, > + { 0x80000002ULL, 0 } > + }; > + /* Return is kernel does not support __NR_utimensat_time64. */ > + if (utimesat_call (path, tsp) == -1) > + return false; > + > + /* Verify if the last access and last modification time match the ones > + obtained with statx. */ > + struct statx stx; > + TEST_VERIFY_EXIT (statx (AT_FDCWD, path, 0, STATX_BASIC_STATS, &stx) == 0); > + > + bool support = stx.stx_atime.tv_sec == tsp[0].tv_sec > + && stx.stx_mtime.tv_sec == tsp[1].tv_sec; > + > + /* Reset to original timestamps. */ > + const struct __timespec64 otsp[] = > + { > + { ostx.stx_atime.tv_sec, ostx.stx_atime.tv_nsec }, > + { ostx.stx_mtime.tv_sec, ostx.stx_mtime.tv_nsec }, > + }; > + TEST_VERIFY_EXIT (utimesat_call (path, otsp) == 0); > + > + return support; > +#else > + return true; > +#endif > +} > diff --git a/sysdeps/unix/sysv/linux/tst-futimens.c b/sysdeps/unix/sysv/linux/tst-futimens.c > index 8f48cfee63..785cd87557 100644 > --- a/sysdeps/unix/sysv/linux/tst-futimens.c > +++ b/sysdeps/unix/sysv/linux/tst-futimens.c > @@ -21,10 +21,12 @@ > #include <stdlib.h> > #include <sys/stat.h> > #include <support/check.h> > +#include <support/support.h> > #include <support/xunistd.h> > #include <support/temp_file.h> > > static int temp_fd = -1; > +static char *testfile; > > /* struct timespec array with Y2038 threshold minus 2 and 1 seconds. */ > const struct timespec t1[2] = { { 0x7FFFFFFE, 0 }, { 0x7FFFFFFF, 0 } }; > @@ -39,13 +41,17 @@ const struct timespec t3[2] = { { 0x7FFFFFFE, 0 }, { 0x80000002ULL, 0 } }; > static void > do_prepare (int argc, char *argv[]) > { > - temp_fd = create_temp_file ("futimensat", NULL); > + temp_fd = create_temp_file ("futimensat", &testfile); > TEST_VERIFY_EXIT (temp_fd > 0); > } > > static int > test_futimens_helper (const struct timespec *ts) > { > + if (!support_path_support_time64 (testfile)) > + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", > + testfile); OK. XFAIL thes test. > + > struct stat64 st; > int result; > time_t t; > diff --git a/sysdeps/unix/sysv/linux/tst-utime.c b/sysdeps/unix/sysv/linux/tst-utime.c > index 6735421657..21e4e41dea 100644 > --- a/sysdeps/unix/sysv/linux/tst-utime.c > +++ b/sysdeps/unix/sysv/linux/tst-utime.c > @@ -23,11 +23,12 @@ > #include <sys/types.h> > #include <utime.h> > #include <support/check.h> > +#include <support/support.h> > #include <support/xunistd.h> > #include <support/temp_file.h> > > static int temp_fd = -1; > -char *testfile; > +static char *testfile; > > /* struct utimbuf with Y2038 threshold minus 2 and 1 seconds. */ > const static struct utimbuf t1 = { 0x7FFFFFFE, 0x7FFFFFFF }; > @@ -49,6 +50,10 @@ do_prepare (int argc, char *argv[]) > static int > test_utime_helper (const struct utimbuf *ut) > { > + if (!support_path_support_time64 (testfile)) > + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", > + testfile); OK. XFAIL the test. > + > struct stat64 st; > int result; > time_t t; > diff --git a/sysdeps/unix/sysv/linux/tst-utimes.c b/sysdeps/unix/sysv/linux/tst-utimes.c > index 8c7b006a22..0f23e44897 100644 > --- a/sysdeps/unix/sysv/linux/tst-utimes.c > +++ b/sysdeps/unix/sysv/linux/tst-utimes.c > @@ -22,11 +22,12 @@ > #include <sys/stat.h> > #include <sys/time.h> > #include <support/check.h> > +#include <support/support.h> > #include <support/xunistd.h> > #include <support/temp_file.h> > > static int temp_fd = -1; > -char *testfile; > +static char *testfile; > > /* struct timeval array with Y2038 threshold minus 2 and 1 seconds. */ > const static struct timeval t1[2] = { { 0x7FFFFFFE, 0 }, { 0x7FFFFFFF, 0 } }; > @@ -50,6 +51,10 @@ do_prepare (int argc, char *argv[]) > static int > test_utime_helper (const struct timeval *tv) > { > + if (!support_path_support_time64 (testfile)) > + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", > + testfile); OK. XFAIL the test. > + > struct stat64 st; > int result; > time_t t; > -- Cheers, Carlos. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps 2021-03-11 12:35 [RFC] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps Adhemerval Zanella 2021-03-11 15:08 ` Christoph Hellwig @ 2021-03-11 15:32 ` Lukasz Majewski 1 sibling, 0 replies; 6+ messages in thread From: Lukasz Majewski @ 2021-03-11 15:32 UTC (permalink / raw) To: Adhemerval Zanella Cc: libc-alpha, Florian Weimer, Mike Frysinger, DJ Delorie, Arjun Shankar [-- Attachment #1: Type: text/plain, Size: 8623 bytes --] On Thu, 11 Mar 2021 09:35:57 -0300 Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote: > Some Linux filesystems might not fully support 64 bit timestamps [1], > which make some Linux specific tests to fail when they check for the > functionality. > > This patch make them return as 'unsupported' is the target file is > created on a buggy filesystem: > > $ dd if=/dev/zero of=loopbackfile.img bs=100M count=1 > 1+0 records in > 1+0 records out > 104857600 bytes (105 MB, 100 MiB) copied, 0,0589568 s, 1,8 GB/s > $ sudo losetup -fP loopbackfile.img > $ mkfs.xfs loopbackfile.img > meta-data=loopbackfile.img isize=512 agcount=4, > agsize=6400 blks = sectsz=512 attr=2, > projid32bit=1 = crc=1 finobt=1, > sparse=1, rmapbt=0 = reflink=1 > data = bsize=4096 blocks=25600, > imaxpct=25 = sunit=0 swidth=0 blks > naming =version 2 bsize=4096 ascii-ci=0, ftype=1 > log =internal log bsize=4096 blocks=1368, version=2 > = sectsz=512 sunit=0 blks, > lazy-count=1 realtime =none extsz=4096 blocks=0, > rtextents=0 $ mkdir loopfs > $ sudo mount -o loop /dev/loop0 loopfs/ > $ sudo chown -R azanella:azanella loopfs > $ TMPDIR=loopfs/ ./testrun.sh misc/tst-utimes > error: ../sysdeps/unix/sysv/linux/tst-utimes.c:55: File > loopfs//utimesfECsK1 does not support 64-bit timestamps > > [1] https://bugzilla.redhat.com/show_bug.cgi?id=1795576 > --- > support/Makefile | 1 + > support/support.h | 5 ++++ > support/support_path_support_time64.c | 38 > ++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/tst-futimens.c | > 8 +++++- sysdeps/unix/sysv/linux/tst-utime.c | 7 ++++- > sysdeps/unix/sysv/linux/tst-utimes.c | 7 ++++- > 6 files changed, 63 insertions(+), 3 deletions(-) > create mode 100644 support/support_path_support_time64.c > > diff --git a/support/Makefile b/support/Makefile > index 8d63fbd5da..5904cdd412 100644 > --- a/support/Makefile > +++ b/support/Makefile > @@ -59,6 +59,7 @@ libsupport-routines = \ > support_format_hostent \ > support_format_netent \ > support_isolate_in_subprocess \ > + support_path_support_time64 \ > support_process_state \ > support_ptrace \ > support_openpty \ > diff --git a/support/support.h b/support/support.h > index 9cbc455720..2e477c9e7c 100644 > --- a/support/support.h > +++ b/support/support.h > @@ -23,6 +23,7 @@ > #ifndef SUPPORT_H > #define SUPPORT_H > > +#include <stdbool.h> > #include <stddef.h> > #include <sys/cdefs.h> > /* For mode_t. */ > @@ -129,6 +130,10 @@ extern void support_copy_file (const char *from, > const char *to); extern ssize_t support_copy_file_range (int, off64_t > *, int, off64_t *, size_t, unsigned int); > > +/* Return true is PATH supports 64-bit time_t interfaces for file > + operations (such as fstatat or utimensat). */ > +extern bool support_path_support_time64 (const char *path); > + > __END_DECLS > > #endif /* SUPPORT_H */ > diff --git a/support/support_path_support_time64.c > b/support/support_path_support_time64.c new file mode 100644 > index 0000000000..c780dcd4aa > --- /dev/null > +++ b/support/support_path_support_time64.c > @@ -0,0 +1,38 @@ > +/* Check if path supports 64-bit time interfaces. > + Copyright (C) 2021 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be > useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <support/check.h> > +#include <support/support.h> > +#include <sys/vfs.h> > +#ifdef __linux > +#include <linux_fsinfo.h> > +#endif > + > +bool > +support_path_support_time64 (const char *path) > +{ > +#ifdef __linux__ > + struct statfs64 fs; > + if (statfs64 (path, &fs) < 0) > + FAIL_EXIT1 ("statfs64 (\"%s\"): %m", path); > + /* Kernel silent truncate metadata timestamps on some version. */ > + return ! (fs.f_type == XFS_SUPER_MAGIC); > +#else > + return true; > +#endif > +} > diff --git a/sysdeps/unix/sysv/linux/tst-futimens.c > b/sysdeps/unix/sysv/linux/tst-futimens.c index 8f48cfee63..785cd87557 > 100644 --- a/sysdeps/unix/sysv/linux/tst-futimens.c > +++ b/sysdeps/unix/sysv/linux/tst-futimens.c > @@ -21,10 +21,12 @@ > #include <stdlib.h> > #include <sys/stat.h> > #include <support/check.h> > +#include <support/support.h> > #include <support/xunistd.h> > #include <support/temp_file.h> > > static int temp_fd = -1; > +static char *testfile; > > /* struct timespec array with Y2038 threshold minus 2 and 1 seconds. > */ const struct timespec t1[2] = { { 0x7FFFFFFE, 0 }, { 0x7FFFFFFF, > 0 } }; @@ -39,13 +41,17 @@ const struct timespec t3[2] = { { > 0x7FFFFFFE, 0 }, { 0x80000002ULL, 0 } }; static void > do_prepare (int argc, char *argv[]) > { > - temp_fd = create_temp_file ("futimensat", NULL); > + temp_fd = create_temp_file ("futimensat", &testfile); > TEST_VERIFY_EXIT (temp_fd > 0); > } > > static int > test_futimens_helper (const struct timespec *ts) > { > + if (!support_path_support_time64 (testfile)) > + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", > + testfile); > + > struct stat64 st; > int result; > time_t t; > diff --git a/sysdeps/unix/sysv/linux/tst-utime.c > b/sysdeps/unix/sysv/linux/tst-utime.c index 6735421657..21e4e41dea > 100644 --- a/sysdeps/unix/sysv/linux/tst-utime.c > +++ b/sysdeps/unix/sysv/linux/tst-utime.c > @@ -23,11 +23,12 @@ > #include <sys/types.h> > #include <utime.h> > #include <support/check.h> > +#include <support/support.h> > #include <support/xunistd.h> > #include <support/temp_file.h> > > static int temp_fd = -1; > -char *testfile; > +static char *testfile; > > /* struct utimbuf with Y2038 threshold minus 2 and 1 seconds. */ > const static struct utimbuf t1 = { 0x7FFFFFFE, 0x7FFFFFFF }; > @@ -49,6 +50,10 @@ do_prepare (int argc, char *argv[]) > static int > test_utime_helper (const struct utimbuf *ut) > { > + if (!support_path_support_time64 (testfile)) > + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", > + testfile); > + > struct stat64 st; > int result; > time_t t; > diff --git a/sysdeps/unix/sysv/linux/tst-utimes.c > b/sysdeps/unix/sysv/linux/tst-utimes.c index 8c7b006a22..0f23e44897 > 100644 --- a/sysdeps/unix/sysv/linux/tst-utimes.c > +++ b/sysdeps/unix/sysv/linux/tst-utimes.c > @@ -22,11 +22,12 @@ > #include <sys/stat.h> > #include <sys/time.h> > #include <support/check.h> > +#include <support/support.h> > #include <support/xunistd.h> > #include <support/temp_file.h> > > static int temp_fd = -1; > -char *testfile; > +static char *testfile; > > /* struct timeval array with Y2038 threshold minus 2 and 1 seconds. > */ const static struct timeval t1[2] = { { 0x7FFFFFFE, 0 }, { > 0x7FFFFFFF, 0 } }; @@ -50,6 +51,10 @@ do_prepare (int argc, char > *argv[]) static int > test_utime_helper (const struct timeval *tv) > { > + if (!support_path_support_time64 (testfile)) > + FAIL_UNSUPPORTED ("File %s does not support 64-bit timestamps", > + testfile); > + > struct stat64 st; > int result; > time_t t; Approach proposed in this patch seems to be logical, as those tests shall simply be "UNSUPPORTED" when called on FS not supporting 64 bit time_t. Reviewed-by: Lukasz Majewski <lukma@denx.de> Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-03-11 23:06 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-03-11 12:35 [RFC] io: Return UNSUPPORTED if filesystem do not support 64 bit timestamps Adhemerval Zanella 2021-03-11 15:08 ` Christoph Hellwig 2021-03-11 17:20 ` Adhemerval Zanella 2021-03-11 19:29 ` [RFC v2] " Adhemerval Zanella 2021-03-11 23:06 ` Carlos O'Donell 2021-03-11 15:32 ` [RFC] " Lukasz Majewski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).