1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * BTRFS filesystem implementation for U-Boot
4  *
5  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
6  */
7 
8 #include "btrfs.h"
9 
read_root_item(struct btrfs_path * p,struct btrfs_root_item * item)10 static void read_root_item(struct btrfs_path *p, struct btrfs_root_item *item)
11 {
12 	u32 len;
13 	int reset = 0;
14 
15 	len = btrfs_path_item_size(p);
16 	memcpy(item, btrfs_path_item_ptr(p, struct btrfs_root_item), len);
17 	btrfs_root_item_to_cpu(item);
18 
19 	if (len < sizeof(*item))
20 		reset = 1;
21 	if (!reset && item->generation != item->generation_v2) {
22 		if (item->generation_v2 != 0)
23 			printf("%s: generation != generation_v2 in root item",
24 			       __func__);
25 		reset = 1;
26 	}
27 	if (reset) {
28 		memset(&item->generation_v2, 0,
29 		       sizeof(*item) - offsetof(struct btrfs_root_item,
30 						generation_v2));
31 	}
32 }
33 
btrfs_find_root(u64 objectid,struct btrfs_root * root,struct btrfs_root_item * root_item)34 int btrfs_find_root(u64 objectid, struct btrfs_root *root,
35 		    struct btrfs_root_item *root_item)
36 {
37 	struct btrfs_path path;
38 	struct btrfs_root_item my_root_item;
39 
40 	if (!btrfs_search_tree_key_type(&btrfs_info.tree_root, objectid,
41 					BTRFS_ROOT_ITEM_KEY, &path))
42 		return -1;
43 
44 	if (!root_item)
45 		root_item = &my_root_item;
46 	read_root_item(&path, root_item);
47 
48 	if (root) {
49 		root->objectid = objectid;
50 		root->bytenr = root_item->bytenr;
51 		root->root_dirid = root_item->root_dirid;
52 	}
53 
54 	btrfs_free_path(&path);
55 	return 0;
56 }
57 
btrfs_lookup_root_ref(u64 subvolid,struct btrfs_root_ref * refp,char * name)58 u64 btrfs_lookup_root_ref(u64 subvolid, struct btrfs_root_ref *refp, char *name)
59 {
60 	struct btrfs_path path;
61 	struct btrfs_key *key;
62 	struct btrfs_root_ref *ref;
63 	u64 res = -1ULL;
64 
65 	key = btrfs_search_tree_key_type(&btrfs_info.tree_root, subvolid,
66 					       BTRFS_ROOT_BACKREF_KEY, &path);
67 
68 	if (!key)
69 		return -1ULL;
70 
71 	ref = btrfs_path_item_ptr(&path, struct btrfs_root_ref);
72 	btrfs_root_ref_to_cpu(ref);
73 
74 	if (refp)
75 		*refp = *ref;
76 
77 	if (name) {
78 		if (ref->name_len > BTRFS_VOL_NAME_MAX) {
79 			printf("%s: volume name too long: %u\n", __func__,
80 			       ref->name_len);
81 			goto out;
82 		}
83 
84 		memcpy(name, ref + 1, ref->name_len);
85 	}
86 
87 	res = key->offset;
88 out:
89 	btrfs_free_path(&path);
90 	return res;
91 }
92 
93