update key stored in back-reference after tree block's key
changes.

Signed-off-by: Yan Zheng <zheng....@oracle.com>

---
diff -urp 2/fs/btrfs/ctree.c 3/fs/btrfs/ctree.c
--- 2/fs/btrfs/ctree.c  2010-05-11 14:00:04.122357838 +0800
+++ 3/fs/btrfs/ctree.c  2010-05-11 14:09:45.050108153 +0800
@@ -348,10 +348,8 @@ static noinline int update_ref_for_cow(s
                        BUG_ON(ret);
                }
                if (new_flags != 0) {
-                       ret = btrfs_set_disk_extent_flags(trans, root,
-                                                         buf->start,
-                                                         buf->len,
-                                                         new_flags, 0);
+                       ret = btrfs_update_tree_block_info(trans, root, buf,
+                                                          NULL, new_flags, 0);
                        BUG_ON(ret);
                }
        } else {
@@ -1126,6 +1124,10 @@ static noinline int balance_level(struct
                        btrfs_node_key(right, &right_key, 0);
                        btrfs_set_node_key(parent, &right_key, pslot + 1);
                        btrfs_mark_buffer_dirty(parent);
+
+                       wret = btrfs_update_tree_block_key(trans, root,
+                                                       right, &right_key);
+                       BUG_ON(wret);
                }
        }
        if (btrfs_header_nritems(mid) == 1) {
@@ -1167,6 +1169,10 @@ static noinline int balance_level(struct
                btrfs_node_key(mid, &mid_key, 0);
                btrfs_set_node_key(parent, &mid_key, pslot);
                btrfs_mark_buffer_dirty(parent);
+
+               wret = btrfs_update_tree_block_key(trans, root,
+                                               mid, &mid_key);
+               BUG_ON(wret);
        }
 
        /* update the path */
@@ -1266,6 +1272,11 @@ static noinline int push_nodes_for_inser
                        btrfs_node_key(mid, &disk_key, 0);
                        btrfs_set_node_key(parent, &disk_key, pslot);
                        btrfs_mark_buffer_dirty(parent);
+
+                       wret = btrfs_update_tree_block_key(trans, root,
+                                                       mid, &disk_key);
+                       BUG_ON(wret);
+
                        if (btrfs_header_nritems(left) > orig_slot) {
                                path->nodes[level] = left;
                                path->slots[level + 1] -= 1;
@@ -1318,6 +1329,10 @@ static noinline int push_nodes_for_inser
                        btrfs_set_node_key(parent, &disk_key, pslot + 1);
                        btrfs_mark_buffer_dirty(parent);
 
+                       wret = btrfs_update_tree_block_key(trans, root,
+                                                       right, &disk_key);
+                       BUG_ON(wret);
+
                        if (btrfs_header_nritems(mid) <= orig_slot) {
                                path->nodes[level] = right;
                                path->slots[level + 1] += 1;
@@ -1893,6 +1908,8 @@ static int fixup_low_keys(struct btrfs_t
                btrfs_mark_buffer_dirty(path->nodes[i]);
                if (tslot != 0)
                        break;
+               ret = btrfs_update_tree_block_key(trans, root, t, key);
+               BUG_ON(ret);
        }
        return ret;
 }
@@ -1927,9 +1944,13 @@ int btrfs_set_item_key_safe(struct btrfs
        btrfs_cpu_key_to_disk(&disk_key, new_key);
        btrfs_set_item_key(eb, &disk_key, slot);
        btrfs_mark_buffer_dirty(eb);
-       if (slot == 0)
+       if (slot == 0) {
+               int ret;
+               btrfs_set_path_blocking(path);
+               ret = btrfs_update_tree_block_key(trans, root, eb, &disk_key);
+               BUG_ON(ret);
                fixup_low_keys(trans, root, path, &disk_key, 1);
-
+       }
        return 0;
 }
 
@@ -2312,6 +2333,7 @@ static noinline int __push_leaf_right(st
        struct extent_buffer *upper = path->nodes[1];
        struct btrfs_disk_key disk_key;
        int slot;
+       int ret;
        u32 i;
        int push_space = 0;
        int push_items = 0;
@@ -2439,6 +2461,9 @@ static noinline int __push_leaf_right(st
        btrfs_set_node_key(upper, &disk_key, slot + 1);
        btrfs_mark_buffer_dirty(upper);
 
+       ret = btrfs_update_tree_block_key(trans, root, right, &disk_key);
+       BUG_ON(ret);
+
        /* then fixup the leaf pointer in the path */
        if (path->slots[0] >= left_nritems) {
                path->slots[0] -= left_nritems;
@@ -2677,6 +2702,10 @@ static noinline int __push_leaf_left(str
        if (right_nritems) {
                btrfs_mark_buffer_dirty(right);
                btrfs_item_key(right, &disk_key, 0);
+               wret = btrfs_update_tree_block_key(trans, root, right,
+                                                  &disk_key);
+               BUG_ON(wret);
+
                wret = fixup_low_keys(trans, root, path, &disk_key, 1);
                if (wret)
                        ret = wret;
@@ -3324,8 +3353,13 @@ int btrfs_truncate_item(struct btrfs_tra
                offset = btrfs_disk_key_offset(&disk_key);
                btrfs_set_disk_key_offset(&disk_key, offset + size_diff);
                btrfs_set_item_key(leaf, &disk_key, slot);
-               if (slot == 0)
+               if (slot == 0) {
+                       btrfs_set_path_blocking(path);
+                       ret = btrfs_update_tree_block_key(trans, root,
+                                                       leaf, &disk_key);
+                       BUG_ON(ret);
                        fixup_low_keys(trans, root, path, &disk_key, 1);
+               }
        }
 
        item = btrfs_item_nr(leaf, slot);
@@ -3561,6 +3595,11 @@ int btrfs_insert_some_items(struct btrfs
        ret = 0;
        if (slot == 0) {
                btrfs_cpu_key_to_disk(&disk_key, cpu_key);
+
+               btrfs_set_path_blocking(path);
+               ret = btrfs_update_tree_block_key(trans, root, leaf,
+                                                 &disk_key);
+               BUG_ON(ret);
                ret = fixup_low_keys(trans, root, path, &disk_key, 1);
        }
 
@@ -3669,6 +3708,11 @@ setup_items_for_insert(struct btrfs_tran
        if (slot == 0) {
                struct btrfs_disk_key disk_key;
                btrfs_cpu_key_to_disk(&disk_key, cpu_key);
+
+               btrfs_set_path_blocking(path);
+               ret = btrfs_update_tree_block_key(trans, root, leaf,
+                                                 &disk_key);
+               BUG_ON(ret);
                ret = fixup_low_keys(trans, root, path, &disk_key, 1);
        }
        btrfs_unlock_up_safe(path, 1);
@@ -3775,8 +3819,11 @@ static int del_ptr(struct btrfs_trans_ha
                btrfs_set_header_level(root->node, 0);
        } else if (slot == 0) {
                struct btrfs_disk_key disk_key;
-
                btrfs_node_key(parent, &disk_key, 0);
+
+               ret = btrfs_update_tree_block_key(trans, root, parent,
+                                                 &disk_key);
+               BUG_ON(ret);
                wret = fixup_low_keys(trans, root, path, &disk_key, level + 1);
                if (wret)
                        ret = wret;
@@ -3893,8 +3940,12 @@ int btrfs_del_items(struct btrfs_trans_h
                int used = leaf_space_used(leaf, 0, nritems);
                if (slot == 0) {
                        struct btrfs_disk_key disk_key;
-
                        btrfs_item_key(leaf, &disk_key, 0);
+
+                       btrfs_set_path_blocking(path);
+                       wret = btrfs_update_tree_block_key(trans, root,
+                                                       leaf, &disk_key);
+                       BUG_ON(wret);
                        wret = fixup_low_keys(trans, root, path,
                                              &disk_key, 1);
                        if (wret)
diff -urp 2/fs/btrfs/ctree.h 3/fs/btrfs/ctree.h
--- 2/fs/btrfs/ctree.h  2010-05-11 13:57:39.448108941 +0800
+++ 3/fs/btrfs/ctree.h  2010-05-11 14:09:45.052107958 +0800
@@ -2013,10 +2013,15 @@ int btrfs_inc_ref(struct btrfs_trans_han
                  struct extent_buffer *buf, int full_backref);
 int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                  struct extent_buffer *buf, int full_backref);
-int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
+int btrfs_update_tree_block_key(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
-                               u64 bytenr, u64 num_bytes, u64 flags,
-                               int is_data);
+                               struct extent_buffer *eb,
+                               struct btrfs_disk_key *key);
+int btrfs_update_tree_block_info(struct btrfs_trans_handle *trans,
+                                struct btrfs_root *root,
+                                struct extent_buffer *eb,
+                                struct btrfs_disk_key *key,
+                                u64 flags_to_set, int update_gen);
 int btrfs_free_extent(struct btrfs_trans_handle *trans,
                      struct btrfs_root *root,
                      u64 bytenr, u64 num_bytes, u64 parent,
diff -urp 2/fs/btrfs/delayed-ref.c 3/fs/btrfs/delayed-ref.c
--- 2/fs/btrfs/delayed-ref.c    2010-05-11 13:52:01.071108165 +0800
+++ 3/fs/btrfs/delayed-ref.c    2010-05-11 14:09:45.053108175 +0800
@@ -509,6 +509,9 @@ update_existing_head_ref(struct btrfs_de
                                       sizeof(ref->extent_op->key));
                                existing_ref->extent_op->update_key = 1;
                        }
+                       if (ref->extent_op->update_gen)
+                               existing_ref->extent_op->update_gen = 1;
+
                        if (ref->extent_op->update_flags) {
                                existing_ref->extent_op->flags_to_set |=
                                        ref->extent_op->flags_to_set;
diff -urp 2/fs/btrfs/delayed-ref.h 3/fs/btrfs/delayed-ref.h
--- 2/fs/btrfs/delayed-ref.h    2010-05-11 13:52:01.072108243 +0800
+++ 3/fs/btrfs/delayed-ref.h    2010-05-11 14:09:45.054107903 +0800
@@ -58,6 +58,7 @@ struct btrfs_delayed_extent_op {
        struct btrfs_disk_key key;
        u64 flags_to_set;
        unsigned int update_key:1;
+       unsigned int update_gen:1;
        unsigned int update_flags:1;
        unsigned int is_data:1;
 };
diff -urp 2/fs/btrfs/extent-tree.c 3/fs/btrfs/extent-tree.c
--- 2/fs/btrfs/extent-tree.c    2010-05-11 14:00:54.906106739 +0800
+++ 3/fs/btrfs/extent-tree.c    2010-05-11 14:12:00.044357180 +0800
@@ -46,7 +46,7 @@ static int __btrfs_free_extent(struct bt
                                struct btrfs_delayed_extent_op *extra_op);
 static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op,
                                    struct extent_buffer *leaf,
-                                   struct btrfs_extent_item *ei);
+                                   struct btrfs_extent_item *ei, u64 transid);
 static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
                                      struct btrfs_root *root,
                                      u64 parent, u64 root_objectid,
@@ -55,8 +55,8 @@ static int alloc_reserved_file_extent(st
 static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                                     struct btrfs_root *root,
                                     u64 parent, u64 root_objectid,
-                                    u64 flags, struct btrfs_disk_key *key,
-                                    int level, struct btrfs_key *ins);
+                                    int level, struct btrfs_key *ins,
+                                    struct btrfs_delayed_extent_op *extent_op);
 static int do_chunk_alloc(struct btrfs_trans_handle *trans,
                          struct btrfs_root *extent_root, u64 alloc_bytes,
                          u64 flags, int force);
@@ -1389,7 +1389,7 @@ int setup_inline_extent_backref(struct b
        refs += refs_to_add;
        btrfs_set_extent_refs(leaf, ei, refs);
        if (extent_op)
-               __run_delayed_extent_op(extent_op, leaf, ei);
+               __run_delayed_extent_op(extent_op, leaf, ei, trans->transid);
 
        ptr = (unsigned long)ei + item_offset;
        end = (unsigned long)ei + btrfs_item_size_nr(leaf, path->slots[0]);
@@ -1478,7 +1478,7 @@ int update_inline_extent_backref(struct 
        refs += refs_to_mod;
        btrfs_set_extent_refs(leaf, ei, refs);
        if (extent_op)
-               __run_delayed_extent_op(extent_op, leaf, ei);
+               __run_delayed_extent_op(extent_op, leaf, ei, trans->transid);
 
        type = btrfs_extent_inline_ref_type(leaf, iref);
 
@@ -1681,7 +1681,7 @@ static int __btrfs_inc_extent_ref(struct
        refs = btrfs_extent_refs(leaf, item);
        btrfs_set_extent_refs(leaf, item, refs + refs_to_add);
        if (extent_op)
-               __run_delayed_extent_op(extent_op, leaf, item);
+               __run_delayed_extent_op(extent_op, leaf, item, trans->transid);
 
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(root->fs_info->extent_root, path);
@@ -1724,6 +1724,7 @@ static int run_delayed_data_ref(struct b
 
        if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
                if (extent_op) {
+                       BUG_ON(extent_op->update_gen);
                        BUG_ON(extent_op->update_key);
                        flags |= extent_op->flags_to_set;
                }
@@ -1751,7 +1752,7 @@ static int run_delayed_data_ref(struct b
 
 static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op,
                                    struct extent_buffer *leaf,
-                                   struct btrfs_extent_item *ei)
+                                   struct btrfs_extent_item *ei, u64 transid)
 {
        u64 flags = btrfs_extent_flags(leaf, ei);
        if (extent_op->update_flags) {
@@ -1759,6 +1760,9 @@ static void __run_delayed_extent_op(stru
                btrfs_set_extent_flags(leaf, ei, flags);
        }
 
+       if (extent_op->update_gen)
+               btrfs_set_extent_generation(leaf, ei, transid);
+
        if (extent_op->update_key) {
                struct btrfs_tree_block_info *bi;
                BUG_ON(!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK));
@@ -1817,7 +1821,7 @@ static int run_delayed_extent_op(struct 
 #endif
        BUG_ON(item_size < sizeof(*ei));
        ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
-       __run_delayed_extent_op(extent_op, leaf, ei);
+       __run_delayed_extent_op(extent_op, leaf, ei, trans->transid);
 
        btrfs_mark_buffer_dirty(leaf);
 out:
@@ -1849,13 +1853,10 @@ static int run_delayed_tree_ref(struct b
 
        BUG_ON(node->ref_mod != 1);
        if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
-               BUG_ON(!extent_op || !extent_op->update_flags ||
-                      !extent_op->update_key);
                ret = alloc_reserved_tree_block(trans, root,
                                                parent, ref_root,
-                                               extent_op->flags_to_set,
-                                               &extent_op->key,
-                                               ref->level, &ins);
+                                               ref->level, &ins,
+                                               extent_op);
        } else if (node->action == BTRFS_ADD_DELAYED_REF) {
                ret = __btrfs_inc_extent_ref(trans, root, node->bytenr,
                                             node->num_bytes, parent, ref_root,
@@ -2156,24 +2157,55 @@ out:
        return 0;
 }
 
-int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
+int btrfs_update_tree_block_key(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
-                               u64 bytenr, u64 num_bytes, u64 flags,
-                               int is_data)
+                               struct extent_buffer *eb,
+                               struct btrfs_disk_key *key)
 {
        struct btrfs_delayed_extent_op *extent_op;
        int ret;
 
-       extent_op = kmalloc(sizeof(*extent_op), GFP_NOFS);
+       if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID)
+               return 0;
+
+       extent_op = kzalloc(sizeof(*extent_op), GFP_NOFS);
        if (!extent_op)
                return -ENOMEM;
 
-       extent_op->flags_to_set = flags;
-       extent_op->update_flags = 1;
-       extent_op->update_key = 0;
-       extent_op->is_data = is_data ? 1 : 0;
+       memcpy(&extent_op->key, key, sizeof(extent_op->key));
+       extent_op->update_key = 1;
 
-       ret = btrfs_add_delayed_extent_op(trans, bytenr, num_bytes, extent_op);
+       ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, extent_op);
+       if (ret)
+               kfree(extent_op);
+       return ret;
+}
+
+int btrfs_update_tree_block_info(struct btrfs_trans_handle *trans,
+                                struct btrfs_root *root,
+                                struct extent_buffer *eb,
+                                struct btrfs_disk_key *key,
+                                u64 flags_to_set, int update_gen)
+{
+       struct btrfs_delayed_extent_op *extent_op;
+       int ret;
+
+       extent_op = kzalloc(sizeof(*extent_op), GFP_NOFS);
+       if (!extent_op)
+               return -ENOMEM;
+
+       if (key) {
+               memcpy(&extent_op->key, key, sizeof(extent_op->key));
+               extent_op->update_key = 1;
+       }
+       if (flags_to_set) {
+               extent_op->flags_to_set = flags_to_set;
+               extent_op->update_flags = 1;
+       }
+       if (update_gen)
+               extent_op->update_gen = 1;
+
+       ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, extent_op);
        if (ret)
                kfree(extent_op);
        return ret;
@@ -3883,7 +3915,8 @@ static int __btrfs_free_extent(struct bt
 
        if (refs > 0) {
                if (extent_op)
-                       __run_delayed_extent_op(extent_op, leaf, ei);
+                       __run_delayed_extent_op(extent_op, leaf, ei,
+                                               trans->transid);
                /*
                 * In the case of inline back ref, reference count will
                 * be updated by remove_extent_backref
@@ -4783,8 +4816,8 @@ static int alloc_reserved_file_extent(st
 static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                                     struct btrfs_root *root,
                                     u64 parent, u64 root_objectid,
-                                    u64 flags, struct btrfs_disk_key *key,
-                                    int level, struct btrfs_key *ins)
+                                    int level, struct btrfs_key *ins,
+                                    struct btrfs_delayed_extent_op *extent_op)
 {
        int ret;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -4795,6 +4828,9 @@ static int alloc_reserved_tree_block(str
        struct extent_buffer *leaf;
        u32 size = sizeof(*extent_item) + sizeof(*block_info) + sizeof(*iref);
 
+       BUG_ON(!extent_op ||
+              !extent_op->update_flags || !extent_op->update_key);
+
        path = btrfs_alloc_path();
        BUG_ON(!path);
 
@@ -4807,17 +4843,23 @@ static int alloc_reserved_tree_block(str
        extent_item = btrfs_item_ptr(leaf, path->slots[0],
                                     struct btrfs_extent_item);
        btrfs_set_extent_refs(leaf, extent_item, 1);
-       btrfs_set_extent_generation(leaf, extent_item, trans->transid);
        btrfs_set_extent_flags(leaf, extent_item,
-                              flags | BTRFS_EXTENT_FLAG_TREE_BLOCK);
-       block_info = (struct btrfs_tree_block_info *)(extent_item + 1);
+                              BTRFS_EXTENT_FLAG_TREE_BLOCK |
+                              extent_op->flags_to_set);
+       if (extent_op->update_gen)
+               btrfs_set_extent_generation(leaf, extent_item,
+                                           trans->transid);
+       else
+               btrfs_set_extent_generation(leaf, extent_item, 0);
 
-       btrfs_set_tree_block_key(leaf, block_info, key);
+       block_info = (struct btrfs_tree_block_info *)(extent_item + 1);
+       btrfs_set_tree_block_key(leaf, block_info, &extent_op->key);
        btrfs_set_tree_block_level(leaf, block_info, level);
 
        iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
        if (parent > 0) {
-               BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
+               BUG_ON(!(extent_op->flags_to_set &
+                        BTRFS_BLOCK_FLAG_FULL_BACKREF));
                btrfs_set_extent_inline_ref_type(leaf, iref,
                                                 BTRFS_SHARED_BLOCK_REF_KEY);
                btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
@@ -4946,16 +4988,14 @@ static int alloc_tree_block(struct btrfs
 
        if (root_objectid != BTRFS_TREE_LOG_OBJECTID) {
                struct btrfs_delayed_extent_op *extent_op;
-               extent_op = kmalloc(sizeof(*extent_op), GFP_NOFS);
+               extent_op = kzalloc(sizeof(*extent_op), GFP_NOFS);
                BUG_ON(!extent_op);
                if (key)
                        memcpy(&extent_op->key, key, sizeof(extent_op->key));
-               else
-                       memset(&extent_op->key, 0, sizeof(extent_op->key));
                extent_op->flags_to_set = flags;
                extent_op->update_key = 1;
+               extent_op->update_gen = 1;
                extent_op->update_flags = 1;
-               extent_op->is_data = 0;
 
                ret = btrfs_add_delayed_tree_ref(trans, ins->objectid,
                                        ins->offset, parent, root_objectid,
@@ -5193,8 +5233,8 @@ static noinline int walk_down_proc(struc
                BUG_ON(ret);
                ret = btrfs_dec_ref(trans, root, eb, 0);
                BUG_ON(ret);
-               ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
-                                                 eb->len, flag, 0);
+               ret = btrfs_update_tree_block_info(trans, root, eb,
+                                                  NULL, flag, 0);
                BUG_ON(ret);
                wc->flags[level] |= flag;
        }
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to