Need an entry in .gitignore file too.
Will add this.
SUBDIRS =
diff --git a/src/y2038_futimens.c b/src/y2038_futimens.c new file mode 100644 index 0000000..291e4fa --- /dev/null +++ b/src/y2038_futimens.c @@ -0,0 +1,61 @@ +#include <fcntl.h> +#include <stdio.h> +#include <sys/stat.h> +#include <errno.h> +#include <stdlib.h>
+int +do_utime(int fd, long long time) +{
struct timespec t[2];
/*
* Convert long long to timespec format.
* Seconds precision is assumed here.
*/
t[0].tv_sec = time;
t[0].tv_nsec = 0;
t[1].tv_sec = time;
t[1].tv_nsec = 0;
/* Call utimens to update time. */
if (futimens(fd, t)) {
perror("futimens");
return 1;
}
return 0;
+}
+int +main(int argc, char **argv) +{
int fd;
long long time;
if(argc < 3) {
fprintf(stderr, "Usage: %s filename timestamp\n"
"Filename: file to be created or opened in current directory\n"
"Timestamp: is seconds since 1970-01-01 00:00:00 UTC\n", argv[0]);
exit(1);
Seems there's no need for an extra level of indention :)
Ok, will fix this.
}
/* Create the file */
fd = creat(argv[1], 0666);
if(fd < 0) {
perror("creat");
exit(1);
}
/* Get the timestamp */
time = strtoull(argv[2], NULL, 0);
if (errno) {
From errno(3), errno is never set to zero by any system call or library function, so errno isn't reset to zero on strtoull and this check always fails for me, with errno = ENOENT, because:
... access("/usr/share/dracut/modules.d/01fips", F_OK) = -1 ENOENT (No such file or directory) ... write(4, "strtoull: No such file or direct"..., 36strtoull: No such file or directory
the errno was from access(2) call in my case.
Right. Man page for strtoull() says:
Since strtoul() can legitimately return 0 or ULONG_MAX (ULLONG_MAX for strtoull()) on both success and failure, the calling program should set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a nonzero value after the call.
I will set errno to 0 before strtoull(). Thanks.
diff --git a/tests/generic/390 b/tests/generic/390 new file mode 100755 index 0000000..f069988 --- /dev/null +++ b/tests/generic/390 @@ -0,0 +1,238 @@ +#! /bin/bash +# FS QA Test No. generic/390 +# +# Tests to verify policy for filesystem timestamps for +# supported ranges: +# 1. Verify filesystem rw mount according to sysctl +# timestamp_supported. +# 2. Verify timestamp clamping for timestamps beyond max +# timestamp supported. +# +# Exit status 1: either or both tests above fail. +# Exit status 0: both the above tests pass.
Please use "./new" script to generate template, which contains all necessary initial setups and the copyright info.
Thanks, will do.
+seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" +#echo "output in $seqres.full" +here=`pwd`
+# Get standard environment, filters and checks. +. ./common/rc +. ./common/filter +. ./common/attr
+SRC_GROUPS=`find tests -not -path tests -type d -printf "%f "`
What's this for? Seems it's not used in the test.
Yes, this is not required. Leftovers from some previous version of the test. Thanks.
+# Prerequisites for the test run. +_supported_fs generic +_supported_os Linux +_require_scratch
Need to check the existence of y2038_futimens program, to make sure it's really built, e.g.
_require_test_program "y2038_futimens"
Will add this
+Y2038_PROG=$here/src/y2038_futimens
+#initialize exit status +status=0
We use 1 as the default value of status, so you can just "exit" on failure (because trap will catch the signal and exit with $status again) and only set status=0 and exit when test passes. "./new" already sets it up for you :)
Will take care of this.
+# Generic test cleanup function. +_cleanup() +{
- # Remove any leftover files from last run.
- rm -f ${SCRATCH_MNT}/test_?
No need to cleanup files on SCRATCH_DEV, it's meant to be mkfs'ed every time before using it.
Ok, makes sense. I will remove this clean up.
+#unmount and mount $SCRATCH_DEV. +_umount_mount_scratch_dev()
There's a helper to do this: _scratch_cycle_mount, only that it doesn't change PWD. And if you don't want to write $SCRATCH_MNT again, this is what we do usually in fstests:
testfile=$SCRATCH_MNT/<somefile> ... do_test $testfile
Thanks, will change it similar to what you suggest.
+{
- #change directory so that you are not using SCRATCH_MNT anymore.
- cd $here
- # Unmount the ${SCRATCH_DEV}
- _scratch_unmount
- if [ $? != 0 ]; then
return $?
- fi
- # Mount the ${SCRATCH_DEV}
- _scratch_mount
- if [ $? != 0 ]; then
return $?
- fi
- cd ${SCRATCH_MNT}
+}
+# Compare file timestamps obtained from stat +# with a given timestamp. +_check_stat() #check_stat(file, timestamp)
Name local functions without the leading underscore, that's usually for common helper functions, like functions in common/rc, common/attr.
Will do.
+{
- stat_timestamp=`stat -c"%X;%Y" $1`
And please use one tab (8 spaces width) for indention.
Will do.
- prev_timestamp="$2;$2"
- if [ $prev_timestamp != $stat_timestamp ]; then
echo "$prev_timestamp != $stat_timestamp" >> $seqres.full
return 1
No need to return 0 or 1, just echo the "... != ..." to stdout, and tee -a the output to $seqres.full if you want verbose debug too.
Because all the outputs, including stdout and stderr, from the test will be captured and compared with the .out file at the end of each test, and test harness reports failure if the two outputs don't match. That way, you don't have to check return value of commands most of the times.
Ok, will fix this.
- else
return 0
- fi
+}
+_run_test_individual() #_run_individual_test(file, timestamp, update_time) +{
- file=$1
- timestamp=$2
- update_time=$3
- #check if the time needs update
- if [ $update_time -eq 1 ]; then
echo "Updating file: $file to timestamp `date -d @$timestamp`" >> $seqres.full
$Y2038_PROG $file $timestamp &>> $seqres.full
if [ $? != 0 ]; then
echo "Failed to run the y2038 program" >> $seqres.full
return 1
fi
- fi
Seems $Y2038_PROG outputs nothing on success, so again, just run the program without checking results & redirecting outputs, test harness will report failure if there's error messages from this program. e.g.
$Y2038_PROG $file $timestamp
and just let test run even if something goes wrong.
Will do.
- tsclamp=$(($timestamp>$tsmax?$tsmax:$timestamp))
- _check_stat $file $tsclamp
- echo "Checking file: $file Updated timestamp is `date -d @$tsclamp`" >> $seqres.full
- if [ $? != 0 ]; then
echo "Failed to set time to $timestamp" >> $seqres.full
return 1
- fi
- return 0
+}
+_run_test() #_run_test(update_time) +{
- #initialization iterator
- n=1
- for TIME in "${TIMESTAMPS[@]}"
- do
#Run the test
_run_test_individual ${SCRATCH_MNT}/test_$n $TIME $1
if [ $? != 0 ]; then
echo "file timestamp update failed `date -d @$TIME`" >> $seqres.full
if [ $n -lt 4 ]; then
This is not obvious to me, need some comments on the magic number 4 :)
This is leftover from a previous version. Will clean this up. Thanks.
echo "Test failed"
return 1
fi
fi
#update iterator
((n++))
- done
- return 0
+}
+#Remove log from last run +rm -f $seqres.full
+#install cleaner +trap "_cleanup; exit $status" 0 1 2 3 15
+_scratch_mkfs &>> $seqres.full 2>&1 || _fail "mkfs failed" +read tsmin tsmax <<<$(_filesystem_timestamp_range $SCRATCH_DEV)
+if [ $tsmin -eq -1 -a $tsmax -eq -1 ]; then
- _notrun "filesystem $FSTYP timestamp bounds are unknown"
+fi
+echo min supported timestamp $tsmin $(date --date=@$tsmin) >> $seqres.full +echo max supported timestamp $tsmax $(date --date=@$tsmax) >> $seqres.full
+#Test timestamps array
+declare -a TIMESTAMPS=(
- $tsmin
- 0
- $tsmax
- $((tsmax+1))
- 4294967295
- 8589934591
- 34359738367
+)
+# Max timestamp is hardcoded to Mon Jan 18 19:14:07 PST 2038 +sys_tsmax=2147483647 +echo "min timestamp that needs to be supported by fs for rw mount is $sys_tsmax $(date --date=@$sys_tsmax)" >> $seqres.full
+read ts_check <<<$(cat /proc/sys/fs/fs-timestamp-check-on)
This fails on systems without this procfs entry, so we need another _require rule, e.g.
_require_proc_attr sys/fs/fs-timestamp-check-on
So test _notrun if kernel has no such procfs entry.
I realized this after I sent out the test. Will update this. Thanks.
Can you please point me a test kernel tree so I can actually run this test?
Will post a pointer along with v2.
+_scratch_mount +result=$?
+if [ $ts_check != 0 ]; then
- echo "sysctl filesystem timestamp check is on" >> $seqres.full
- if [ $sys_tsmax > $tsmax ]; then
if [ $result != -1 ]; then
echo "mount test failed" >> $seqres.full
fi
- else
if [ $result != 0 ]; then
echo "mount test failed" >> $seqres.full
fi
- fi
+else
- echo "sysctl filesystem timestamp check is off" >> $seqres.full
- if [ $result != 0 ]; then
echo "mount test failed" >> $seqres.full
- fi
echo error messages to stdout on mount failure, test harness could catch the failures.
will do.
+fi
+#cd to the SCRATCH_MNT to run the tests +cd $SCRATCH_MNT
+# Begin test case 1 +echo "In memory timestamps update test start" >> $seqres.full
+#update time on the file +update_time=1
+#Run test +_run_test $update_time
+if [ $? != 0 ]; then
- echo "In memory timestamps update failed" >> $seqres.full
- status=1
- exit
+fi
+echo "In memory timestamps update complete" >> $seqres.full
+echo "Unmounting and mounting scratch $SCRATCH_MNT" >> $seqres.full
+#unmount and remount $SCRATCH_DEV +_umount_mount_scratch_dev
+if [ $? != 0 ];then
- status=1
- exit
+fi
+# Begin test case 2
+#re-initialize iterator +n=1
+#Do not update time on the file, just read from disk +update_time=0
+echo "On disk timestamps update test start" >> $seqres.full
+#Re-run test +_run_test $update_time
+if [ $? != 0 ];then
- status=1
- exit
+fi
+echo "On disk timestamps update test complete" >> $seqres.full
+echo "y2038 inode filestamp update successful"
I may have more comments after you sent v2 and I can actually run the test :)
Sounds good :) Thanks for the comments. Will post v2 addressing the issues.
-Deepa