• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Copyright (c) 2014 Fujitsu Ltd.
3  *   Author: Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com>
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  */
15 
16 /*
17  * Note: this test has already been in xfstests generic/028 test case,
18  * I just port it to LTP.
19  *
20  * Kernel commit '232d2d60aa5469bb097f55728f65146bd49c1d25' introduced a race
21  * condition that causes getcwd(2) to return "/" instead of correct path.
22  *     232d2d6 dcache: Translating dentry into pathname without
23  *             taking rename_lock
24  *
25  * And these two kernel commits fixed the bug:
26  *   ede4cebce16f5643c61aedd6d88d9070a1d23a68
27  *	prepend_path() needs to reinitialize dentry/vfsmount/mnt on restarts
28  *   f6500801522c61782d4990fa1ad96154cb397cd4
29  *	f650080 __dentry_path() fixes
30  *
31  * This test is to check whether this bug exists in the running kernel,
32  * or whether this bug has been fixed.
33  *
34  */
35 
36 #include <stdio.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include "test.h"
42 #include "safe_macros.h"
43 
44 #define TIMEOUT	5
45 
46 static void setup(void);
47 static void cleanup(void);
48 static void do_child(void);
49 static void sigproc(int sig);
50 static volatile sig_atomic_t end;
51 static char init_cwd[PATH_MAX];
52 
53 char *TCID = "getcwd04";
54 int TST_TOTAL = 1;
55 
main(int ac,char ** av)56 int main(int ac, char **av)
57 {
58 	int status;
59 	char cur_cwd[PATH_MAX];
60 	pid_t child;
61 
62 	tst_parse_opts(ac, av, NULL, NULL);
63 
64 	setup();
65 
66 	child = tst_fork();
67 	if (child < 0)
68 		tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
69 
70 	if (child == 0)
71 		do_child();
72 
73 	 while (1) {
74 		SAFE_GETCWD(cleanup, cur_cwd, PATH_MAX);
75 		if (strncmp(init_cwd, cur_cwd, PATH_MAX)) {
76 			tst_resm(TFAIL, "initial current work directory is "
77 				 "%s, now is %s. Bug is reproduced!",
78 				 init_cwd, cur_cwd);
79 			break;
80 		}
81 
82 		if (end) {
83 			tst_resm(TPASS, "Bug is not reproduced!");
84 			break;
85 		}
86 	}
87 
88 	SAFE_KILL(cleanup, child, SIGKILL);
89 	SAFE_WAITPID(cleanup, child, &status, 0);
90 
91 	cleanup();
92 	tst_exit();
93 }
94 
setup(void)95 static void setup(void)
96 {
97 	tst_sig(FORK, DEF_HANDLER, cleanup);
98 
99 	TEST_PAUSE;
100 
101 	if (tst_ncpus() == 1)
102 		tst_brkm(TCONF, NULL, "This test needs two cpus at least");
103 
104 	tst_tmpdir();
105 
106 	if (signal(SIGALRM, sigproc) == SIG_ERR)
107 		tst_brkm(TBROK | TERRNO, cleanup, "signal(SIGALRM) failed");
108 
109 	alarm(TIMEOUT);
110 
111 	SAFE_GETCWD(cleanup, init_cwd, PATH_MAX);
112 }
113 
sigproc(int sig)114 static void sigproc(int sig)
115 {
116 	end = sig;
117 }
118 
do_child(void)119 static void do_child(void)
120 {
121 	unsigned int i = 0;
122 	char c_name[PATH_MAX] = "testfile", n_name[PATH_MAX];
123 
124 	SAFE_TOUCH(NULL, c_name, 0644, NULL);
125 
126 	while (1) {
127 		snprintf(n_name, PATH_MAX, "testfile%u", i++);
128 		SAFE_RENAME(NULL, c_name, n_name);
129 		strncpy(c_name, n_name, PATH_MAX);
130 	}
131 }
132 
cleanup(void)133 static void cleanup(void)
134 {
135 	tst_rmdir();
136 }
137