]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - historic/frag.c
1 /* frag.c - simple fragmentation checker
2 V1.0 by Werner Almesberger
3 V1.1 by Steffen Zahn, adding directory recursion
4 V1.2 by Rob Hooft, adding hole counts
5 V1.3 by Steffen Zahn, email: szahn%masterix@emndev.siemens.co.at
8 - don't cross filesys borders
9 - get filesystem block size at runtime
10 V1.4 by Michael Bischoff <mbi@mo.math.nat.tu-bs.de> to handle
11 indirect blocks better, but only for ext2fs
12 (applied by faith@cs.unc.edu, Sat Feb 4 22:06:27 1995)
14 TODO: - handle hard links
26 #include <linux/fs.h> /* for FIBMAP */
28 typedef struct StackElem
{
29 struct StackElem
*backref
, *next
;
35 StackElem
*top
= NULL
;
47 void push( StackElem
* se
)
53 char *p2s( StackElem
*se
, char *path
)
56 if( se
->backref
!=NULL
) {
57 path
= p2s( se
->backref
, path
);
67 char *path2str( StackElem
*se
, char *path
)
73 void *xmalloc( size_t size
)
76 if( (p
=malloc(size
))==NULL
) {
77 fprintf(stderr
,"\nvirtual memory exhausted.\n");
83 int main(int argc
,char **argv
)
85 int fd
,last_phys_block
,
86 fragments_in_file
, blocks_in_file
,
87 blocks
,current_phys_block
,
88 this_fragment
, largest_fragment
, i
;
89 long sum_blocks
=0, sum_frag_blocks
=0, sum_files
=0, sum_frag_files
=0;
90 long num_hole
=0, sum_hole
=0, hole
;
94 char path
[PATH_MAX
], pathlink
[PATH_MAX
], *p
;
103 fprintf(stderr
,"usage: %s [-s [-s]] filename ...\n",argv
[0]);
115 silent_flag
++; /* may be 1 or 2 */
118 fprintf(stderr
,"\nunknown flag %c\n", *p
);
123 se
= xmalloc( sizeof(StackElem
) );
124 se
->backref
=NULL
; se
->dir_seen
=0; se
->from_cmd_line
=1;
125 strcpy( se
->name
, p
);
137 path2str( se
, path
);
138 if( readlink( path
, pathlink
, sizeof(pathlink
) )>=0 )
139 { /* ignore symlinks */
142 printf("symlink %s\n", path
);
146 else if( stat( path
,&st
) < 0)
151 else if( !se
->from_cmd_line
&& (local_fs
!=st
.st_dev
) )
152 { /* do not cross filesystem borders */
155 printf("different filesystem %s\n", path
);
161 if( se
->from_cmd_line
)
163 local_fs
= st
.st_dev
;
164 if ( statfs( path
, &stfs
)<0 )
170 block_size
= stfs
.f_bsize
;
172 if( S_ISREG(st
.st_mode
)) /* regular file */
174 if ( (fd
= open( path
,O_RDONLY
)) < 0 )
181 last_phys_block
= -1;
182 fragments_in_file
= 0;
183 hole
= 0; this_fragment
=0;
185 blocks_in_file
= (st
.st_size
+block_size
-1)/block_size
;
186 for (blocks
= 0; blocks
< blocks_in_file
; blocks
++)
188 current_phys_block
= blocks
;
189 if (ioctl(fd
,FIBMAP
,¤t_phys_block
) < 0)
194 if (current_phys_block
) { /* no hole here */
196 /* indirect is the number of indirection */
197 /* blocks which must be skipped */
199 /* every 256 blocks there is an indirect block,
200 the first of these is before block 12 */
201 if (blocks
>= 12 && (blocks
-12) % 256 == 0)
203 /* there is a block pointing to the indirect
204 blocks every 64K blocks */
205 if (blocks
>= 256+12 && (blocks
-256-12) % 65536 == 0)
206 ++indirect
; /* 2nd indirect block */
207 /* there is a single triple indirect block */
208 if (blocks
== 65536 + 256 + 12)
210 if (last_phys_block
== current_phys_block
-1-indirect
)
212 else { /* start of first or new fragment */
213 if( largest_fragment
<this_fragment
)
214 largest_fragment
=this_fragment
;
218 last_phys_block
= current_phys_block
;
225 if( largest_fragment
<this_fragment
)
226 largest_fragment
=this_fragment
;
227 blocks_in_file
-=hole
;
228 /* number of allocated blocks in file */
231 if( fragments_in_file
< 2
232 || blocks_in_file
< 2 )
233 i
= 0; /* fragmentation 0 % */
235 i
= (fragments_in_file
- 1) * 100 /
237 /* maximum fragmentation 100%
238 means every block is an fragment */
239 printf(" %3d%% %s (%d block(s), %d fragment(s), largest %d",
240 i
, path
, blocks_in_file
,
241 fragments_in_file
,largest_fragment
);
244 printf(", %d hole(s))\n",hole
);
251 sum_blocks
+=blocks_in_file
;
256 if( fragments_in_file
>1 )
258 sum_frag_blocks
+=blocks_in_file
-largest_fragment
;
265 else if( S_ISDIR( st
.st_mode
) ) /* push dir contents */
267 if( (dir
=opendir( path
))==NULL
)
275 printf("reading %s\n", path
);
276 while( (de
=readdir(dir
))!=NULL
)
278 if( (strcmp(de
->d_name
,".")!=0)
279 && (strcmp(de
->d_name
,"..")!=0) )
281 se1
= xmalloc( sizeof(StackElem
) );
282 se1
->backref
=se
; se1
->dir_seen
=0;
283 se1
->from_cmd_line
=0;
284 strcpy( se1
->name
, de
->d_name
);
292 else /* if( S_ISREG(st.st_mode)) */
295 } /* if( se->dir_seen ) */
296 } /* while ( top != NULL) */
299 printf("\nsummary:\n");
300 printf(" %3ld%% file fragmentation (%ld of %ld files contain fragments)\n",
301 sum_files
<1 ? 0L : sum_frag_files
*100/sum_files
,
302 sum_frag_files
, sum_files
);
303 printf(" %3ld%% block fragmentation (%ld of %ld blocks are in fragments)\n",
304 sum_blocks
<1 ? 0L : sum_frag_blocks
*100/sum_blocks
,
305 sum_frag_blocks
, sum_blocks
);
307 printf(" %ld files contain %ld blocks in holes\n",