179 lines
4.4 KiB
C
179 lines
4.4 KiB
C
// 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.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#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"
|
|
|
|
#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 buf;
|
|
|
|
TEST(statx(AT_FDCWD, file_name, flag_type, STATX_ALL, &buf));
|
|
|
|
if (TST_RET == -1) {
|
|
tst_brk(TFAIL | TST_ERR,
|
|
"statx(AT_FDCWD, %s, %s, STATX_ALL, &buf)",
|
|
file_name, flag_name);
|
|
}
|
|
|
|
tst_res(TINFO, "statx(AT_FDCWD, %s, %s, STATX_ALL, &buf) = %o",
|
|
file_name, flag_name, buf.stx_mode);
|
|
|
|
return buf.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;
|
|
|
|
get_mode(tc->client_file, AT_STATX_FORCE_SYNC, "AT_STATX_FORCE_SYNC");
|
|
|
|
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",
|
|
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);
|
|
}
|
|
|
|
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,fsid=%d *%.1024s",
|
|
getpid(), 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 || errno == ECONNREFUSED
|
|
|| errno == ETIMEDOUT)
|
|
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,
|
|
};
|