Více mě ale zajímá to, jak defrag zjistí počet fragmentů souboru - pokud vím, na úrovni Linux VFS neexistuje žádná rutina, na základě které by se to dalo deterministicky zjistit. Bojím se toho, že defrag pouze určitým způsobem odhaduje počet fragmentů porovnáním velikosti souboru, času O_DIRECT přečtení souboru a rychlosti sekvenčního čtení disku (hdparm -tT --direct, pokud chcete změřit svůj disk). Budu rád, pokud mi toto někdo vyvrátí.Mno, já si zkusmo zbastlil tohle:
#include <stdio.h>
#include <linux/fs.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
int fd=0, block, block_size, block_position, fragment_size=0, last_block_position, fragments=1;
struct stat st;
if (argc < 2)
{
printf("Enter a file name.\n");
exit(EXIT_FAILURE);
}
printf("File: '%s'\n", argv[1]);
fd = open(argv[1], O_RDONLY);
if(fd==-1)
{
perror(argv[1]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &st) == -1)
{
perror("stat");
exit(EXIT_FAILURE);
}
if (ioctl(fd, FIGETBSZ, &block_size) == -1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf("File size: %d (%d blocks, a block has %d bytes)\n", (int)st.st_size, 1+((int)st.st_size/block_size), (int)block_size);
for (block=0; block<=st.st_size/block_size; block++)
{
last_block_position = block_position;
block_position = block;
if (ioctl(fd, FIBMAP, &block_position) == -1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
/* printf("%d: %d\n", block, block_position); */
if (fragment_size > 0 && block_position != last_block_position+1)
{
printf("A fragment (%d blocks) ends at block %d\n", fragment_size, block);
fragment_size = 0;
fragments++;
}
else
{
fragment_size++;
}
}
printf("Total: The file has %d fragments with average size of %.1f blocks each.\n", fragments, (1+st.st_size/block_size)/(double)fragments);
exit(0);
}
Je to "narychlo zprasené" (jsou tři ráno ;-)), ale zdá se mi, že to funguje. :-) (A nekamenovat za formu, prosím, Cčko neumím. ;-))
nb-esprimo /usr/portage/distfiles # filefrag -v tetex-src-3.0_p1.tar.gz.new Checking tetex-src-3.0_p1.tar.gz.new Filesystem type is: 52654973 Filesystem cylinder groups is approximately 80 Blocksize of file tetex-src-3.0_p1.tar.gz.new is 4096 File size of tetex-src-3.0_p1.tar.gz.new is 13357541 (3262 blocks) First block: 79879 Last block: 84138 Discontinuity: Block 221 is at 80101 (was 80099) -- vzdálenost mezi fragmenty je jen 1 blok Discontinuity: Block 993 is at 81867 (was 80872) -- vzdálenost ~1000 bloků (4MB) Discontinuity: Block 1010 is at 81885 (was 81883) -- vzdálenost 1 blok Discontinuity: Block 2013 is at 82889 (was 82887) -- 1 blok Discontinuity: Block 3033 is at 83910 (was 83908) -- 1 blok tetex-src-3.0_p1.tar.gz.new: 6 extents foundFilefrag tedy reportuje 6 fragmentů, ale prakticky jsou pouze 2 (2 čtení s díru 1 blok spojí kernel do jednoho čtení, a když to neudělá kernel, tak to spadne do disk readaheadu). Jediné, co nevím, je jestli reiserfs dělá tyto díry schválně a jsou prázdné, či jestli to jsou data jiných souborů (jednoblokových souborů mám hodně - portage), či metadata.