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