1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2014 Fujitsu Ltd.
4f08c3bdfSopenharmony_ci * Author: Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com>
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci/*
8f08c3bdfSopenharmony_ci * Note: this test has already been in xfstests generic/028 test case,
9f08c3bdfSopenharmony_ci * I just port it to LTP.
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * Kernel commit '232d2d60aa5469bb097f55728f65146bd49c1d25' introduced a race
12f08c3bdfSopenharmony_ci * condition that causes getcwd(2) to return "/" instead of correct path.
13f08c3bdfSopenharmony_ci *     232d2d6 dcache: Translating dentry into pathname without
14f08c3bdfSopenharmony_ci *             taking rename_lock
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci * And these two kernel commits fixed the bug:
17f08c3bdfSopenharmony_ci *   ede4cebce16f5643c61aedd6d88d9070a1d23a68
18f08c3bdfSopenharmony_ci *	prepend_path() needs to reinitialize dentry/vfsmount/mnt on restarts
19f08c3bdfSopenharmony_ci *   f6500801522c61782d4990fa1ad96154cb397cd4
20f08c3bdfSopenharmony_ci *	f650080 __dentry_path() fixes
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci * This test is to check whether this bug exists in the running kernel,
23f08c3bdfSopenharmony_ci * or whether this bug has been fixed.
24f08c3bdfSopenharmony_ci */
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_ci#include <stdio.h>
27f08c3bdfSopenharmony_ci#include <errno.h>
28f08c3bdfSopenharmony_ci#include <fcntl.h>
29f08c3bdfSopenharmony_ci#include <sys/types.h>
30f08c3bdfSopenharmony_ci#include <unistd.h>
31f08c3bdfSopenharmony_ci#include "tst_test.h"
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci#define TIMEOUT	5
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_cistatic void do_child(void);
36f08c3bdfSopenharmony_cistatic void sigproc(int sig);
37f08c3bdfSopenharmony_cistatic volatile sig_atomic_t end;
38f08c3bdfSopenharmony_cistatic char init_cwd[PATH_MAX];
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_cistatic void verify_getcwd(void)
41f08c3bdfSopenharmony_ci{
42f08c3bdfSopenharmony_ci	int status;
43f08c3bdfSopenharmony_ci	char cur_cwd[PATH_MAX];
44f08c3bdfSopenharmony_ci	pid_t child;
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci	child = SAFE_FORK();
47f08c3bdfSopenharmony_ci	if (child == 0)
48f08c3bdfSopenharmony_ci		do_child();
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci	 while (1) {
51f08c3bdfSopenharmony_ci		SAFE_GETCWD(cur_cwd, PATH_MAX);
52f08c3bdfSopenharmony_ci		if (strncmp(init_cwd, cur_cwd, PATH_MAX)) {
53f08c3bdfSopenharmony_ci			tst_res(TFAIL, "initial current work directory is "
54f08c3bdfSopenharmony_ci				 "%s, now is %s. Bug is reproduced!",
55f08c3bdfSopenharmony_ci				 init_cwd, cur_cwd);
56f08c3bdfSopenharmony_ci			break;
57f08c3bdfSopenharmony_ci		}
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_ci		if (end) {
60f08c3bdfSopenharmony_ci			tst_res(TPASS, "Bug is not reproduced!");
61f08c3bdfSopenharmony_ci			break;
62f08c3bdfSopenharmony_ci		}
63f08c3bdfSopenharmony_ci	}
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci	SAFE_KILL(child, SIGKILL);
66f08c3bdfSopenharmony_ci	SAFE_WAITPID(child, &status, 0);
67f08c3bdfSopenharmony_ci}
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_cistatic void setup(void)
70f08c3bdfSopenharmony_ci{
71f08c3bdfSopenharmony_ci	SAFE_SIGNAL(SIGALRM, sigproc);
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	alarm(TIMEOUT);
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci	SAFE_GETCWD(init_cwd, PATH_MAX);
76f08c3bdfSopenharmony_ci}
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_cistatic void sigproc(int sig)
79f08c3bdfSopenharmony_ci{
80f08c3bdfSopenharmony_ci	end = sig;
81f08c3bdfSopenharmony_ci}
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_cistatic void do_child(void)
84f08c3bdfSopenharmony_ci{
85f08c3bdfSopenharmony_ci	unsigned int i = 0;
86f08c3bdfSopenharmony_ci	char c_name[PATH_MAX] = "testfile", n_name[PATH_MAX];
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci	SAFE_TOUCH(c_name, 0644, NULL);
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ci	while (1) {
91f08c3bdfSopenharmony_ci		snprintf(n_name, PATH_MAX, "testfile%u", i++);
92f08c3bdfSopenharmony_ci		SAFE_RENAME(c_name, n_name);
93f08c3bdfSopenharmony_ci		strncpy(c_name, n_name, PATH_MAX);
94f08c3bdfSopenharmony_ci	}
95f08c3bdfSopenharmony_ci}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_cistatic struct tst_test test = {
98f08c3bdfSopenharmony_ci	.setup = setup,
99f08c3bdfSopenharmony_ci	.test_all = verify_getcwd,
100f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
101f08c3bdfSopenharmony_ci	.forks_child = 1,
102f08c3bdfSopenharmony_ci	.min_cpus = 2
103f08c3bdfSopenharmony_ci};
104