• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************/
2 /*                                                                            */
3 /* Copyright (c) 2009 FUJITSU LIMITED                                         */
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 /* You should have received a copy of the GNU General Public License          */
16 /* along with this program;  if not, write to the Free Software               */
17 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
18 /*                                                                            */
19 /* Author: Li Zefan <lizf@cn.fujitsu.com>                                     */
20 /*                                                                            */
21 /******************************************************************************/
22 
23 #include <unistd.h>
24 #include <sys/wait.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <sys/mman.h>
32 
33 char *filename;
34 char *filepath;
35 int fd;
36 
37 int old_inode_version;
38 int new_inode_version;
39 
get_inode_version(void)40 int get_inode_version(void)
41 {
42 	char buf[1024];
43 
44 	sprintf(buf, "ext4_get_inode_version.sh %s 1", filename);
45 
46 	/* sync before run debugfs to get inode version */
47 	sync();
48 
49 	return WEXITSTATUS(system(buf));
50 }
51 
test_chmod(void)52 void test_chmod(void)
53 {
54 	if (fchmod(fd, S_IRUSR | S_IWUSR)) {
55 		fprintf(stderr, "fchmod failed\n");
56 		exit(1);
57 	}
58 }
59 
test_chown(void)60 void test_chown(void)
61 {
62 	if (fchown(fd, 1, 1)) {
63 		fprintf(stderr, "fchown failed\n");
64 		exit(1);
65 	}
66 }
67 
test_read(void)68 void test_read(void)
69 {
70 	char buf[2];
71 
72 	/* write something before read */
73 	if (write(fd, "abc", 4) == -1) {
74 		perror("write");
75 		exit(1);
76 	}
77 	close(fd);
78 
79 	if (open(filepath, O_RDONLY) == -1) {
80 		perror("open");
81 		exit(1);
82 	}
83 
84 	old_inode_version = get_inode_version();
85 
86 	if (read(fd, buf, 1) == -1) {
87 		perror("read");
88 		exit(1);
89 	}
90 }
91 
test_write(void)92 void test_write(void)
93 {
94 	if (write(fd, "a", 1) == -1) {
95 		fprintf(stderr, "write failed\n");
96 		exit(1);
97 	}
98 }
99 
test_mmap_read(void)100 void test_mmap_read(void)
101 {
102 	char *p;
103 	char c;
104 
105 	/* write something before read */
106 	if (write(fd, "abc", 4) == -1) {
107 		perror("write");
108 		exit(1);
109 	}
110 	close(fd);
111 
112 	if (open(filepath, O_RDONLY) == -1) {
113 		perror("open");
114 		exit(1);
115 	}
116 
117 	old_inode_version = get_inode_version();
118 
119 	p = mmap(NULL, 1, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0);
120 	if (p == (void *)-1) {
121 		perror("mmap");
122 		exit(1);
123 	}
124 	c = *p;
125 
126 	new_inode_version = get_inode_version();
127 
128 	msync(p, 1, MS_SYNC);
129 }
130 
test_mmap_write(void)131 void test_mmap_write(void)
132 {
133 	char *p;
134 
135 	if (write(fd, "abc", 4) == -1) {
136 		perror("write");
137 		exit(1);
138 	}
139 	close(fd);
140 
141 	if (open(filepath, O_RDWR) == -1) {
142 		perror("open");
143 		exit(1);
144 	}
145 
146 	old_inode_version = get_inode_version();
147 
148 	p = mmap(NULL, 1, PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);
149 	if (p == (void *)-1) {
150 		perror("mmap");
151 		exit(1);
152 	}
153 	*p = 'x';
154 
155 	new_inode_version = get_inode_version();
156 
157 	msync(p, 1, MS_SYNC);
158 }
159 
160 /**
161  * argv[1]: file operation
162  * argv[2]: file to test (with path)
163  * argv[3]: file to test (without path)
164  */
main(int argc,char * argv[])165 int main(int argc, char *argv[])
166 {
167 	if (argc != 4) {
168 		fprintf(stderr, "wrong argument number\n");
169 		return 1;
170 	}
171 	filepath = argv[2];
172 	filename = argv[3];
173 
174 	/* create file and get the initial inode version */
175 	fd = creat(argv[2], O_RDWR);
176 	if (fd == -1) {
177 		fprintf(stderr, "failed to create file: %s\n", argv[2]);
178 		return 1;
179 	}
180 
181 	old_inode_version = get_inode_version();
182 
183 	if (strcmp(argv[1], "create") == 0) {
184 		printf("%d\n", old_inode_version);
185 		return 0;
186 	} else if (strcmp(argv[1], "chmod") == 0) {
187 		test_chmod();
188 	} else if (strcmp(argv[1], "chown") == 0) {
189 		test_chown();
190 	} else if (strcmp(argv[1], "read") == 0) {
191 		test_read();
192 	} else if (strcmp(argv[1], "write") == 0) {
193 		test_write();
194 	} else if (strcmp(argv[1], "mmap_read") == 0) {
195 		test_mmap_read();
196 	} else if (strcmp(argv[1], "mmap_write") == 0) {
197 		test_mmap_write();
198 	} else {
199 		fprintf(stderr, "wrong file operation: %s\n", argv[1]);
200 		return 1;
201 	}
202 
203 	new_inode_version = get_inode_version();
204 #if 0
205 	fprintf(stderr, "test_inode_version: old - %d\n", old_inode_version);
206 	fprintf(stderr, "test_inode_version: new - %d\n", new_inode_version);
207 #endif
208 	/* wrong inode version, test failed */
209 	if (new_inode_version <= old_inode_version)
210 		return 1;
211 
212 	printf("%d\n", new_inode_version);
213 
214 	close(fd);
215 
216 	return 0;
217 }
218