|
@@ -1454,12 +1454,18 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path,
|
|
|
struct btrfs_extent_data_ref *ref1;
|
|
|
struct btrfs_shared_data_ref *ref2;
|
|
|
u32 num_refs = 0;
|
|
|
+ int type;
|
|
|
|
|
|
leaf = path->nodes[0];
|
|
|
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
|
|
|
if (iref) {
|
|
|
- if (btrfs_extent_inline_ref_type(leaf, iref) ==
|
|
|
- BTRFS_EXTENT_DATA_REF_KEY) {
|
|
|
+ /*
|
|
|
+ * If type is invalid, we should have bailed out earlier than
|
|
|
+ * this call.
|
|
|
+ */
|
|
|
+ type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA);
|
|
|
+ ASSERT(type != BTRFS_REF_TYPE_INVALID);
|
|
|
+ if (type == BTRFS_EXTENT_DATA_REF_KEY) {
|
|
|
ref1 = (struct btrfs_extent_data_ref *)(&iref->offset);
|
|
|
num_refs = btrfs_extent_data_ref_count(leaf, ref1);
|
|
|
} else {
|
|
@@ -1620,6 +1626,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
|
|
|
int ret;
|
|
|
int err = 0;
|
|
|
bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA);
|
|
|
+ int needed;
|
|
|
|
|
|
key.objectid = bytenr;
|
|
|
key.type = BTRFS_EXTENT_ITEM_KEY;
|
|
@@ -1711,6 +1718,11 @@ again:
|
|
|
BUG_ON(ptr > end);
|
|
|
}
|
|
|
|
|
|
+ if (owner >= BTRFS_FIRST_FREE_OBJECTID)
|
|
|
+ needed = BTRFS_REF_TYPE_DATA;
|
|
|
+ else
|
|
|
+ needed = BTRFS_REF_TYPE_BLOCK;
|
|
|
+
|
|
|
err = -ENOENT;
|
|
|
while (1) {
|
|
|
if (ptr >= end) {
|
|
@@ -1718,7 +1730,12 @@ again:
|
|
|
break;
|
|
|
}
|
|
|
iref = (struct btrfs_extent_inline_ref *)ptr;
|
|
|
- type = btrfs_extent_inline_ref_type(leaf, iref);
|
|
|
+ type = btrfs_get_extent_inline_ref_type(leaf, iref, needed);
|
|
|
+ if (type == BTRFS_REF_TYPE_INVALID) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
if (want < type)
|
|
|
break;
|
|
|
if (want > type) {
|
|
@@ -1910,7 +1927,12 @@ void update_inline_extent_backref(struct btrfs_fs_info *fs_info,
|
|
|
if (extent_op)
|
|
|
__run_delayed_extent_op(extent_op, leaf, ei);
|
|
|
|
|
|
- type = btrfs_extent_inline_ref_type(leaf, iref);
|
|
|
+ /*
|
|
|
+ * If type is invalid, we should have bailed out after
|
|
|
+ * lookup_inline_extent_backref().
|
|
|
+ */
|
|
|
+ type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_ANY);
|
|
|
+ ASSERT(type != BTRFS_REF_TYPE_INVALID);
|
|
|
|
|
|
if (type == BTRFS_EXTENT_DATA_REF_KEY) {
|
|
|
dref = (struct btrfs_extent_data_ref *)(&iref->offset);
|
|
@@ -3195,6 +3217,7 @@ static noinline int check_committed_ref(struct btrfs_root *root,
|
|
|
struct btrfs_extent_item *ei;
|
|
|
struct btrfs_key key;
|
|
|
u32 item_size;
|
|
|
+ int type;
|
|
|
int ret;
|
|
|
|
|
|
key.objectid = bytenr;
|
|
@@ -3236,8 +3259,9 @@ static noinline int check_committed_ref(struct btrfs_root *root,
|
|
|
goto out;
|
|
|
|
|
|
iref = (struct btrfs_extent_inline_ref *)(ei + 1);
|
|
|
- if (btrfs_extent_inline_ref_type(leaf, iref) !=
|
|
|
- BTRFS_EXTENT_DATA_REF_KEY)
|
|
|
+
|
|
|
+ type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_DATA);
|
|
|
+ if (type != BTRFS_EXTENT_DATA_REF_KEY)
|
|
|
goto out;
|
|
|
|
|
|
ref = (struct btrfs_extent_data_ref *)(&iref->offset);
|