1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 4f08c3bdfSopenharmony_ci * Email : code@zilogic.com 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/*\ 8f08c3bdfSopenharmony_ci * [Description] 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This code tests the following flags: 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * - AT_STATX_FORCE_SYNC 13f08c3bdfSopenharmony_ci * - AT_STATX_DONT_SYNC 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * By exportfs cmd creating NFS setup. 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * A test file is created in server folder and statx is being 18f08c3bdfSopenharmony_ci * done in client folder. 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * BY AT_STATX_SYNC_AS_STAT getting predefined mode value. 21f08c3bdfSopenharmony_ci * Then, by using AT_STATX_FORCE_SYNC getting new updated vaue 22f08c3bdfSopenharmony_ci * from server file changes. 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * BY AT_STATX_SYNC_AS_STAT getting predefined mode value. 25f08c3bdfSopenharmony_ci * AT_STATX_FORCE_SYNC is called to create cache data of the file. 26f08c3bdfSopenharmony_ci * Then, by using DONT_SYNC_FILE getting old cached data in client folder, 27f08c3bdfSopenharmony_ci * but mode has been chaged in server file. 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * The support for SYNC flags was implemented in NFS in: 30f08c3bdfSopenharmony_ci * 9ccee940bd5b ("Support statx() mask and query flags parameters") 31f08c3bdfSopenharmony_ci */ 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci#define _GNU_SOURCE 34f08c3bdfSopenharmony_ci#include <netdb.h> 35f08c3bdfSopenharmony_ci#include <stdio.h> 36f08c3bdfSopenharmony_ci#include <stdlib.h> 37f08c3bdfSopenharmony_ci#include <errno.h> 38f08c3bdfSopenharmony_ci#include <linux/limits.h> 39f08c3bdfSopenharmony_ci#include <sys/mount.h> 40f08c3bdfSopenharmony_ci#include "tst_test.h" 41f08c3bdfSopenharmony_ci#include "lapi/stat.h" 42f08c3bdfSopenharmony_ci#include "lapi/fcntl.h" 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci#define MODE(X) (X & (~S_IFMT)) 45f08c3bdfSopenharmony_ci#define FLAG_NAME(x) .flag = x, .flag_name = #x 46f08c3bdfSopenharmony_ci#define BUFF_SIZE PATH_MAX 47f08c3bdfSopenharmony_ci#define DEFAULT_MODE 0644 48f08c3bdfSopenharmony_ci#define CURRENT_MODE 0777 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci#define CLI_PATH "client" 51f08c3bdfSopenharmony_ci#define SERV_PATH "server" 52f08c3bdfSopenharmony_ci#define CLI_FORCE_SYNC "client/force_sync_file" 53f08c3bdfSopenharmony_ci#define CLI_DONT_SYNC "client/dont_sync_file" 54f08c3bdfSopenharmony_ci#define SERV_FORCE_SYNC "server/force_sync_file" 55f08c3bdfSopenharmony_ci#define SERV_DONT_SYNC "server/dont_sync_file" 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic char *cwd; 58f08c3bdfSopenharmony_cistatic char cmd[BUFF_SIZE]; 59f08c3bdfSopenharmony_cistatic int mounted; 60f08c3bdfSopenharmony_cistatic int exported; 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_cistatic int get_mode(char *file_name, int flag_type, char *flag_name) 63f08c3bdfSopenharmony_ci{ 64f08c3bdfSopenharmony_ci struct statx buf; 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci TEST(statx(AT_FDCWD, file_name, flag_type, STATX_BASIC_STATS, &buf)); 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci if (TST_RET == -1) { 69f08c3bdfSopenharmony_ci tst_brk(TFAIL | TST_ERR, 70f08c3bdfSopenharmony_ci "statx(AT_FDCWD, %s, %s, STATX_BASIC_STATS, &buf)", 71f08c3bdfSopenharmony_ci file_name, flag_name); 72f08c3bdfSopenharmony_ci } 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci tst_res(TINFO, "statx(AT_FDCWD, %s, %s, STATX_BASIC_STATS, &buf) = %o", 75f08c3bdfSopenharmony_ci file_name, flag_name, buf.stx_mode); 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci return buf.stx_mode; 78f08c3bdfSopenharmony_ci} 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_cistatic const struct test_cases { 81f08c3bdfSopenharmony_ci int flag; 82f08c3bdfSopenharmony_ci char *flag_name; 83f08c3bdfSopenharmony_ci char *server_file; 84f08c3bdfSopenharmony_ci char *client_file; 85f08c3bdfSopenharmony_ci unsigned int mode; 86f08c3bdfSopenharmony_ci} tcases[] = { 87f08c3bdfSopenharmony_ci {FLAG_NAME(AT_STATX_DONT_SYNC), SERV_DONT_SYNC, CLI_DONT_SYNC, DEFAULT_MODE}, 88f08c3bdfSopenharmony_ci {FLAG_NAME(AT_STATX_FORCE_SYNC), SERV_FORCE_SYNC, CLI_FORCE_SYNC, CURRENT_MODE} 89f08c3bdfSopenharmony_ci}; 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_cistatic void test_statx(unsigned int i) 92f08c3bdfSopenharmony_ci{ 93f08c3bdfSopenharmony_ci const struct test_cases *tc = &tcases[i]; 94f08c3bdfSopenharmony_ci unsigned int cur_mode; 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci get_mode(tc->client_file, AT_STATX_FORCE_SYNC, "AT_STATX_FORCE_SYNC"); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci SAFE_CHMOD(tc->server_file, CURRENT_MODE); 99f08c3bdfSopenharmony_ci cur_mode = get_mode(tc->client_file, tc->flag, tc->flag_name); 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci if (MODE(cur_mode) == tc->mode) { 102f08c3bdfSopenharmony_ci tst_res(TPASS, 103f08c3bdfSopenharmony_ci "statx() with %s for mode %o", 104f08c3bdfSopenharmony_ci tc->flag_name, tc->mode); 105f08c3bdfSopenharmony_ci } else { 106f08c3bdfSopenharmony_ci tst_res(TFAIL, 107f08c3bdfSopenharmony_ci "statx() with %s for mode %o %o", 108f08c3bdfSopenharmony_ci tc->flag_name, tc->mode, MODE(cur_mode)); 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci SAFE_CHMOD(tc->server_file, DEFAULT_MODE); 112f08c3bdfSopenharmony_ci} 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_cistatic void setup(void) 115f08c3bdfSopenharmony_ci{ 116f08c3bdfSopenharmony_ci int ret; 117f08c3bdfSopenharmony_ci char server_path[BUFF_SIZE]; 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci cwd = tst_get_tmpdir(); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci SAFE_MKDIR(SERV_PATH, DEFAULT_MODE); 122f08c3bdfSopenharmony_ci SAFE_MKDIR(CLI_PATH, DEFAULT_MODE); 123f08c3bdfSopenharmony_ci SAFE_CREAT(SERV_FORCE_SYNC, DEFAULT_MODE); 124f08c3bdfSopenharmony_ci SAFE_CREAT(SERV_DONT_SYNC, DEFAULT_MODE); 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci snprintf(server_path, sizeof(server_path), ":%s/%s", cwd, SERV_PATH); 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci snprintf(cmd, sizeof(cmd), 129f08c3bdfSopenharmony_ci "exportfs -i -o no_root_squash,rw,sync,no_subtree_check,fsid=%d *%.1024s", 130f08c3bdfSopenharmony_ci getpid(), server_path); 131f08c3bdfSopenharmony_ci exported = 1; 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci ret = tst_system(cmd); 134f08c3bdfSopenharmony_ci if (ret) 135f08c3bdfSopenharmony_ci tst_brk(TBROK | TST_ERR, "failed to exportfs"); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci if (mount(server_path, CLI_PATH, "nfs", 0, "addr=127.0.0.1")) { 138f08c3bdfSopenharmony_ci if (errno == EOPNOTSUPP || errno == ECONNREFUSED 139f08c3bdfSopenharmony_ci || errno == ETIMEDOUT) 140f08c3bdfSopenharmony_ci tst_brk(TCONF | TERRNO, "nfs server not set up?"); 141f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "mount() nfs failed"); 142f08c3bdfSopenharmony_ci } 143f08c3bdfSopenharmony_ci mounted = 1; 144f08c3bdfSopenharmony_ci} 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_cistatic void cleanup(void) 147f08c3bdfSopenharmony_ci{ 148f08c3bdfSopenharmony_ci if (mounted) 149f08c3bdfSopenharmony_ci SAFE_UMOUNT(CLI_PATH); 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci if (!exported) 152f08c3bdfSopenharmony_ci return; 153f08c3bdfSopenharmony_ci snprintf(cmd, sizeof(cmd), 154f08c3bdfSopenharmony_ci "exportfs -u *:%s/%s", cwd, SERV_PATH); 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci if (tst_system(cmd) == -1) 157f08c3bdfSopenharmony_ci tst_res(TWARN | TST_ERR, "failed to clear exportfs"); 158f08c3bdfSopenharmony_ci} 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_cistatic struct tst_test test = { 161f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 162f08c3bdfSopenharmony_ci .test = test_statx, 163f08c3bdfSopenharmony_ci .setup = setup, 164f08c3bdfSopenharmony_ci .cleanup = cleanup, 165f08c3bdfSopenharmony_ci .min_kver = "4.16", 166f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 167f08c3bdfSopenharmony_ci .dev_fs_type = "nfs", 168f08c3bdfSopenharmony_ci .needs_root = 1, 169f08c3bdfSopenharmony_ci .needs_cmds = (const char *[]) { 170f08c3bdfSopenharmony_ci "exportfs", 171f08c3bdfSopenharmony_ci NULL 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci}; 174