int bfree(int dev, int block) { u8* bmap = get_bmap(dev); clear_bit(&bmap, block); set_free_blocks(dev, +1); put_bmap(dev, bmap); }
int balloc(int dev) { int block_count = get_blocks_count(dev); u8* bmap = get_bmap(dev); int i; for (i = 0; i < block_count; i++) { if (test_bit(bmap, i) == 0) { set_bit(&bmap, i); set_free_blocks(dev, -1); put_bmap(dev, bmap); return i; } } printf("balloc(): no more free blocks\n"); return -1; }
static void frag_report(const char *filename) { struct statfs fsinfo; #ifdef HAVE_FSTAT64 struct stat64 fileinfo; #else struct stat fileinfo; #endif int bs; long fd; unsigned long block, last_block = 0, numblocks, i, count; long bpib; /* Blocks per indirect block */ long cylgroups; int discont = 0, expected; int is_ext2 = 0; unsigned int flags; if (statfs(filename, &fsinfo) < 0) { perror("statfs"); return; } #ifdef HAVE_FSTAT64 if (stat64(filename, &fileinfo) < 0) { #else if (stat(filename, &fileinfo) < 0) { #endif perror("stat"); return; } if (!S_ISREG(fileinfo.st_mode)) { printf("%s: Not a regular file\n", filename); return; } if ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) || (fsinfo.f_type == 0xef53)) is_ext2++; if (verbose) { printf("Filesystem type is: %lx\n", (unsigned long) fsinfo.f_type); } cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize*8); if (verbose) { printf("Filesystem cylinder groups is approximately %ld\n", cylgroups); } #ifdef HAVE_OPEN64 fd = open64(filename, O_RDONLY); #else fd = open(filename, O_RDONLY); #endif if (fd < 0) { perror("open"); return; } if (ioctl(fd, FIGETBSZ, &bs) < 0) { /* FIGETBSZ takes an int */ perror("FIGETBSZ"); close(fd); return; } if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0) flags = 0; if (flags & EXT4_EXTENTS_FL) { if (verbose) printf("File is stored in extents format\n"); is_ext2 = 0; } if (verbose) printf("Blocksize of file %s is %d\n", filename, bs); bpib = bs / 4; numblocks = (fileinfo.st_size + (bs-1)) / bs; if (verbose) { printf("File size of %s is %lld (%ld blocks)\n", filename, (long long) fileinfo.st_size, numblocks); printf("First block: %lu\nLast block: %lu\n", get_bmap(fd, 0), get_bmap(fd, numblocks - 1)); } for (i=0, count=0; i < numblocks; i++) { if (is_ext2 && last_block) { if (((i-EXT2_DIRECT) % bpib) == 0) last_block++; if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0) last_block++; if (((i-EXT2_DIRECT-bpib-bpib*bpib) % (bpib*bpib*bpib)) == 0) last_block++; } block = get_bmap(fd, i); if (block == 0) continue; count++; if (last_block && (block != last_block +1) ) { if (verbose) printf("Discontinuity: Block %ld is at %lu (was %lu)\n", i, block, last_block); discont++; } last_block = block; } if (discont==0) printf("%s: 1 extent found", filename); else printf("%s: %d extents found", filename, discont+1); expected = (count/((bs*8)-(fsinfo.f_files/8/cylgroups)-3))+1; if (is_ext2 && expected < discont+1) printf(", perfection would be %d extent%s\n", expected, (expected>1) ? "s" : ""); else fputc('\n', stdout); close(fd); } static void usage(const char *progname) { fprintf(stderr, "Usage: %s [-v] file ...\n", progname); exit(1); }
static void frag_report(const char *filename) { struct statfs fsinfo; #ifdef HAVE_FSTAT64 struct stat64 fileinfo; #else struct stat fileinfo; #endif int bs; long fd; unsigned long block, last_block = 0, numblocks, i, count; long bpib; /* Blocks per indirect block */ long cylgroups; int num_extents = 0, expected; int is_ext2 = 0; static int once = 1; unsigned int flags; int rc; #ifdef HAVE_OPEN64 fd = open64(filename, O_RDONLY); #else fd = open(filename, O_RDONLY); #endif if (fd < 0) { perror("open"); return; } if (statfs(filename, &fsinfo) < 0) { perror("statfs"); return; } #ifdef HAVE_FSTAT64 if (stat64(filename, &fileinfo) < 0) { #else if (stat(filename, &fileinfo) < 0) { #endif perror("stat"); return; } if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0) flags = 0; if (!(flags & EXT4_EXTENTS_FL) && ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) || (fsinfo.f_type == 0xef53))) is_ext2++; if (verbose && once) printf("Filesystem type is: %lx\n", (unsigned long) fsinfo.f_type); cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize*8); if (verbose && is_ext2 && once) printf("Filesystem cylinder groups is approximately %ld\n", cylgroups); physical_width = int_log10(fsinfo.f_blocks); if (physical_width < 8) physical_width = 8; if (ioctl(fd, FIGETBSZ, &bs) < 0) { /* FIGETBSZ takes an int */ perror("FIGETBSZ"); close(fd); return; } if (no_bs) bs = 1024; bpib = bs / 4; numblocks = (fileinfo.st_size + (bs-1)) / bs; logical_width = int_log10(numblocks); if (logical_width < 7) logical_width = 7; filesize = (long long)fileinfo.st_size; if (verbose) printf("File size of %s is %lld (%ld block%s, blocksize %d)\n", filename, (long long) fileinfo.st_size, numblocks, numblocks == 1 ? "" : "s", bs); if (force_bmap || filefrag_fiemap(fd, int_log2(bs), &num_extents) != 0) { for (i = 0, count = 0; i < numblocks; i++) { if (is_ext2 && last_block) { if (((i-EXT2_DIRECT) % bpib) == 0) last_block++; if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0) last_block++; if (((i-EXT2_DIRECT-bpib-bpib*bpib) % (bpib*bpib*bpib)) == 0) last_block++; } rc = get_bmap(fd, i, &block); if (block == 0) continue; if (!num_extents) num_extents++; count++; if (last_block && (block != last_block+1) ) { if (verbose) printf("Discontinuity: Block %ld is at " "%lu (was %lu)\n", i, block, last_block+1); num_extents++; } last_block = block; } } if (num_extents == 1) printf("%s: 1 extent found", filename); else printf("%s: %d extents found", filename, num_extents); expected = (count/((bs*8)-(fsinfo.f_files/8/cylgroups)-3))+1; if (is_ext2 && expected < num_extents) printf(", perfection would be %d extent%s\n", expected, (expected>1) ? "s" : ""); else fputc('\n', stdout); close(fd); once = 0; } static void usage(const char *progname) { fprintf(stderr, "Usage: %s [-Bbvsx] file ...\n", progname); exit(1); }
static void copy_sparse_file(const char *src, const char *dest) { struct stat64 fileinfo; long lb, i, fd, ofd, bs, block, numblocks; ssize_t got, got2; off64_t offset = 0, should_be; char *buf; if (verbose) printf("Copying sparse file from %s to %s\n", src, dest); if (strcmp(src, "-")) { if (stat64(src, &fileinfo) < 0) { perror("stat"); exit(1); } if (!S_ISREG(fileinfo.st_mode)) { printf("%s: Not a regular file\n", src); exit(1); } fd = open(src, O_RDONLY | O_LARGEFILE); if (fd < 0) { perror("open"); exit(1); } if (ioctl(fd, FIGETBSZ, &bs) < 0) { perror("FIGETBSZ"); close(fd); exit(1); } if (bs < 0) { printf("%s: Invalid block size: %ld\n", src, bs); exit(1); } if (verbose) printf("Blocksize of file %s is %ld\n", src, bs); numblocks = (fileinfo.st_size + (bs-1)) / bs; if (verbose) printf("File size of %s is %lld (%ld blocks)\n", src, (long long) fileinfo.st_size, numblocks); } else { fd = 0; bs = 1024; } ofd = open(dest, O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0777); if (ofd < 0) { perror(dest); exit(1); } buf = malloc(bs); if (!buf) { fprintf(stderr, "Couldn't allocate buffer"); exit(1); } for (lb = 0; !fd || lb < numblocks; lb++) { if (fd) { block = get_bmap(fd, lb); if (!block) continue; should_be = ((off64_t) lb) * bs; if (offset != should_be) { if (verbose) printf("Seeking to %lld\n", should_be); if (lseek64(fd, should_be, SEEK_SET) == (off_t) -1) { perror("lseek src"); exit(1); } if (lseek64(ofd, should_be, SEEK_SET) == (off_t) -1) { perror("lseek dest"); exit(1); } offset = should_be; } } got = full_read(fd, buf, bs); if (fd == 0 && got == 0) break; if (got == bs) { for (i=0; i < bs; i++) if (buf[i]) break; if (i == bs) { lseek(ofd, bs, SEEK_CUR); offset += bs; continue; } } got2 = write(ofd, buf, got); if (got != got2) { printf("short write\n"); exit(1); } offset += got; } offset = fileinfo.st_size; if (fstat64(ofd, &fileinfo) < 0) { perror("fstat"); exit(1); } if (fileinfo.st_size != offset) { lseek64(ofd, offset-1, SEEK_CUR); buf[0] = 0; write(ofd, buf, 1); } close(fd); close(ofd); }