Tree root operations for root_tree and chunk_tree

This commit is contained in:
Yehia Hafez
2024-10-07 12:20:41 -05:00
parent 7d3a1eadcc
commit 0b01fd1f91
7 changed files with 154 additions and 27 deletions

View File

@@ -1,18 +1,19 @@
KMOD = btrfs
SRCS = vnode_if.h btrfs.c btrfs_kmod.c
SRCS = vnode_if.h btrfs.c btrfs_tree.c btrfs_kmod.c
MACHINE_ARCH = amd64
MACHINE = amd64
LDFLAGS = -m elf_x86_64
CFLAGS = --target=x86_64-freebsd -I../include
CC = clang
LD = ld.lld
OBJCOPY = llvm-objcopy
CC = clang-14
LD = ld.lld-14
OBJCOPY = llvm-objcopy-14
.if ${.MAKE.OS} == "Linux"
# `xargs` on Linux doesn't support '-J' (a FreeBSD extension), which results in error
EXPORT_SYMS = YES
# Debian clang 14.0.6 breaks fstack-protector, this is a temp workaround
CFLAGS += -DLINUX_CROSS_BUILD
# __stack_chk_guard is just breaking randomly on clang. Adding O2 for some
# absurd reason fixes linking.
CFLAGS += -DLINUX_CROSS_BUILD -O2
.endif
.include <bsd.kmod.mk>

View File

@@ -24,14 +24,16 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#ifndef _BTRFS_TREE_OPS_H
#define _BTRFS_TREE_OPS_H
#ifndef _BTRFS_H
#define _BTRFS_H
#include <sys/tree.h>
#include "btrfs_mount.h"
int btrfs_lookup_dir_item(struct btrfsmount_internal *bmp, struct btrfs_dir_item *dir_result, const char *name, int name_len);
// bo_ - Block operations
// bc_ - BTRFS Cache
int bo_read_key_into_buf(struct vnode *devvp, struct btrfs_key key, struct btrfs_sys_chunks *cache_head, uint8_t *dest);
struct b_chunk_list *bc_find_key_in_cache(struct btrfs_key key, struct btrfs_sys_chunks *head);
struct b_chunk_list *bc_find_logical_in_cache(uint64_t logical_addr, struct btrfs_sys_chunks *head);

View File

@@ -77,6 +77,7 @@
#include "btrfs_mount.h"
#include "btrfs.h"
#include "btrfs_tree.h"
#ifdef LINUX_CROSS_BUILD
// clang on debian breaks fstack-protector as of 14.0.6
@@ -306,7 +307,12 @@ static int mount_btrfs_filesystem(struct vnode *odevvp, struct mount *mp) {
// store superblock in the in-memory structure
bmp->pm_superblock = *prim_sblock;
bmp->pm_fsinfo.chunk_root = NULL;
bmp->pm_fsinfo.tree_root = NULL;
bmp->pm_fsinfo.fs_root = NULL;
bmp->pm_fsinfo.extent_root = NULL;
brelse(bp);
LIST_INIT(&bmp->pm_backing_dev_bootstrap);
@@ -345,24 +351,52 @@ static int mount_btrfs_filesystem(struct vnode *odevvp, struct mount *mp) {
if(tmp_chunk_entry == NULL)
goto error_exit;
// - Read chunk tree root
// - Read the root tree root (requires chunk tree for logical->physical mapping)
// - Read FS root to begin traversal
uint8_t *temp_buf = malloc(tmp_chunk_entry->chunk_item.size, M_BTRFSMOUNT, M_WAITOK | M_ZERO);
bmp->pm_fsinfo.chunk_root = malloc(tmp_chunk_entry->chunk_item.size, M_BTRFSMOUNT, M_WAITOK | M_ZERO);
error = bo_read_key_into_buf(devvp, tmp_chunk_entry->key, &bmp->pm_backing_dev_bootstrap, temp_buf);
error = bo_read_key_into_buf(devvp, tmp_chunk_entry->key, &bmp->pm_backing_dev_bootstrap, bmp->pm_fsinfo.chunk_root);
if(error)
goto error_exit;
/*
struct btrfs_tree_header *head = (struct btrfs_tree_header *)temp_buf;
uprintf("addr %lu num items %u level %d\n", head->address, head->num_items, head->level);
uint8_t *tst = (temp_buf + sizeof(struct btrfs_tree_header));
for(int i = 0; i < head->num_items; ++i) {
struct btrfs_tree_header head = BTRFSHEADER(bmp->pm_fsinfo.chunk_root);
uint8_t *tst = BTRFSDATABUF(bmp->pm_fsinfo.chunk_root);
for(int i = 0; i < head.num_items; ++i) {
struct btrfs_leaf_node *to_dump_item = (struct btrfs_leaf_node *) (tst + (i * (sizeof(struct btrfs_leaf_node))));
uprintf("\n[ key = {obj_id=%lu obj_type=0x%X off=%lu} ]\n", to_dump_item->key.obj_id, to_dump_item->key.obj_type, to_dump_item->key.offset);
switch(to_dump_item->key.obj_type) {
case TYPE_CHUNK_ITEM: {
struct btrfs_chunk_item *tmp_chnk = (struct btrfs_chunk_item *)(tst + to_dump_item->offset);
for(int j = 0; j < tmp_chnk->num_stripes; ++j) {
// We're skipping all chunks past the first.
// Stripes after the first are for RAID setups, which we don't support
if(j > 0)
continue;
struct btrfs_chunk_item_stripe *tmp_stripe = (struct btrfs_chunk_item_stripe *)(tst + to_dump_item->offset + sizeof(struct btrfs_chunk_item));
if(!bc_add_to_chunk_cache(to_dump_item->key, *tmp_chnk, *tmp_stripe, &bmp->pm_backing_dev_bootstrap)) {
uprintf("Overlap in chunk cache %lu %X\n", to_dump_item->key.obj_id, to_dump_item->key.obj_type);
}
}
break;
}
default:
break;
}
}
*/
tmp_chunk_entry = bc_find_logical_in_cache(bmp->pm_superblock.root_tree_addr, &bmp->pm_backing_dev_bootstrap);
// if we cannot read the root tree, we cannot continue
if(tmp_chunk_entry == NULL)
goto error_exit;
bmp->pm_fsinfo.tree_root = malloc(tmp_chunk_entry->chunk_item.size, M_BTRFSMOUNT, M_WAITOK | M_ZERO);
error = bo_read_key_into_buf(devvp, tmp_chunk_entry->key, &bmp->pm_backing_dev_bootstrap, bmp->pm_fsinfo.tree_root);
if(error)
goto error_exit;
head = BTRFSHEADER(bmp->pm_fsinfo.tree_root);
uprintf("TREE ROOT addr %lu num items %u level %d\n", head.address, head.num_items, head.level);
// assign our internal structure to mp
bmp->pm_devvp = devvp;
bmp->pm_odevvp = odevvp;
@@ -370,7 +404,6 @@ static int mount_btrfs_filesystem(struct vnode *odevvp, struct mount *mp) {
mp->mnt_data = bmp;
free(temp_buf, M_BTRFSMOUNT);
return(0);
error_exit:
@@ -397,6 +430,7 @@ error_exit:
}
static int btrfs_unmount(struct mount *mp, int mntflags) {
uprintf("[BTRFS] Unmount called\n");
int error;
struct btrfsmount_internal *bmp;
@@ -416,6 +450,10 @@ static int btrfs_unmount(struct mount *mp, int mntflags) {
dev_rel(bmp->pm_dev);
bc_free_cache_list(&bmp->pm_backing_dev_bootstrap);
if(bmp->pm_fsinfo.chunk_root != NULL)
free(bmp->pm_fsinfo.chunk_root, M_BTRFSMOUNT);
if(bmp->pm_fsinfo.tree_root != NULL)
free(bmp->pm_fsinfo.tree_root, M_BTRFSMOUNT);
lockdestroy(&bmp->pm_btrfslock);
free(bmp, M_BTRFSMOUNT);
@@ -426,6 +464,7 @@ static int btrfs_unmount(struct mount *mp, int mntflags) {
static int btrfs_root(struct mount *mp, int flags, struct vnode **vpp) {
// struct btrfsmount_internal *bmp = VFSTOBTRFS(mp);
// return(bmp->pm_superblock.leaf_size);
uprintf("[BTRFS] btrfs_root called\n");
// After mount is called, this function is called. We're returning an error to kill the process
// for testing purposes

View File

@@ -48,16 +48,16 @@ struct b_chunk_list {
// Linux kernel has a helpful struct (btrfs/fs.h) that holds pointers to all the roots
// we will encounter. Seems like a good idea to me.
struct btrfs_fs_info {
struct btrfs_root *tree_root;
struct btrfs_root *chunk_root;
struct btrfs_root *fs_root;
struct btrfs_root *extent_root;
uint8_t *tree_root;
uint8_t *chunk_root;
uint8_t *fs_root;
uint8_t *extent_root;
};
// RB root item
//@todo: implement btrfs_root struct methods to hold RB roots
struct btrfs_root {
RB_ENTRY(btrfs_root) rb_node;
// RB_ENTRY(btrfs_root) rb_node;
struct btrfs_root_item root_item;
struct btrfs_key root_key;

View File

@@ -0,0 +1,47 @@
/*
Copyright (c) 2024, Yehia Hafez
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/buf.h>
#include "btrfs_tree.h"
int bt_search_by_key(struct btrfs_key in, struct vnode *devvp, struct btrfs_sys_chunks *cache_head, uint8_t *tree_root, void *dest) {
struct btrfs_tree_header t_header = BTRFSHEADER(tree_root);
if(t_header.level == 1) {
uprintf("node\n");
} else {
uprintf("leaf\n");
}
return(0);
}
int bt_walk_leaves(struct btrfs_sys_chunks *head) {
return(0);
}

View File

@@ -0,0 +1,38 @@
/*
Copyright (c) 2024, Yehia Hafez
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
#ifndef _BTRFS_TREE_H
#define _BTRFS_TREE_H
#include "btrfs_mount.h"
#define BTRFSHEADER(x) *((struct btrfs_tree_header *) x)
#define BTRFSDATABUF(x) (x + sizeof(struct btrfs_tree_header))
int bt_search_by_key(struct btrfs_key in, struct vnode *devvp, struct btrfs_sys_chunks *cache_head, uint8_t *tree_root, void *dest);
int bt_walk_leaves(struct btrfs_sys_chunks *head);
#endif //_BTRFS_TREE_H

View File

@@ -536,7 +536,7 @@ typedef struct INODE_ITEM {
@field stime Timestamp for stransid.
@field rtime Timestamp for rtransid.
@field reserved For future expansion
@discussion This structure holds defines the the root of a btree. It is associated with the ROOT_ITEM type. This structure is never used outside of this item.
@discussion This structure holds defines the root of a btree. It is associated with the ROOT_ITEM type. This structure is never used outside of this item.
*/
struct btrfs_root_item {
btrfs_inode_item inode;