diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2009-06-11 08:51:10 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-06-11 08:51:34 -0400 |
commit | 85d4198e40c289dd623cecd16601fa613559bed7 (patch) | |
tree | 8f76a9567063bded47b69f2f39d557307cdf5b54 | |
parent | fd0fb038d5a308c7faddd1701be5e70aaffec98b (diff) |
Btrfs: check duplicate backrefs for both data and metadata
lookup_inline_extent_backref only checks for duplicate backref for data
extents. It assumes backrefs for tree block never conflict.
This patch makes lookup_inline_extent_backref check for duplicate backrefs
for both data and tree block, so that we can detect potential bug earlier.
This is a safety check, strictly speaking it is not required.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/extent-tree.c | 15 |
1 files changed, 4 insertions, 11 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 33a65f2c8a37..edc7d208c5ce 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1056,8 +1056,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, | |||
1056 | want = extent_ref_type(parent, owner); | 1056 | want = extent_ref_type(parent, owner); |
1057 | if (insert) { | 1057 | if (insert) { |
1058 | extra_size = btrfs_extent_inline_ref_size(want); | 1058 | extra_size = btrfs_extent_inline_ref_size(want); |
1059 | if (owner >= BTRFS_FIRST_FREE_OBJECTID) | 1059 | path->keep_locks = 1; |
1060 | path->keep_locks = 1; | ||
1061 | } else | 1060 | } else |
1062 | extra_size = -1; | 1061 | extra_size = -1; |
1063 | ret = btrfs_search_slot(trans, root, &key, path, extra_size, 1); | 1062 | ret = btrfs_search_slot(trans, root, &key, path, extra_size, 1); |
@@ -1087,12 +1086,6 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, | |||
1087 | #endif | 1086 | #endif |
1088 | BUG_ON(item_size < sizeof(*ei)); | 1087 | BUG_ON(item_size < sizeof(*ei)); |
1089 | 1088 | ||
1090 | if (owner < BTRFS_FIRST_FREE_OBJECTID && insert && | ||
1091 | item_size + extra_size >= BTRFS_MAX_EXTENT_ITEM_SIZE(root)) { | ||
1092 | err = -EAGAIN; | ||
1093 | goto out; | ||
1094 | } | ||
1095 | |||
1096 | ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); | 1089 | ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); |
1097 | flags = btrfs_extent_flags(leaf, ei); | 1090 | flags = btrfs_extent_flags(leaf, ei); |
1098 | 1091 | ||
@@ -1165,15 +1158,15 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, | |||
1165 | * For simplicity, we just do not add new inline back | 1158 | * For simplicity, we just do not add new inline back |
1166 | * ref if there is any kind of item for this block | 1159 | * ref if there is any kind of item for this block |
1167 | */ | 1160 | */ |
1168 | if (owner >= BTRFS_FIRST_FREE_OBJECTID && | 1161 | if (find_next_key(path, &key) == 0 && key.objectid == bytenr && |
1169 | find_next_key(path, &key) == 0 && key.objectid == bytenr) { | 1162 | key.type < BTRFS_BLOCK_GROUP_ITEM_KEY) { |
1170 | err = -EAGAIN; | 1163 | err = -EAGAIN; |
1171 | goto out; | 1164 | goto out; |
1172 | } | 1165 | } |
1173 | } | 1166 | } |
1174 | *ref_ret = (struct btrfs_extent_inline_ref *)ptr; | 1167 | *ref_ret = (struct btrfs_extent_inline_ref *)ptr; |
1175 | out: | 1168 | out: |
1176 | if (insert && owner >= BTRFS_FIRST_FREE_OBJECTID) { | 1169 | if (insert) { |
1177 | path->keep_locks = 0; | 1170 | path->keep_locks = 0; |
1178 | btrfs_unlock_up_safe(path, 1); | 1171 | btrfs_unlock_up_safe(path, 1); |
1179 | } | 1172 | } |