#define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #ifndef FIBMAP #define FIBMAP BMAP_IOCTL #endif struct lookup { unsigned int l,p; /* logical block, physical block */ }; void rsort(struct lookup* tab,unsigned long blocksperchunk) { struct lookup* x[2]; unsigned long i,j,c[2]; x[0]=(struct lookup*)malloc(blocksperchunk*sizeof(*tab)); x[1]=(struct lookup*)malloc(blocksperchunk*sizeof(*tab)); if (!x[0] || !x[1]) return; for (i=1; i; i<<=1) { c[0]=c[1]=0; for (j=0; j tab[i].p) { printf("not sorted: %lu : %lu vs %lu\n",i-1,tab[i-1].p,tab[i].p); exit(1); } } #endif } static int dryrun; volatile int x; void touch(const char* block) { x=*block; } static unsigned long myabs(long a) { return (a<0)?-a:a; } int main(int argc,char* argv[]) { int fd=open(argv[1],O_RDONLY); unsigned int block,i,blocks,chunk,chunks,cur,blocksleft,blocksdone,delta; unsigned long long h1,h2; struct stat s; struct lookup *lt; if (argc<2) { fprintf(stderr,"usage: defrag filename > destination\n"); return 0; } if (fd<0) { perror("open"); return 1; } if (fstat(fd,&s)) { perror("fstat"); return 1; } blocks=s.st_size/s.st_blksize; fprintf(stderr,"%u blocks, allocating look-up table\n",blocks); lt=(struct lookup*)malloc(blocks*sizeof(struct lookup)); if (!lt) { perror("malloc"); return 1; } h1=h2=0; for (i=0; iblocksleft*s.st_blksize) { delta=blocksleft; chunksize=s.st_size-blocksdone*s.st_blksize; } else delta=chunksize/s.st_blksize; blocksleft-=delta; if (!dryrun) { map=mmap(0,chunksize,PROT_READ,MAP_SHARED,fd,blocksdone*s.st_blksize); if (map==(char*)-1) { perror("mmap"); return 1; } madvise(map,chunksize,MADV_RANDOM); /* tell the OS not to read ahead */ } /* how many blocks are in this chunk? */ blocksperchunk=chunksize/s.st_blksize; rsort(lt+cur,blocksperchunk); for (i=0; i