diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 14 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 4 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 18 |
4 files changed, 26 insertions, 14 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6647b90ef745..ad72e2192015 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -861,6 +861,10 @@ int close_ctree(struct btrfs_root *root) | |||
861 | write_ctree_super(NULL, root); | 861 | write_ctree_super(NULL, root); |
862 | mutex_unlock(&fs_info->fs_mutex); | 862 | mutex_unlock(&fs_info->fs_mutex); |
863 | 863 | ||
864 | if (fs_info->delalloc_bytes) { | ||
865 | printk("btrfs: at unmount delalloc count %Lu\n", | ||
866 | fs_info->delalloc_bytes); | ||
867 | } | ||
864 | if (fs_info->extent_root->node) | 868 | if (fs_info->extent_root->node) |
865 | free_extent_buffer(fs_info->extent_root->node); | 869 | free_extent_buffer(fs_info->extent_root->node); |
866 | 870 | ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 6999b819db62..624aabc3e6f2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -262,7 +262,7 @@ static void set_state_cb(struct extent_io_tree *tree, | |||
262 | { | 262 | { |
263 | if (tree->ops && tree->ops->set_bit_hook) { | 263 | if (tree->ops && tree->ops->set_bit_hook) { |
264 | tree->ops->set_bit_hook(tree->mapping->host, state->start, | 264 | tree->ops->set_bit_hook(tree->mapping->host, state->start, |
265 | state->end, bits); | 265 | state->end, state->state, bits); |
266 | } | 266 | } |
267 | } | 267 | } |
268 | 268 | ||
@@ -272,7 +272,7 @@ static void clear_state_cb(struct extent_io_tree *tree, | |||
272 | { | 272 | { |
273 | if (tree->ops && tree->ops->set_bit_hook) { | 273 | if (tree->ops && tree->ops->set_bit_hook) { |
274 | tree->ops->clear_bit_hook(tree->mapping->host, state->start, | 274 | tree->ops->clear_bit_hook(tree->mapping->host, state->start, |
275 | state->end, bits); | 275 | state->end, state->state, bits); |
276 | } | 276 | } |
277 | } | 277 | } |
278 | 278 | ||
@@ -298,10 +298,10 @@ static int insert_state(struct extent_io_tree *tree, | |||
298 | } | 298 | } |
299 | if (bits & EXTENT_DIRTY) | 299 | if (bits & EXTENT_DIRTY) |
300 | tree->dirty_bytes += end - start + 1; | 300 | tree->dirty_bytes += end - start + 1; |
301 | set_state_cb(tree, state, bits); | ||
301 | state->state |= bits; | 302 | state->state |= bits; |
302 | state->start = start; | 303 | state->start = start; |
303 | state->end = end; | 304 | state->end = end; |
304 | set_state_cb(tree, state, bits); | ||
305 | node = tree_insert(&tree->state, end, &state->rb_node); | 305 | node = tree_insert(&tree->state, end, &state->rb_node); |
306 | if (node) { | 306 | if (node) { |
307 | struct extent_state *found; | 307 | struct extent_state *found; |
@@ -369,8 +369,8 @@ static int clear_state_bit(struct extent_io_tree *tree, | |||
369 | WARN_ON(range > tree->dirty_bytes); | 369 | WARN_ON(range > tree->dirty_bytes); |
370 | tree->dirty_bytes -= range; | 370 | tree->dirty_bytes -= range; |
371 | } | 371 | } |
372 | state->state &= ~bits; | ||
373 | clear_state_cb(tree, state, bits); | 372 | clear_state_cb(tree, state, bits); |
373 | state->state &= ~bits; | ||
374 | if (wake) | 374 | if (wake) |
375 | wake_up(&state->wq); | 375 | wake_up(&state->wq); |
376 | if (delete || state->state == 0) { | 376 | if (delete || state->state == 0) { |
@@ -574,8 +574,8 @@ static void set_state_bits(struct extent_io_tree *tree, | |||
574 | u64 range = state->end - state->start + 1; | 574 | u64 range = state->end - state->start + 1; |
575 | tree->dirty_bytes += range; | 575 | tree->dirty_bytes += range; |
576 | } | 576 | } |
577 | state->state |= bits; | ||
578 | set_state_cb(tree, state, bits); | 577 | set_state_cb(tree, state, bits); |
578 | state->state |= bits; | ||
579 | } | 579 | } |
580 | 580 | ||
581 | /* | 581 | /* |
@@ -997,8 +997,8 @@ search_again: | |||
997 | free_extent_state(state); | 997 | free_extent_state(state); |
998 | goto search_again; | 998 | goto search_again; |
999 | } | 999 | } |
1000 | state->state |= EXTENT_LOCKED; | ||
1001 | set_state_cb(tree, state, EXTENT_LOCKED); | 1000 | set_state_cb(tree, state, EXTENT_LOCKED); |
1001 | state->state |= EXTENT_LOCKED; | ||
1002 | if (!found) | 1002 | if (!found) |
1003 | *start = state->start; | 1003 | *start = state->start; |
1004 | found++; | 1004 | found++; |
@@ -1497,8 +1497,8 @@ static int end_bio_extent_readpage(struct bio *bio, | |||
1497 | } else { | 1497 | } else { |
1498 | state = NULL; | 1498 | state = NULL; |
1499 | } | 1499 | } |
1500 | clear->state |= EXTENT_UPTODATE; | ||
1501 | set_state_cb(tree, clear, EXTENT_UPTODATE); | 1500 | set_state_cb(tree, clear, EXTENT_UPTODATE); |
1501 | clear->state |= EXTENT_UPTODATE; | ||
1502 | clear_state_bit(tree, clear, EXTENT_LOCKED, | 1502 | clear_state_bit(tree, clear, EXTENT_LOCKED, |
1503 | 1, 0); | 1503 | 1, 0); |
1504 | if (cur == start) | 1504 | if (cur == start) |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index a96c5a14134e..6fd5e2c90615 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -34,9 +34,9 @@ struct extent_io_ops { | |||
34 | void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, | 34 | void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end, |
35 | struct extent_state *state); | 35 | struct extent_state *state); |
36 | int (*set_bit_hook)(struct inode *inode, u64 start, u64 end, | 36 | int (*set_bit_hook)(struct inode *inode, u64 start, u64 end, |
37 | unsigned long bits); | 37 | unsigned long old, unsigned long bits); |
38 | int (*clear_bit_hook)(struct inode *inode, u64 start, u64 end, | 38 | int (*clear_bit_hook)(struct inode *inode, u64 start, u64 end, |
39 | unsigned long bits); | 39 | unsigned long old, unsigned long bits); |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct extent_io_tree { | 42 | struct extent_io_tree { |
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 = { |