David Sterba
2011-Dec-19 14:17 UTC
[PATCH] btrfs: add new ioctl to determine size of compressed file
Go through all extents of a file in a given [start,end) range and sum for: * regular extent: ->block_len, size is already rounded up to blocks * inline extents: length rounded up to 512 The range is start inclusive / end exclusive. For the whole file pass 0 and (u64)-1. The resulting value is number of occupied 512B sectors so this can be easily compared to stat.st_blocks to determine rough compression ratio of a file. Based on implementation from Ulrich Hecht, http://comments.gmane.org/gmane.comp.file-systems.btrfs/6253 Signed-off-by: David Sterba <dsterba@suse.cz> --- fs/btrfs/ioctl.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/ioctl.h | 11 +++++++ 2 files changed, 88 insertions(+), 0 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c04f02c..82c3810 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2972,6 +2972,81 @@ static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx) return 0; } +/* + * Returns the compressed size of an inode in 512 byte blocks. + * Count the on-disk space used by extents starting in range [start, end), + * inline data are rounded up to sector, ie. 512. + * + * The range is start inclusive and end exclusive so it can be used to + * determine compressed size of a given extent by its start and start of the + * next extent easily, without counting length. + * Whole file is specified as start = 0, end = (u64)-1 + */ +static long btrfs_ioctl_compr_size(struct file *file, void __user *argp) +{ + struct inode *inode = fdentry(file)->d_inode; + struct btrfs_ioctl_compr_size_args compr_args; + u64 len; + u64 compressed_size = 0; + u64 offset = 0; + + if (S_ISDIR(inode->i_mode)) + return -EISDIR; + + if (copy_from_user(&compr_args, argp, + sizeof(struct btrfs_ioctl_compr_size_args))) + return -EFAULT; + + if (compr_args.start > compr_args.end) + return -EINVAL; + + mutex_lock(&inode->i_mutex); + + offset = compr_args.start; + if (inode->i_size > compr_args.end) + len = compr_args.end; + else + len = inode->i_size; + + /* + * do any pending delalloc/csum calc on inode, one way or + * another, and lock file content + */ + btrfs_wait_ordered_range(inode, compr_args.start, len); + + while (offset < len) { + struct extent_map *em; + + em = btrfs_get_extent(inode, NULL, 0, offset, 1, 0); + if (IS_ERR_OR_NULL(em)) + goto error; + if (em->block_len != (u64)-1) + compressed_size += em->block_len; + else if (em->block_start == EXTENT_MAP_INLINE) { + compressed_size += ALIGN(em->len, 512); + } + offset += em->len; + free_extent_map(em); + } + mutex_unlock(&inode->i_mutex); + + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS); + + compr_args.size = compressed_size >> 9; + + if (copy_to_user(argp, &compr_args, sizeof(struct + btrfs_ioctl_compr_size_args))) + return -EFAULT; + + return 0; + +error: + mutex_unlock(&inode->i_mutex); + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS); + + return -EIO; +} + static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, void __user *arg) { @@ -3110,6 +3185,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_scrub_cancel(root, argp); case BTRFS_IOC_SCRUB_PROGRESS: return btrfs_ioctl_scrub_progress(root, argp); + case BTRFS_IOC_COMPR_SIZE: + return btrfs_ioctl_compr_size(file, argp); } return -ENOTTY; diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 252ae99..bce761c 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h @@ -217,6 +217,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]; +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -276,5 +285,7 @@ struct btrfs_ioctl_logical_ino_args { struct btrfs_ioctl_ino_path_args) #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ struct btrfs_ioctl_ino_path_args) +#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ + struct btrfs_ioctl_compr_size_args) #endif -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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
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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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 <dsterba@suse.cz> Signed-off-by: David Sterba <dsterba@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 end range 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, \ struct btrfs_ioctl_ino_path_args) +#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ + struct btrfs_ioctl_compr_size_args) #endif -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Liu Bo
2011-Dec-20 01:33 UTC
Re: [PATCH] btrfs: add new ioctl to determine size of compressed file
On 12/19/2011 10:17 PM, David Sterba wrote:> Go through all extents of a file in a given [start,end) range and sum > for: > * regular extent: ->block_len, size is already rounded up to blocks > * inline extents: length rounded up to 512 > > The range is start inclusive / end exclusive. For the whole file pass > 0 and (u64)-1. > > The resulting value is number of occupied 512B sectors so this can > be easily compared to stat.st_blocks to determine rough compression > ratio of a file. > > Based on implementation from Ulrich Hecht, > http://comments.gmane.org/gmane.comp.file-systems.btrfs/6253 > > Signed-off-by: David Sterba <dsterba@suse.cz> > --- > fs/btrfs/ioctl.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > fs/btrfs/ioctl.h | 11 +++++++ > 2 files changed, 88 insertions(+), 0 deletions(-) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index c04f02c..82c3810 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -2972,6 +2972,81 @@ static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx) > return 0; > } > > +/* > + * Returns the compressed size of an inode in 512 byte blocks. > + * Count the on-disk space used by extents starting in range [start, end), > + * inline data are rounded up to sector, ie. 512. > + * > + * The range is start inclusive and end exclusive so it can be used to > + * determine compressed size of a given extent by its start and start of the > + * next extent easily, without counting length. > + * Whole file is specified as start = 0, end = (u64)-1 > + */ > +static long btrfs_ioctl_compr_size(struct file *file, void __user *argp) > +{ > + struct inode *inode = fdentry(file)->d_inode; > + struct btrfs_ioctl_compr_size_args compr_args; > + u64 len; > + u64 compressed_size = 0; > + u64 offset = 0; > + > + if (S_ISDIR(inode->i_mode)) > + return -EISDIR; > + > + if (copy_from_user(&compr_args, argp, > + sizeof(struct btrfs_ioctl_compr_size_args))) > + return -EFAULT; > + > + if (compr_args.start > compr_args.end) > + return -EINVAL; > + > + mutex_lock(&inode->i_mutex); > + > + offset = compr_args.start; > + if (inode->i_size > compr_args.end) > + len = compr_args.end; > + else > + len = inode->i_size; > + > + /* > + * do any pending delalloc/csum calc on inode, one way or > + * another, and lock file content > + */ > + btrfs_wait_ordered_range(inode, compr_args.start, len); > +missing a lock_extent() ? and we may adjust i_mutex and [un]lock_extent. thanks, liubo> + while (offset < len) { > + struct extent_map *em; > + > + em = btrfs_get_extent(inode, NULL, 0, offset, 1, 0); > + if (IS_ERR_OR_NULL(em)) > + goto error; > + if (em->block_len != (u64)-1) > + compressed_size += em->block_len; > + else if (em->block_start == EXTENT_MAP_INLINE) { > + compressed_size += ALIGN(em->len, 512); > + } > + offset += em->len; > + free_extent_map(em); > + } > + mutex_unlock(&inode->i_mutex); > + > + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS); > + > + compr_args.size = compressed_size >> 9; > + > + if (copy_to_user(argp, &compr_args, sizeof(struct > + btrfs_ioctl_compr_size_args))) > + return -EFAULT; > + > + return 0; > + > +error: > + mutex_unlock(&inode->i_mutex); > + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS); > + > + return -EIO; > +} > + > static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, > void __user *arg) > { > @@ -3110,6 +3185,8 @@ long btrfs_ioctl(struct file *file, unsigned int > return btrfs_ioctl_scrub_cancel(root, argp); > case BTRFS_IOC_SCRUB_PROGRESS: > return btrfs_ioctl_scrub_progress(root, argp); > + case BTRFS_IOC_COMPR_SIZE: > + return btrfs_ioctl_compr_size(file, argp); > } > > return -ENOTTY; > diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h > index 252ae99..bce761c 100644 > --- a/fs/btrfs/ioctl.h > +++ b/fs/btrfs/ioctl.h > @@ -217,6 +217,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]; > +}; > + > #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ > struct btrfs_ioctl_vol_args) > #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ > @@ -276,5 +285,7 @@ struct btrfs_ioctl_logical_ino_args { > struct btrfs_ioctl_ino_path_args) > #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ > struct btrfs_ioctl_ino_path_args) > +#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ > + struct btrfs_ioctl_compr_size_args) > > #endif-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2011-Dec-20 17:26 UTC
Re: [PATCH] btrfs: add new ioctl to determine size of compressed file
On Tue, Dec 20, 2011 at 09:33:06AM +0800, Liu Bo wrote:> > +static long btrfs_ioctl_compr_size(struct file *file, void __user *argp) > > +{ > > + struct inode *inode = fdentry(file)->d_inode; > > + struct btrfs_ioctl_compr_size_args compr_args; > > + u64 len; > > + u64 compressed_size = 0; > > + u64 offset = 0; > > + > > + if (S_ISDIR(inode->i_mode)) > > + return -EISDIR; > > + > > + if (copy_from_user(&compr_args, argp, > > + sizeof(struct btrfs_ioctl_compr_size_args))) > > + return -EFAULT; > > + > > + if (compr_args.start > compr_args.end) > > + return -EINVAL; > > + > > + mutex_lock(&inode->i_mutex); > > + > > + offset = compr_args.start; > > + if (inode->i_size > compr_args.end) > > + len = compr_args.end; > > + else > > + len = inode->i_size; > > + > > + /* > > + * do any pending delalloc/csum calc on inode, one way or > > + * another, and lock file content > > + */ > > + btrfs_wait_ordered_range(inode, compr_args.start, len); > > + > > missing a lock_extent() ?yeah right, thanks, it was missing even in the original implementation and was left unnoticed.> and we may adjust i_mutex and [un]lock_extent.adjusted which way? I have swapped order of unlock_extent/mutex_unlock as it was in the wrong order wrt locking. I''ll send V2 in a minute. thanks, david -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2011-Dec-20 17:46 UTC
[PATCH V2] btrfs: add new ioctl to determine size of compressed file
Go through all extents of a file in a given [start,end) range and sum for: * regular extent: ->block_len, size is already rounded up to blocks * inline extents: length rounded up to 512 The range is start inclusive / end exclusive. For whole a file pass 0 and (u64)-1. The values returned are number of occupied 512B sectors for uncompressed and compressed size and can be easily compared to determine rough compression ratio of the given file range. Based on implementation from Ulrich Hecht, http://comments.gmane.org/gmane.comp.file-systems.btrfs/6253 Signed-off-by: David Sterba <dsterba@suse.cz> --- V1-V2: * count uncompressed length as well * add missed lock_extent * properly ordered unlocking sequence of mutex and extent fs/btrfs/ioctl.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/ioctl.h | 12 ++++++++ 2 files changed, 94 insertions(+), 0 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c04f02c..4e058d7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2972,6 +2972,86 @@ static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx) return 0; } +/* + * Returns the compressed size of an inode in 512 byte blocks. + * Count the on-disk space used by extents starting in range [start, end), + * inline data are rounded up to sector, ie. 512. + * + * The range is start inclusive and end exclusive so it can be used to + * determine compressed size of a given extent by its start and start of the + * next extent easily, without counting length. + * Whole file is specified as start = 0, end = (u64)-1 + */ +static long btrfs_ioctl_compr_size(struct file *file, void __user *argp) +{ + struct inode *inode = fdentry(file)->d_inode; + struct btrfs_ioctl_compr_size_args compr_args; + u64 len; + u64 compressed_size = 0; + u64 size = 0; + u64 offset = 0; + + if (S_ISDIR(inode->i_mode)) + return -EISDIR; + + if (copy_from_user(&compr_args, argp, + sizeof(struct btrfs_ioctl_compr_size_args))) + return -EFAULT; + + if (compr_args.start > compr_args.end) + return -EINVAL; + + mutex_lock(&inode->i_mutex); + + offset = compr_args.start; + if (inode->i_size > compr_args.end) + len = compr_args.end; + else + len = inode->i_size; + + /* + * do any pending delalloc/csum calc on inode, one way or + * another, and lock file content + */ + btrfs_wait_ordered_range(inode, compr_args.start, len); + + lock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS); + + while (offset < len) { + struct extent_map *em; + + em = btrfs_get_extent(inode, NULL, 0, offset, 1, 0); + if (IS_ERR_OR_NULL(em)) + goto error; + if (em->block_len != (u64)-1) { + compressed_size += em->block_len; + size += ALIGN(em->len, inode->i_sb->s_blocksize); + } else if (em->block_start == EXTENT_MAP_INLINE) { + compressed_size += ALIGN(em->len, 512); + size += ALIGN(em->len, 512); + } + offset += em->len; + free_extent_map(em); + } + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS); + mutex_unlock(&inode->i_mutex); + + compr_args.size = size >> 9; + compr_args.compressed_size = compressed_size >> 9; + + if (copy_to_user(argp, &compr_args, + sizeof(struct btrfs_ioctl_compr_size_args))) + return -EFAULT; + + return 0; + +error: + unlock_extent(&BTRFS_I(inode)->io_tree, compr_args.start, len, GFP_NOFS); + mutex_unlock(&inode->i_mutex); + + return -EIO; +} + static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, void __user *arg) { @@ -3110,6 +3190,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_scrub_cancel(root, argp); case BTRFS_IOC_SCRUB_PROGRESS: return btrfs_ioctl_scrub_progress(root, argp); + case BTRFS_IOC_COMPR_SIZE: + return btrfs_ioctl_compr_size(file, argp); } return -ENOTTY; diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 252ae99..d7b425a 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h @@ -217,6 +217,16 @@ 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 compressed_size; /* out */ + __u64 reserved[2]; +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -276,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, \ struct btrfs_ioctl_ino_path_args) +#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ + struct btrfs_ioctl_compr_size_args) #endif -- 1.7.6.233.gd79bc -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2011-Dec-20 17:49 UTC
[PATCH V2] btrfs-progs: Add ioctl to read compressed size of a file
Signed-off-by: David Sterba <dsterba@suse.cz> --- V1-V2: * match current kernel side and print uncompressed length as well * now it''s easy to print the compression ratio for the given range btrfs.c | 9 ++++++- btrfs_cmds.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ btrfs_cmds.h | 1 + ioctl.h | 13 +++++++++++ 4 files changed, 90 insertions(+), 1 deletions(-) diff --git a/btrfs.c b/btrfs.c index 1def354..dbb7224 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 ordinary and compressed size of extents in the range [start,end)\n" + "-s start range start inclusive, accepts K/M/G modifiers\n" + "-e end range end exclusive, accepts K/M/G modifiers\n", + NULL }, { do_scrub_start, -1, "scrub start", "[-Bdqr] <path>|<device>\n" diff --git a/btrfs_cmds.c b/btrfs_cmds.c index b59e9cb..1074ade 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -1305,3 +1305,71 @@ 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:r"); + 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("File name: %s\n", argv[optind]); + if (args.end == (u64)-1) + printf("File range: %llu-EOF\n", + (unsigned long long)args.start); + else + printf("File range: %llu-%llu\n", + (unsigned long long)args.start, + (unsigned long long)args.end); + + printf("Compressed size: %llu\n", + (unsigned long long)(args.compressed_size << 9)); + printf("Uncompressed size: %llu\n", + (unsigned long long)(args.size << 9)); + printf("Ratio: %3.2f%%\n", + 100.0 * args.compressed_size / args.size); + 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..5b5208a 100644 --- a/ioctl.h +++ b/ioctl.h @@ -224,6 +224,17 @@ 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 compressed_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 +288,7 @@ struct btrfs_ioctl_logical_ino_args { struct btrfs_ioctl_ino_path_args) #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ struct btrfs_ioctl_ino_path_args) +#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ + struct btrfs_ioctl_compr_size_args) #endif -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Goffredo Baroncelli
2011-Dec-20 20:32 UTC
Re: [PATCH V2] btrfs-progs: Add ioctl to read compressed size of a file
Hi David On Tuesday, 20 December, 2011 18:49:58 David Sterba wrote:> Signed-off-by: David Sterba <dsterba@suse.cz> > --- > V1-V2: > * match current kernel side and print uncompressed length as well > * now it''s easy to print the compression ratio for the given range > > btrfs.c | 9 ++++++- > btrfs_cmds.c | 68 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ btrfs_cmds.h | > 1 + > ioctl.h | 13 +++++++++++Please, update the man page too> 4 files changed, 90 insertions(+), 1 deletions(-) > > diff --git a/btrfs.c b/btrfs.c > index 1def354..dbb7224 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 ordinary and compressed size of extents in the range > [start,end)\n" + "-s start range start inclusive, accepts K/M/G > modifiers\n" > + "-e end range end exclusive, accepts K/M/G modifiers\n", > + NULL > }, > { do_scrub_start, -1, > "scrub start", "[-Bdqr] <path>|<device>\n" > diff --git a/btrfs_cmds.c b/btrfs_cmds.c > index b59e9cb..1074ade 100644 > --- a/btrfs_cmds.c > +++ b/btrfs_cmds.c > @@ -1305,3 +1305,71 @@ 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:r"); > + 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("File name: %s\n", argv[optind]); > + if (args.end == (u64)-1) > + printf("File range: %llu-EOF\n", > + (unsigned long long)args.start); > + else > + printf("File range: %llu-%llu\n", > + (unsigned long long)args.start, > + (unsigned long long)args.end); > + > + printf("Compressed size: %llu\n", > + (unsigned long long)(args.compressed_size << 9)); > + printf("Uncompressed size: %llu\n", > + (unsigned long long)(args.size << 9)); > + printf("Ratio: %3.2f%%\n", > + 100.0 * args.compressed_size / args.size); > + 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..5b5208a 100644 > --- a/ioctl.h > +++ b/ioctl.h > @@ -224,6 +224,17 @@ 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 compressed_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 +288,7 @@ struct btrfs_ioctl_logical_ino_args { > struct btrfs_ioctl_ino_path_args) > #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ > struct btrfs_ioctl_ino_path_args) > +#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ > + struct btrfs_ioctl_compr_size_args) > > #endif-- gpg key@ keyserver.linux.it: Goffredo Baroncelli (ghigo) <kreijack@inwind.it> Key fingerprint = 4769 7E51 5293 D36C 814E C054 BF04 F161 3DC5 0512 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2012-Jan-06 18:21 UTC
[PATCH v3] btrfs-progs: Add ioctl to read compressed size of a file
Signed-off-by: David Sterba <dsterba@suse.cz> --- v2->v3: manpage updated, added <...> around file in command description btrfs.c | 9 ++++++- btrfs_cmds.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ btrfs_cmds.h | 1 + ioctl.h | 13 ++++++++++ man/btrfs.8.in | 10 ++++++++ 5 files changed, 100 insertions(+), 1 deletions(-) diff --git a/btrfs.c b/btrfs.c index 1def354..d6a7665 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 ordinary and compressed size of extents in the range [start,end)\n" + "-s start range start inclusive, accepts K/M/G modifiers\n" + "-e end range end exclusive, accepts K/M/G modifiers\n", + NULL }, { do_scrub_start, -1, "scrub start", "[-Bdqr] <path>|<device>\n" diff --git a/btrfs_cmds.c b/btrfs_cmds.c index b59e9cb..1074ade 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -1305,3 +1305,71 @@ 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:r"); + 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("File name: %s\n", argv[optind]); + if (args.end == (u64)-1) + printf("File range: %llu-EOF\n", + (unsigned long long)args.start); + else + printf("File range: %llu-%llu\n", + (unsigned long long)args.start, + (unsigned long long)args.end); + + printf("Compressed size: %llu\n", + (unsigned long long)(args.compressed_size << 9)); + printf("Uncompressed size: %llu\n", + (unsigned long long)(args.size << 9)); + printf("Ratio: %3.2f%%\n", + 100.0 * args.compressed_size / args.size); + 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..5b5208a 100644 --- a/ioctl.h +++ b/ioctl.h @@ -224,6 +224,17 @@ 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 compressed_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 +288,7 @@ struct btrfs_ioctl_logical_ino_args { struct btrfs_ioctl_ino_path_args) #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ struct btrfs_ioctl_ino_path_args) +#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \ + struct btrfs_ioctl_compr_size_args) #endif diff --git a/man/btrfs.8.in b/man/btrfs.8.in index be478e0..b7dacea 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -31,6 +31,8 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBfilesystem defragment\fP\fI <file>|<dir> [<file>|<dir>...]\fP .PP +\fBbtrfs\fP \fBfilesystem csize \fP\fI [-s start] [-e end] <file> \fP +.PP \fBbtrfs\fP \fBdevice scan\fP\fI [--all-devices|<device> [<device>...]]\fP .PP \fBbtrfs\fP \fBdevice show\fP\fI [--all-devices|<uuid>|<label>]\fP @@ -209,6 +211,14 @@ If \fB--all-devices\fP is passed, all the devices under /dev are scanned; otherwise the devices list is extracted from the /proc/partitions file. .TP +\fBfilesystem csize \fR \fI [-s start] [-e end] <file> \fR +Read ordinary and compressed size of extents in the range [start,end) of \fI<file>\fR +.IP +\fB-s start\fP range start inclusive, accepts K/M/G modifiers +.IP +\fB-e end\fP range end exclusive, accepts K/M/G modifiers +.TP + \fBdevice balance\fR \fI<path>\fR Balance the chunks of the filesystem identified by \fI<path>\fR across the devices. -- 1.7.6.233.gd79bc -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html