aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-05-08 16:31:21 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:02 -0400
commitbbaf549e0c3d28399fc5abd68020d4025ae5c3a7 (patch)
tree19443b7e2a18fd04556ab9c5d914de3d29034a0d /fs/btrfs/extent-tree.c
parentc1c4d91c38e6e5b29543b02d4a4fb7f007e44f70 (diff)
Btrfs: A number of nodatacow fixes
Once part of a delalloc request fails the cow checks, just cow the entire range It is possible for the back references to all be from the same root, but still have snapshots against an extent. The checks are now more strict, forcing cow any time there are multiple refs against the data extent. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c20
1 files changed, 20 insertions, 0 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;