u64 found_owner;
        u64 root_objectid = root->root_key.objectid;
        u32 total_count = 0;
+       u32 extent_refs;
        u32 cur_count;
        u32 nritems;
        int ret;
        }
 
        item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
+       extent_refs = btrfs_extent_refs(l, item);
        while (1) {
                l = path->nodes[0];
                nritems = btrfs_header_nritems(l);
                                total_count = 2;
                                goto out;
                        }
+                       /*
+                        * nasty.  we don't count a reference held by
+                        * the running transaction.  This allows nodatacow
+                        * to avoid cow most of the time
+                        */
+                       if (found_owner >= BTRFS_FIRST_FREE_OBJECTID &&
+                           btrfs_ref_generation(l, ref_item) ==
+                           root->fs_info->generation) {
+                               extent_refs--;
+                       }
                }
                total_count = 1;
                path->slots[0]++;
        }
+       /*
+        * if there is more than one reference against a data extent,
+        * we have to assume the other ref is another snapshot
+        */
+       if (level == -1 && extent_refs > 1) {
+               total_count = 2;
+               goto out;
+       }
        if (cur_count == 0) {
                total_count = 0;
                goto out;
 
        btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
        found_type = btrfs_key_type(&found_key);
        if (found_key.objectid != inode->i_ino ||
-           found_type != BTRFS_EXTENT_DATA_KEY) {
+           found_type != BTRFS_EXTENT_DATA_KEY)
                goto not_found;
-       }
 
        found_type = btrfs_file_extent_type(leaf, item);
        extent_start = found_key.offset;
                if (!block_group || block_group->ro)
                        goto not_found;
 
-
                start = extent_end;
        } else {
                goto not_found;
        goto again;
 
 not_found:
-       cow_file_range(inode, start, cow_end);
-       start = cow_end + 1;
+       cow_file_range(inode, start, end);
+       start = end + 1;
        goto loop;
 }