From 19488d5c688f14f4045971d0f019bff934ab699d Mon Sep 17 00:00:00 2001 From: CruxBox Date: Mon, 20 Jul 2020 15:13:04 +0530 Subject: [PATCH] xfs: Reading Node Directories Node directories can now be read. With this, extent directories are complete. Change-Id: Ic42c8464e810137cff4946e8c975edc121daaa4f Reviewed-on: https://review.haiku-os.org/c/haiku/+/3045 Reviewed-by: Adrien Destugues --- .../kernel/file_systems/xfs/Directory.cpp | 27 +- .../kernel/file_systems/xfs/Directory.h | 2 + .../kernel/file_systems/xfs/Extent.cpp | 10 +- src/add-ons/kernel/file_systems/xfs/Extent.h | 10 +- src/add-ons/kernel/file_systems/xfs/Inode.h | 9 + src/add-ons/kernel/file_systems/xfs/Jamfile | 1 + .../kernel/file_systems/xfs/LeafDirectory.cpp | 24 +- .../kernel/file_systems/xfs/LeafDirectory.h | 15 +- src/add-ons/kernel/file_systems/xfs/Node.cpp | 390 ++++++++++++++++++ src/add-ons/kernel/file_systems/xfs/Node.h | 62 +++ .../file_systems/xfs/ShortDirectory.cpp | 2 +- .../kernel/file_systems/xfs/xfs_shell/Jamfile | 1 + 12 files changed, 507 insertions(+), 46 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/xfs/Node.cpp create mode 100644 src/add-ons/kernel/file_systems/xfs/Node.h diff --git a/src/add-ons/kernel/file_systems/xfs/Directory.cpp b/src/add-ons/kernel/file_systems/xfs/Directory.cpp index dd48d5f523..9e51431d8c 100644 --- a/src/add-ons/kernel/file_systems/xfs/Directory.cpp +++ b/src/add-ons/kernel/file_systems/xfs/Directory.cpp @@ -12,7 +12,8 @@ DirectoryIterator::DirectoryIterator(Inode* inode) fInode(inode), fShortDir(NULL), fExtentDir(NULL), - fLeafDir(NULL) + fLeafDir(NULL), + fNodeDir(NULL) { } @@ -22,6 +23,7 @@ DirectoryIterator::~DirectoryIterator() delete fShortDir; delete fLeafDir; delete fExtentDir; + delete fNodeDir; } @@ -52,10 +54,21 @@ DirectoryIterator::Init() status_t status = fLeafDir->Init(); if (status != B_OK) return status; - if (fLeafDir->IsLeafType() == false) { - delete fLeafDir; - fLeafDir = NULL; - } + if (fLeafDir->IsLeafType()) + return B_OK; + delete fLeafDir; + fLeafDir = NULL; + + fNodeDir = new(std::nothrow) NodeDirectory(fInode); + if (fNodeDir == NULL) + return B_NO_MEMORY; + status = fNodeDir->Init(); + if (status != B_OK) + return status; + if (fNodeDir->IsNodeType()) + return B_OK; + delete fNodeDir; + fNodeDir = NULL; } /* Return B_OK so even if the shortform directory has an extent directory @@ -95,7 +108,7 @@ DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino) else if (fLeafDir != NULL) status = fLeafDir->GetNext(name, length, ino); else - return B_BAD_VALUE; + status = fNodeDir->GetNext(name, length, ino); return status; } @@ -127,7 +140,7 @@ DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino) else if (fLeafDir != NULL) status = fLeafDir->Lookup(name, length, ino); else - return B_BAD_VALUE; + status = fNodeDir->Lookup(name, length, ino); return status; } diff --git a/src/add-ons/kernel/file_systems/xfs/Directory.h b/src/add-ons/kernel/file_systems/xfs/Directory.h index 4a4d05e0e4..25efcea289 100644 --- a/src/add-ons/kernel/file_systems/xfs/Directory.h +++ b/src/add-ons/kernel/file_systems/xfs/Directory.h @@ -9,6 +9,7 @@ #include "Extent.h" #include "Inode.h" #include "LeafDirectory.h" +#include "Node.h" #include "ShortDirectory.h" @@ -36,6 +37,7 @@ private: // TODO: Rename all to block type LeafDirectory* fLeafDir; // Extent based leaf directory + NodeDirectory* fNodeDir; }; diff --git a/src/add-ons/kernel/file_systems/xfs/Extent.cpp b/src/add-ons/kernel/file_systems/xfs/Extent.cpp index a71862b412..fd6c2f6032 100644 --- a/src/add-ons/kernel/file_systems/xfs/Extent.cpp +++ b/src/add-ons/kernel/file_systems/xfs/Extent.cpp @@ -33,12 +33,8 @@ Extent::FillMapEntry(void* pointerToMap) 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 - ); + "state:(%d)\n", fMap->br_startoff, fMap->br_startblock, + fMap->br_blockcount, fMap->br_state); } @@ -184,7 +180,7 @@ Extent::GetNext(char* name, size_t* length, xfs_ino_t* ino) continue; } - if (dataEntry->namelen > *length) + if (dataEntry->namelen + 1 > *length) return B_BUFFER_OVERFLOW; fOffset = currentOffset; diff --git a/src/add-ons/kernel/file_systems/xfs/Extent.h b/src/add-ons/kernel/file_systems/xfs/Extent.h index 6a3cf5745f..92d5bc4042 100644 --- a/src/add-ons/kernel/file_systems/xfs/Extent.h +++ b/src/add-ons/kernel/file_systems/xfs/Extent.h @@ -16,9 +16,13 @@ #define XFS_DIR2_DATA_FD_COUNT 3 #define EXTENT_REC_SIZE 128 #define MASK(n) ((1UL << n) - 1) -#define FSBLOCKS_TO_AGNO(n, volume) (n >> volume->AgBlocksLog()) -#define FSBLOCKS_TO_AGBLOCKNO(n, volume) (n & MASK(volume->AgBlocksLog())) - +#define FSBLOCKS_TO_AGNO(n, volume) ((n) >> volume->AgBlocksLog()) +#define FSBLOCKS_TO_AGBLOCKNO(n, volume) ((n) & MASK(volume->AgBlocksLog())) +#define EXTENT_SIZE 16 +#define BLOCKNO_FROM_ADDRESS(n, volume) \ + ((n) >> (volume->BlockLog() + volume->DirBlockLog())) +#define BLOCKOFFSET_FROM_ADDRESS(n, inode) ((n) & (inode->DirBlockSize() - 1)) +#define LEAF_STARTOFFSET(n) 1UL << (35 - (n)) // xfs_exntst_t diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.h b/src/add-ons/kernel/file_systems/xfs/Inode.h index 33e1836a2c..0849150304 100644 --- a/src/add-ons/kernel/file_systems/xfs/Inode.h +++ b/src/add-ons/kernel/file_systems/xfs/Inode.h @@ -38,6 +38,15 @@ #define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0 +// xfs_da_blkinfo_t +struct BlockInfo { + uint32 forw; + uint32 back; + uint16 magic; + uint16 pad; +}; + + uint32 hashfunction(const char* name, int length); diff --git a/src/add-ons/kernel/file_systems/xfs/Jamfile b/src/add-ons/kernel/file_systems/xfs/Jamfile index 554aae567f..2c2c74f139 100644 --- a/src/add-ons/kernel/file_systems/xfs/Jamfile +++ b/src/add-ons/kernel/file_systems/xfs/Jamfile @@ -27,6 +27,7 @@ local xfsSources = kernel_cpp.cpp kernel_interface.cpp LeafDirectory.cpp + Node.cpp ShortDirectory.cpp Volume.cpp xfs.cpp diff --git a/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp b/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp index f854d8e6aa..c7e3b2925f 100644 --- a/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp +++ b/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp @@ -75,6 +75,7 @@ void LeafDirectory::FillMapEntry(int num, ExtentMapEntry* fMap) { void* directoryFork = DIR_DFORK_PTR(fInode->Buffer()); + uint64* pointerToMap = (uint64*)((char*)directoryFork + num * EXTENT_SIZE); uint64 firstHalf = pointerToMap[0]; uint64 secondHalf = pointerToMap[1]; @@ -99,9 +100,10 @@ LeafDirectory::FillBuffer(int type, char* blockBuffer, int howManyBlocksFurthur) ExtentMapEntry* map; if (type == DATA) map = fDataMap; - - if (type == LEAF) + else if (type == LEAF) map = fLeafMap; + else + return B_BAD_VALUE; if (map->br_state !=0) return B_BAD_VALUE; @@ -132,18 +134,8 @@ LeafDirectory::FillBuffer(int type, char* blockBuffer, int howManyBlocksFurthur) return B_IO_ERROR; } - if (type == DATA) - fDataBuffer = blockBuffer; - - if (type == LEAF) - fLeafBuffer = blockBuffer; - - if (type == LEAF) { - ExtentLeafHeader* header = (ExtentLeafHeader*) fLeafBuffer; - TRACE("NumberOfEntries in leaf: (%d)\n", - B_BENDIAN_TO_HOST_INT16(header->count)); - } if (type == DATA) { + fDataBuffer = blockBuffer; ExtentDataHeader* header = (ExtentDataHeader*) fDataBuffer; if (B_BENDIAN_TO_HOST_INT32(header->magic) == HEADER_MAGIC) TRACE("DATA BLOCK VALID\n"); @@ -151,6 +143,10 @@ LeafDirectory::FillBuffer(int type, char* blockBuffer, int howManyBlocksFurthur) TRACE("DATA BLOCK INVALID\n"); return B_BAD_VALUE; } + } else if (type == LEAF) { + fLeafBuffer = blockBuffer; + ExtentLeafHeader* header = (ExtentLeafHeader*) fLeafBuffer; + TRACE("NumberOfEntries in leaf: (%d)\n", B_BENDIAN_TO_HOST_INT16(header->count)); } return B_OK; } @@ -281,7 +277,7 @@ LeafDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino) continue; } - if (dataEntry->namelen > *length) + if (dataEntry->namelen + 1 > *length) return B_BUFFER_OVERFLOW; fOffset = fOffset + EntrySize(dataEntry->namelen); diff --git a/src/add-ons/kernel/file_systems/xfs/LeafDirectory.h b/src/add-ons/kernel/file_systems/xfs/LeafDirectory.h index de5ef7445e..6bcc3861a7 100644 --- a/src/add-ons/kernel/file_systems/xfs/LeafDirectory.h +++ b/src/add-ons/kernel/file_systems/xfs/LeafDirectory.h @@ -11,25 +11,12 @@ #include "system_dependencies.h" -#define EXTENT_SIZE 16 -#define BLOCKNO_FROM_ADDRESS(n, volume) \ - (n >> (volume->BlockLog() + volume->DirBlockLog())) -#define BLOCKOFFSET_FROM_ADDRESS(n, inode) (n & (inode->DirBlockSize() - 1)) #define HEADER_MAGIC 0x58443244 -#define LEAF_STARTOFFSET(n) 1UL << (35 - n) + enum ContentType { DATA, LEAF }; -// xfs_da_blkinfo_t -struct BlockInfo { - uint32 forw; - uint32 back; - uint16 magic; - uint16 pad; -}; - - //xfs_dir2_leaf_hdr_t struct ExtentLeafHeader { BlockInfo info; diff --git a/src/add-ons/kernel/file_systems/xfs/Node.cpp b/src/add-ons/kernel/file_systems/xfs/Node.cpp new file mode 100644 index 0000000000..80ac6d076c --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Node.cpp @@ -0,0 +1,390 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + + +#include "Node.h" + + +NodeDirectory::NodeDirectory(Inode* inode) + : + fInode(inode), + fOffset(0), + fDataBuffer(NULL), + fLeafBuffer(NULL), + fLeafMap(NULL), + fDataMap(NULL), + fCurBlockNumber(-1) +{ +} + + +NodeDirectory::~NodeDirectory() +{ + delete fDataMap; + delete fLeafMap; + delete fDataBuffer; + delete fLeafBuffer; +} + + +status_t +NodeDirectory::Init() +{ + fLeafMap = new(std::nothrow) ExtentMapEntry; + if (fLeafMap == NULL) + return B_NO_MEMORY; + + fDataMap = new(std::nothrow) ExtentMapEntry; + if (fDataMap == NULL) + return B_NO_MEMORY; + + FillMapEntry(fInode->DataExtentsCount()-3, fLeafMap); + fCurLeafMapNumber = 1; + FillMapEntry(0, fDataMap); + return B_OK; +} + + +bool +NodeDirectory::IsNodeType() +{ + if (fCurLeafMapNumber != 1) { + FillMapEntry(fInode->DataExtentsCount() - 3, fLeafMap); + fCurLeafMapNumber = 1; + } + return fLeafMap->br_startoff == LEAF_STARTOFFSET(fInode->GetVolume()->BlockLog()); +} + + +void +NodeDirectory::FillMapEntry(int num, ExtentMapEntry* fMap) +{ + void* directoryFork = DIR_DFORK_PTR(fInode->Buffer()); + void* pointerToMap = (void*)((char*)directoryFork + num * EXTENT_SIZE); + 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("FillMapEntry: startoff:(%ld), startblock:(%ld), blockcount:(%ld)," + "state:(%d)\n", fMap->br_startoff, fMap->br_startblock, + fMap->br_blockcount, fMap->br_state); +} + + +status_t +NodeDirectory::FillBuffer(int type, char* blockBuffer, int howManyBlocksFurthur) +{ + TRACE("FILLBUFFER\n"); + ExtentMapEntry* map; + if (type == DATA) + map = fDataMap; + else if (type == LEAF) + map = fLeafMap; + else + return B_BAD_VALUE; + + if (map->br_state !=0) + return B_BAD_VALUE; + + size_t len = fInode->DirBlockSize(); + if (blockBuffer == NULL) { + blockBuffer = new(std::nothrow) char[len]; + if (blockBuffer == NULL) + return B_NO_MEMORY; + } + + Volume* volume = fInode->GetVolume(); + xfs_agblock_t numberOfBlocksInAg = volume->AgBlocks(); + + uint64 agNo + = FSBLOCKS_TO_AGNO(map->br_startblock + howManyBlocksFurthur, volume); + uint64 agBlockNo + = FSBLOCKS_TO_AGBLOCKNO(map->br_startblock + howManyBlocksFurthur, volume); + + xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(volume->BlockLog(), + ((uint64)(agNo * numberOfBlocksInAg) + agBlockNo)); + + xfs_daddr_t readPos = blockToRead * (BASICBLOCKSIZE); + + TRACE("blockToRead: (%ld), readPos: (%ld)\n", blockToRead, readPos); + if (read_pos(volume->Device(), readPos, blockBuffer, len) != len) { + ERROR("Extent::FillBlockBuffer(): IO Error"); + return B_IO_ERROR; + } + + if (type == DATA) { + fDataBuffer = blockBuffer; + ExtentDataHeader* header = (ExtentDataHeader*) fDataBuffer; + if (B_BENDIAN_TO_HOST_INT32(header->magic) == HEADER_MAGIC) { + TRACE("DATA BLOCK VALID\n"); + } else { + TRACE("DATA BLOCK INVALID\n"); + return B_BAD_VALUE; + } + } else if (type == LEAF) { + fLeafBuffer = blockBuffer; + ExtentLeafHeader* header = (ExtentLeafHeader*) fLeafBuffer; + } + + return B_OK; +} + + +uint32 +NodeDirectory::GetOffsetFromAddress(uint32 address) +{ + address = address * 8; + // block offset in eight bytes, hence multiple with 8 + return address & (fInode->DirBlockSize() - 1); +} + + +uint32 +NodeDirectory::FindHashInNode(uint32 hashVal) +{ + NodeHeader* header = (NodeHeader*)(void*)(fLeafBuffer); + NodeEntry* entry = (NodeEntry*)(void*)(fLeafBuffer + sizeof(NodeHeader)); + int count = B_BENDIAN_TO_HOST_INT16(header->count); + if ((NodeEntry*)(void*)fLeafBuffer + fInode->DirBlockSize() + < &entry[count]) { + return B_BAD_VALUE; + } + + for (int i = 0; i < count; i++) { + if (hashVal <= B_BENDIAN_TO_HOST_INT32(entry[i].hashval)) + return B_BENDIAN_TO_HOST_INT32(entry[i].before); + } + + return 1; +} + + +int +NodeDirectory::EntrySize(int len) const +{ + int entrySize= sizeof(xfs_ino_t) + sizeof(uint8) + len + sizeof(uint16); + // uint16 is for the tag + if (fInode->HasFileTypeField()) + entrySize += sizeof(uint8); + + return (entrySize + 7) & -8; + // rounding off to closest multiple of 8 +} + + +void +NodeDirectory::SearchAndFillDataMap(int blockNo) +{ + int len = fInode->DataExtentsCount(); + + for (int i = 0; i < len - 3; i++) { + FillMapEntry(i, fDataMap); + if (fDataMap->br_startoff <= blockNo + && (blockNo <= fDataMap->br_startoff + fDataMap->br_blockcount - 1)) + // Map found + return; + } +} + + +status_t +NodeDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino) +{ + TRACE("NodeDirectory::GetNext\n"); + status_t status; + + if (fDataBuffer == NULL) { + status = FillBuffer(DATA, fDataBuffer, 0); + if (status != B_OK) + return status; + } + + Volume* volume = fInode->GetVolume(); + void* entry = (void*)((ExtentDataHeader*)fDataBuffer + 1); + // This could be an unused entry so we should check + + uint32 blockNoFromAddress = BLOCKNO_FROM_ADDRESS(fOffset, volume); + if (fOffset != 0 && blockNoFromAddress == fCurBlockNumber) + entry = (void*)(fDataBuffer + BLOCKOFFSET_FROM_ADDRESS(fOffset, fInode)); + // This gets us a little faster to the next entry + + uint32 curDirectorySize = fInode->Size(); + + while (fOffset != curDirectorySize) { + blockNoFromAddress = BLOCKNO_FROM_ADDRESS(fOffset, volume); + + TRACE("fOffset:(%d), blockNoFromAddress:(%d)\n", + fOffset, blockNoFromAddress); + if (fCurBlockNumber != blockNoFromAddress + && blockNoFromAddress > fDataMap->br_startoff + && blockNoFromAddress + <= fDataMap->br_startoff + fDataMap->br_blockcount - 1) { + // When the block is mapped in the same data + // map entry but is not the first block + status = FillBuffer(DATA, fDataBuffer, + blockNoFromAddress - fDataMap->br_startoff); + if (status != B_OK) + return status; + entry = (void*)((ExtentDataHeader*)fDataBuffer + 1); + fOffset = fOffset + sizeof(ExtentDataHeader); + fCurBlockNumber = blockNoFromAddress; + } else if (fCurBlockNumber != blockNoFromAddress) { + // When the block isn't mapped in the current data map entry + SearchAndFillDataMap(blockNoFromAddress); + status = FillBuffer(DATA, fDataBuffer, + blockNoFromAddress - fDataMap->br_startoff); + if (status != B_OK) + return status; + entry = (void*)((ExtentDataHeader*)fDataBuffer + 1); + fOffset = fOffset + sizeof(ExtentDataHeader); + fCurBlockNumber = blockNoFromAddress; + } + + ExtentUnusedEntry* unusedEntry = (ExtentUnusedEntry*)entry; + + if (B_BENDIAN_TO_HOST_INT16(unusedEntry->freetag) == DIR2_FREE_TAG) { + TRACE("Unused entry found\n"); + fOffset = fOffset + B_BENDIAN_TO_HOST_INT16(unusedEntry->length); + entry = (void*) + ((char*)entry + B_BENDIAN_TO_HOST_INT16(unusedEntry->length)); + continue; + } + ExtentDataEntry* dataEntry = (ExtentDataEntry*) entry; + + uint16 currentOffset = (char*)dataEntry - fDataBuffer; + TRACE("GetNext: fOffset:(%d), currentOffset:(%d)\n", + BLOCKOFFSET_FROM_ADDRESS(fOffset, fInode), currentOffset); + + if (BLOCKOFFSET_FROM_ADDRESS(fOffset, fInode) > currentOffset) { + entry = (void*)((char*)entry + EntrySize(dataEntry->namelen)); + continue; + } + + if (dataEntry->namelen + 1 > *length) + return B_BUFFER_OVERFLOW; + + fOffset = fOffset + EntrySize(dataEntry->namelen); + memcpy(name, dataEntry->name, dataEntry->namelen); + name[dataEntry->namelen] = '\0'; + *length = dataEntry->namelen + 1; + *ino = B_BENDIAN_TO_HOST_INT64(dataEntry->inumber); + + TRACE("Entry found. Name: (%s), Length: (%ld),ino: (%ld)\n", name, + *length, *ino); + return B_OK; + } + + return B_ENTRY_NOT_FOUND; +} + + +status_t +NodeDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino) +{ + TRACE("NodeDirectory: Lookup\n"); + TRACE("Name: %s\n", name); + uint32 hashValueOfRequest = hashfunction(name, length); + TRACE("Hashval:(%ld)\n", hashValueOfRequest); + + status_t status; + if (fCurLeafBufferNumber != 1) { + if (fCurLeafMapNumber != 1) { + FillMapEntry(fInode->DataExtentsCount() - 3, fLeafMap); + fCurLeafMapNumber = 1; + } + status = FillBuffer(LEAF, fLeafBuffer, 0); + if (status != B_OK) + return status; + fCurLeafBufferNumber = 1; + } + /* Leaf now has the nodes. */ + uint32 rightMapOffset = FindHashInNode(hashValueOfRequest); + if (rightMapOffset == 1){ + TRACE("Not in this directory.\n"); + return B_ENTRY_NOT_FOUND; + } + + TRACE("rightMapOffset:(%d)\n", rightMapOffset); + + FillMapEntry(fInode->DataExtentsCount() - 2, fLeafMap); + fCurLeafMapNumber = 2; + status = FillBuffer(LEAF, fLeafBuffer, rightMapOffset - fLeafMap->br_startoff); + if (status != B_OK) + return status; + fCurLeafBufferNumber = 2; + + ExtentLeafHeader* leafHeader = (ExtentLeafHeader*)(void*)fLeafBuffer; + ExtentLeafEntry* leafEntry = + (ExtentLeafEntry*)(void*)(fLeafBuffer + sizeof(ExtentLeafHeader)); + if (leafEntry == NULL) + return B_NO_MEMORY; + + int numberOfLeafEntries = B_BENDIAN_TO_HOST_INT16(leafHeader->count); + TRACE("numberOfLeafEntries:(%d)\n", numberOfLeafEntries); + int left = 0; + int mid; + int right = numberOfLeafEntries - 1; + Volume* volume = fInode->GetVolume(); + + /* + * Trying to find the lowerbound of hashValueOfRequest + * This is slightly different from bsearch(), as we want the first + * instance of hashValueOfRequest and not any instance. + */ + while (left < right) { + mid = (left+right)/2; + uint32 hashval = B_BENDIAN_TO_HOST_INT32(leafEntry[mid].hashval); + if (hashval >= hashValueOfRequest) { + right = mid; + continue; + } + if (hashval < hashValueOfRequest) { + left = mid+1; + } + } + TRACE("left:(%d), right:(%d)\n", left, right); + + while (B_BENDIAN_TO_HOST_INT32(leafEntry[left].hashval) + == hashValueOfRequest) { + + uint32 address = B_BENDIAN_TO_HOST_INT32(leafEntry[left].address); + if (address == 0) { + left++; + continue; + } + + uint32 dataBlockNumber = BLOCKNO_FROM_ADDRESS(address * 8, volume); + uint32 offset = BLOCKOFFSET_FROM_ADDRESS(address * 8, fInode); + + TRACE("DataBlockNumber:(%d), offset:(%d)\n", dataBlockNumber, offset); + if (dataBlockNumber != fCurBlockNumber) { + fCurBlockNumber = dataBlockNumber; + SearchAndFillDataMap(dataBlockNumber); + status = FillBuffer(DATA, fDataBuffer, + dataBlockNumber - fDataMap->br_startoff); + if (status != B_OK) + return B_OK; + } + + TRACE("offset:(%d)\n", offset); + ExtentDataEntry* entry = (ExtentDataEntry*)(fDataBuffer + offset); + + int retVal = strncmp(name, (char*)entry->name, entry->namelen); + if (retVal == 0) { + *ino = B_BENDIAN_TO_HOST_INT64(entry->inumber); + TRACE("ino:(%d)\n", *ino); + return B_OK; + } + left++; + } + + return B_ENTRY_NOT_FOUND; +} diff --git a/src/add-ons/kernel/file_systems/xfs/Node.h b/src/add-ons/kernel/file_systems/xfs/Node.h new file mode 100644 index 0000000000..6039e57f01 --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Node.h @@ -0,0 +1,62 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _NODE_H_ +#define _NODE_H_ + + +#include "Extent.h" +#include "LeafDirectory.h" + + +#define XFS_DIR2_LEAFN_MAGIC (0xd2ff) +#define XFS_DA_NODE_MAGIC (0xfebe) + + +//xfs_da_node_hdr +struct NodeHeader { + BlockInfo info; + uint16 count; + uint16 level; +}; + + +//xfs_da_node_entry +struct NodeEntry { + uint32 hashval; + uint32 before; +}; + + +class NodeDirectory { +public: + NodeDirectory(Inode* inode); + ~NodeDirectory(); + status_t Init(); + bool IsNodeType(); + void FillMapEntry(int num, ExtentMapEntry* map); + status_t FillBuffer(int type, char* buffer, + int howManyBlocksFurthur); + void SearchAndFillDataMap(int blockNo); + uint32 FindHashInNode(uint32 hashVal); + uint32 GetOffsetFromAddress(uint32 address); + int EntrySize(int len) const; + 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* fDataMap; + ExtentMapEntry* fLeafMap; + uint32 fOffset; + char* fDataBuffer; + // This isn't inode data. It holds the directory block. + char* fLeafBuffer; + uint32 fCurBlockNumber; + uint8 fCurLeafMapNumber; + uint8 fCurLeafBufferNumber; +}; + +#endif \ No newline at end of file diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp index ff3f6619e5..3d894f074f 100644 --- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp +++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp @@ -147,7 +147,7 @@ ShortDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino) uint16 curOffset = B_BENDIAN_TO_HOST_INT16(entry->offset.i); if (curOffset > fLastEntryOffset) { - if (entry->namelen > *length) + if (entry->namelen + 1 > *length) return B_BUFFER_OVERFLOW; fLastEntryOffset = curOffset; 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 8f6dbac0fc..d10cd76d20 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 @@ -45,6 +45,7 @@ local xfsSource = Inode.cpp kernel_interface.cpp LeafDirectory.cpp + Node.cpp ShortDirectory.cpp Volume.cpp xfs.cpp