xref: /aosp_15_r20/external/f2fs-tools/tools/check_f2fs.c (revision 59bfda1f02d633cd6b8b69f31eee485d40f6eef6)
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 "/mnt/androidwritable/0/emulated/0/Android/data/database_file2"
27 #define FILE_PATH "/data/testfile"
28 
29 #define F2FS_BLKSIZE 4096
30 #define BLKS_TO_SECTOR_BITS 3
31 #define BLOCK 4096
32 #define BLOCKS (2 * BLOCK)
33 
34 char buf[BLOCKS];
35 char cmd[BLOCK];
36 
run(const char * cmd)37 static int run(const char *cmd)
38 {
39 	int status;
40 
41 	fflush(stdout);
42 
43 	switch (fork()) {
44 	case 0:
45 		/* redirect stderr to stdout */
46 		dup2(1, 2);
47 		execl("/system/bin/sh", "sh", "-c", cmd, (char *) NULL);
48 	case -1:
49 		printf("fork failed in run() errno:%d\n", errno);
50 		return -1;
51 	default:
52 		wait(&status);
53 	}
54 	return 0;
55 }
56 
test_atomic_write(char * path)57 static int test_atomic_write(char *path)
58 {
59 	int db, ret, written;
60 
61 	printf("\tOpen  %s... \n", path);
62 	db = open(path, O_RDWR|O_CREAT, 0666);
63 	if (db < 0) {
64 		printf("open failed errno:%d\n", errno);
65 		return -1;
66 	}
67 	printf("\tStart ... \n");
68 	ret = ioctl(db, F2FS_IOC_START_ATOMIC_WRITE);
69 	if (ret) {
70 		printf("ioctl failed errno:%d\n", errno);
71 		return -1;
72 	}
73 	printf("\tWrite to the %dkB ... \n", BLOCKS / 1024);
74 	written = write(db, buf, BLOCKS);
75 	if (written != BLOCKS) {
76 		printf("write fail written:%d, errno:%d\n", written, errno);
77 		return -1;
78 	}
79 	printf("\tCheck : Atomic in-memory count: 2\n");
80 	if (access("/dev/sys/fs/by-name/userdata/current_atomic_write", F_OK)
81 			== 0) {
82 		printf("- inmem: ");
83 		run("cat /dev/sys/fs/by-name/userdata/current_atomic_write");
84 	} else {
85 		run("grep \"atomic IO\" /sys/kernel/debug/f2fs/status");
86 	}
87 
88 	printf("\tCommit  ... \n");
89 	ret = ioctl(db, F2FS_IOC_COMMIT_ATOMIC_WRITE);
90 	if (ret) {
91 		printf("ioctl failed errno:%d\n", errno);
92 		return -1;
93 	}
94 	return 0;
95 }
96 
test_bad_write_call(char * path)97 static int test_bad_write_call(char *path)
98 {
99 	int fd, written;
100 	struct stat sb;
101 	int large_size = 1024 * 1024 * 100;	/* 100 MB */
102 	int blocks;
103 
104 	printf("\tOpen  %s... \n", path);
105 	fd = open(path, O_RDWR|O_CREAT|O_TRUNC, 0666);
106 	if (fd < 0) {
107 		printf("open failed errno:%d\n", errno);
108 		return -1;
109 	}
110 
111 	/* 8KB-sized buffer, but submit 100 MB size */
112 	printf("\tWrite to the %dkB ... \n", BLOCKS / 1024);
113 	written = write(fd, buf, large_size);
114 	if (written != BLOCKS)
115 		printf("Ok: write fail written:%d, errno:%d\n", written, errno);
116 	close(fd);
117 
118 	fd = open(path, O_RDONLY);
119 	if (fd < 0) {
120 		printf("open failed errno:%d\n", errno);
121 		return -1;
122 	}
123 
124 	if (stat(path, &sb) == -1) {
125 		printf("stat failed errno:%d\n", errno);
126 		return -1;
127 	}
128 
129 	blocks = (long long)sb.st_size / F2FS_BLKSIZE;
130 	if (sb.st_size % F2FS_BLKSIZE)
131 		blocks++;
132 
133 	if (blocks << BLKS_TO_SECTOR_BITS != (long long)sb.st_blocks) {
134 		printf("FAIL: Mismatch i_size and i_blocks: %lld %lld\n",
135 			(long long)sb.st_size, (long long)sb.st_blocks);
136 		printf("FAIL: missing patch "
137 			"\"f2fs: do not preallocate blocks which has wrong buffer\"\n");
138 	}
139 	close(fd);
140 	unlink(path);
141 	return 0;
142 }
143 
main(void)144 int main(void)
145 {
146 	memset(buf, 0xff, BLOCKS);
147 
148 	printf("# Test 0: Check F2FS support\n");
149 	run("cat /proc/filesystems");
150 
151 	printf("# Test 1: Check F2FS status on /userdata\n");
152 	printf("\t= FS type /userdata\n");
153 	run("mount | grep data");
154 
155 	printf("\n\t= F2FS features\n");
156 	run("ls -1 /sys/fs/f2fs/features/");
157 	run("find /sys/fs/f2fs -type f -name \"features\" -print -exec cat {} \\;");
158 	run("find /sys/fs/f2fs -type f -name \"ipu_policy\" -print -exec cat {} \\;");
159 	run("find /sys/fs/f2fs -type f -name \"discard_granularity\" -print -exec cat {} \\;");
160 	run("cat /sys/kernel/debug/f2fs/status");
161 
162 	printf("\n\n# Test 2: Atomic_write on /userdata\n");
163 	if (test_atomic_write(DB1_PATH))
164 		return 0;
165 
166 	printf("# Test 3: Atomic_write on /sdcard\n");
167 	if (test_atomic_write(DB2_PATH))
168 		return 0;
169 
170 	printf("# Test 4: Bad write(2) call\n");
171 	if (test_bad_write_call(FILE_PATH))
172 		return 0;
173 	return 0;
174 }
175