From: "Yan, Zheng" <zheng.yan@oracle.com>
To: linux-btrfs@vger.kernel.org
Cc: Chris Mason <chris.mason@oracle.com>
Subject: [PATCH 2/5] btrfs: track changes to tree blocks' key
Date: Tue, 11 May 2010 16:24:32 +0800 [thread overview]
Message-ID: <4BE91440.5040502@oracle.com> (raw)
update key stored in back-reference after tree block's key
changes.
Signed-off-by: Yan Zheng <zheng.yan@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;
}
reply other threads:[~2010-05-11 8:24 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4BE91440.5040502@oracle.com \
--to=zheng.yan@oracle.com \
--cc=chris.mason@oracle.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).