Liu Bo
2013-Aug-16 08:27 UTC
[RFC PATCH] Btrfs: export btrfs space shared info to userspace
Similar to ocfs2, btrfs also supports that extents can be shared by different inodes, and there are some userspace tools requesting for this kind of ''space shared infomation''.[1] ocfs2 uses flag FIEMAP_EXTENT_SHARED, so does btrfs. [1]: http://thr3ads.net/ocfs2-devel/2010/09/489052-PATCH-3-3-shared-du-using-fiemap-to-figure-up-the-shared-extents-per-file-and-the-footprint-in Signed-off-by: Liu Bo <bo.li.liu@oracle.com> --- fs/btrfs/extent_io.c | 34 +++++++++++++++++++++++++++++++++- 1 files changed, 33 insertions(+), 1 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index fe443fe..2b3dd4a 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -20,6 +20,7 @@ #include "check-integrity.h" #include "locking.h" #include "rcu-string.h" +#include "backref.h" static struct kmem_cache *extent_state_cache; static struct kmem_cache *extent_buffer_cache; @@ -3957,6 +3958,19 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode, return NULL; } +static noinline int count_ext_ref(u64 inum, u64 offset, u64 root_id, void *ctx) +{ + int cnt = *((int *)ctx); + + cnt++; + *((int *)ctx) = cnt; + + /* Now we''re sure that the extent is shared. */ + if (cnt > 1) + return 1; + return 0; +} + int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, __u64 start, __u64 len, get_extent_t *get_extent) { @@ -4023,7 +4037,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, last = found_key.offset; last_for_get_extent = last + 1; } - btrfs_free_path(path); + btrfs_release_path(path); /* * we might have some extents allocated but more delalloc past those @@ -4093,7 +4107,24 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, flags |= (FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN); } else { + int ref_cnt = 0; + disko = em->block_start + offset_in_extent; + + /* + * As btrfs supports shared space, this information + * can be exported to userspace tools via + * flag FIEMAP_EXTENT_SHARED. + */ + ret = iterate_inodes_from_logical( + em->block_start, + BTRFS_I(inode)->root->fs_info, + path, count_ext_ref, &ref_cnt); + if (ret < 0) + goto out_free; + + if (ref_cnt > 1) + flags |= FIEMAP_EXTENT_SHARED; } if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) flags |= FIEMAP_EXTENT_ENCODED; @@ -4127,6 +4158,7 @@ out_free: out: unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, start + len - 1, &cached_state, GFP_NOFS); + btrfs_free_path(path); return ret; } -- 1.7.7 -- 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
2013-Aug-28 17:29 UTC
Re: [RFC PATCH] Btrfs: export btrfs space shared info to userspace
On Fri, Aug 16, 2013 at 04:27:28PM +0800, Liu Bo wrote:> Similar to ocfs2, btrfs also supports that extents can be shared by > different inodes, and there are some userspace tools requesting > for this kind of ''space shared infomation''.[1] > > ocfs2 uses flag FIEMAP_EXTENT_SHARED, so does btrfs.Looks ok to me.> + int ref_cnt = 0;I think using long is cleaner here, it always fits into (void*), int does not.> + /* > + * As btrfs supports shared space, this information > + * can be exported to userspace tools via > + * flag FIEMAP_EXTENT_SHARED. > + */ > + ret = iterate_inodes_from_logical( > + em->block_start, > + BTRFS_I(inode)->root->fs_info, > + path, count_ext_ref, &ref_cnt); > + if (ret < 0) > + goto out_free; > + > + if (ref_cnt > 1) > + flags |= FIEMAP_EXTENT_SHARED;AFAICS, e2fsprogs filefrag does not yet know about FIEMAP_EXTENT_SHARED. 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
Liu Bo
2013-Aug-29 03:06 UTC
Re: [RFC PATCH] Btrfs: export btrfs space shared info to userspace
On Wed, Aug 28, 2013 at 07:29:38PM +0200, David Sterba wrote:> On Fri, Aug 16, 2013 at 04:27:28PM +0800, Liu Bo wrote: > > Similar to ocfs2, btrfs also supports that extents can be shared by > > different inodes, and there are some userspace tools requesting > > for this kind of ''space shared infomation''.[1] > > > > ocfs2 uses flag FIEMAP_EXTENT_SHARED, so does btrfs. > > Looks ok to me. > > > + int ref_cnt = 0; > > I think using long is cleaner here, it always fits into (void*), int > does not.Good point.> > > + /* > > + * As btrfs supports shared space, this information > > + * can be exported to userspace tools via > > + * flag FIEMAP_EXTENT_SHARED. > > + */ > > + ret = iterate_inodes_from_logical( > > + em->block_start, > > + BTRFS_I(inode)->root->fs_info, > > + path, count_ext_ref, &ref_cnt); > > + if (ret < 0) > > + goto out_free; > > + > > + if (ref_cnt > 1) > > + flags |= FIEMAP_EXTENT_SHARED; > > AFAICS, e2fsprogs filefrag does not yet know about FIEMAP_EXTENT_SHARED.With checking filefrag''s code, it''s easy to make filefrag aware of this flag. I''ll make a patch for filefrag unless someone has already done it, thanks. -liubo -- 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