diff --git a/Makefile b/Makefile index 017d1ba..ad8bec5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ ## This makefile is explicitly for GNU Make, and to cross-compile for FreeBSD ## You MUST define MAKESYSPATH below, or you can't build for BSD. -.PHONY: all clean bsd +.PHONY: all clean macos export MAKESYSPATH=/home/yehia/extra_storage/freebsd_src/usr/src/share/mk @@ -12,3 +12,7 @@ all: clean: if [ -d "$(MAKESYSPATH)" ]; then bmake -C kernel/freebsd clean; fi $(MAKE) -C test clean + +macos: + $(MAKE) -C kernel/macos + $(MAKE) -C tools \ No newline at end of file diff --git a/kernel/freebsd/Makefile b/kernel/freebsd/Makefile index b841612..f3f1c67 100644 --- a/kernel/freebsd/Makefile +++ b/kernel/freebsd/Makefile @@ -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 diff --git a/kernel/freebsd/btrfs.h b/kernel/freebsd/btrfs.h index 1fa11e0..d6d83df 100644 --- a/kernel/freebsd/btrfs.h +++ b/kernel/freebsd/btrfs.h @@ -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 #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); diff --git a/kernel/freebsd/btrfs_kmod.c b/kernel/freebsd/btrfs_kmod.c index bdf79be..846e565 100644 --- a/kernel/freebsd/btrfs_kmod.c +++ b/kernel/freebsd/btrfs_kmod.c @@ -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 diff --git a/kernel/freebsd/btrfs_mount.h b/kernel/freebsd/btrfs_mount.h index 4e2b9c0..7ee1685 100644 --- a/kernel/freebsd/btrfs_mount.h +++ b/kernel/freebsd/btrfs_mount.h @@ -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; diff --git a/kernel/freebsd/btrfs_tree.c b/kernel/freebsd/btrfs_tree.c new file mode 100644 index 0000000..4df7ead --- /dev/null +++ b/kernel/freebsd/btrfs_tree.c @@ -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 +#include +#include +#include +#include +#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); +} \ No newline at end of file diff --git a/kernel/freebsd/btrfs_tree.h b/kernel/freebsd/btrfs_tree.h new file mode 100644 index 0000000..1925b85 --- /dev/null +++ b/kernel/freebsd/btrfs_tree.h @@ -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 \ No newline at end of file diff --git a/kernel/include/btrfs_filesystem.h b/kernel/include/btrfs_filesystem.h index 78ead77..74851be 100644 --- a/kernel/include/btrfs_filesystem.h +++ b/kernel/include/btrfs_filesystem.h @@ -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;