aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-05-08 14:11:56 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:02 -0400
commita68d5933a0e409592860229b35230c8e87155472 (patch)
treef58e963b03034935429b42be735ee59cd06110e1
parentbf4ef67924d87b0addb32f084e83a9283496350e (diff)
Btrfs: Update nodatacow mode to support cloned single files and resizing
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>
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c9
-rw-r--r--fs/btrfs/inode.c13
3 files changed, 19 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f4b4677bec77..6c2c2c4e4d2a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1325,7 +1325,7 @@ static inline struct dentry *fdentry(struct file *file) {
1325/* extent-tree.c */ 1325/* extent-tree.c */
1326u32 btrfs_count_snapshots_in_path(struct btrfs_root *root, 1326u32 btrfs_count_snapshots_in_path(struct btrfs_root *root,
1327 struct btrfs_path *count_path, 1327 struct btrfs_path *count_path,
1328 u64 first_extent); 1328 u64 expected_owner, u64 first_extent);
1329int btrfs_extent_post_op(struct btrfs_trans_handle *trans, 1329int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
1330 struct btrfs_root *root); 1330 struct btrfs_root *root);
1331int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy); 1331int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8e69b5acfeff..30a5094fffa7 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -721,12 +721,14 @@ out:
721 721
722u32 btrfs_count_snapshots_in_path(struct btrfs_root *root, 722u32 btrfs_count_snapshots_in_path(struct btrfs_root *root,
723 struct btrfs_path *count_path, 723 struct btrfs_path *count_path,
724 u64 expected_owner,
724 u64 first_extent) 725 u64 first_extent)
725{ 726{
726 struct btrfs_root *extent_root = root->fs_info->extent_root; 727 struct btrfs_root *extent_root = root->fs_info->extent_root;
727 struct btrfs_path *path; 728 struct btrfs_path *path;
728 u64 bytenr; 729 u64 bytenr;
729 u64 found_objectid; 730 u64 found_objectid;
731 u64 found_owner;
730 u64 root_objectid = root->root_key.objectid; 732 u64 root_objectid = root->root_key.objectid;
731 u32 total_count = 0; 733 u32 total_count = 0;
732 u32 cur_count; 734 u32 cur_count;
@@ -792,6 +794,13 @@ again:
792 total_count = 2; 794 total_count = 2;
793 goto out; 795 goto out;
794 } 796 }
797 if (level == -1) {
798 found_owner = btrfs_ref_objectid(l, ref_item);
799 if (found_owner != expected_owner) {
800 total_count = 2;
801 goto out;
802 }
803 }
795 total_count = 1; 804 total_count = 1;
796 path->slots[0]++; 805 path->slots[0]++;
797 } 806 }
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b437d3bdf95e..1bf37d15b174 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -172,6 +172,7 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end)
172 u64 loops = 0; 172 u64 loops = 0;
173 u64 total_fs_bytes; 173 u64 total_fs_bytes;
174 struct btrfs_root *root = BTRFS_I(inode)->root; 174 struct btrfs_root *root = BTRFS_I(inode)->root;
175 struct btrfs_block_group_cache *block_group;
175 struct extent_buffer *leaf; 176 struct extent_buffer *leaf;
176 int found_type; 177 int found_type;
177 struct btrfs_path *path; 178 struct btrfs_path *path;
@@ -230,16 +231,20 @@ again:
230 if (bytenr == 0) 231 if (bytenr == 0)
231 goto not_found; 232 goto not_found;
232 233
234 if (btrfs_count_snapshots_in_path(root, path, inode->i_ino,
235 bytenr) != 1) {
236 goto not_found;
237 }
238
233 /* 239 /*
234 * we may be called by the resizer, make sure we're inside 240 * we may be called by the resizer, make sure we're inside
235 * the limits of the FS 241 * the limits of the FS
236 */ 242 */
237 if (bytenr + extent_num_bytes > total_fs_bytes) 243 block_group = btrfs_lookup_block_group(root->fs_info,
244 bytenr);
245 if (!block_group || block_group->ro)
238 goto not_found; 246 goto not_found;
239 247
240 if (btrfs_count_snapshots_in_path(root, path, bytenr) != 1) {
241 goto not_found;
242 }
243 248
244 start = extent_end; 249 start = extent_end;
245 } else { 250 } else {