Btrfs: Update nodatacow mode to support cloned single files and resizing
authorChris Mason <chris.mason@oracle.com>
Thu, 8 May 2008 18:11:56 +0000 (14:11 -0400)
committerChris Mason <chris.mason@oracle.com>
Thu, 25 Sep 2008 15:04:02 +0000 (11:04 -0400)
Before, nodatacow only checked to make sure multiple roots didn't have
references on a single extent.  This check makes sure that multiple
inodes don't have references.

nodatacow needed an extra check to see if the block group was currently
readonly.  This way cows forced by the chunk relocation code are honored.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/inode.c

index f4b4677bec77e0b171f7d2dd29ec81d5adc2f9cb..6c2c2c4e4d2a43408c15560dad4e30d7611e4098 100644 (file)
@@ -1325,7 +1325,7 @@ static inline struct dentry *fdentry(struct file *file) {
 /* extent-tree.c */
 u32 btrfs_count_snapshots_in_path(struct btrfs_root *root,
                                  struct btrfs_path *count_path,
-                                 u64 first_extent);
+                                 u64 expected_owner, u64 first_extent);
 int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
                         struct btrfs_root *root);
 int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy);
index 8e69b5acfeff6018d7337ecc3b2aca838e415a04..30a5094fffa71b86e65d3465f52a1250738c6696 100644 (file)
@@ -721,12 +721,14 @@ out:
 
 u32 btrfs_count_snapshots_in_path(struct btrfs_root *root,
                                  struct btrfs_path *count_path,
+                                 u64 expected_owner,
                                  u64 first_extent)
 {
        struct btrfs_root *extent_root = root->fs_info->extent_root;
        struct btrfs_path *path;
        u64 bytenr;
        u64 found_objectid;
+       u64 found_owner;
        u64 root_objectid = root->root_key.objectid;
        u32 total_count = 0;
        u32 cur_count;
@@ -792,6 +794,13 @@ again:
                        total_count = 2;
                        goto out;
                }
+               if (level == -1) {
+                       found_owner = btrfs_ref_objectid(l, ref_item);
+                       if (found_owner != expected_owner) {
+                               total_count = 2;
+                               goto out;
+                       }
+               }
                total_count = 1;
                path->slots[0]++;
        }
index b437d3bdf95e7ba3ce3223b7862c9892609bbe1e..1bf37d15b17411c77f2428dd2afa40692720f5d3 100644 (file)
@@ -172,6 +172,7 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end)
        u64 loops = 0;
        u64 total_fs_bytes;
        struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_block_group_cache *block_group;
        struct extent_buffer *leaf;
        int found_type;
        struct btrfs_path *path;
@@ -230,16 +231,20 @@ again:
                if (bytenr == 0)
                        goto not_found;
 
+               if (btrfs_count_snapshots_in_path(root, path, inode->i_ino,
+                                                 bytenr) != 1) {
+                       goto not_found;
+               }
+
                /*
                 * we may be called by the resizer, make sure we're inside
                 * the limits of the FS
                 */
-               if (bytenr + extent_num_bytes > total_fs_bytes)
+               block_group = btrfs_lookup_block_group(root->fs_info,
+                                                      bytenr);
+               if (!block_group || block_group->ro)
                        goto not_found;
 
-               if (btrfs_count_snapshots_in_path(root, path, bytenr) != 1) {
-                       goto not_found;
-               }
 
                start = extent_end;
        } else {