blob: 1f7647b4771a60fcd326ec38e3a0128f314cb3e8 [file] [log] [blame]
/******************************************************************************/
/* */
/* 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 <lizf@cn.fujitsu.com> */
/* */
/******************************************************************************/
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
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;
}