Btrfs: Update metadata reservation for delayed allocation
[safe/jmp/linux-2.6] / fs / btrfs / extent_io.c
index d2d0368..1a57c17 100644 (file)
@@ -335,21 +335,18 @@ static int merge_state(struct extent_io_tree *tree,
 }
 
 static int set_state_cb(struct extent_io_tree *tree,
-                        struct extent_state *state,
-                        unsigned long bits)
+                        struct extent_state *state, int *bits)
 {
        if (tree->ops && tree->ops->set_bit_hook) {
                return tree->ops->set_bit_hook(tree->mapping->host,
-                                              state->start, state->end,
-                                              state->state, bits);
+                                              state, bits);
        }
 
        return 0;
 }
 
 static void clear_state_cb(struct extent_io_tree *tree,
-                          struct extent_state *state,
-                          unsigned long bits)
+                          struct extent_state *state, int *bits)
 {
        if (tree->ops && tree->ops->clear_bit_hook)
                tree->ops->clear_bit_hook(tree->mapping->host, state, bits);
@@ -367,9 +364,10 @@ static void clear_state_cb(struct extent_io_tree *tree,
  */
 static int insert_state(struct extent_io_tree *tree,
                        struct extent_state *state, u64 start, u64 end,
-                       int bits)
+                       int *bits)
 {
        struct rb_node *node;
+       int bits_to_set = *bits & ~EXTENT_CTLBITS;
        int ret;
 
        if (end < start) {
@@ -384,9 +382,9 @@ static int insert_state(struct extent_io_tree *tree,
        if (ret)
                return ret;
 
-       if (bits & EXTENT_DIRTY)
+       if (bits_to_set & EXTENT_DIRTY)
                tree->dirty_bytes += end - start + 1;
-       state->state |= bits;
+       state->state |= bits_to_set;
        node = tree_insert(&tree->state, end, &state->rb_node);
        if (node) {
                struct extent_state *found;
@@ -456,13 +454,13 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
  * struct is freed and removed from the tree
  */
 static int clear_state_bit(struct extent_io_tree *tree,
-                           struct extent_state *state, int bits, int wake,
-                           int delete)
+                           struct extent_state *state,
+                           int *bits, int wake)
 {
-       int bits_to_clear = bits & ~EXTENT_DO_ACCOUNTING;
+       int bits_to_clear = *bits & ~EXTENT_CTLBITS;
        int ret = state->state & bits_to_clear;
 
-       if ((bits & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
+       if ((bits_to_clear & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
                u64 range = state->end - state->start + 1;
                WARN_ON(range > tree->dirty_bytes);
                tree->dirty_bytes -= range;
@@ -471,9 +469,8 @@ static int clear_state_bit(struct extent_io_tree *tree,
        state->state &= ~bits_to_clear;
        if (wake)
                wake_up(&state->wq);
-       if (delete || state->state == 0) {
+       if (state->state == 0) {
                if (state->tree) {
-                       clear_state_cb(tree, state, state->state);
                        rb_erase(&state->rb_node, &tree->state);
                        state->tree = NULL;
                        free_extent_state(state);
@@ -514,6 +511,10 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
        int set = 0;
        int clear = 0;
 
+       if (delete)
+               bits |= ~EXTENT_CTLBITS;
+       bits |= EXTENT_FIRST_DELALLOC;
+
        if (bits & (EXTENT_IOBITS | EXTENT_BOUNDARY))
                clear = 1;
 again:
@@ -580,8 +581,7 @@ hit_next:
                if (err)
                        goto out;
                if (state->end <= end) {
-                       set |= clear_state_bit(tree, state, bits, wake,
-                                              delete);
+                       set |= clear_state_bit(tree, state, &bits, wake);
                        if (last_end == (u64)-1)
                                goto out;
                        start = last_end + 1;
@@ -602,7 +602,7 @@ hit_next:
                if (wake)
                        wake_up(&state->wq);
 
-               set |= clear_state_bit(tree, prealloc, bits, wake, delete);
+               set |= clear_state_bit(tree, prealloc, &bits, wake);
 
                prealloc = NULL;
                goto out;
@@ -613,7 +613,7 @@ hit_next:
        else
                next_node = NULL;
 
-       set |= clear_state_bit(tree, state, bits, wake, delete);
+       set |= clear_state_bit(tree, state, &bits, wake);
        if (last_end == (u64)-1)
                goto out;
        start = last_end + 1;
@@ -706,19 +706,19 @@ out:
 
 static int set_state_bits(struct extent_io_tree *tree,
                           struct extent_state *state,
-                          int bits)
+                          int *bits)
 {
        int ret;
+       int bits_to_set = *bits & ~EXTENT_CTLBITS;
 
        ret = set_state_cb(tree, state, bits);
        if (ret)
                return ret;
-
-       if ((bits & EXTENT_DIRTY) && !(state->state & EXTENT_DIRTY)) {
+       if ((bits_to_set & EXTENT_DIRTY) && !(state->state & EXTENT_DIRTY)) {
                u64 range = state->end - state->start + 1;
                tree->dirty_bytes += range;
        }
-       state->state |= bits;
+       state->state |= bits_to_set;
 
        return 0;
 }
@@ -757,6 +757,7 @@ static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
        u64 last_start;
        u64 last_end;
 
+       bits |= EXTENT_FIRST_DELALLOC;
 again:
        if (!prealloc && (mask & __GFP_WAIT)) {
                prealloc = alloc_extent_state(mask);
@@ -778,7 +779,7 @@ again:
         */
        node = tree_search(tree, start);
        if (!node) {
-               err = insert_state(tree, prealloc, start, end, bits);
+               err = insert_state(tree, prealloc, start, end, &bits);
                prealloc = NULL;
                BUG_ON(err == -EEXIST);
                goto out;
@@ -802,7 +803,7 @@ hit_next:
                        goto out;
                }
 
-               err = set_state_bits(tree, state, bits);
+               err = set_state_bits(tree, state, &bits);
                if (err)
                        goto out;
 
@@ -852,7 +853,7 @@ hit_next:
                if (err)
                        goto out;
                if (state->end <= end) {
-                       err = set_state_bits(tree, state, bits);
+                       err = set_state_bits(tree, state, &bits);
                        if (err)
                                goto out;
                        cache_state(state, cached_state);
@@ -877,7 +878,7 @@ hit_next:
                else
                        this_end = last_start - 1;
                err = insert_state(tree, prealloc, start, this_end,
-                                  bits);
+                                  &bits);
                BUG_ON(err == -EEXIST);
                if (err) {
                        prealloc = NULL;
@@ -903,7 +904,7 @@ hit_next:
                err = split_state(tree, state, prealloc, end + 1);
                BUG_ON(err == -EEXIST);
 
-               err = set_state_bits(tree, prealloc, bits);
+               err = set_state_bits(tree, prealloc, &bits);
                if (err) {
                        prealloc = NULL;
                        goto out;
@@ -966,8 +967,7 @@ int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
 {
        return clear_extent_bit(tree, start, end,
                                EXTENT_DIRTY | EXTENT_DELALLOC |
-                               EXTENT_DO_ACCOUNTING, 0, 0,
-                               NULL, mask);
+                               EXTENT_DO_ACCOUNTING, 0, 0, NULL, mask);
 }
 
 int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end,
@@ -1435,9 +1435,6 @@ int extent_clear_unlock_delalloc(struct inode *inode,
        if (op & EXTENT_CLEAR_DELALLOC)
                clear_bits |= EXTENT_DELALLOC;
 
-       if (op & EXTENT_CLEAR_ACCOUNTING)
-               clear_bits |= EXTENT_DO_ACCOUNTING;
-
        clear_extent_bit(tree, start, end, clear_bits, 1, 0, NULL, GFP_NOFS);
        if (!(op & (EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY |
                    EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK |