generic: check userspace handling of extreme timestamps
[xfstests-dev.git] / tests / generic / 634
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Copyright (c) 2021 Oracle.  All Rights Reserved.
4 #
5 # FS QA Test No. 634
6 #
7 # Make sure we can store and retrieve timestamps on the extremes of the
8 # date ranges supported by userspace, and the common places where overflows
9 # can happen.
10 #
11 # This differs from generic/402 in that we don't constrain ourselves to the
12 # range that the filesystem claims to support; we attempt various things that
13 # /userspace/ can parse, and then check that the vfs clamps and persists the
14 # values correctly.
15 #
16 # NOTE: Old kernels (pre 5.4) allow filesystems to truncate timestamps silently
17 # when writing timestamps to disk!  This test detects this silent truncation
18 # and fails.  If you see a failure on such a kernel, contact your distributor
19 # for an update.
20
21 seq=`basename $0`
22 seqres=$RESULT_DIR/$seq
23 echo "QA output created by $seq"
24
25 here=`pwd`
26 tmp=/tmp/$$
27 status=1    # failure is the default!
28 trap "_cleanup; exit \$status" 0 1 2 3 15
29
30 _cleanup()
31 {
32         cd /
33         rm -f $tmp.*
34 }
35
36 # get standard environment, filters and checks
37 . ./common/rc
38
39 # real QA test starts here
40 _supported_fs generic
41 _require_scratch
42
43 rm -f $seqres.full
44
45 _scratch_mkfs > $seqres.full
46 _scratch_mount
47
48 # Does our userspace even support large dates?
49 test_bigdates=1
50 touch -d 'May 30 01:53:03 UTC 2514' $SCRATCH_MNT 2>/dev/null || test_bigdates=0
51
52 # And can we do statx?
53 test_statx=1
54 ($XFS_IO_PROG -c 'help statx' | grep -q 'Print raw statx' && \
55  $XFS_IO_PROG -c 'statx -r' $SCRATCH_MNT 2>/dev/null | grep -q 'stat.mtime') || \
56         test_statx=0
57
58 echo "Userspace support of large timestamps: $test_bigdates" >> $seqres.full
59 echo "xfs_io support of statx: $test_statx" >> $seqres.full
60
61 touchme() {
62         local arg="$1"
63         local name="$2"
64
65         echo "$arg" > $SCRATCH_MNT/t_$name
66         touch -d "$arg" $SCRATCH_MNT/t_$name
67 }
68
69 report() {
70         local files=($SCRATCH_MNT/t_*)
71         for file in "${files[@]}"; do
72                 echo "${file}: $(cat "${file}")"
73                 TZ=UTC stat -c '%y %Y %n' "${file}"
74                 test $test_statx -gt 0 && \
75                         $XFS_IO_PROG -c 'statx -r' "${file}" | grep 'stat.mtime'
76         done
77 }
78
79 # -2147483648 (S32_MIN, or classic unix min)
80 touchme 'Dec 13 20:45:52 UTC 1901' s32_min
81
82 # 2147483647 (S32_MAX, or classic unix max)
83 touchme 'Jan 19 03:14:07 UTC 2038' s32_max
84
85 # 7956915742, all twos
86 touchme 'Feb 22 22:22:22 UTC 2222' all_twos
87
88 if [ $test_bigdates -gt 0 ]; then
89         # 16299260424 (u64 nsec counter from s32_min, like xfs does)
90         touchme 'Tue Jul  2 20:20:24 UTC 2486' u64ns_from_s32_min
91
92         # 15032385535 (u34 time if you start from s32_min, like ext4 does)
93         touchme 'May 10 22:38:55 UTC 2446' u34_from_s32_min
94
95         # 17179869183 (u34 time if you start from the unix epoch)
96         touchme 'May 30 01:53:03 UTC 2514' u34_max
97
98         # Latest date we can synthesize(?)
99         touchme 'Dec 31 23:59:59 UTC 2147483647' abs_max_time
100
101         # Earliest date we can synthesize(?)
102         touchme 'Jan 1 00:00:00 UTC 0' abs_min_time
103 fi
104
105 # Query timestamps from incore
106 echo before >> $seqres.full
107 report > $tmp.before_remount
108 cat $tmp.before_remount >> $seqres.full
109
110 _scratch_cycle_mount
111
112 # Query timestamps from disk
113 echo after >> $seqres.full
114 report > $tmp.after_remount
115 cat $tmp.after_remount >> $seqres.full
116
117 # Did they match?
118 cmp -s $tmp.before_remount $tmp.after_remount
119
120 # success, all done
121 echo Silence is golden.
122 status=0
123 exit