All of lore.kernel.org
 help / color / mirror / Atom feed
From: Deepa Dinamani <deepa.kernel@gmail.com>
To: fstests@vger.kernel.org
Cc: arnd@arndb.de, y2038@lists.linaro.org
Subject: [PATCH] generic/390: Add tests for inode timestamp policy
Date: Wed, 23 Nov 2016 16:52:02 -0800	[thread overview]
Message-ID: <1479948722-2936-1-git-send-email-deepa.kernel@gmail.com> (raw)

The test helps to validate clamping and mount behaviors
according to supported file system timestamp ranges.

Note that the test can fail on 32-bit systems for a
few file systems. This will be corrected when vfs is
transitioned to use 64-bit timestamps.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
 common/attr           |  27 ++++++
 src/Makefile          |   2 +-
 src/y2038_futimens.c  |  61 +++++++++++++
 tests/generic/390     | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/generic/390.out |   2 +
 tests/generic/group   |   1 +
 6 files changed, 330 insertions(+), 1 deletion(-)
 create mode 100644 src/y2038_futimens.c
 create mode 100755 tests/generic/390
 create mode 100644 tests/generic/390.out

diff --git a/common/attr b/common/attr
index ce2d76a..579dc9b 100644
--- a/common/attr
+++ b/common/attr
@@ -56,6 +56,33 @@ _acl_get_max()
 	esac
 }
 
+_filesystem_timestamp_range()
+{
+	device=${1:-$TEST_DEV}
+	case $FSTYP in
+	ext4)	#dumpe2fs
+		if [ $(dumpe2fs -h $device 2>/dev/null | grep "Inode size:" | cut -d: -f2) -gt 128 ]; then
+			echo "-2147483648 15032385535"
+		else
+			echo "-2147483648 2147483647"
+		fi
+		;;
+
+	xfs)
+		echo "-2147483648 2147483647"
+		;;
+	jfs)
+		echo "0 4294967295"
+		;;
+	f2fs)
+		echo "-2147483648 2147483647"
+		;;
+	*)
+		echo "-1 -1"
+		;;
+	esac
+}
+
 _require_acl_get_max()
 {
 	if [ $(_acl_get_max) -eq 0 ]; then
diff --git a/src/Makefile b/src/Makefile
index dd51216..0b99ae4 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -21,7 +21,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \
 	seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec cloner \
 	renameat2 t_getcwd e4compact test-nextquota punch-alternating \
-	attr-list-by-handle-cursor-test listxattr
+	attr-list-by-handle-cursor-test listxattr y2038_futimens
 
 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);
+	}
+
+	/* 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) {
+		perror("strtoull");
+		exit(1);
+	}
+
+	if (do_utime(fd, time))
+		return 1;
+
+	return 0;
+}
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.
+
+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 "`
+
+# Prerequisites for the test run.
+_supported_fs generic
+_supported_os Linux
+_require_scratch
+
+Y2038_PROG=$here/src/y2038_futimens
+
+#initialize exit status
+status=0
+
+# Generic test cleanup function.
+_cleanup()
+{
+    # Remove any leftover files from last run.
+    rm -f ${SCRATCH_MNT}/test_?
+}
+
+#unmount and mount  $SCRATCH_DEV.
+_umount_mount_scratch_dev()
+{
+    #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)
+{
+    stat_timestamp=`stat -c"%X;%Y" $1`
+
+    prev_timestamp="$2;$2"
+    if [ $prev_timestamp != $stat_timestamp ]; then
+	echo "$prev_timestamp != $stat_timestamp" >> $seqres.full
+	return 1
+    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
+
+    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
+		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)
+
+_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
+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"
diff --git a/tests/generic/390.out b/tests/generic/390.out
new file mode 100644
index 0000000..355f28e
--- /dev/null
+++ b/tests/generic/390.out
@@ -0,0 +1,2 @@
+QA output created by 390
+y2038 inode filestamp update successful
diff --git a/tests/generic/group b/tests/generic/group
index 08007d7..d137d01 100644
--- a/tests/generic/group
+++ b/tests/generic/group
@@ -392,3 +392,4 @@
 387 auto clone
 388 auto log metadata
 389 auto quick acl
+390 auto quick rw
-- 
2.7.4


             reply	other threads:[~2016-11-24  0:52 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-24  0:52 Deepa Dinamani [this message]
2016-11-24 10:40 ` [PATCH] generic/390: Add tests for inode timestamp policy Eryu Guan
2016-11-25 12:20   ` Arnd Bergmann
2016-12-02 20:44     ` Deepa Dinamani
2016-12-02 18:26   ` Deepa Dinamani
2016-11-24 23:15 ` Dave Chinner
2016-12-03  1:43   ` Deepa Dinamani

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1479948722-2936-1-git-send-email-deepa.kernel@gmail.com \
    --to=deepa.kernel@gmail.com \
    --cc=arnd@arndb.de \
    --cc=fstests@vger.kernel.org \
    --cc=y2038@lists.linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.