93 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// 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;
 | 
						|
}
 | 
						|
 |