1 // SPDX-License-Identifier: GPL-2.0+
3 * BTRFS filesystem implementation for U-Boot
5 * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
11 struct chunk_map_item
{
18 static int add_chunk_mapping(struct btrfs_key
*key
, struct btrfs_chunk
*chunk
)
20 struct btrfs_stripe
*stripe
;
21 u64 block_profile
= chunk
->type
& BTRFS_BLOCK_GROUP_PROFILE_MASK
;
22 struct rb_node
**new = &(btrfs_info
.chunks_root
.rb_node
), *prnt
= NULL
;
23 struct chunk_map_item
*map_item
;
25 if (block_profile
&& block_profile
!= BTRFS_BLOCK_GROUP_DUP
) {
26 printf("%s: unsupported chunk profile %llu\n", __func__
,
29 } else if (!chunk
->length
) {
30 printf("%s: zero length chunk\n", __func__
);
34 stripe
= &chunk
->stripe
;
35 btrfs_stripe_to_cpu(stripe
);
38 struct chunk_map_item
*this;
40 this = rb_entry(*new, struct chunk_map_item
, node
);
43 if (key
->offset
< this->logical
) {
44 new = &((*new)->rb_left
);
45 } else if (key
->offset
> this->logical
) {
46 new = &((*new)->rb_right
);
48 debug("%s: Logical address %llu already in map!\n",
49 __func__
, key
->offset
);
54 map_item
= malloc(sizeof(struct chunk_map_item
));
58 map_item
->logical
= key
->offset
;
59 map_item
->length
= chunk
->length
;
60 map_item
->physical
= le64_to_cpu(chunk
->stripe
.offset
);
61 rb_link_node(&map_item
->node
, prnt
, new);
62 rb_insert_color(&map_item
->node
, &btrfs_info
.chunks_root
);
64 debug("%s: Mapping %llu to %llu\n", __func__
, map_item
->logical
,
70 u64
btrfs_map_logical_to_physical(u64 logical
)
72 struct rb_node
*node
= btrfs_info
.chunks_root
.rb_node
;
75 struct chunk_map_item
*item
;
77 item
= rb_entry(node
, struct chunk_map_item
, node
);
79 if (item
->logical
> logical
)
81 else if (logical
>= item
->logical
+ item
->length
)
82 node
= node
->rb_right
;
84 return item
->physical
+ logical
- item
->logical
;
87 printf("%s: Cannot map logical address %llu to physical\n", __func__
,
93 void btrfs_chunk_map_exit(void)
95 struct rb_node
*now
, *next
;
96 struct chunk_map_item
*item
;
98 for (now
= rb_first_postorder(&btrfs_info
.chunks_root
); now
; now
= next
)
100 item
= rb_entry(now
, struct chunk_map_item
, node
);
101 next
= rb_next_postorder(now
);
106 int btrfs_chunk_map_init(void)
108 u8 sys_chunk_array_copy
[sizeof(btrfs_info
.sb
.sys_chunk_array
)];
109 u8
* const start
= sys_chunk_array_copy
;
110 u8
* const end
= start
+ btrfs_info
.sb
.sys_chunk_array_size
;
112 struct btrfs_key
*key
;
113 struct btrfs_chunk
*chunk
;
115 btrfs_info
.chunks_root
= RB_ROOT
;
117 memcpy(sys_chunk_array_copy
, btrfs_info
.sb
.sys_chunk_array
,
118 sizeof(sys_chunk_array_copy
));
120 for (cur
= start
; cur
< end
;) {
121 key
= (struct btrfs_key
*) cur
;
122 cur
+= sizeof(struct btrfs_key
);
123 chunk
= (struct btrfs_chunk
*) cur
;
125 btrfs_key_to_cpu(key
);
126 btrfs_chunk_to_cpu(chunk
);
128 if (key
->type
!= BTRFS_CHUNK_ITEM_KEY
) {
129 printf("%s: invalid key type %u\n", __func__
,
134 if (add_chunk_mapping(key
, chunk
))
137 cur
+= sizeof(struct btrfs_chunk
);
138 cur
+= sizeof(struct btrfs_stripe
) * (chunk
->num_stripes
- 1);
144 int btrfs_read_chunk_tree(void)
146 struct btrfs_path path
;
147 struct btrfs_key key
, *found_key
;
148 struct btrfs_chunk
*chunk
;
151 key
.objectid
= BTRFS_FIRST_CHUNK_TREE_OBJECTID
;
152 key
.type
= BTRFS_CHUNK_ITEM_KEY
;
155 if (btrfs_search_tree(&btrfs_info
.chunk_root
, &key
, &path
))
159 found_key
= btrfs_path_leaf_key(&path
);
160 if (btrfs_comp_keys_type(&key
, found_key
))
163 chunk
= btrfs_path_item_ptr(&path
, struct btrfs_chunk
);
164 btrfs_chunk_to_cpu(chunk
);
165 if (add_chunk_mapping(found_key
, chunk
)) {
169 } while (!(res
= btrfs_next_slot(&path
)));
171 btrfs_free_path(&path
);