xref: /aosp_15_r20/external/e2fsprogs/e2fsck/iscan.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * Test to see how quickly we can scan the inode table (not doing
3*6a54128fSAndroid Build Coastguard Worker  * anything else)
4*6a54128fSAndroid Build Coastguard Worker  */
5*6a54128fSAndroid Build Coastguard Worker 
6*6a54128fSAndroid Build Coastguard Worker #include "config.h"
7*6a54128fSAndroid Build Coastguard Worker #include <string.h>
8*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
9*6a54128fSAndroid Build Coastguard Worker #include <ctype.h>
10*6a54128fSAndroid Build Coastguard Worker #include <termios.h>
11*6a54128fSAndroid Build Coastguard Worker #include <time.h>
12*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
13*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
14*6a54128fSAndroid Build Coastguard Worker #endif
15*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
16*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_ERRNO_H
17*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
18*6a54128fSAndroid Build Coastguard Worker #endif
19*6a54128fSAndroid Build Coastguard Worker #include <sys/ioctl.h>
20*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_MALLOC_H
21*6a54128fSAndroid Build Coastguard Worker #include <malloc.h>
22*6a54128fSAndroid Build Coastguard Worker #endif
23*6a54128fSAndroid Build Coastguard Worker #include <sys/time.h>
24*6a54128fSAndroid Build Coastguard Worker #include <sys/resource.h>
25*6a54128fSAndroid Build Coastguard Worker 
26*6a54128fSAndroid Build Coastguard Worker #if EXT2_FLAT_INCLUDES
27*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
28*6a54128fSAndroid Build Coastguard Worker #include "ext2fs.h"
29*6a54128fSAndroid Build Coastguard Worker #include "blkid.h"
30*6a54128fSAndroid Build Coastguard Worker #else
31*6a54128fSAndroid Build Coastguard Worker #include "ext2fs/ext2_fs.h"
32*6a54128fSAndroid Build Coastguard Worker #include "ext2fs/ext2fs.h"
33*6a54128fSAndroid Build Coastguard Worker #include "blkid/blkid.h"
34*6a54128fSAndroid Build Coastguard Worker #endif
35*6a54128fSAndroid Build Coastguard Worker 
36*6a54128fSAndroid Build Coastguard Worker #include "et/com_err.h"
37*6a54128fSAndroid Build Coastguard Worker #include "../version.h"
38*6a54128fSAndroid Build Coastguard Worker 
39*6a54128fSAndroid Build Coastguard Worker struct resource_track {
40*6a54128fSAndroid Build Coastguard Worker 	struct timeval time_start;
41*6a54128fSAndroid Build Coastguard Worker 	struct timeval user_start;
42*6a54128fSAndroid Build Coastguard Worker 	struct timeval system_start;
43*6a54128fSAndroid Build Coastguard Worker 	void	*brk_start;
44*6a54128fSAndroid Build Coastguard Worker 	unsigned long long bytes_read;
45*6a54128fSAndroid Build Coastguard Worker 	unsigned long long bytes_written;
46*6a54128fSAndroid Build Coastguard Worker };
47*6a54128fSAndroid Build Coastguard Worker 
48*6a54128fSAndroid Build Coastguard Worker extern int isatty(int);
49*6a54128fSAndroid Build Coastguard Worker 
50*6a54128fSAndroid Build Coastguard Worker const char * program_name = "iscan";
51*6a54128fSAndroid Build Coastguard Worker const char * device_name = NULL;
52*6a54128fSAndroid Build Coastguard Worker 
53*6a54128fSAndroid Build Coastguard Worker int yflag = 0;
54*6a54128fSAndroid Build Coastguard Worker int nflag = 0;
55*6a54128fSAndroid Build Coastguard Worker int preen = 0;
56*6a54128fSAndroid Build Coastguard Worker int inode_buffer_blocks = 0;
57*6a54128fSAndroid Build Coastguard Worker int invalid_bitmaps = 0;
58*6a54128fSAndroid Build Coastguard Worker 
59*6a54128fSAndroid Build Coastguard Worker struct resource_track	global_rtrack;
60*6a54128fSAndroid Build Coastguard Worker 
init_resource_track(struct resource_track * track,io_channel channel)61*6a54128fSAndroid Build Coastguard Worker void init_resource_track(struct resource_track *track, io_channel channel)
62*6a54128fSAndroid Build Coastguard Worker {
63*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETRUSAGE
64*6a54128fSAndroid Build Coastguard Worker 	struct rusage r;
65*6a54128fSAndroid Build Coastguard Worker #endif
66*6a54128fSAndroid Build Coastguard Worker 	io_stats io_start = 0;
67*6a54128fSAndroid Build Coastguard Worker 
68*6a54128fSAndroid Build Coastguard Worker 	track->brk_start = sbrk(0);
69*6a54128fSAndroid Build Coastguard Worker 	gettimeofday(&track->time_start, 0);
70*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETRUSAGE
71*6a54128fSAndroid Build Coastguard Worker #ifdef sun
72*6a54128fSAndroid Build Coastguard Worker 	memset(&r, 0, sizeof(struct rusage));
73*6a54128fSAndroid Build Coastguard Worker #endif
74*6a54128fSAndroid Build Coastguard Worker 	getrusage(RUSAGE_SELF, &r);
75*6a54128fSAndroid Build Coastguard Worker 	track->user_start = r.ru_utime;
76*6a54128fSAndroid Build Coastguard Worker 	track->system_start = r.ru_stime;
77*6a54128fSAndroid Build Coastguard Worker #else
78*6a54128fSAndroid Build Coastguard Worker 	track->user_start.tv_sec = track->user_start.tv_usec = 0;
79*6a54128fSAndroid Build Coastguard Worker 	track->system_start.tv_sec = track->system_start.tv_usec = 0;
80*6a54128fSAndroid Build Coastguard Worker #endif
81*6a54128fSAndroid Build Coastguard Worker 	track->bytes_read = 0;
82*6a54128fSAndroid Build Coastguard Worker 	track->bytes_written = 0;
83*6a54128fSAndroid Build Coastguard Worker 	if (channel && channel->manager && channel->manager->get_stats)
84*6a54128fSAndroid Build Coastguard Worker 		channel->manager->get_stats(channel, &io_start);
85*6a54128fSAndroid Build Coastguard Worker 	if (io_start) {
86*6a54128fSAndroid Build Coastguard Worker 		track->bytes_read = io_start->bytes_read;
87*6a54128fSAndroid Build Coastguard Worker 		track->bytes_written = io_start->bytes_written;
88*6a54128fSAndroid Build Coastguard Worker 	}
89*6a54128fSAndroid Build Coastguard Worker }
90*6a54128fSAndroid Build Coastguard Worker 
timeval_subtract(struct timeval * tv1,struct timeval * tv2)91*6a54128fSAndroid Build Coastguard Worker static float timeval_subtract(struct timeval *tv1,
92*6a54128fSAndroid Build Coastguard Worker 				       struct timeval *tv2)
93*6a54128fSAndroid Build Coastguard Worker {
94*6a54128fSAndroid Build Coastguard Worker 	return ((tv1->tv_sec - tv2->tv_sec) +
95*6a54128fSAndroid Build Coastguard Worker 		((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
96*6a54128fSAndroid Build Coastguard Worker }
97*6a54128fSAndroid Build Coastguard Worker 
print_resource_track(const char * desc,struct resource_track * track,io_channel channel)98*6a54128fSAndroid Build Coastguard Worker void print_resource_track(const char *desc,
99*6a54128fSAndroid Build Coastguard Worker 			  struct resource_track *track, io_channel channel)
100*6a54128fSAndroid Build Coastguard Worker {
101*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETRUSAGE
102*6a54128fSAndroid Build Coastguard Worker 	struct rusage r;
103*6a54128fSAndroid Build Coastguard Worker #endif
104*6a54128fSAndroid Build Coastguard Worker 	struct timeval time_end;
105*6a54128fSAndroid Build Coastguard Worker 
106*6a54128fSAndroid Build Coastguard Worker 	gettimeofday(&time_end, 0);
107*6a54128fSAndroid Build Coastguard Worker 
108*6a54128fSAndroid Build Coastguard Worker 	if (desc)
109*6a54128fSAndroid Build Coastguard Worker 		printf("%s: ", desc);
110*6a54128fSAndroid Build Coastguard Worker 
111*6a54128fSAndroid Build Coastguard Worker #define kbytes(x)	(((unsigned long long)(x) + 1023) / 1024)
112*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_MALLINFO2
113*6a54128fSAndroid Build Coastguard Worker 	if (1) {
114*6a54128fSAndroid Build Coastguard Worker 		struct mallinfo2 malloc_info = mallinfo2();
115*6a54128fSAndroid Build Coastguard Worker 
116*6a54128fSAndroid Build Coastguard Worker 		printf("Memory used: %lluk/%lluk (%lluk/%lluk), ",
117*6a54128fSAndroid Build Coastguard Worker 		       kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
118*6a54128fSAndroid Build Coastguard Worker 		       kbytes(malloc_info.uordblks),
119*6a54128fSAndroid Build Coastguard Worker 		       kbytes(malloc_info.fordblks));
120*6a54128fSAndroid Build Coastguard Worker 	} else
121*6a54128fSAndroid Build Coastguard Worker #elif defined HAVE_MALLINFO
122*6a54128fSAndroid Build Coastguard Worker 	/* don't use mallinfo() if over 2GB used, since it returns "int" */
123*6a54128fSAndroid Build Coastguard Worker 	if ((char *)sbrk(0) - (char *)track->brk_start < 2LL << 30) {
124*6a54128fSAndroid Build Coastguard Worker 		struct mallinfo	malloc_info = mallinfo();
125*6a54128fSAndroid Build Coastguard Worker 
126*6a54128fSAndroid Build Coastguard Worker 		printf("Memory used: %lluk/%lluk (%lluk/%lluk), ",
127*6a54128fSAndroid Build Coastguard Worker 		       kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
128*6a54128fSAndroid Build Coastguard Worker 		       kbytes(malloc_info.uordblks),
129*6a54128fSAndroid Build Coastguard Worker 		       kbytes(malloc_info.fordblks));
130*6a54128fSAndroid Build Coastguard Worker 	} else
131*6a54128fSAndroid Build Coastguard Worker #endif
132*6a54128fSAndroid Build Coastguard Worker 		printf("Memory used: %lluk, ",
133*6a54128fSAndroid Build Coastguard Worker 		       kbytes(((char *)sbrk(0)) - ((char *)track->brk_start)));
134*6a54128fSAndroid Build Coastguard Worker 
135*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETRUSAGE
136*6a54128fSAndroid Build Coastguard Worker 	getrusage(RUSAGE_SELF, &r);
137*6a54128fSAndroid Build Coastguard Worker 
138*6a54128fSAndroid Build Coastguard Worker 	printf("time: %5.2f/%5.2f/%5.2f\n",
139*6a54128fSAndroid Build Coastguard Worker 	       timeval_subtract(&time_end, &track->time_start),
140*6a54128fSAndroid Build Coastguard Worker 	       timeval_subtract(&r.ru_utime, &track->user_start),
141*6a54128fSAndroid Build Coastguard Worker 	       timeval_subtract(&r.ru_stime, &track->system_start));
142*6a54128fSAndroid Build Coastguard Worker #else
143*6a54128fSAndroid Build Coastguard Worker 	printf("elapsed time: %6.3f\n",
144*6a54128fSAndroid Build Coastguard Worker 	       timeval_subtract(&time_end, &track->time_start));
145*6a54128fSAndroid Build Coastguard Worker #endif
146*6a54128fSAndroid Build Coastguard Worker #define mbytes(x)	(((x) + 1048575) / 1048576)
147*6a54128fSAndroid Build Coastguard Worker 	if (channel && channel->manager && channel->manager->get_stats) {
148*6a54128fSAndroid Build Coastguard Worker 		io_stats delta = 0;
149*6a54128fSAndroid Build Coastguard Worker 		unsigned long long bytes_read = 0;
150*6a54128fSAndroid Build Coastguard Worker 		unsigned long long bytes_written = 0;
151*6a54128fSAndroid Build Coastguard Worker 
152*6a54128fSAndroid Build Coastguard Worker 		if (desc)
153*6a54128fSAndroid Build Coastguard Worker 			printf("%s: ", desc);
154*6a54128fSAndroid Build Coastguard Worker 
155*6a54128fSAndroid Build Coastguard Worker 		channel->manager->get_stats(channel, &delta);
156*6a54128fSAndroid Build Coastguard Worker 		if (delta) {
157*6a54128fSAndroid Build Coastguard Worker 			bytes_read = delta->bytes_read - track->bytes_read;
158*6a54128fSAndroid Build Coastguard Worker 			bytes_written = delta->bytes_written -
159*6a54128fSAndroid Build Coastguard Worker 				track->bytes_written;
160*6a54128fSAndroid Build Coastguard Worker 		}
161*6a54128fSAndroid Build Coastguard Worker 		printf("I/O read: %lluMB, write: %lluMB, "
162*6a54128fSAndroid Build Coastguard Worker 		       "rate: %.2fMB/s\n",
163*6a54128fSAndroid Build Coastguard Worker 		       mbytes(bytes_read), mbytes(bytes_written),
164*6a54128fSAndroid Build Coastguard Worker 		       (double)mbytes(bytes_read + bytes_written) /
165*6a54128fSAndroid Build Coastguard Worker 		       timeval_subtract(&time_end, &track->time_start));
166*6a54128fSAndroid Build Coastguard Worker 	}
167*6a54128fSAndroid Build Coastguard Worker }
168*6a54128fSAndroid Build Coastguard Worker 
usage(void)169*6a54128fSAndroid Build Coastguard Worker static void usage(void)
170*6a54128fSAndroid Build Coastguard Worker {
171*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr,
172*6a54128fSAndroid Build Coastguard Worker 		"Usage: %s [-F] [-I inode_buffer_blocks] device\n",
173*6a54128fSAndroid Build Coastguard Worker 		program_name);
174*6a54128fSAndroid Build Coastguard Worker 	exit(1);
175*6a54128fSAndroid Build Coastguard Worker }
176*6a54128fSAndroid Build Coastguard Worker 
PRS(int argc,char * argv[])177*6a54128fSAndroid Build Coastguard Worker static void PRS(int argc, char *argv[])
178*6a54128fSAndroid Build Coastguard Worker {
179*6a54128fSAndroid Build Coastguard Worker 	int		flush = 0;
180*6a54128fSAndroid Build Coastguard Worker 	int		c;
181*6a54128fSAndroid Build Coastguard Worker #ifdef MTRACE
182*6a54128fSAndroid Build Coastguard Worker 	extern void	*mallwatch;
183*6a54128fSAndroid Build Coastguard Worker #endif
184*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
185*6a54128fSAndroid Build Coastguard Worker 
186*6a54128fSAndroid Build Coastguard Worker 	setbuf(stdout, NULL);
187*6a54128fSAndroid Build Coastguard Worker 	setbuf(stderr, NULL);
188*6a54128fSAndroid Build Coastguard Worker 	initialize_ext2_error_table();
189*6a54128fSAndroid Build Coastguard Worker 
190*6a54128fSAndroid Build Coastguard Worker 	if (argc && *argv)
191*6a54128fSAndroid Build Coastguard Worker 		program_name = *argv;
192*6a54128fSAndroid Build Coastguard Worker 	while ((c = getopt (argc, argv, "FI")) != EOF)
193*6a54128fSAndroid Build Coastguard Worker 		switch (c) {
194*6a54128fSAndroid Build Coastguard Worker 		case 'F':
195*6a54128fSAndroid Build Coastguard Worker 			flush = 1;
196*6a54128fSAndroid Build Coastguard Worker 			break;
197*6a54128fSAndroid Build Coastguard Worker 		case 'I':
198*6a54128fSAndroid Build Coastguard Worker 			inode_buffer_blocks = atoi(optarg);
199*6a54128fSAndroid Build Coastguard Worker 			break;
200*6a54128fSAndroid Build Coastguard Worker 		default:
201*6a54128fSAndroid Build Coastguard Worker 			usage ();
202*6a54128fSAndroid Build Coastguard Worker 		}
203*6a54128fSAndroid Build Coastguard Worker 	device_name = argv[optind];
204*6a54128fSAndroid Build Coastguard Worker 	if (flush) {
205*6a54128fSAndroid Build Coastguard Worker 		int	fd = open(device_name, O_RDONLY, 0);
206*6a54128fSAndroid Build Coastguard Worker 
207*6a54128fSAndroid Build Coastguard Worker 		if (fd < 0) {
208*6a54128fSAndroid Build Coastguard Worker 			com_err("open", errno,
209*6a54128fSAndroid Build Coastguard Worker 			    "while opening %s for flushing", device_name);
210*6a54128fSAndroid Build Coastguard Worker 			exit(1);
211*6a54128fSAndroid Build Coastguard Worker 		}
212*6a54128fSAndroid Build Coastguard Worker 		if ((retval = ext2fs_sync_device(fd, 1))) {
213*6a54128fSAndroid Build Coastguard Worker 			com_err("ext2fs_sync_device", retval,
214*6a54128fSAndroid Build Coastguard Worker 				"while trying to flush %s", device_name);
215*6a54128fSAndroid Build Coastguard Worker 			exit(1);
216*6a54128fSAndroid Build Coastguard Worker 		}
217*6a54128fSAndroid Build Coastguard Worker 		close(fd);
218*6a54128fSAndroid Build Coastguard Worker 	}
219*6a54128fSAndroid Build Coastguard Worker }
220*6a54128fSAndroid Build Coastguard Worker 
main(int argc,char * argv[])221*6a54128fSAndroid Build Coastguard Worker int main (int argc, char *argv[])
222*6a54128fSAndroid Build Coastguard Worker {
223*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval = 0;
224*6a54128fSAndroid Build Coastguard Worker 	int		exit_value = 0;
225*6a54128fSAndroid Build Coastguard Worker 	ext2_filsys	fs;
226*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t	ino;
227*6a54128fSAndroid Build Coastguard Worker 	__u32	num_inodes = 0;
228*6a54128fSAndroid Build Coastguard Worker 	struct ext2_inode inode;
229*6a54128fSAndroid Build Coastguard Worker 	ext2_inode_scan	scan;
230*6a54128fSAndroid Build Coastguard Worker 
231*6a54128fSAndroid Build Coastguard Worker 	PRS(argc, argv);
232*6a54128fSAndroid Build Coastguard Worker 
233*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_open(device_name, 0,
234*6a54128fSAndroid Build Coastguard Worker 			     0, 0, unix_io_manager, &fs);
235*6a54128fSAndroid Build Coastguard Worker 	if (retval) {
236*6a54128fSAndroid Build Coastguard Worker 		com_err(program_name, retval, "while trying to open '%s'",
237*6a54128fSAndroid Build Coastguard Worker 			device_name);
238*6a54128fSAndroid Build Coastguard Worker 		exit(1);
239*6a54128fSAndroid Build Coastguard Worker 	}
240*6a54128fSAndroid Build Coastguard Worker 
241*6a54128fSAndroid Build Coastguard Worker 	init_resource_track(&global_rtrack, fs->io);
242*6a54128fSAndroid Build Coastguard Worker 
243*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
244*6a54128fSAndroid Build Coastguard Worker 	if (retval) {
245*6a54128fSAndroid Build Coastguard Worker 		com_err(program_name, retval, "while opening inode scan");
246*6a54128fSAndroid Build Coastguard Worker 		exit(1);
247*6a54128fSAndroid Build Coastguard Worker 	}
248*6a54128fSAndroid Build Coastguard Worker 
249*6a54128fSAndroid Build Coastguard Worker 	while (1) {
250*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_get_next_inode(scan, &ino, &inode);
251*6a54128fSAndroid Build Coastguard Worker 		if (retval) {
252*6a54128fSAndroid Build Coastguard Worker 			com_err(program_name, retval,
253*6a54128fSAndroid Build Coastguard Worker 				"while getting next inode");
254*6a54128fSAndroid Build Coastguard Worker 			exit(1);
255*6a54128fSAndroid Build Coastguard Worker 		}
256*6a54128fSAndroid Build Coastguard Worker 		if (ino == 0)
257*6a54128fSAndroid Build Coastguard Worker 			break;
258*6a54128fSAndroid Build Coastguard Worker 		num_inodes++;
259*6a54128fSAndroid Build Coastguard Worker 	}
260*6a54128fSAndroid Build Coastguard Worker 
261*6a54128fSAndroid Build Coastguard Worker 	print_resource_track(NULL, &global_rtrack, fs->io);
262*6a54128fSAndroid Build Coastguard Worker 	printf("%u inodes scanned.\n", num_inodes);
263*6a54128fSAndroid Build Coastguard Worker 
264*6a54128fSAndroid Build Coastguard Worker 	exit(0);
265*6a54128fSAndroid Build Coastguard Worker }
266