aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/disk-io.c4
-rw-r--r--fs/btrfs/extent_io.c14
-rw-r--r--fs/btrfs/extent_io.h4
-rw-r--r--fs/btrfs/inode.c18
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
42struct extent_io_tree { 42struct 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
262int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, 262int 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
274int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end, 274int 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
3007static struct address_space_operations btrfs_aops = { 3015static struct address_space_operations btrfs_aops = {