[LTP] [PATCH V5 5/5] syscalls/clock_adjtime: Add support for time64 tests

Viresh Kumar viresh.kumar@linaro.org
Fri Apr 24 09:18:46 CEST 2020


This adds support for time64 tests to the existing clock_adjtime()
syscall tests.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../syscalls/clock_adjtime/clock_adjtime.h    | 216 +++++++++++++++---
 .../syscalls/clock_adjtime/clock_adjtime01.c  | 124 ++++++----
 .../syscalls/clock_adjtime/clock_adjtime02.c  |  95 +++++---
 3 files changed, 332 insertions(+), 103 deletions(-)

diff --git a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h
index d7f553a3a04b..138e6ca7f3d0 100644
--- a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h
+++ b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime.h
@@ -16,43 +16,191 @@
 #include <sys/types.h>
 #include "lapi/timex.h"
 
-static int sys_clock_adjtime(clockid_t, struct timex *);
-static void timex_show(char *, struct timex);
+#ifndef __kernel_timex
+struct __kernel_timex_timeval {
+	__kernel_time64_t       tv_sec;
+	long long		tv_usec;
+};
 
-/*
- * bad pointer w/ libc causes SIGSEGV signal, call syscall directly
- */
-static int sys_clock_adjtime(clockid_t clk_id, struct timex *txc)
+struct __kernel_timex {
+	unsigned int modes;	/* mode selector */
+	int :32;            /* pad */
+	long long offset;	/* time offset (usec) */
+	long long freq;	/* frequency offset (scaled ppm) */
+	long long maxerror;/* maximum error (usec) */
+	long long esterror;/* estimated error (usec) */
+	int status;		/* clock command/status */
+	int :32;            /* pad */
+	long long constant;/* pll time constant */
+	long long precision;/* clock precision (usec) (read only) */
+	long long tolerance;/* clock frequency tolerance (ppm)
+				   * (read only)
+				   */
+	struct __kernel_timex_timeval time;	/* (read only, except for ADJ_SETOFFSET) */
+	long long tick;	/* (modified) usecs between clock ticks */
+
+	long long ppsfreq;/* pps frequency (scaled ppm) (ro) */
+	long long jitter; /* pps jitter (us) (ro) */
+	int shift;              /* interval duration (s) (shift) (ro) */
+	int :32;            /* pad */
+	long long stabil;            /* pps stability (scaled ppm) (ro) */
+	long long jitcnt; /* jitter limit exceeded (ro) */
+	long long calcnt; /* calibration intervals (ro) */
+	long long errcnt; /* calibration errors (ro) */
+	long long stbcnt; /* stability limit exceeded (ro) */
+
+	int tai;		/* TAI offset (ro) */
+
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32;
+};
+#endif
+
+enum tst_timex_type {
+	TST_LIBC_TIMEX,
+	TST_KERN_TIMEX
+};
+
+struct tst_timex {
+	enum tst_timex_type type;
+	union {
+		struct timex libc_timex;
+		struct __kernel_timex kern_timex;
+	} ts;
+};
+
+static inline void *tst_timex_get(struct tst_timex *t)
+{
+	switch (t->type) {
+	case TST_LIBC_TIMEX:
+		return &t->ts.libc_timex;
+	case TST_KERN_TIMEX:
+		return &t->ts.kern_timex;
+	default:
+		tst_brk(TBROK, "Invalid type: %d", t->type);
+		return NULL;
+	}
+}
+
+static inline int sys_clock_adjtime(clockid_t clk_id, void *timex)
 {
-	return tst_syscall(__NR_clock_adjtime, clk_id, txc);
+	return tst_syscall(__NR_clock_adjtime, clk_id, timex);
 }
 
-static void timex_show(char *given, struct timex txc)
+static inline int sys_clock_adjtime64(clockid_t clk_id, void *timex)
 {
-	tst_res(TINFO,  "%s\n"
-			"             mode: %d\n"
-			"           offset: %ld\n"
-			"        frequency: %ld\n"
-			"         maxerror: %ld\n"
-			"         esterror: %ld\n"
-			"           status: %d (0x%x)\n"
-			"    time_constant: %ld\n"
-			"        precision: %ld\n"
-			"        tolerance: %ld\n"
-			"             tick: %ld\n"
-			"         raw time: %d(s) %d(us)",
-			given,
-			txc.modes,
-			txc.offset,
-			txc.freq,
-			txc.maxerror,
-			txc.esterror,
-			txc.status,
-			txc.status,
-			txc.constant,
-			txc.precision,
-			txc.tolerance,
-			txc.tick,
-			(int)txc.time.tv_sec,
-			(int)txc.time.tv_usec);
+	return tst_syscall(__NR_clock_adjtime64, clk_id, timex);
+}
+
+#define _timex_show(_timex, _desc)					\
+	tst_res(TINFO,  "%s\n"						\
+			"             mode: %u\n"			\
+			"           offset: "#_desc"\n"			\
+			"        frequency: "#_desc"\n"			\
+			"         maxerror: "#_desc"\n"			\
+			"         esterror: "#_desc"\n"			\
+			"           status: %d (0x%x)\n"		\
+			"    time_constant: "#_desc"\n"			\
+			"        precision: "#_desc"\n"			\
+			"        tolerance: "#_desc"\n"			\
+			"             tick: "#_desc"\n"			\
+			"         raw time: "#_desc"(s) "#_desc"(us)",	\
+			given,						\
+			_timex.modes,					\
+			_timex.offset,					\
+			_timex.freq,					\
+			_timex.maxerror,				\
+			_timex.esterror,				\
+			_timex.status,					\
+			_timex.status,					\
+			_timex.constant,				\
+			_timex.precision,				\
+			_timex.tolerance,				\
+			_timex.tick,					\
+			_timex.time.tv_sec,				\
+			_timex.time.tv_usec)
+
+static inline void timex_show(char *given, struct tst_timex *timex)
+{
+	switch (timex->type) {
+	case TST_LIBC_TIMEX:
+		_timex_show(timex->ts.libc_timex, %ld);
+		return;
+	case TST_KERN_TIMEX:
+		_timex_show(timex->ts.kern_timex, %lld);
+		return;
+	default:
+		tst_res(TFAIL, "Invalid type: %d", timex->type);
+	}
+}
+
+#define ADJ_MODES	0
+
+#define _select_field(_timex, _field)					\
+{									\
+	if (_field == ADJ_MODES)					\
+		return &_timex.modes;					\
+	if (_field == ADJ_OFFSET)					\
+		return &_timex.offset;					\
+	if (_field == ADJ_FREQUENCY)					\
+		return &_timex.freq;					\
+	if (_field == ADJ_MAXERROR)					\
+		return &_timex.maxerror;				\
+	if (_field == ADJ_ESTERROR)					\
+		return &_timex.esterror;				\
+	if (_field == ADJ_TIMECONST)					\
+		return &_timex.constant;				\
+	if (_field == ADJ_TICK)						\
+		return &_timex.tick;					\
+	if (_field == ADJ_STATUS)					\
+		return &_timex.status;					\
+	tst_res(TFAIL, "Invalid type: %d", timex->type);		\
+	return NULL;							\
+}
+
+static inline void *_get_field(struct tst_timex *timex, unsigned int field)
+{
+	switch (timex->type) {
+	case TST_LIBC_TIMEX:
+		_select_field(timex->ts.libc_timex, field);
+	case TST_KERN_TIMEX:
+		_select_field(timex->ts.kern_timex, field);
+	default:
+		tst_res(TFAIL, "Invalid type: %d", timex->type);
+		return NULL;
+	}
+}
+
+#define timex_get_set_field_type(_type_libc, _type_kern)		\
+static inline _type_kern						\
+timex_get_field_##_type_libc(struct tst_timex *timex, unsigned int field) \
+{									\
+	switch (timex->type) {						\
+	case TST_LIBC_TIMEX:						\
+		return *((_type_libc*)_get_field(timex, field));	\
+	case TST_KERN_TIMEX:						\
+		return *((_type_kern*)_get_field(timex, field));	\
+	default:							\
+		tst_res(TFAIL, "Invalid type: %d", timex->type);	\
+		return 0;						\
+	}								\
+}									\
+									\
+static inline void							\
+timex_set_field_##_type_libc(struct tst_timex *timex, unsigned int field, \
+			    _type_kern value)				\
+{									\
+	switch (timex->type) {						\
+	case TST_LIBC_TIMEX:						\
+		*((_type_libc*)_get_field(timex, field)) = value;	\
+		return;							\
+	case TST_KERN_TIMEX:						\
+		*((_type_kern*)_get_field(timex, field)) = value;	\
+		return;							\
+	default:							\
+		tst_res(TFAIL, "Invalid type: %d", timex->type);	\
+	}								\
 }
+timex_get_set_field_type(uint, uint);
+timex_get_set_field_type(long, long long);
diff --git a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime01.c b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime01.c
index 1262d34fa0d6..a5b8792e50e3 100644
--- a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime01.c
+++ b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime01.c
@@ -55,15 +55,15 @@
  */
 
 #include "clock_adjtime.h"
+#include "lapi/abisize.h"
 
 static long hz;
-static struct timex saved, ttxc;
+static struct tst_timex saved, ttxc;
 static int supported;
 
 struct test_case {
 	unsigned int modes;
 	long highlimit;
-	long *ptr;
 	long delta;
 };
 
@@ -80,79 +80,103 @@ struct test_case tc[] = {
 	{
 	 .modes = ADJ_OFFSET,
 	 .highlimit = 500000,
-	 .ptr = &ttxc.offset,
 	 .delta = 10000,
 	},
 	{
 	 .modes = ADJ_FREQUENCY,
-	 .ptr = &ttxc.freq,
 	 .delta = 100,
 	},
 	{
 	 .modes = ADJ_MAXERROR,
-	 .ptr = &ttxc.maxerror,
 	 .delta = 100,
 	},
 	{
 	 .modes = ADJ_ESTERROR,
-	 .ptr = &ttxc.esterror,
 	 .delta = 100,
 	},
 	{
 	 .modes = ADJ_TIMECONST,
-	 .ptr = &ttxc.constant,
 	 .delta = 1,
 	},
 	{
 	 .modes = ADJ_TICK,
 	 .highlimit = 1100000,
-	 .ptr = &ttxc.tick,
 	 .delta = 1000,
 	},
 };
 
+static struct test_variants {
+	int (*func)(clockid_t clk_id, void *timex);
+	enum tst_timex_type type;
+	char *desc;
+} variants[] = {
+#if defined(TST_ABI32)
+	{ .func = sys_clock_adjtime, .type = TST_LIBC_TIMEX, .desc = "syscall with libc spec"},
+#endif
+
+#if defined(TST_ABI64)
+	{ .func = sys_clock_adjtime, .type = TST_KERN_TIMEX, .desc = "syscall with kernel spec64"},
+#endif
+
+#if (__NR_clock_adjtime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_clock_adjtime64, .type = TST_KERN_TIMEX, .desc = "syscall time64 with kernel spec64"},
+#endif
+};
+
 static void verify_clock_adjtime(unsigned int i)
 {
-	long ptroff, *ptr = NULL;
-	struct timex verify;
+	struct test_variants *tv = &variants[tst_variant];
+	struct tst_timex verify;
+	long long val;
+	int rval;
 
-	memset(&ttxc, 0, sizeof(struct timex));
-	memset(&verify, 0, sizeof(struct timex));
+	memset(&ttxc, 0, sizeof(ttxc));
+	memset(&verify, 0, sizeof(verify));
 
-	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &ttxc);
-	timex_show("GET", ttxc);
+	ttxc.type = verify.type = tv->type;
+
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(&ttxc));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
+	}
 
-	ttxc.modes = tc[i].modes;
+	timex_show("GET", &ttxc);
 
-	if (tc[i].ptr && tc[i].delta) {
+	timex_set_field_uint(&ttxc, ADJ_MODES, tc[i].modes);
 
-		*tc[i].ptr += tc[i].delta;
+	if (tc[i].delta) {
+		val = timex_get_field_long(&ttxc, tc[i].modes);
+		val += tc[i].delta;
 
 		/* fix limits, if existent, so no errors occur */
+		if (tc[i].highlimit && val >= tc[i].highlimit)
+			val = tc[i].highlimit;
 
-		if (tc[i].highlimit) {
-			if (*tc[i].ptr >= tc[i].highlimit)
-				*tc[i].ptr = tc[i].highlimit;
-		}
+		timex_set_field_long(&ttxc, tc[i].modes, val);
 	}
 
-	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &ttxc);
-	timex_show("SET", ttxc);
-
-	if (tc[i].ptr) {
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(&ttxc));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
+	}
 
-		/* adjtimex field being tested so we can verify later */
+	timex_show("SET", &ttxc);
 
-		ptroff = (long) tc[i].ptr - (long) &ttxc;
-		ptr = (void *) &verify + ptroff;
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(&verify));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
 	}
 
-	TEST(sys_clock_adjtime(CLOCK_REALTIME, &verify));
-	timex_show("VERIFY", verify);
+	timex_show("VERIFY", &verify);
 
-	if (tc[i].ptr && *tc[i].ptr != *ptr) {
+	if (tc[i].delta &&
+	    timex_get_field_long(&ttxc, tc[i].modes) !=
+	    timex_get_field_long(&verify, tc[i].modes)) {
 		tst_res(TFAIL, "clock_adjtime(): could not set value (mode=%x)",
-				tc[i].modes);
+			tc[i].modes);
 	}
 
 	if (TST_RET < 0) {
@@ -165,14 +189,23 @@ static void verify_clock_adjtime(unsigned int i)
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	size_t i;
 	int rval;
 
-	rval = SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+
+	saved.type = tv->type;
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(&saved));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
+	}
+
 	supported = 1;
 
 	if (rval != TIME_OK && rval != TIME_ERROR) {
-		timex_show("SAVE_STATUS", saved);
+		timex_show("SAVE_STATUS", &saved);
 		tst_brk(TBROK | TTERRNO, "clock has on-going leap changes, "
 				"returned: %i", rval);
 	}
@@ -188,7 +221,7 @@ static void setup(void)
 
 		/* fix usec as being test default resolution */
 
-		if (saved.modes & ADJ_NANO) {
+		if (timex_get_field_uint(&saved, ADJ_MODES) & ADJ_NANO) {
 			if (tc[i].modes == ADJ_OFFSET) {
 				tc[i].highlimit *= 1000;
 				tc[i].delta *= 1000;
@@ -199,21 +232,29 @@ static void setup(void)
 
 static void cleanup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+	unsigned int modes = ADJ_ALL;
+	int rval;
+
 	if (supported == 0)
 		return;
 
-	saved.modes = ADJ_ALL;
-
 	/* restore clock resolution based on original status flag */
 
-	if (saved.status & STA_NANO)
-		saved.modes |= ADJ_NANO;
+	if (timex_get_field_uint(&saved, ADJ_STATUS) & STA_NANO)
+		modes |= ADJ_NANO;
 	else
-		saved.modes |= ADJ_MICRO;
+		modes |= ADJ_MICRO;
+
+	timex_set_field_uint(&saved, ADJ_MODES, modes);
 
 	/* restore original clock flags */
 
-	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(&saved));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
+	}
 }
 
 static struct tst_test test = {
@@ -221,6 +262,7 @@ static struct tst_test test = {
 	.setup = setup,
 	.cleanup = cleanup,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = ARRAY_SIZE(variants),
 	.needs_root = 1,
 	.restore_wallclock = 1,
 };
diff --git a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime02.c b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime02.c
index ba8eae54f5ed..9f957f7643b0 100644
--- a/testcases/kernel/syscalls/clock_adjtime/clock_adjtime02.c
+++ b/testcases/kernel/syscalls/clock_adjtime/clock_adjtime02.c
@@ -56,9 +56,10 @@
  */
 
 #include "clock_adjtime.h"
+#include "lapi/abisize.h"
 
 static long hz;
-static struct timex saved, ttxc;
+static struct tst_timex saved, ttxc;
 static int supported;
 
 static void cleanup(void);
@@ -68,7 +69,6 @@ struct test_case {
 	unsigned int modes;
 	long lowlimit;
 	long highlimit;
-	long *ptr;
 	long delta;
 	int exp_err;
 	int droproot;
@@ -92,7 +92,6 @@ struct test_case tc[] = {
 	 .clktype = CLOCK_REALTIME,
 	 .modes = ADJ_TICK,
 	 .lowlimit = 900000,
-	 .ptr = &ttxc.tick,
 	 .delta = 1,
 	 .exp_err = EINVAL,
 	},
@@ -100,7 +99,6 @@ struct test_case tc[] = {
 	 .clktype = CLOCK_REALTIME,
 	 .modes = ADJ_TICK,
 	 .highlimit = 1100000,
-	 .ptr = &ttxc.tick,
 	 .delta = 1,
 	 .exp_err = EINVAL,
 	},
@@ -112,19 +110,43 @@ struct test_case tc[] = {
 	},
 };
 
+static struct test_variants {
+	int (*func)(clockid_t clk_id, void *timex);
+	enum tst_timex_type type;
+	char *desc;
+} variants[] = {
+#if defined(TST_ABI32)
+	{ .func = sys_clock_adjtime, .type = TST_LIBC_TIMEX, .desc = "syscall with libc spec"},
+#endif
+
+#if defined(TST_ABI64)
+	{ .func = sys_clock_adjtime, .type = TST_KERN_TIMEX, .desc = "syscall with kernel spec64"},
+#endif
+
+#if (__NR_clock_adjtime64 != __LTP__NR_INVALID_SYSCALL)
+	{ .func = sys_clock_adjtime64, .type = TST_KERN_TIMEX, .desc = "syscall time64 with kernel spec64"},
+#endif
+};
+
 static void verify_clock_adjtime(unsigned int i)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	uid_t whoami = 0;
-	struct timex *txcptr;
+	struct tst_timex *txcptr = &ttxc;
 	struct passwd *nobody;
 	static const char name[] = "nobody";
+	int rval;
 
-	txcptr = &ttxc;
+	memset(txcptr, 0, sizeof(*txcptr));
 
-	memset(txcptr, 0, sizeof(struct timex));
+	txcptr->type = tv->type;
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(txcptr));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
+	}
 
-	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, txcptr);
-	timex_show("GET", *txcptr);
+	timex_show("GET", txcptr);
 
 	if (tc[i].droproot) {
 		nobody = SAFE_GETPWNAM(name);
@@ -132,24 +154,23 @@ static void verify_clock_adjtime(unsigned int i)
 		SAFE_SETEUID(whoami);
 	}
 
-	txcptr->modes = tc[i].modes;
-
-	if (tc[i].ptr) {
+	timex_set_field_uint(txcptr, ADJ_MODES, tc[i].modes);
 
+	if (tc[i].delta) {
 		if (tc[i].lowlimit)
-			*tc[i].ptr = tc[i].lowlimit - tc[i].delta;
+			timex_set_field_long(&ttxc, tc[i].modes, tc[i].lowlimit - tc[i].delta);
 
 		if (tc[i].highlimit)
-			*tc[i].ptr = tc[i].highlimit + tc[i].delta;
+			timex_set_field_long(&ttxc, tc[i].modes, tc[i].highlimit + tc[i].delta);
 	}
 
 	/* special case: EFAULT for bad addresses */
-	if (tc[i].exp_err == EFAULT)
-		txcptr = tst_get_bad_addr(cleanup);
-
-	TEST(sys_clock_adjtime(tc[i].clktype, txcptr));
-	if (txcptr && tc[i].exp_err != EFAULT)
-		timex_show("TEST", *txcptr);
+	if (tc[i].exp_err == EFAULT) {
+		TEST(tv->func(tc[i].clktype, tst_get_bad_addr(NULL)));
+	} else {
+		TEST(tv->func(tc[i].clktype, tst_timex_get(txcptr)));
+		timex_show("TEST", txcptr);
+	}
 
 	if (TST_RET >= 0) {
 		tst_res(TFAIL, "clock_adjtime(): passed unexpectedly (mode=%x, "
@@ -173,14 +194,23 @@ static void verify_clock_adjtime(unsigned int i)
 
 static void setup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
 	size_t i;
 	int rval;
 
-	rval = SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
+	tst_res(TINFO, "Testing variant: %s", tv->desc);
+
+	saved.type = tv->type;
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(&saved));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
+	}
+
 	supported = 1;
 
 	if (rval != TIME_OK && rval != TIME_ERROR) {
-		timex_show("SAVE_STATUS", saved);
+		timex_show("SAVE_STATUS", &saved);
 		tst_brk(TBROK | TTERRNO, "clock has on-going leap changes, "
 				"returned: %i", rval);
 	}
@@ -199,21 +229,29 @@ static void setup(void)
 
 static void cleanup(void)
 {
+	struct test_variants *tv = &variants[tst_variant];
+	unsigned int modes = ADJ_ALL;
+	int rval;
+
 	if (supported == 0)
 		return;
 
-	saved.modes = ADJ_ALL;
-
 	/* restore clock resolution based on original status flag */
 
-	if (saved.status & STA_NANO)
-		saved.modes |= ADJ_NANO;
+	if (timex_get_field_uint(&saved, ADJ_STATUS) & STA_NANO)
+		modes |= ADJ_NANO;
 	else
-		saved.modes |= ADJ_MICRO;
+		modes |= ADJ_MICRO;
+
+	timex_set_field_uint(&saved, ADJ_MODES, modes);
 
 	/* restore original clock flags */
 
-	SAFE_CLOCK_ADJTIME(CLOCK_REALTIME, &saved);
+	rval = tv->func(CLOCK_REALTIME, tst_timex_get(&saved));
+	if (rval < 0) {
+		tst_res(TFAIL | TERRNO, "clock_adjtime() failed %i", rval);
+		return;
+	}
 }
 
 static struct tst_test test = {
@@ -221,6 +259,7 @@ static struct tst_test test = {
 	.setup = setup,
 	.cleanup = cleanup,
 	.tcnt = ARRAY_SIZE(tc),
+	.test_variants = ARRAY_SIZE(variants),
 	.needs_root = 1,
 	.restore_wallclock = 1,
 };
-- 
2.25.0.rc1.19.g042ed3e048af



More information about the ltp mailing list