diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h b/src/add-ons/kernel/file_systems/xfs/Debug.h index ec5a36b935..ac7413cce3 100644 --- a/src/add-ons/kernel/file_systems/xfs/Debug.h +++ b/src/add-ons/kernel/file_systems/xfs/Debug.h @@ -9,7 +9,7 @@ #ifndef _DEBUG_H_ #define _DEBUG_H_ -// #define TRACE_XFS +#define TRACE_XFS #ifdef TRACE_XFS #define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x) #define ASSERT(x) \ diff --git a/src/add-ons/kernel/file_systems/xfs/Directory.cpp b/src/add-ons/kernel/file_systems/xfs/Directory.cpp index ad825ec886..1f8a9643a1 100644 --- a/src/add-ons/kernel/file_systems/xfs/Directory.cpp +++ b/src/add-ons/kernel/file_systems/xfs/Directory.cpp @@ -30,6 +30,14 @@ DirectoryIterator::Init() return B_NO_MEMORY; return B_OK; } + if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) { + // TODO: Only working with Block directories, not leaf. + fExtentDir = new(std::nothrow) Extent(fInode); + if (fExtentDir == NULL) + return B_NO_MEMORY; + status_t status = fExtentDir->Init(); + return status; + } /* Return B_OK so even if the shortform directory has an extent directory * we can atleast still list the shortform directory @@ -87,6 +95,10 @@ DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino) //TODO: Reading from extent based dirs if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) { TRACE("Iterator:Lookup: EXTENTS"); + #if 0 + status_t status = fExtentDir->Lookup(name, length, ino); + return status; + #endif return B_NOT_SUPPORTED; } diff --git a/src/add-ons/kernel/file_systems/xfs/Directory.h b/src/add-ons/kernel/file_systems/xfs/Directory.h index fd0e3bec6b..342cf4adbe 100644 --- a/src/add-ons/kernel/file_systems/xfs/Directory.h +++ b/src/add-ons/kernel/file_systems/xfs/Directory.h @@ -6,6 +6,7 @@ #define _DIRECTORY_H_ +#include "Extent.h" #include "Inode.h" #include "ShortDirectory.h" @@ -29,6 +30,8 @@ private: Inode* fInode; ShortDirectory* fShortDir; // Short form Directory type + Extent* fExtentDir; + // Extent form Directory type }; diff --git a/src/add-ons/kernel/file_systems/xfs/Extent.cpp b/src/add-ons/kernel/file_systems/xfs/Extent.cpp new file mode 100644 index 0000000000..106c73756c --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Extent.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + + +#include "Extent.h" + + +Extent::Extent(Inode* inode) + : + fInode(inode) +{ +} + + +void +Extent::FillMapEntry(void* pointerToMap) +{ + uint64 firstHalf = *((uint64*)pointerToMap); + uint64 secondHalf = *((uint64*)pointerToMap + 1); + //dividing the 128 bits into 2 parts. + firstHalf = B_BENDIAN_TO_HOST_INT64(firstHalf); + secondHalf = B_BENDIAN_TO_HOST_INT64(secondHalf); + fMap->br_state = (firstHalf >> 63); + fMap->br_startoff = (firstHalf & MASK(63)) >> 9; + fMap->br_startblock = ((firstHalf & MASK(9)) << 43) | (secondHalf >> 21); + fMap->br_blockcount = (secondHalf & MASK(21)); + TRACE("Extent::Init: startoff:(%ld), startblock:(%ld), blockcount:(%ld)," + "state:(%d)\n", + fMap->br_startoff, + fMap->br_startblock, + fMap->br_blockcount, + fMap->br_state + ); +} + + +status_t +Extent::Init() +{ + fMap = new(std::nothrow) ExtentMapEntry; + if (fMap == NULL) + return B_NO_MEMORY; + + ASSERT(BlockType() == true); + void* pointerToMap = DIR_DFORK_PTR(fInode->Buffer()); + FillMapEntry(pointerToMap); + + return B_NOT_SUPPORTED; +} + + +ExtentBlockTail* +Extent::BlockTail(ExtentDataHeader* header) +{ + return (ExtentBlockTail*) + ((char*)header + fInode->DirBlockSize() - sizeof(ExtentBlockTail)); +} + + +ExtentLeafEntry* +Extent::BlockFirstLeaf(ExtentBlockTail* tail) +{ + return (ExtentLeafEntry*)tail - B_BENDIAN_TO_HOST_INT32(tail->count); +} + + +bool +Extent::BlockType() +{ + bool status = true; + if (fInode->NoOfBlocks() != 1) + status = false; + if (fInode->Size() != fInode->DirBlockSize()) + status = false; + return status; +} + diff --git a/src/add-ons/kernel/file_systems/xfs/Extent.h b/src/add-ons/kernel/file_systems/xfs/Extent.h new file mode 100644 index 0000000000..39b4d28025 --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Extent.h @@ -0,0 +1,116 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _EXTENT_H_ +#define _EXTENT_H_ + + +#include "Inode.h" +#include "system_dependencies.h" + + +#define DIR2_BLOCK_HEADER_MAGIC 0x58443242 + // for v4 system +#define XFS_DIR2_DATA_FD_COUNT 3 +#define EXTENT_REC_SIZE 128 +#define MASK(n) ((1UL << n) - 1) + + +// xfs_exntst_t +enum ExtentState { + XFS_EXT_NORM, + XFS_EXT_UNWRITTEN, + XFS_EXT_INVALID +}; + + +// xfs_dir2_data_free_t +struct FreeRegion { + uint16 offset; + uint16 length; +}; + + +// xfs_dir2_data_hdr_t +struct ExtentDataHeader { + uint32 magic; + FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT]; +}; + + +// xfs_dir2_data_entry_t +struct ExtentDataEntry { + xfs_ino_t inumber; + uint8 namelen; + uint8 name[]; + +// Followed by a file type (8bit) if applicable and a 16bit tag +// tag is the offset from start of the block +}; + + +// xfs_dir2_data_unused_t +struct ExtentUnusedEntry { + uint16 freetag; + // takes the value 0xffff + uint16 length; + // freetag+length overrides the inumber of an entry + uint16 tag; +}; + + +// xfs_dir2_leaf_entry_t +struct ExtentLeafEntry { + uint32 hashval; + uint32 address; + // offset into block after >> 3 +}; + + +// xfs_dir2_block_tail_t +struct ExtentBlockTail { + uint32 count; + // # of entries in leaf + uint32 stale; + // # of free leaf entries +}; + + +struct ExtentMapEntry { + xfs_fileoff_t br_startoff; + // logical file block offset + xfs_fsblock_t br_startblock; + // absolute block number + xfs_filblks_t br_blockcount; + // # of blocks + uint8 br_state; + // state of the extent +}; + + +class Extent +{ +public: + Extent(Inode* inode); + ~Extent(); + status_t Init(); + bool BlockType(); + void FillMapEntry(void* pointerToMap); + ExtentDataHeader* BlockHeader(); + ExtentBlockTail* BlockTail(ExtentDataHeader* header); + ExtentLeafEntry* BlockFirstLeaf(ExtentBlockTail* tail); + xfs_ino_t GetIno(); + status_t GetNext(char* name, size_t* length, + xfs_ino_t* ino); + status_t Lookup(const char* name, size_t length, + xfs_ino_t* id); +private: + Inode* fInode; + ExtentMapEntry* fMap; + char* fBlockBuffer; + // This isn't inode data. It holds the directory block. +}; + + +#endif diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp b/src/add-ons/kernel/file_systems/xfs/Inode.cpp index 787ccd6bfa..f855443e77 100644 --- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp @@ -175,7 +175,8 @@ Inode::GetFromDisk() // Inode len to read (size of inode) TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d)," - "Offset: (%d), len: (%d)\n", agNo, agInodeNo, agBlock, offset, len); + "Offset: (%d), len: (%d)\n", agNo, + agRelativeInodeNo, agBlock, offset, len); if (agNo > fVolume->AgCount()) { ERROR("Inode::GetFromDisk : AG Number more than number of AGs"); @@ -206,3 +207,38 @@ Inode::~Inode() delete fBuffer; delete fNode; } + + +uint32 +hashfunction(const char* name, int length) +{ + uint32 hashVal = 0; + + int lengthCovered = 0; + int index = 0; + if (length >= 4) { + for (; index <= length; index+=4) + { + lengthCovered = index; + hashVal = (name[index] << 21) ^ (name[index+1] << 14) + ^ (name[index+2] << 7) ^ (name[index+3] << 0) + ^ ((hashVal << 28) | (hashVal >> (4))); + } + } + + int leftToCover = length - lengthCovered; + if (leftToCover == 3) { + hashVal = (name[index] << 14) ^ (name[index+1] << 7) + ^ (name[index+2] << 0) ^ ((hashVal << 21) | (hashVal >> (11))); + } + if (leftToCover == 2) { + hashVal = (name[index] << 7) ^ (name[index+1] << 0) + ^ ((hashVal << 14) | (hashVal >> (32 - 14))); + } + if (leftToCover == 1) { + hashVal = (name[index] << 0) + ^ ((hashVal << 7) | (hashVal >> (32 - 7))); + } + + return hashVal; +} diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.h b/src/add-ons/kernel/file_systems/xfs/Inode.h index d891c8ef09..7a1f16ff66 100644 --- a/src/add-ons/kernel/file_systems/xfs/Inode.h +++ b/src/add-ons/kernel/file_systems/xfs/Inode.h @@ -38,6 +38,10 @@ #define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0 +uint32 +hashfunction(const char* name, int length); + + struct xfs_timestamp_t { int32 t_sec; int32 t_nsec; @@ -159,6 +163,9 @@ public: xfs_fsize_t Size() const { return fNode->Size(); } + uint32 DirBlockSize() const + { return fVolume->DirBlockSize(); } + void GetChangeTime(struct timespec& timestamp) const { fNode->GetChangeTime(timestamp); } diff --git a/src/add-ons/kernel/file_systems/xfs/Jamfile b/src/add-ons/kernel/file_systems/xfs/Jamfile index 0509ce2e83..e1857d2be5 100644 --- a/src/add-ons/kernel/file_systems/xfs/Jamfile +++ b/src/add-ons/kernel/file_systems/xfs/Jamfile @@ -22,6 +22,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ; local xfsSources = DeviceOpener.cpp Directory.cpp + Extent.cpp Inode.cpp kernel_cpp.cpp kernel_interface.cpp @@ -42,4 +43,4 @@ SEARCH on [ FGristFiles DeviceOpener.cpp ] = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ; SEARCH on [ FGristFiles kernel_cpp.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel util ] ; \ No newline at end of file + = [ FDirName $(HAIKU_TOP) src system kernel util ] ; diff --git a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp index 1eabf9e8eb..c7e3fd8371 100644 --- a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp @@ -152,7 +152,7 @@ xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type, _node->ops = &gxfsVnodeOps; *_type = inode->Mode(); *_flags = 0; - TRACE("(%d)\n", inode->ID()); + TRACE("(%ld)\n", inode->ID()); return B_OK; } @@ -230,7 +230,7 @@ xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, return status; } - TRACE("XFS_LOOKUP: ID: (%d)\n", *_vnodeID); + TRACE("XFS_LOOKUP: ID: (%ld)\n", *_vnodeID); status = get_vnode(volume->FSVolume(), *_vnodeID, NULL); TRACE("get_vnode status: (%d)\n", status); return status; @@ -249,7 +249,7 @@ static status_t xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) { Inode* inode = (Inode*)_node->private_node; - TRACE("XFS_READ_STAT: id: (%d)\n", inode->ID()); + TRACE("XFS_READ_STAT: id: (%ld)\n", inode->ID()); stat->st_dev = inode->GetVolume()->ID(); stat->st_ino = inode->ID(); stat->st_nlink = 1; @@ -351,7 +351,7 @@ static status_t xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie) { Inode* inode = (Inode*)_node->private_node; - TRACE("XFS_OPEN_DIR: (%d)\n", inode->ID()); + TRACE("XFS_OPEN_DIR: (%ld)\n", inode->ID()); if (!inode->IsDirectory()) return B_NOT_A_DIRECTORY; diff --git a/src/add-ons/kernel/file_systems/xfs/xfs_types.h b/src/add-ons/kernel/file_systems/xfs/xfs_types.h index 3b1fd6e379..ae32585f26 100644 --- a/src/add-ons/kernel/file_systems/xfs/xfs_types.h +++ b/src/add-ons/kernel/file_systems/xfs/xfs_types.h @@ -29,10 +29,9 @@ typedef uint32 xfs_dablk_t; // block number for directories typedef uint32 xfs_dahash_t; // hash of a directory file name // or extended attribute name typedef uint64 xfs_fsblock_t; // filesystem block number combining AG number - // and block offset into the AG typedef uint64 xfs_rfsblock_t; // raw filesystem block number typedef uint64 xfs_rtblock_t; // extent number in the real-time sub-volume -typedef uint64 xfs_filoff_t; // block offset into a file +typedef uint64 xfs_fileoff_t; // block offset into a file typedef uint64 xfs_filblks_t; // block count for a file typedef int64 xfs_fsize_t; // byte size of a file diff --git a/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile b/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile index c9fe209f6f..1f3f52b17f 100644 --- a/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile +++ b/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile @@ -41,6 +41,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ; local xfsSource = DeviceOpener.cpp Directory.cpp + Extent.cpp Inode.cpp kernel_interface.cpp ShortDirectory.cpp