summaryrefslogtreecommitdiff
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-01-08 15:46:31 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:59 -0400
commitc31f8830f0dfd31e7e196b85ca1b39aef8b77d57 (patch)
tree2ee8038af3d28460dd9004ab69d48d301c0a76b8 /fs/btrfs/inode.c
parentb0331a4c4c339ba7786472b137d6ece9e7f810ec (diff)
downloadlwn-c31f8830f0dfd31e7e196b85ca1b39aef8b77d57.tar.gz
lwn-c31f8830f0dfd31e7e196b85ca1b39aef8b77d57.zip
Btrfs: online shrinking fixes
While shrinking the FS, the allocation functions need to make sure they don't try to allocate bytes past the end of the FS. nodatacow needed an extra check to force cows when the existing extents are past the end of the FS. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 2cb2dd32407e..281757007ddb 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -148,6 +148,7 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end)
u64 bytenr;
u64 cow_end;
u64 loops = 0;
+ u64 total_fs_bytes;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct extent_buffer *leaf;
int found_type;
@@ -157,6 +158,7 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end)
int err;
struct btrfs_key found_key;
+ total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
path = btrfs_alloc_path();
BUG_ON(!path);
again:
@@ -189,8 +191,10 @@ again:
found_type = btrfs_file_extent_type(leaf, item);
extent_start = found_key.offset;
if (found_type == BTRFS_FILE_EXTENT_REG) {
- extent_end = extent_start +
- btrfs_file_extent_num_bytes(leaf, item);
+ u64 extent_num_bytes;
+
+ extent_num_bytes = btrfs_file_extent_num_bytes(leaf, item);
+ extent_end = extent_start + extent_num_bytes;
err = 0;
if (loops && start != extent_start)
@@ -204,6 +208,13 @@ again:
if (bytenr == 0)
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)
+ goto not_found;
+
if (btrfs_count_snapshots_in_path(root, path, bytenr) != 1) {
goto not_found;
}