[v6] syscalls/statx: Add test for sync flags

Message ID 1545807270-3790-1-git-send-email-vaishnavi.d@zilogic.com
State Accepted
Headers show
Series
  • [v6] syscalls/statx: Add test for sync flags
Related show

Commit Message

vaishnavi.d Dec. 26, 2018, 6:54 a.m.
Testcase 1: AT_STATX_DONT_SYNC
 With AT_STATX_DONT_SYNC server changes should not get sync with client.

Testcase 2: AT_STATX_FORCE_SYNC
 With AT_STATX_FORCE_SYNC server changes should get sync with client.

Signed-off-by: Kewal Ukunde <kewal@zilogic.com>
Signed-off-by: Vaishnavi.d <vaishnavi.d@zilogic.com>
Signed-off-by: Tarun.T.U <tarun@zilogic.com>
---
 include/lapi/stat.h                        |   2 +
 runtest/syscalls                           |   1 +
 testcases/kernel/syscalls/statx/.gitignore |   1 +
 testcases/kernel/syscalls/statx/statx07.c  | 164 +++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+)
 create mode 100644 testcases/kernel/syscalls/statx/statx07.c

Comments

Cyril Hrubis Jan. 4, 2019, 11:36 a.m. | #1
Hi!
I've been playing with this test and apart from minor things there is
one problem that has to be fixed. It looks like the nfs cache is not
fully deterministic.

For instance the test fails on freshly booted machine, then line about
initializing nfs fs cache appears in kernel log. From that point on the
probability of failure is small but still not neglectible.

So for now I would like to skip this test from being included in the
release, then once LTP is released I will return to it and try to figure
out how to fix it.
Cyril Hrubis Feb. 21, 2019, 11:09 a.m. | #2
Hi!
Pushed with a few changes, see below, thanks a lot for the work.

Also sorry for the long delay.

--- a/testcases/kernel/syscalls/statx/statx07.c
+++ b/testcases/kernel/syscalls/statx/statx07.c
@@ -26,8 +26,19 @@
  * AT_STATX_FORCE_SYNC is called to create cache data of the file.
  * Then, by using DONT_SYNC_FILE getting old cached data in client folder,
  * but mode has been chaged in server file.
+ *
+ * The support for SYNC flags was implemented in NFS in:
+ *
+ * commit 9ccee940bd5b766b6dab6c1a80908b9490a4850d
+ * Author: Trond Myklebust <trond.myklebust@primarydata.com>
+ * Date:   Thu Jan 4 17:46:09 2018 -0500
+ *
+ *     Support statx() mask and query flags parameters
+ *
+ * Hence we skip the test on anything older than 4.16.
  */

(Added explanation why we skip the test on kernels prior 4.16)

+#define _GNU_SOURCE
(The _GNU_SOURCE has to be defined before we include anything from libc,
moved it here from the lapi header)
 #include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -58,19 +69,20 @@ static int exported;
 
 static int get_mode(char *file_name, int flag_type, char *flag_name)
 {
-	struct statx buff;
+	struct statx buf;
 
-	TEST(statx(AT_FDCWD, file_name, flag_type, STATX_ALL, &buff));
+	TEST(statx(AT_FDCWD, file_name, flag_type, STATX_ALL, &buf));
 
-	if (TST_RET == -1)
+	if (TST_RET == -1) {
 		tst_brk(TFAIL | TST_ERR,
-			"statx(AT_FDCWD, %s, %s, STATX_ALL, &buff)",
-			file_name, flag_name);
-	else
-		tst_res(TINFO, "statx(AT_FDCWD, %s, %s, STATX_ALL, &buff)",
+			"statx(AT_FDCWD, %s, %s, STATX_ALL, &buf)",
 			file_name, flag_name);
+	}
 
-	return buff.stx_mode;
+	tst_res(TINFO, "statx(AT_FDCWD, %s, %s, STATX_ALL, &buf) = %o",
+		file_name, flag_name, buf.stx_mode);
+
+	return buf.stx_mode;
 }

(Just minor changes)

 const struct test_cases {
@@ -89,20 +101,22 @@ static void test_statx(unsigned int i)
 	const struct test_cases *tc = &tcases[i];
 	unsigned int cur_mode;
 
-	if (tc->flag == AT_STATX_DONT_SYNC)
-		get_mode(tc->client_file, tc->flag, tc->flag_name);
+	get_mode(tc->client_file, AT_STATX_FORCE_SYNC, "AT_STATX_FORCE_SYNC");

(This has been changed so that we are sure that the old data are in the
cache so we do FORCE_SYNC statx regardless the test)
 
 	SAFE_CHMOD(tc->server_file, CURRENT_MODE);
 	cur_mode = get_mode(tc->client_file, tc->flag, tc->flag_name);
 
-	if (MODE(cur_mode) == tc->mode)
+	if (MODE(cur_mode) == tc->mode) {
 		tst_res(TPASS,
-			"statx() with %s for mode %o %o",
-			tc->flag_name, tc->mode, MODE(cur_mode));
-	else
+			"statx() with %s for mode %o",
+			tc->flag_name, tc->mode);
+	} else {
 		tst_res(TFAIL,
 			"statx() with %s for mode %o %o",
 			tc->flag_name, tc->mode, MODE(cur_mode));
+	}
+
+	SAFE_CHMOD(tc->server_file, DEFAULT_MODE);

(And we reset the file mode back after the test so that we do something
meaningful for the -i test option)

 }


 static void setup(void)
@@ -131,7 +145,7 @@ static void setup(void)
 		tst_brk(TBROK | TST_ERR, "failed to exportfs");
 
 	if (mount(server_path, CLI_PATH, "nfs", 0, "addr=127.0.0.1")) {
-		if (errno == EOPNOTSUPP)
+		if (errno == EOPNOTSUPP || errno == ECONNREFUSED)
 			tst_brk(TCONF | TERRNO, "nfs server not set up?");

(And I've found that on some distros we got ECONNREFUSED if nfs server
is not set up)

 		tst_brk(TBROK | TERRNO, "mount() nfs failed");
 	}

Patch

diff --git a/include/lapi/stat.h b/include/lapi/stat.h
index 979e42d..9e55130 100644
--- a/include/lapi/stat.h
+++ b/include/lapi/stat.h
@@ -7,6 +7,8 @@ 
 #ifndef LAPI_STAT_H
 #define LAPI_STAT_H
 
+#define _GNU_SOURCE
+
 #include <stdint.h>
 #include <unistd.h>
 #include "lapi/syscalls.h"
diff --git a/runtest/syscalls b/runtest/syscalls
index ac1d2d2..957b999 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1524,5 +1524,6 @@  statx03 statx03
 statx04 statx04
 statx05 statx05
 statx06 statx06
+statx07 statx07
 
 membarrier01 membarrier01
diff --git a/testcases/kernel/syscalls/statx/.gitignore b/testcases/kernel/syscalls/statx/.gitignore
index c1cedda..2f5457e 100644
--- a/testcases/kernel/syscalls/statx/.gitignore
+++ b/testcases/kernel/syscalls/statx/.gitignore
@@ -4,3 +4,4 @@ 
 /statx04
 /statx05
 /statx06
+/statx07
diff --git a/testcases/kernel/syscalls/statx/statx07.c b/testcases/kernel/syscalls/statx/statx07.c
new file mode 100644
index 0000000..e61ef69
--- /dev/null
+++ b/testcases/kernel/syscalls/statx/statx07.c
@@ -0,0 +1,164 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  Copyright (c) Zilogic Systems Pvt. Ltd., 2018
+ *  Email : code@zilogic.com
+ */
+
+/*
+ * Test statx
+ *
+ * This code tests the following flags:
+ * 1) AT_STATX_FORCE_SYNC
+ * 2) AT_STATX_DONT_SYNC
+ *
+ * By exportfs cmd creating NFS setup.
+ *
+ * A test file is created in server folder and statx is being
+ * done in client folder.
+ *
+ * TESTCASE 1:
+ * BY AT_STATX_SYNC_AS_STAT getting predefined mode value.
+ * Then, by using AT_STATX_FORCE_SYNC getting new updated vaue
+ * from server file changes.
+ *
+ * TESTCASE 2:
+ * BY AT_STATX_SYNC_AS_STAT getting predefined mode value.
+ * AT_STATX_FORCE_SYNC is called to create cache data of the file.
+ * Then, by using DONT_SYNC_FILE getting old cached data in client folder,
+ * but mode has been chaged in server file.
+ */
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/limits.h>
+#include <sys/mount.h>
+#include "tst_test.h"
+#include "lapi/stat.h"
+#include "old_tmpdir.h"
+
+#define MODE(X) (X & (~S_IFMT))
+#define FLAG_NAME(x) .flag = x, .flag_name = #x
+#define BUFF_SIZE PATH_MAX
+#define DEFAULT_MODE 0644
+#define CURRENT_MODE 0777
+
+#define CLI_PATH "client"
+#define SERV_PATH "server"
+#define CLI_FORCE_SYNC "client/force_sync_file"
+#define CLI_DONT_SYNC "client/dont_sync_file"
+#define SERV_FORCE_SYNC "server/force_sync_file"
+#define SERV_DONT_SYNC "server/dont_sync_file"
+
+static char *cwd;
+static char cmd[BUFF_SIZE];
+static int mounted;
+static int exported;
+
+static int get_mode(char *file_name, int flag_type, char *flag_name)
+{
+	struct statx buff;
+
+	TEST(statx(AT_FDCWD, file_name, flag_type, STATX_ALL, &buff));
+
+	if (TST_RET == -1)
+		tst_brk(TFAIL | TST_ERR,
+			"statx(AT_FDCWD, %s, %s, STATX_ALL, &buff)",
+			file_name, flag_name);
+	else
+		tst_res(TINFO, "statx(AT_FDCWD, %s, %s, STATX_ALL, &buff)",
+			file_name, flag_name);
+
+	return buff.stx_mode;
+}
+
+const struct test_cases {
+	int flag;
+	char *flag_name;
+	char *server_file;
+	char *client_file;
+	unsigned int mode;
+} tcases[] = {
+	{FLAG_NAME(AT_STATX_DONT_SYNC), SERV_DONT_SYNC, CLI_DONT_SYNC, DEFAULT_MODE},
+	{FLAG_NAME(AT_STATX_FORCE_SYNC), SERV_FORCE_SYNC, CLI_FORCE_SYNC, CURRENT_MODE}
+};
+
+static void test_statx(unsigned int i)
+{
+	const struct test_cases *tc = &tcases[i];
+	unsigned int cur_mode;
+
+	if (tc->flag == AT_STATX_DONT_SYNC)
+		get_mode(tc->client_file, tc->flag, tc->flag_name);
+
+	SAFE_CHMOD(tc->server_file, CURRENT_MODE);
+	cur_mode = get_mode(tc->client_file, tc->flag, tc->flag_name);
+
+	if (MODE(cur_mode) == tc->mode)
+		tst_res(TPASS,
+			"statx() with %s for mode %o %o",
+			tc->flag_name, tc->mode, MODE(cur_mode));
+	else
+		tst_res(TFAIL,
+			"statx() with %s for mode %o %o",
+			tc->flag_name, tc->mode, MODE(cur_mode));
+}
+
+static void setup(void)
+{
+	int ret;
+	char server_path[BUFF_SIZE];
+
+	cwd = tst_get_tmpdir();
+
+	SAFE_MKDIR(SERV_PATH, DEFAULT_MODE);
+	SAFE_MKDIR(CLI_PATH, DEFAULT_MODE);
+	SAFE_CREAT(SERV_FORCE_SYNC, DEFAULT_MODE);
+	SAFE_CREAT(SERV_DONT_SYNC, DEFAULT_MODE);
+
+	snprintf(server_path, sizeof(server_path), ":%s/%s", cwd, SERV_PATH);
+
+	snprintf(cmd, sizeof(cmd),
+		 "exportfs -i -o no_root_squash,rw,sync,no_subtree_check *%.1024s",
+		 server_path);
+	exported = 1;
+
+	ret = tst_system(cmd);
+	if (WEXITSTATUS(ret) == 127)
+		tst_brk(TCONF | TST_ERR, "%s not found", cmd);
+	if (ret)
+		tst_brk(TBROK | TST_ERR, "failed to exportfs");
+
+	if (mount(server_path, CLI_PATH, "nfs", 0, "addr=127.0.0.1")) {
+		if (errno == EOPNOTSUPP)
+			tst_brk(TCONF | TERRNO, "nfs server not set up?");
+		tst_brk(TBROK | TERRNO, "mount() nfs failed");
+	}
+	mounted = 1;
+}
+
+static void cleanup(void)
+{
+	if (!exported)
+		return;
+	snprintf(cmd, sizeof(cmd),
+		 "exportfs -u *:%s/%s", cwd, SERV_PATH);
+
+	if (tst_system(cmd) == -1)
+		tst_res(TWARN | TST_ERR, "failed to clear exportfs");
+
+	if (mounted)
+		SAFE_UMOUNT(CLI_PATH);
+}
+
+static struct tst_test test = {
+	.tcnt = ARRAY_SIZE(tcases),
+	.test = test_statx,
+	.setup = setup,
+	.cleanup = cleanup,
+	.min_kver = "4.16",
+	.needs_tmpdir = 1,
+	.dev_fs_type = "nfs",
+	.needs_root = 1,
+};