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 | expand |
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.
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"); }
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, +};