aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c40
1 files changed, 15 insertions, 25 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index d70feb545066..d5e71d4646dd 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4169,19 +4169,6 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode,
4169 return NULL; 4169 return NULL;
4170} 4170}
4171 4171
4172static noinline int count_ext_ref(u64 inum, u64 offset, u64 root_id, void *ctx)
4173{
4174 unsigned long cnt = *((unsigned long *)ctx);
4175
4176 cnt++;
4177 *((unsigned long *)ctx) = cnt;
4178
4179 /* Now we're sure that the extent is shared. */
4180 if (cnt > 1)
4181 return 1;
4182 return 0;
4183}
4184
4185int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 4172int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
4186 __u64 start, __u64 len, get_extent_t *get_extent) 4173 __u64 start, __u64 len, get_extent_t *get_extent)
4187{ 4174{
@@ -4198,6 +4185,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
4198 struct extent_map *em = NULL; 4185 struct extent_map *em = NULL;
4199 struct extent_state *cached_state = NULL; 4186 struct extent_state *cached_state = NULL;
4200 struct btrfs_path *path; 4187 struct btrfs_path *path;
4188 struct btrfs_root *root = BTRFS_I(inode)->root;
4201 int end = 0; 4189 int end = 0;
4202 u64 em_start = 0; 4190 u64 em_start = 0;
4203 u64 em_len = 0; 4191 u64 em_len = 0;
@@ -4218,8 +4206,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
4218 * lookup the last file extent. We're not using i_size here 4206 * lookup the last file extent. We're not using i_size here
4219 * because there might be preallocation past i_size 4207 * because there might be preallocation past i_size
4220 */ 4208 */
4221 ret = btrfs_lookup_file_extent(NULL, BTRFS_I(inode)->root, 4209 ret = btrfs_lookup_file_extent(NULL, root, path, btrfs_ino(inode), -1,
4222 path, btrfs_ino(inode), -1, 0); 4210 0);
4223 if (ret < 0) { 4211 if (ret < 0) {
4224 btrfs_free_path(path); 4212 btrfs_free_path(path);
4225 return ret; 4213 return ret;
@@ -4312,25 +4300,27 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
4312 } else if (em->block_start == EXTENT_MAP_DELALLOC) { 4300 } else if (em->block_start == EXTENT_MAP_DELALLOC) {
4313 flags |= (FIEMAP_EXTENT_DELALLOC | 4301 flags |= (FIEMAP_EXTENT_DELALLOC |
4314 FIEMAP_EXTENT_UNKNOWN); 4302 FIEMAP_EXTENT_UNKNOWN);
4315 } else { 4303 } else if (fieinfo->fi_extents_max) {
4316 unsigned long ref_cnt = 0; 4304 u64 bytenr = em->block_start -
4305 (em->start - em->orig_start);
4317 4306
4318 disko = em->block_start + offset_in_extent; 4307 disko = em->block_start + offset_in_extent;
4319 4308
4320 /* 4309 /*
4321 * As btrfs supports shared space, this information 4310 * As btrfs supports shared space, this information
4322 * can be exported to userspace tools via 4311 * can be exported to userspace tools via
4323 * flag FIEMAP_EXTENT_SHARED. 4312 * flag FIEMAP_EXTENT_SHARED. If fi_extents_max == 0
4313 * then we're just getting a count and we can skip the
4314 * lookup stuff.
4324 */ 4315 */
4325 ret = iterate_inodes_from_logical( 4316 ret = btrfs_check_shared(NULL, root->fs_info,
4326 em->block_start, 4317 root->objectid,
4327 BTRFS_I(inode)->root->fs_info, 4318 btrfs_ino(inode), bytenr);
4328 path, count_ext_ref, &ref_cnt); 4319 if (ret < 0)
4329 if (ret < 0 && ret != -ENOENT)
4330 goto out_free; 4320 goto out_free;
4331 4321 if (ret)
4332 if (ref_cnt > 1)
4333 flags |= FIEMAP_EXTENT_SHARED; 4322 flags |= FIEMAP_EXTENT_SHARED;
4323 ret = 0;
4334 } 4324 }
4335 if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) 4325 if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
4336 flags |= FIEMAP_EXTENT_ENCODED; 4326 flags |= FIEMAP_EXTENT_ENCODED;