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);