Re: [PATCH] generic/390: Add tests for inode timestamp policy

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]



> 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
--
To unsubscribe from this list: send the line "unsubscribe fstests" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux