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