diff mbox series

[V3,03/17] syscalls/timerfd: Add support for time64 tests

Message ID ea4cbfb7d4ee0a9414ca84e38e37cedc4386aaff.1589789487.git.viresh.kumar@linaro.org
State Superseded
Headers show
Series Syscalls: Add support for time64 variants | expand

Commit Message

Viresh Kumar May 18, 2020, 8:14 a.m. UTC
This adds support for time64 tests to the existing timerfd_gettime() and
timerfd_settime() syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 include/tst_timer.h                           |  58 +++++++-
 testcases/kernel/syscalls/timerfd/timerfd01.c |  53 +++++--
 testcases/kernel/syscalls/timerfd/timerfd04.c |  51 +++++--
 .../syscalls/timerfd/timerfd_gettime01.c      | 133 ++++++++---------
 .../syscalls/timerfd/timerfd_settime01.c      | 136 ++++++++----------
 .../syscalls/timerfd/timerfd_settime02.c      |  28 +++-
 6 files changed, 284 insertions(+), 175 deletions(-)
diff mbox series

Patch

diff --git a/include/tst_timer.h b/include/tst_timer.h
index c4107ed65dea..f3d948d0fed7 100644
--- a/include/tst_timer.h
+++ b/include/tst_timer.h
@@ -269,16 +269,64 @@  static inline int sys_timer_settime64(kernel_timer_t timerid, int flags,
 	return tst_syscall(__NR_timer_settime64, timerid, flags, its, old_its);
 }
 
+static inline int sys_timerfd_gettime(int fd, void *its)
+{
+	return tst_syscall(__NR_timerfd_gettime, fd, its);
+}
+
+static inline int sys_timerfd_gettime64(int fd, void *its)
+{
+	return tst_syscall(__NR_timerfd_gettime64, fd, its);
+}
+
+static inline int sys_timerfd_settime(int fd, int flags, void *its,
+				      void *old_its)
+{
+	return tst_syscall(__NR_timerfd_settime, fd, flags, its, old_its);
+}
+
+static inline int sys_timerfd_settime64(int fd, int flags, void *its,
+				      void *old_its)
+{
+	return tst_syscall(__NR_timerfd_settime64, fd, flags, its, old_its);
+}
+
+static inline long long tst_its_get_val_sec(struct tst_its its)
+{
+	switch (its.type) {
+	case TST_KERN_OLD_TIMESPEC:
+		return its.ts.kern_old_its.it_value.tv_sec;
+	case TST_KERN_TIMESPEC:
+		return its.ts.kern_its.it_value.tv_sec;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its.type);
+		return -1;
+	}
+}
+
+static inline long long tst_its_get_val_nsec(struct tst_its its)
+{
+	switch (its.type) {
+	case TST_KERN_OLD_TIMESPEC:
+		return its.ts.kern_old_its.it_value.tv_nsec;
+	case TST_KERN_TIMESPEC:
+		return its.ts.kern_its.it_value.tv_nsec;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", its.type);
+		return -1;
+	}
+}
+
 static inline void tst_its_set_time(struct tst_its *its, long long value_sec,
 				long long value_nsec, long long interval_sec,
 				long long interval_nsec)
 {
 	switch (its->type) {
-	case TST_LIBC_TIMESPEC:
-		its->ts.libc_its.it_value.tv_sec = value_sec;
-		its->ts.libc_its.it_value.tv_nsec = value_nsec;
-		its->ts.libc_its.it_interval.tv_sec = interval_sec;
-		its->ts.libc_its.it_interval.tv_nsec = interval_nsec;
+	case TST_KERN_OLD_TIMESPEC:
+		its->ts.kern_old_its.it_value.tv_sec = value_sec;
+		its->ts.kern_old_its.it_value.tv_nsec = value_nsec;
+		its->ts.kern_old_its.it_interval.tv_sec = interval_sec;
+		its->ts.kern_old_its.it_interval.tv_nsec = interval_nsec;
 	break;
 	case TST_KERN_TIMESPEC:
 		its->ts.kern_its.it_value.tv_sec = value_sec;
diff --git a/testcases/kernel/syscalls/timerfd/timerfd01.c b/testcases/kernel/syscalls/timerfd/timerfd01.c
index 45d4c5d5ea0d..262db0e55450 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd01.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd01.c
@@ -17,7 +17,6 @@ 
 
 #define _GNU_SOURCE
 #include <poll.h>
-#include "tst_test.h"
 #include "tst_timer.h"
 #include "tst_safe_timerfd.h"
 
@@ -29,25 +28,46 @@  static struct tcase {
 	{CLOCK_REALTIME, "CLOCK REALTIME"},
 };
 
+static struct test_variants {
+	int (*cgettime)(clockid_t clk_id, void *ts);
+	int (*tfd_gettime)(int fd, void *its);
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_gettime != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime, .tfd_gettime = sys_timerfd_gettime, .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_gettime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime64, .tfd_gettime = sys_timerfd_gettime64, .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
 static unsigned long long getustime(int clockid)
 {
-	struct timespec tp;
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts tp = {.type = tv->type, };
 
-	if (clock_gettime((clockid_t) clockid, &tp)) {
+	if (tv->cgettime((clockid_t) clockid, tst_ts_get(&tp))) {
 		tst_res(TFAIL | TERRNO, "clock_gettime() failed");
 		return 0;
 	}
 
-	return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
+	return 1000000ULL * tst_ts_get_sec(tp) + tst_ts_get_nsec(tp) / 1000;
 }
 
-static void settime(int tfd, struct itimerspec *tmr, int tflags,
+static void settime(int tfd, struct tst_its *tmr, int tflags,
                     unsigned long long tvalue, int tinterval)
 {
-	tmr->it_value = tst_timespec_from_us(tvalue);
-	tmr->it_interval = tst_timespec_from_us(tinterval);
+	struct test_variants *tv = &variants[tst_variant];
+	struct timespec value = tst_timespec_from_us(tvalue);
+	struct timespec interval = tst_timespec_from_us(tinterval);
 
-	SAFE_TIMERFD_SETTIME(tfd, tflags, tmr, NULL);
+	tst_its_set_time(tmr, value.tv_sec, value.tv_nsec, interval.tv_sec, interval.tv_nsec);
+
+	if (tv->tfd_settime(tfd, tflags, tst_its_get(tmr), NULL))
+		tst_res(TFAIL, "timerfd_settime() failed");
 }
 
 static void waittmr(int tfd, unsigned int exp_ticks)
@@ -78,10 +98,11 @@  static void waittmr(int tfd, unsigned int exp_ticks)
 
 static void run(unsigned int n)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	int tfd;
 	unsigned long long tnow;
 	uint64_t uticks;
-	struct itimerspec tmr;
+	struct tst_its tmr = {.type = tv->type, };
 	struct tcase *clks = &tcases[n];
 
 	tst_res(TINFO, "testing %s", clks->name);
@@ -102,11 +123,12 @@  static void run(unsigned int n)
 	settime(tfd, &tmr, TFD_TIMER_ABSTIME, tnow + 50 * 1000, 50 * 1000);
 
 	memset(&tmr, 0, sizeof(tmr));
-	if (timerfd_gettime(tfd, &tmr))
-		tst_res(TFAIL | TERRNO, "timerfd_gettime() failed");
+	tmr.type = tv->type;
 
+	if (tv->tfd_gettime(tfd, tst_its_get(&tmr)))
+		tst_res(TFAIL | TERRNO, "timerfd_gettime() failed");
 
-	if (tmr.it_value.tv_sec != 0 || tmr.it_value.tv_nsec > 50 * 1000000)
+	if (tst_its_get_val_sec(tmr) != 0 || tst_its_get_val_nsec(tmr) > 50 * 1000000)
 		tst_res(TFAIL, "Timer read back value not relative");
 	else
 		tst_res(TPASS, "Timer read back value is relative");
@@ -132,8 +154,15 @@  static void run(unsigned int n)
 	SAFE_CLOSE(tfd);
 }
 
+static void setup(void)
+{
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+}
+
 static struct tst_test test = {
 	.test = run,
 	.tcnt = ARRAY_SIZE(tcases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
 	.min_kver = "2.6.25",
 };
diff --git a/testcases/kernel/syscalls/timerfd/timerfd04.c b/testcases/kernel/syscalls/timerfd/timerfd04.c
index 7197fc67ed47..ee5382dd52f8 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd04.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd04.c
@@ -19,7 +19,6 @@ 
 #include "tst_safe_timerfd.h"
 #include "tst_timer.h"
 #include "lapi/namespaces_constants.h"
-#include "tst_test.h"
 
 #define SLEEP_US 40000
 
@@ -35,26 +34,56 @@  static struct tcase {
 	{CLOCK_BOOTTIME, CLOCK_BOOTTIME, -10},
 };
 
+static struct test_variants {
+	int (*cgettime)(clockid_t clk_id, void *ts);
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime, .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .cgettime = sys_clock_gettime64, .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void setup(void)
+{
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+}
+
 static void verify_timerfd(unsigned int n)
 {
-	struct timespec start, end;
-	struct itimerspec it = {};
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_ts start, end;
+	struct tst_its it;
 	struct tcase *tc = &tcases[n];
 
+	start.type = end.type = it.type = tv->type;
 	SAFE_UNSHARE(CLONE_NEWTIME);
 
 	SAFE_FILE_PRINTF("/proc/self/timens_offsets", "%d %d 0",
 	                 tc->clk_off, tc->off);
 
-	SAFE_CLOCK_GETTIME(tc->clk_id, &start);
+	if (tv->cgettime(tc->clk_id, tst_ts_get(&start))) {
+		tst_res(TFAIL | TTERRNO, "clock_gettime(2) failed for clock %s",
+			tst_clock_name(tc->clk_id));
+		return;
+	}
 
-	it.it_value = tst_timespec_add_us(start, 1000000 * tc->off + SLEEP_US);
+	end = tst_ts_add_us(start, 1000000 * tc->off + SLEEP_US);
+	tst_its_set_time(&it, tst_ts_get_sec(end), tst_ts_get_nsec(end), 0, 0);
 
 	if (!SAFE_FORK()) {
 		uint64_t exp;
 		int fd = SAFE_TIMERFD_CREATE(tc->clk_id, 0);
 
-		SAFE_TIMERFD_SETTIME(fd, TFD_TIMER_ABSTIME, &it, NULL);
+		if (tv->tfd_settime(fd, TFD_TIMER_ABSTIME, tst_its_get(&it), NULL)) {
+			tst_res(TFAIL, "timerfd_settime() failed");
+			return;
+		}
 
 		SAFE_READ(1, fd, &exp, sizeof(exp));
 
@@ -67,9 +96,13 @@  static void verify_timerfd(unsigned int n)
 
 	SAFE_WAIT(NULL);
 
-	SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &end);
+	if (tv->cgettime(CLOCK_MONOTONIC, tst_ts_get(&end))) {
+		tst_res(TFAIL | TTERRNO, "clock_gettime(2) failed for clock %s",
+			tst_clock_name(CLOCK_MONOTONIC));
+		return;
+	}
 
-	long long diff = tst_timespec_diff_us(end, start);
+	long long diff = tst_ts_diff_us(end, start);
 
 	if (diff > 5 * SLEEP_US) {
 		tst_res(TFAIL, "timerfd %s slept too long %lli",
@@ -90,6 +123,8 @@  static void verify_timerfd(unsigned int n)
 static struct tst_test test = {
 	.tcnt = ARRAY_SIZE(tcases),
 	.test = verify_timerfd,
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
 	.needs_root = 1,
 	.forks_child = 1,
 	.needs_kconfigs = (const char *[]) {
diff --git a/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c b/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c
index 5f3240bdc7d7..49f5aa59a96b 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd_gettime01.c
@@ -1,20 +1,8 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) 2014 Fujitsu Ltd.
  * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
  * DESCRIPTION
  *  Verify that,
  *   1. fd is not a valid file descriptor, EBADF would return.
@@ -24,99 +12,96 @@ 
 
 #define _GNU_SOURCE
 
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "safe_macros.h"
-#include "lapi/timerfd.h"
+#include "tst_timer.h"
+#include "tst_safe_timerfd.h"
 
 char *TCID = "timerfd_gettime01";
 
 static int bad_clockfd = -1;
 static int clockfd;
 static int fd;
+static void *bad_addr;
 
 static struct test_case_t {
 	int *fd;
-	struct itimerspec *curr_value;
+	struct tst_its *curr_value;
 	int exp_errno;
 } test_cases[] = {
 	{&bad_clockfd, NULL, EBADF},
-	{&clockfd, (struct itimerspec *)-1, EFAULT},
+	{&clockfd, NULL, EFAULT},
 	{&fd, NULL, EINVAL},
 };
 
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-static void setup(void);
-static void timerfd_gettime_verify(const struct test_case_t *);
-static void cleanup(void);
+static struct test_variants {
+	int (*tfd_gettime)(int fd, void *its);
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_gettime != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_gettime = sys_timerfd_gettime, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_gettime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_gettime = sys_timerfd_gettime64, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
-int main(int argc, char *argv[])
+static void setup(void)
 {
-	int lc;
-	int i;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-	setup();
+	tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+	bad_addr = tst_get_bad_addr(NULL);
 
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-		for (i = 0; i < TST_TOTAL; i++)
-			timerfd_gettime_verify(&test_cases[i]);
+	clockfd = timerfd_create(CLOCK_REALTIME, 0);
+	if (clockfd == -1) {
+		tst_brk(TFAIL | TERRNO, "timerfd_create() fail");
+		return;
 	}
 
-	cleanup();
-	tst_exit();
+	fd = SAFE_OPEN("test_file", O_RDWR | O_CREAT, 0644);
 }
 
-static void setup(void)
+static void cleanup(void)
 {
-	if ((tst_kvercmp(2, 6, 25)) < 0)
-		tst_brkm(TCONF, NULL, "This test needs kernel 2.6.25 or newer");
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
-	clockfd = timerfd_create(CLOCK_REALTIME, 0);
-	if (clockfd == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "timerfd_create() fail");
+	if (clockfd > 0)
+		close(clockfd);
 
-	fd = SAFE_OPEN(cleanup, "test_file", O_RDWR | O_CREAT, 0644);
+	if (fd > 0)
+		close(fd);
 }
 
-static void timerfd_gettime_verify(const struct test_case_t *test)
+static void run(unsigned int n)
 {
-	TEST(timerfd_gettime(*test->fd, test->curr_value));
+	struct test_variants *tv = &variants[tst_variant];
+	struct test_case_t *test = &test_cases[n];
+	void *its;
 
-	if (TEST_RETURN != -1) {
-		tst_resm(TFAIL, "timerfd_gettime() succeeded unexpectedly");
+	if (test->exp_errno == EFAULT)
+		its = bad_addr;
+	else
+		its = tst_its_get(test->curr_value);
+
+	TEST(tv->tfd_gettime(*test->fd, its));
+
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "timerfd_gettime() succeeded unexpectedly");
 		return;
 	}
 
-	if (TEST_ERRNO == test->exp_errno) {
-		tst_resm(TPASS | TTERRNO,
-			 "timerfd_gettime() failed as expected");
+	if (TST_ERR == test->exp_errno) {
+		tst_res(TPASS | TTERRNO,
+			"timerfd_gettime() failed as expected");
 	} else {
-		tst_resm(TFAIL | TTERRNO,
-			 "timerfd_gettime() failed unexpectedly; expected: "
-			 "%d - %s", test->exp_errno, strerror(test->exp_errno));
+		tst_res(TFAIL | TTERRNO,
+			"timerfd_gettime() failed unexpectedly; expected: "
+			"%d - %s", test->exp_errno, strerror(test->exp_errno));
 	}
 }
 
-static void cleanup(void)
-{
-	if (clockfd > 0)
-		close(clockfd);
-
-	if (fd > 0)
-		close(fd);
-
-	tst_rmdir();
-}
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(test_cases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.min_kver = "2.6.25",
+};
diff --git a/testcases/kernel/syscalls/timerfd/timerfd_settime01.c b/testcases/kernel/syscalls/timerfd/timerfd_settime01.c
index 2e65d23ae825..2fd64c1c6a04 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd_settime01.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd_settime01.c
@@ -1,20 +1,8 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (c) 2014 Fujitsu Ltd.
  * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
  * DESCRIPTION
  *  Verify that,
  *   1. fd is not a valid file descriptor, EBADF would return.
@@ -25,13 +13,7 @@ 
 
 #define _GNU_SOURCE
 
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "test.h"
-#include "safe_macros.h"
+#include "tst_timer.h"
 #include "lapi/timerfd.h"
 
 char *TCID = "timerfd_settime01";
@@ -39,80 +21,51 @@  char *TCID = "timerfd_settime01";
 static int bad_clockfd = -1;
 static int clockfd;
 static int fd;
+static void *bad_addr;
 
 static struct test_case_t {
 	int *fd;
 	int flags;
-	struct itimerspec *old_value;
+	struct tst_its *old_value;
 	int exp_errno;
 } test_cases[] = {
 	{&bad_clockfd, 0, NULL, EBADF},
-	{&clockfd, 0, (struct itimerspec *)-1, EFAULT},
+	{&clockfd, 0, NULL, EFAULT},
 	{&fd, 0, NULL, EINVAL},
 	{&clockfd, -1, NULL, EINVAL},
 };
 
-int TST_TOTAL = ARRAY_SIZE(test_cases);
-static void setup(void);
-static void timerfd_settime_verify(const struct test_case_t *);
-static void cleanup(void);
-static struct itimerspec new_value;
+static struct tst_its new_value;
 
-int main(int argc, char *argv[])
-{
-	int lc;
-	int i;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
+static struct test_variants {
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
 
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-		for (i = 0; i < TST_TOTAL; i++)
-			timerfd_settime_verify(&test_cases[i]);
-	}
-
-	cleanup();
-	tst_exit();
-}
+#if (__NR_timerfd_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
 
 static void setup(void)
 {
-	if ((tst_kvercmp(2, 6, 25)) < 0)
-		tst_brkm(TCONF, NULL, "This test needs kernel 2.6.25 or newer");
-
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
+	struct test_variants *tv = &variants[tst_variant];
 
-	TEST_PAUSE;
-
-	tst_tmpdir();
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	bad_addr = tst_get_bad_addr(NULL);
+	new_value.type = tv->type;
 
 	clockfd = timerfd_create(CLOCK_REALTIME, 0);
-	if (clockfd == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "timerfd_create() fail");
-
-	fd = SAFE_OPEN(cleanup, "test_file", O_RDWR | O_CREAT, 0644);
-}
-
-static void timerfd_settime_verify(const struct test_case_t *test)
-{
-	TEST(timerfd_settime(*test->fd, test->flags, &new_value,
-			     test->old_value));
-
-	if (TEST_RETURN != -1) {
-		tst_resm(TFAIL, "timerfd_settime() succeeded unexpectedly");
+	if (clockfd == -1) {
+		tst_brk(TFAIL | TERRNO, "timerfd_create() fail");
 		return;
 	}
 
-	if (TEST_ERRNO == test->exp_errno) {
-		tst_resm(TPASS | TTERRNO,
-			 "timerfd_settime() failed as expected");
-	} else {
-		tst_resm(TFAIL | TTERRNO,
-			 "timerfd_settime() failed unexpectedly; expected: "
-			 "%d - %s", test->exp_errno, strerror(test->exp_errno));
-	}
+	fd = SAFE_OPEN("test_file", O_RDWR | O_CREAT, 0644);
 }
 
 static void cleanup(void)
@@ -122,6 +75,43 @@  static void cleanup(void)
 
 	if (fd > 0)
 		close(fd);
+}
+
+static void run(unsigned int n)
+{
+	struct test_variants *tv = &variants[tst_variant];
+	struct test_case_t *test = &test_cases[n];
+	void *its;
+
+	if (test->exp_errno == EFAULT)
+		its = bad_addr;
+	else
+		its = tst_its_get(test->old_value);
 
-	tst_rmdir();
+	TEST(tv->tfd_settime(*test->fd, test->flags, tst_its_get(&new_value),
+			     its));
+
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "timerfd_settime() succeeded unexpectedly");
+		return;
+	}
+
+	if (TST_ERR == test->exp_errno) {
+		tst_res(TPASS | TTERRNO,
+			"timerfd_settime() failed as expected");
+	} else {
+		tst_res(TFAIL | TTERRNO,
+			"timerfd_settime() failed unexpectedly; expected: "
+			"%d - %s", test->exp_errno, strerror(test->exp_errno));
+	}
 }
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(test_cases),
+	.test_variants = ARRAY_SIZE(variants),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_tmpdir = 1,
+	.min_kver = "2.6.25",
+};
diff --git a/testcases/kernel/syscalls/timerfd/timerfd_settime02.c b/testcases/kernel/syscalls/timerfd/timerfd_settime02.c
index 0565802f4288..c15b69dca9ca 100644
--- a/testcases/kernel/syscalls/timerfd/timerfd_settime02.c
+++ b/testcases/kernel/syscalls/timerfd/timerfd_settime02.c
@@ -15,8 +15,8 @@ 
  *  timerfd: Protect the might cancel mechanism proper
  */
 #include <unistd.h>
+#include "tst_timer.h"
 #include "tst_safe_timerfd.h"
-#include "tst_test.h"
 #include "tst_fuzzy_sync.h"
 #include "tst_taint.h"
 
@@ -27,11 +27,30 @@ 
 #endif
 
 static int fd = -1;
-static struct itimerspec its;
+static struct tst_its its;
 static struct tst_fzsync_pair fzsync_pair;
 
+static struct test_variants {
+	int (*tfd_settime)(int fd, int flags, void *new_value, void *old_value);
+	enum tst_ts_type type;
+	char *desc;
+} variants[] = {
+#if (__NR_timerfd_settime != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_timerfd_settime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .tfd_settime = sys_timerfd_settime64, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+	its.type = tv->type;
+
 	tst_taint_init(TST_TAINT_W | TST_TAINT_D);
 	fd = SAFE_TIMERFD_CREATE(CLOCK_REALTIME, 0);
 
@@ -48,7 +67,9 @@  static void cleanup(void)
 
 static int punch_clock(int flags)
 {
-	return timerfd_settime(fd, flags, &its, NULL);
+	return variants[tst_variant].tfd_settime(fd, flags, tst_its_get(&its),
+						 NULL);
+
 }
 
 static void *thread_run(void *arg)
@@ -91,6 +112,7 @@  static void run(void)
 
 static struct tst_test test = {
 	.test_all = run,
+	.test_variants = ARRAY_SIZE(variants),
 	.setup = setup,
 	.cleanup = cleanup,
 	.min_kver = "2.6.25",