diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 40 |
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 | ||
4172 | static 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 | |||
4185 | int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 4172 | int 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; |