The comment asserting that the value of struct statx_timestamp.tv_nsec must be negative when statx_timestamp.tv_sec is negative, is wrong, as could be seen from the following example: #define _FILE_OFFSET_BITS 64 #include <assert.h> #include <fcntl.h> #include <stdio.h> #include <sys/stat.h> #include <unistd.h> #include <asm/unistd.h> #include <linux/stat.h> int main(void) { static const struct timespec ts[2] = { { .tv_nsec = UTIME_OMIT }, { .tv_sec = -2, .tv_nsec = 42 } }; assert(utimensat(AT_FDCWD, ".", ts, 0) == 0); struct stat st; assert(stat(".", &st) == 0); printf("st_mtim.tv_sec = %lld, st_mtim.tv_nsec = %lu\n", (long long) st.st_mtim.tv_sec, (unsigned long) st.st_mtim.tv_nsec); struct statx stx; assert(syscall(__NR_statx, AT_FDCWD, ".", 0, 0, &stx) == 0); printf("stx_mtime.tv_sec = %lld, stx_mtime.tv_nsec = %lu\n", (long long) stx.stx_mtime.tv_sec, (unsigned long) stx.stx_mtime.tv_nsec); return 0; } It expectedly prints: st_mtim.tv_sec = -2, st_mtim.tv_nsec = 42 stx_mtime.tv_sec = -2, stx_mtime.tv_nsec = 42 The more generic comment asserting that the value of struct statx_timestamp.tv_nsec might be negative is confusing to say the least. It contradicts both the struct stat.st_[acm]time_nsec tradition and struct timespec.tv_nsec requirements in utimensat syscall. If statx syscall ever returns a stx_[acm]time containing a negative tv_nsec that cannot be passed unmodified to utimensat syscall, it will cause an immense confusion. Fix this source of confusion by changing the type of struct statx_timestamp.tv_nsec from __s32 to __u32.
Showing the changes to include/uapi/linux (1 of 1 file). Show all
Unified · Split
| @@ -48,17 +48,13 @@ · 47 unmodified lines | |||
| 48 | * tv_sec holds the number of seconds before (negative) or after (positive) | 48 | * tv_sec holds the number of seconds before (negative) or after (positive) |
| 49 | * 00:00:00 1st January 1970 UTC. | 49 | * 00:00:00 1st January 1970 UTC. |
| 50 | * | 50 | * |
| 51 | * tv_nsec holds a number of nanoseconds before (0..-999,999,999 if tv_sec is | 51 | * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time. |
| 52 | * negative) or after (0..999,999,999 if tv_sec is positive) the tv_sec time. | ||
| 53 | * | ||
| 54 | * Note that if both tv_sec and tv_nsec are non-zero, then the two values must | ||
| 55 | * either be both positive or both negative. | ||
| 56 | * | 52 | * |
| 57 | * __reserved is held in case we need a yet finer resolution. | 53 | * __reserved is held in case we need a yet finer resolution. |
| 58 | */ | 54 | */ |
| 59 | struct statx_timestamp { | 55 | struct statx_timestamp { |
| 60 | __s64 tv_sec; | 56 | __s64 tv_sec; |
| 61 | __s32 tv_nsec; | 57 | __u32 tv_nsec; |
| 62 | __s32 __reserved; | 58 | __s32 __reserved; |
| 63 | }; | 59 | }; |
| 64 | 60 | ||