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 (at) cn.fujitsu.com> */ 20 /* */ 21 /******************************************************************************/ 22 23 #include <unistd.h> 24 #include <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 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 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 60 void test_chown(void) 61 { 62 if (fchown(fd, 1, 1)) { 63 fprintf(stderr, "fchown failed\n"); 64 exit(1); 65 } 66 } 67 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 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 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 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 */ 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