This is a standalone tool I've used to exercise the ioctl, simply pass the name of a file and see the result. The numbers are a rough estimate. It also takes the range arguments, but the ratio will be bogus due to comparison to whole file (st_blocks), an exact extent length from fiemap/filefrag is be the correct one.
david
/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ #include <sys/ioctl.h> #include <sys/stat.h> #include <fcntl.h> #include <dirent.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <inttypes.h> typedef uint64_t __u64; typedef uint64_t u64; #ifndef BTRFS_IOCTL_MAGIC #define BTRFS_IOCTL_MAGIC 0x94 #endif #ifndef BTRFS_IOC_COMPR_SIZE #define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ struct __local__btrfs_ioctl_compr_size_args) #endif struct __local__btrfs_ioctl_compr_size_args { /* Range start, inclusive */ __u64 start; /* in */ /* Range end, exclusive */ __u64 end; /* in */ __u64 size; /* out */ __u64 reserved[2]; }; static u64 parse_size(char *s) { int len = strlen(s); char c; u64 mult = 1; if (!isdigit(s[len - 1])) { c = tolower(s[len - 1]); switch (c) { case 'e': case 'E': mult *= 1024; case 't': case 'T': mult *= 1024; case 'g': case 'G': mult *= 1024; case 'm': case 'M': mult *= 1024; case 'k': case 'K': mult *= 1024; case 'b': case 'B': break; default: fprintf(stderr, "Unknown size descriptor %c\n", c); exit(1); } s[len - 1] = '\0'; } return atoll(s) * mult; } static int open_file_or_dir(const char *fname) { int ret; struct stat st; DIR *dirstream; int fd; ret = stat(fname, &st); if (ret < 0) { perror("stat"); exit(1); } if (S_ISDIR(st.st_mode)) { dirstream = opendir(fname); if (!dirstream) { perror("opendir"); exit(1); } fd = dirfd(dirstream); } else { fd = open(fname, O_RDONLY); } if (fd < 0) { perror("open"); exit(1); } return fd; } static char buf[64]; static const char* end_or_eof(u64 end) { if (end == (u64)-1) return "EOF"; snprintf(buf, 64, "%llu", (unsigned long long)end); return buf; } int main(int argc, char **argv) { int fd; int ret; u64 cblocks; unsigned long sblocks; struct stat st; struct __local__btrfs_ioctl_compr_size_args args; if (argc < 2) { printf("Usage: btrfs-compr-size <file> [start [end] ]\n"); exit(1); } fd = open_file_or_dir(argv[1]); if (fd == -1) { perror("open"); exit(1); } if (argc >= 3) args.start = parse_size(argv[2]); else args.start = 0; if (argc >= 4) args.end = parse_size(argv[3]); else args.end = (u64)-1; ret = ioctl(fd, BTRFS_IOC_COMPR_SIZE, &args); if (ret < 0) { perror("ioctl"); exit(1); } fstat(fd, &st); cblocks=args.size; sblocks=st.st_blocks; printf("Compressed size of %s [%llu,%s)\n", argv[1], (unsigned long long)args.start, end_or_eof(args.end)); printf(" compr size/512: % 11lu\n", cblocks); printf(" stat blocks/512: % 11lu\n", sblocks); if (sblocks) printf(" compr/stat*100: % 14.2f%%\n", (((float)cblocks) / sblocks) * 100); else printf(" compr/stat*100: % 14.2f%%\n", (float)0); return 0; }