1 #include <stdio.h> 2 #include <sys/mman.h> 3 #include <sys/ioctl.h> 4 #include <sys/socket.h> 5 #include <sys/stat.h> 6 #include <sys/types.h> 7 #include <sys/time.h> 8 #include <unistd.h> 9 #include <sys/wait.h> 10 #include <sys/syscall.h> 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <getopt.h> 14 #include <string.h> 15 #include <stdlib.h> 16 17 #define F2FS_IOCTL_MAGIC 0xf5 18 #define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) 19 #define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) 20 #define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3) 21 #define F2FS_IOC_RELEASE_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 4) 22 #define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) 23 #define F2FS_IOC_GARBAGE_COLLECT _IO(F2FS_IOCTL_MAGIC, 6) 24 25 #define DB1_PATH "/data/database_file1" 26 #define DB2_PATH "/sdcard/database_file2" 27 #define FILE_PATH "/data/testfile" 28 29 #define BLOCK 4096 30 #define BLOCKS (2 * BLOCK) 31 32 int buf[BLOCKS]; 33 char cmd[BLOCK]; 34 35 static int run(char *cmd) 36 { 37 int status; 38 39 fflush(stdout); 40 41 switch (fork()) { 42 case 0: 43 /* redirect stderr to stdout */ 44 dup2(1, 2); 45 execl("/system/bin/sh", "sh", "-c", cmd, (char *) 0); 46 default: 47 wait(&status); 48 } 49 return 0; 50 } 51 52 static int test_atomic_write(char *path) 53 { 54 int db, ret, written; 55 56 printf("\tOpen %s... \n", path); 57 db = open(path, O_RDWR|O_CREAT, 0666); 58 if (db < 0) { 59 printf("open failed errno:%d\n", errno); 60 return -1; 61 } 62 printf("\tStart ... \n"); 63 ret = ioctl(db, F2FS_IOC_START_ATOMIC_WRITE); 64 if (ret) { 65 printf("ioctl failed errno:%d\n", errno); 66 return -1; 67 } 68 printf("\tWrite to the %dkB ... \n", BLOCKS / 1024); 69 written = write(db, buf, BLOCKS); 70 if (written != BLOCKS) { 71 printf("write fail written:%d, errno:%d\n", written, errno); 72 return -1; 73 } 74 printf("\tCheck : Atomic in-memory count: 2\n"); 75 run("cat /sys/kernel/debug/f2fs/status | grep atomic"); 76 77 printf("\tCommit ... \n"); 78 ret = ioctl(db, F2FS_IOC_COMMIT_ATOMIC_WRITE); 79 if (ret) { 80 printf("ioctl failed errno:%d\n", errno); 81 return -1; 82 } 83 return 0; 84 } 85 86 static int test_bad_write_call(char *path) 87 { 88 int fd, written; 89 struct stat sb; 90 int large_size = 1024 * 1024 * 100; /* 100 MB */ 91 92 printf("\tOpen %s... \n", path); 93 fd = open(path, O_RDWR|O_CREAT|O_TRUNC, 0666); 94 if (fd < 0) { 95 printf("open failed errno:%d\n", errno); 96 return -1; 97 } 98 99 /* 8KB-sized buffer, but submit 100 MB size */ 100 printf("\tWrite to the %dkB ... \n", BLOCKS / 1024); 101 written = write(fd, buf, large_size); 102 if (written != BLOCKS) 103 printf("Ok: write fail written:%d, errno:%d\n", written, errno); 104 close(fd); 105 106 fd = open(path, O_RDONLY); 107 if (fd < 0) { 108 printf("open failed errno:%d\n", errno); 109 return -1; 110 } 111 112 if (stat(path, &sb) == -1) { 113 printf("stat failed errno:%d\n", errno); 114 return -1; 115 } 116 117 if ((long long)sb.st_size / 512 != (long long)sb.st_blocks) { 118 printf("FAIL: Mismatch i_size and i_blocks: %lld %lld\n", 119 (long long)sb.st_size, (long long)sb.st_blocks); 120 printf("FAIL: missing patch " 121 "\"f2fs: do not preallocate blocks which has wrong buffer\"\n"); 122 } 123 close(fd); 124 unlink(path); 125 return 0; 126 } 127 128 int main(void) 129 { 130 memset(buf, 0xff, BLOCKS); 131 132 printf("# Test 0: Check F2FS support\n"); 133 run("cat /proc/filesystems"); 134 135 printf("# Test 1: Check F2FS status on /userdata\n"); 136 printf("\t= FS type /userdata\n"); 137 run("mount | grep data"); 138 139 printf("\n\t= F2FS features\n"); 140 run("ls -1 /sys/fs/f2fs/features/"); 141 run("find /sys/fs/f2fs -type f -name \"features\" -print -exec cat {} \\;"); 142 run("find /sys/fs/f2fs -type f -name \"ipu_policy\" -print -exec cat {} \\;"); 143 run("find /sys/fs/f2fs -type f -name \"discard_granularity\" -print -exec cat {} \\;"); 144 run("cat /sys/kernel/debug/f2fs/status"); 145 146 printf("\n\n# Test 2: Atomic_write on /userdata\n"); 147 if (test_atomic_write(DB1_PATH)) 148 return -1; 149 150 printf("# Test 3: Atomic_write on /sdcard\n"); 151 if (test_atomic_write(DB2_PATH)) 152 return -1; 153 154 printf("# Test 4: Bad write(2) call\n"); 155 if (test_bad_write_call(FILE_PATH)) 156 return -1; 157 return 0; 158 } 159