diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 20 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 8 |
2 files changed, 23 insertions, 5 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 30a5094fffa7..db996f0edf0b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -731,6 +731,7 @@ u32 btrfs_count_snapshots_in_path(struct btrfs_root *root, | |||
731 | u64 found_owner; | 731 | u64 found_owner; |
732 | u64 root_objectid = root->root_key.objectid; | 732 | u64 root_objectid = root->root_key.objectid; |
733 | u32 total_count = 0; | 733 | u32 total_count = 0; |
734 | u32 extent_refs; | ||
734 | u32 cur_count; | 735 | u32 cur_count; |
735 | u32 nritems; | 736 | u32 nritems; |
736 | int ret; | 737 | int ret; |
@@ -767,6 +768,7 @@ again: | |||
767 | } | 768 | } |
768 | 769 | ||
769 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); | 770 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); |
771 | extent_refs = btrfs_extent_refs(l, item); | ||
770 | while (1) { | 772 | while (1) { |
771 | l = path->nodes[0]; | 773 | l = path->nodes[0]; |
772 | nritems = btrfs_header_nritems(l); | 774 | nritems = btrfs_header_nritems(l); |
@@ -800,10 +802,28 @@ again: | |||
800 | total_count = 2; | 802 | total_count = 2; |
801 | goto out; | 803 | goto out; |
802 | } | 804 | } |
805 | /* | ||
806 | * nasty. we don't count a reference held by | ||
807 | * the running transaction. This allows nodatacow | ||
808 | * to avoid cow most of the time | ||
809 | */ | ||
810 | if (found_owner >= BTRFS_FIRST_FREE_OBJECTID && | ||
811 | btrfs_ref_generation(l, ref_item) == | ||
812 | root->fs_info->generation) { | ||
813 | extent_refs--; | ||
814 | } | ||
803 | } | 815 | } |
804 | total_count = 1; | 816 | total_count = 1; |
805 | path->slots[0]++; | 817 | path->slots[0]++; |
806 | } | 818 | } |
819 | /* | ||
820 | * if there is more than one reference against a data extent, | ||
821 | * we have to assume the other ref is another snapshot | ||
822 | */ | ||
823 | if (level == -1 && extent_refs > 1) { | ||
824 | total_count = 2; | ||
825 | goto out; | ||
826 | } | ||
807 | if (cur_count == 0) { | 827 | if (cur_count == 0) { |
808 | total_count = 0; | 828 | total_count = 0; |
809 | goto out; | 829 | goto out; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1bf37d15b174..a492fd238c88 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -207,9 +207,8 @@ again: | |||
207 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 207 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
208 | found_type = btrfs_key_type(&found_key); | 208 | found_type = btrfs_key_type(&found_key); |
209 | if (found_key.objectid != inode->i_ino || | 209 | if (found_key.objectid != inode->i_ino || |
210 | found_type != BTRFS_EXTENT_DATA_KEY) { | 210 | found_type != BTRFS_EXTENT_DATA_KEY) |
211 | goto not_found; | 211 | goto not_found; |
212 | } | ||
213 | 212 | ||
214 | found_type = btrfs_file_extent_type(leaf, item); | 213 | found_type = btrfs_file_extent_type(leaf, item); |
215 | extent_start = found_key.offset; | 214 | extent_start = found_key.offset; |
@@ -245,7 +244,6 @@ again: | |||
245 | if (!block_group || block_group->ro) | 244 | if (!block_group || block_group->ro) |
246 | goto not_found; | 245 | goto not_found; |
247 | 246 | ||
248 | |||
249 | start = extent_end; | 247 | start = extent_end; |
250 | } else { | 248 | } else { |
251 | goto not_found; | 249 | goto not_found; |
@@ -260,8 +258,8 @@ loop: | |||
260 | goto again; | 258 | goto again; |
261 | 259 | ||
262 | not_found: | 260 | not_found: |
263 | cow_file_range(inode, start, cow_end); | 261 | cow_file_range(inode, start, end); |
264 | start = cow_end + 1; | 262 | start = end + 1; |
265 | goto loop; | 263 | goto loop; |
266 | } | 264 | } |
267 | 265 | ||