aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 f4b4677bec7..6c2c2c4e4d2 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -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);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8e69b5acfef..30a5094fffa 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -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]++;
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b437d3bdf95..1bf37d15b17 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)
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 {