/******************************************************************************/ /* */ /* Copyright (c) 2009 FUJITSU LIMITED */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ /* the GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* */ /* Author: Li Zefan */ /* */ /******************************************************************************/ #include #include #include #include #include #include #include #include #include char *filename; char *filepath; int fd; int old_inode_version; int new_inode_version; int get_inode_version(void) { char buf[1024]; sprintf(buf, "ext4_get_inode_version.sh %s 1", filename); /* sync before run debugfs to get inode version */ sync(); return WEXITSTATUS(system(buf)); } void test_chmod(void) { if (fchmod(fd, S_IRUSR | S_IWUSR)) { fprintf(stderr, "fchmod failed\n"); exit(1); } } void test_chown(void) { if (fchown(fd, 1, 1)) { fprintf(stderr, "fchown failed\n"); exit(1); } } void test_read(void) { char buf[2]; /* write something before read */ if (write(fd, "abc", 4) == -1) { perror("write"); exit(1); } close(fd); if (open(filepath, O_RDONLY) == -1) { perror("open"); exit(1); } old_inode_version = get_inode_version(); if (read(fd, buf, 1) == -1) { perror("read"); exit(1); } } void test_write(void) { if (write(fd, "a", 1) == -1) { fprintf(stderr, "write failed\n"); exit(1); } } void test_mmap_read(void) { char *p; char c; /* write something before read */ if (write(fd, "abc", 4) == -1) { perror("write"); exit(1); } close(fd); if (open(filepath, O_RDONLY) == -1) { perror("open"); exit(1); } old_inode_version = get_inode_version(); p = mmap(NULL, 1, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0); if (p == (void *)-1) { perror("mmap"); exit(1); } c = *p; new_inode_version = get_inode_version(); msync(p, 1, MS_SYNC); } void test_mmap_write(void) { char *p; if (write(fd, "abc", 4) == -1) { perror("write"); exit(1); } close(fd); if (open(filepath, O_RDWR) == -1) { perror("open"); exit(1); } old_inode_version = get_inode_version(); p = mmap(NULL, 1, PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0); if (p == (void *)-1) { perror("mmap"); exit(1); } *p = 'x'; new_inode_version = get_inode_version(); msync(p, 1, MS_SYNC); } /** * argv[1]: file operation * argv[2]: file to test (with path) * argv[3]: file to test (without path) */ int main(int argc, char *argv[]) { if (argc != 4) { fprintf(stderr, "wrong argument number\n"); return 1; } filepath = argv[2]; filename = argv[3]; /* create file and get the initial inode version */ fd = creat(argv[2], O_RDWR); if (fd == -1) { fprintf(stderr, "failed to create file: %s\n", argv[2]); return 1; } old_inode_version = get_inode_version(); if (strcmp(argv[1], "create") == 0) { printf("%d\n", old_inode_version); return 0; } else if (strcmp(argv[1], "chmod") == 0) { test_chmod(); } else if (strcmp(argv[1], "chown") == 0) { test_chown(); } else if (strcmp(argv[1], "read") == 0) { test_read(); } else if (strcmp(argv[1], "write") == 0) { test_write(); } else if (strcmp(argv[1], "mmap_read") == 0) { test_mmap_read(); } else if (strcmp(argv[1], "mmap_write") == 0) { test_mmap_write(); } else { fprintf(stderr, "wrong file operation: %s\n", argv[1]); return 1; } new_inode_version = get_inode_version(); #if 0 fprintf(stderr, "test_inode_version: old - %d\n", old_inode_version); fprintf(stderr, "test_inode_version: new - %d\n", new_inode_version); #endif /* wrong inode version, test failed */ if (new_inode_version <= old_inode_version) return 1; printf("%d\n", new_inode_version); close(fd); return 0; }