// SPDX-License-Identifier: GPL-2.0+
/*
* BTRFS filesystem implementation for U-Boot
*
* 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
*/
#include "btrfs.h"
static void read_root_item(struct btrfs_path *p, struct btrfs_root_item *item)
{
u32 len;
int reset = 0;
len = btrfs_path_item_size(p);
memcpy(item, btrfs_path_item_ptr(p, struct btrfs_root_item), len);
btrfs_root_item_to_cpu(item);
if (len < sizeof(*item))
reset = 1;
if (!reset && item->generation != item->generation_v2) {
if (item->generation_v2 != 0)
printf("%s: generation != generation_v2 in root item",
__func__);
reset = 1;
}
if (reset) {
memset(&item->generation_v2, 0,
sizeof(*item) - offsetof(struct btrfs_root_item,
generation_v2));
}
}
int btrfs_find_root(u64 objectid, struct btrfs_root *root,
struct btrfs_root_item *root_item)
{
struct btrfs_path path;
struct btrfs_root_item my_root_item;
if (!btrfs_search_tree_key_type(&btrfs_info.tree_root, objectid,
BTRFS_ROOT_ITEM_KEY, &path))
return -1;
if (!root_item)
root_item = &my_root_item;
read_root_item(&path, root_item);
if (root) {
root->objectid = objectid;
root->bytenr = root_item->bytenr;
root->root_dirid = root_item->root_dirid;
}
btrfs_free_path(&path);
return 0;
}
u64 btrfs_lookup_root_ref(u64 subvolid, struct btrfs_root_ref *refp, char *name)
{
struct btrfs_path path;
struct btrfs_key *key;
struct btrfs_root_ref *ref;
u64 res = -1ULL;
key = btrfs_search_tree_key_type(&btrfs_info.tree_root, subvolid,
BTRFS_ROOT_BACKREF_KEY, &path);
if (!key)
return -1ULL;
ref = btrfs_path_item_ptr(&path, struct btrfs_root_ref);
btrfs_root_ref_to_cpu(ref);
if (refp)
*refp = *ref;
if (name) {
if (ref->name_len > BTRFS_VOL_NAME_MAX) {
printf("%s: volume name too long: %u\n", __func__,
ref->name_len);
goto out;
}
memcpy(name, ref + 1, ref->name_len);
}
res = key->offset;
out:
btrfs_free_path(&path);
return res;
}