A sample tool how to use the new ioctl
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; }
Re: A sample tool how to use the new ioctl
On Mon, Dec 19, 2011 at 03:25:39PM +0100, David Sterba wrote: 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. Thanks Dave. Could you please add this to btrfs filesystem stat filename -chris -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: A sample tool how to use the new ioctl
On Mon, Dec 19, 2011 at 09:47:06AM -0500, Chris Mason wrote: On Mon, Dec 19, 2011 at 03:25:39PM +0100, David Sterba wrote: This is a standalone tool I've used to exercise the ioctl, simply pass Could you please add this to btrfs filesystem stat filename Here it is, but I haven't really thought about the userspace interface and calling it 'stat' just for reading compressed size does not seem right (and I have renamed to 'csize' for now). I will extend the ioctl to return the uncompressed size as well, it is provided by the extent anyway. The original implementation returned just one u64 for the whole file, I did the range-aware version because the lock_extent blocked for a long time when the file was being modified and it could be avoided. However I missed the options to utilize the information provided by the extents, so this is not a final version. From: David Sterba dste...@suse.cz Signed-off-by: David Sterba dste...@suse.cz --- btrfs.c |9 - btrfs_cmds.c | 53 + btrfs_cmds.h |1 + ioctl.h | 11 +++ 4 files changed, 73 insertions(+), 1 deletions(-) diff --git a/btrfs.c b/btrfs.c index 1def354..5ce207a 100644 --- a/btrfs.c +++ b/btrfs.c @@ -128,7 +128,14 @@ static struct Command commands[] = { filesystem label, device [newlabel]\n With one argument, get the label of filesystem on device.\n If newlabel is passed, set the filesystem label to newlabel.\n - The filesystem must be unmounted.\n + The filesystem must be unmounted. + }, + { do_compr_size, -1, + filesystem csize, [-s start] [-e end] file\n + Read compressed size of extents in the range [start,end)\n + -s start range start inclusive\n + -e endrange end exclusive\n, + NULL }, { do_scrub_start, -1, scrub start, [-Bdqr] path|device\n diff --git a/btrfs_cmds.c b/btrfs_cmds.c index b59e9cb..4c8bf5c 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -1305,3 +1305,56 @@ out: free(inodes); return ret; } + +int do_compr_size(int argc, char **argv) +{ + int ret; + int fd; + struct btrfs_ioctl_compr_size_args args; + + args.start = 0; + args.end = (u64)-1; + optind = 1; + while (1) { + int c = getopt(argc, argv, s:e:); + if (c 0) + break; + switch (c) { + case 's': + args.start = parse_size(optarg); + break; + case 'e': + args.end = parse_size(optarg); + break; + default: + fprintf(stderr, ERROR: Invalid arguments for csize\n); + return 1; + } + } + + if (args.start args.end) { + fprintf(stderr, ERROR: Invalid range for csize\n); + return 1; + } + + if (argc - optind == 0) { + fprintf(stderr, ERROR: Invalid arguments for csize\n); + return 1; + } + argc -= optind; + + fd = open_file_or_dir(argv[optind]); + if (fd 0) { + fprintf(stderr, ERROR: can't access '%s'\n, argv[optind]); + return 1; + } + + ret = ioctl(fd, BTRFS_IOC_COMPR_SIZE, args); + if (ret 0) { + fprintf(stderr, ERROR: ioctl returned %d, errno %d %s\n, ret, errno, strerror(errno)); + return errno; + } + + printf(Compressed size: %llu\n, args.size 9); + return 0; +} diff --git a/btrfs_cmds.h b/btrfs_cmds.h index 81182b1..d171214 100644 --- a/btrfs_cmds.h +++ b/btrfs_cmds.h @@ -42,3 +42,4 @@ int open_file_or_dir(const char *fname); int do_ino_to_path(int nargs, char **argv); int do_logical_to_ino(int nargs, char **argv); char *path_for_root(int fd, u64 root); +int do_compr_size(int argc, char **argv); diff --git a/ioctl.h b/ioctl.h index 1ae7537..792ffc0 100644 --- a/ioctl.h +++ b/ioctl.h @@ -224,6 +224,15 @@ struct btrfs_ioctl_logical_ino_args { __u64 inodes; }; +struct btrfs_ioctl_compr_size_args { + /* Range start, inclusive */ + __u64 start; /* in */ + /* Range end, exclusive */ + __u64 end;/* in */ + __u64 size; /* out */ + __u64 reserved[2]; +}; + /* BTRFS_IOC_SNAP_CREATE is no longer used by the btrfs command */ #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) @@ -277,5 +286,7 @@ struct btrfs_ioctl_logical_ino_args { struct btrfs_ioctl_ino_path_args) #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \