diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index bcf3b35fb65e..f13b1dbc0619 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -260,9 +260,9 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | |||
260 | } | 260 | } |
261 | 261 | ||
262 | int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, | 262 | int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, |
263 | unsigned long bits) | 263 | unsigned long old, unsigned long bits) |
264 | { | 264 | { |
265 | if ((bits & EXTENT_DELALLOC)) { | 265 | if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { |
266 | struct btrfs_root *root = BTRFS_I(inode)->root; | 266 | struct btrfs_root *root = BTRFS_I(inode)->root; |
267 | spin_lock(&root->fs_info->delalloc_lock); | 267 | spin_lock(&root->fs_info->delalloc_lock); |
268 | root->fs_info->delalloc_bytes += end - start + 1; | 268 | root->fs_info->delalloc_bytes += end - start + 1; |
@@ -272,12 +272,18 @@ int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, | |||
272 | } | 272 | } |
273 | 273 | ||
274 | int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end, | 274 | int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end, |
275 | unsigned long bits) | 275 | unsigned long old, unsigned long bits) |
276 | { | 276 | { |
277 | if ((bits & EXTENT_DELALLOC)) { | 277 | if ((old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { |
278 | struct btrfs_root *root = BTRFS_I(inode)->root; | 278 | struct btrfs_root *root = BTRFS_I(inode)->root; |
279 | spin_lock(&root->fs_info->delalloc_lock); | 279 | spin_lock(&root->fs_info->delalloc_lock); |
280 | root->fs_info->delalloc_bytes -= end - start + 1; | 280 | if (end - start + 1 > root->fs_info->delalloc_bytes) { |
281 | printk("warning: delalloc account %Lu %Lu\n", | ||
282 | end - start + 1, root->fs_info->delalloc_bytes); | ||
283 | root->fs_info->delalloc_bytes = 0; | ||
284 | } else { | ||
285 | root->fs_info->delalloc_bytes -= end - start + 1; | ||
286 | } | ||
281 | spin_unlock(&root->fs_info->delalloc_lock); | 287 | spin_unlock(&root->fs_info->delalloc_lock); |
282 | } | 288 | } |
283 | return 0; | 289 | return 0; |
@@ -3002,6 +3008,8 @@ static struct extent_io_ops btrfs_extent_io_ops = { | |||
3002 | .writepage_io_hook = btrfs_writepage_io_hook, | 3008 | .writepage_io_hook = btrfs_writepage_io_hook, |
3003 | .readpage_io_hook = btrfs_readpage_io_hook, | 3009 | .readpage_io_hook = btrfs_readpage_io_hook, |
3004 | .readpage_end_io_hook = btrfs_readpage_end_io_hook, | 3010 | .readpage_end_io_hook = btrfs_readpage_end_io_hook, |
3011 | .set_bit_hook = btrfs_set_bit_hook, | ||
3012 | .clear_bit_hook = btrfs_clear_bit_hook, | ||
3005 | }; | 3013 | }; |
3006 | 3014 | ||
3007 | static struct address_space_operations btrfs_aops = { | 3015 | static struct address_space_operations btrfs_aops = { |