Skip to content

Commit

Permalink
Btrfs: export btrfs space shared info to userspace
Browse files Browse the repository at this point in the history
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

Reviewed-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
  • Loading branch information
Liu Bo authored and Chris Mason committed Nov 12, 2013
1 parent 7451432 commit fe09e16
Showing 1 changed file with 33 additions and 1 deletion.
34 changes: 33 additions & 1 deletion fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -4062,6 +4063,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)
{
unsigned long cnt = *((unsigned long *)ctx);

cnt++;
*((unsigned long *)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)
{
Expand Down Expand Up @@ -4128,7 +4142,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
Expand Down Expand Up @@ -4198,7 +4212,24 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
flags |= (FIEMAP_EXTENT_DELALLOC |
FIEMAP_EXTENT_UNKNOWN);
} else {
unsigned long 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 && ret != -ENOENT)
goto out_free;

if (ref_cnt > 1)
flags |= FIEMAP_EXTENT_SHARED;
}
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
flags |= FIEMAP_EXTENT_ENCODED;
Expand Down Expand Up @@ -4230,6 +4261,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
out_free:
free_extent_map(em);
out:
btrfs_free_path(path);
unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, start + len - 1,
&cached_state, GFP_NOFS);
return ret;
Expand Down

0 comments on commit fe09e16

Please sign in to comment.