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