#define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #ifndef FIBMAP #define FIBMAP BMAP_IOCTL #endif struct lookup { unsigned int l,p; /* logical block, physical block */ }; int compare(const void *a, const void *b) { register const struct lookup* A=a; register const struct lookup* B=b; return A->p-B->p; } static int dryrun; volatile int x; void touch(const char* block) { x=*block; } static unsigned long abs(long a) { return (a<0)?-a:a; } 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; qsort(lt+cur,blocksperchunk,sizeof(struct lookup),compare); for (i=0; i