[haiku-commits] haiku: hrev54636 - src/add-ons/kernel/file_systems/xfs

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 11 Oct 2020 12:00:30 -0400 (EDT)

hrev54636 adds 1 changeset to branch 'master'
old head: 3255108dde2c50590d5077cd33510935fb6ee5ac
new head: fc87b4a2846c207e2ad0817ab0c1eee66f63ba5b
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=fc87b4a2846c+%5E3255108dde2c

----------------------------------------------------------------------------

fc87b4a2846c: xfs: Read Block directories
  
  Block directories can now be read.
  Change-Id: I9aa898638e6ac39cb903f2dd58cd184785e1a06b
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/2992
  Reviewed-by: Adrien Destugues <pulkomandy@xxxxxxxxx>

                                    [ CruxBox <shubhambhagat111@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev54636
Commit:      fc87b4a2846c207e2ad0817ab0c1eee66f63ba5b
URL:         https://git.haiku-os.org/haiku/commit/?id=fc87b4a2846c
Author:      CruxBox <shubhambhagat111@xxxxxxxxx>
Date:        Sun Jul  5 20:49:34 2020 UTC
Committer:   waddlesplash <waddlesplash@xxxxxxxxx>
Commit-Date: Sun Oct 11 16:00:26 2020 UTC

----------------------------------------------------------------------------

8 files changed, 217 insertions(+), 32 deletions(-)
src/add-ons/kernel/file_systems/xfs/Debug.h      |   2 +-
.../kernel/file_systems/xfs/Directory.cpp        |  16 +-
src/add-ons/kernel/file_systems/xfs/Extent.cpp   | 185 ++++++++++++++++++-
src/add-ons/kernel/file_systems/xfs/Extent.h     |  11 +-
src/add-ons/kernel/file_systems/xfs/Inode.cpp    |  17 +-
src/add-ons/kernel/file_systems/xfs/Inode.h      |   1 +
.../kernel/file_systems/xfs/ShortDirectory.cpp   |  16 +-
.../kernel/file_systems/xfs/ShortDirectory.h     |   1 -

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h 
b/src/add-ons/kernel/file_systems/xfs/Debug.h
index ac7413cce3..ec5a36b935 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 1f8a9643a1..5d763710d2 100644
--- a/src/add-ons/kernel/file_systems/xfs/Directory.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Directory.cpp
@@ -62,15 +62,17 @@ DirectoryIterator::Init()
 status_t
 DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino)
 {
+       status_t status;
        if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
-               status_t status = fShortDir->GetNext(name, length, ino);
+               status = fShortDir->GetNext(name, length, ino);
                return status;
        }
 
        //TODO: Reading from extent based directories
        if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
                TRACE("Iterator:GetNext: EXTENTS");
-               return B_NOT_SUPPORTED;
+               status = fExtentDir->GetNext(name, length, ino);
+               return status;
        }
 
        //TODO: Reading from B+Trees based directories
@@ -87,19 +89,17 @@ DirectoryIterator::GetNext(char* name, size_t* length, 
xfs_ino_t* ino)
 status_t
 DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino)
 {
+       status_t status;
        if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
-               status_t status = fShortDir->Lookup(name, length, ino);
+               status = fShortDir->Lookup(name, length, ino);
                return status;
        }
 
        //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;
+               status = fExtentDir->Lookup(name, length, ino);
+               return status;
        }
 
        //TODO: Reading from B+Tree based dirs
diff --git a/src/add-ons/kernel/file_systems/xfs/Extent.cpp 
b/src/add-ons/kernel/file_systems/xfs/Extent.cpp
index 106c73756c..ed499e8860 100644
--- a/src/add-ons/kernel/file_systems/xfs/Extent.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Extent.cpp
@@ -9,7 +9,8 @@
 
 Extent::Extent(Inode* inode)
        :
-       fInode(inode)
+       fInode(inode),
+       fOffset(0)
 {
 }
 
@@ -36,6 +37,37 @@ Extent::FillMapEntry(void* pointerToMap)
 }
 
 
+status_t
+Extent::FillBlockBuffer()
+{
+       if (fMap->br_state != 0)
+               return B_BAD_VALUE;
+
+       int len = fInode->DirBlockSize();
+       fBlockBuffer = new(std::nothrow) char[len];
+       if (fBlockBuffer == NULL)
+               return B_NO_MEMORY;
+
+       Volume* volume = fInode->GetVolume();
+       xfs_agblock_t numberOfBlocksInAg = volume->AgBlocks();
+
+       uint64 agNo = FSBLOCKS_TO_AGNO(fMap->br_startblock, volume);
+       uint64 agBlockNo = FSBLOCKS_TO_AGBLOCKNO(fMap->br_startblock, volume);
+       xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(volume->BlockLog(),
+               ((uint64)(agNo * numberOfBlocksInAg) + agBlockNo));
+
+       xfs_daddr_t readPos = blockToRead * (BASICBLOCKSIZE) + 
fMap->br_startoff;
+
+       TRACE("blockToRead: (%ld), readPos: (%ld)\n", blockToRead, readPos);
+       if (read_pos(volume->Device(), readPos, fBlockBuffer, len) != len) {
+               ERROR("Extent::FillBlockBuffer(): IO Error");
+               return B_IO_ERROR;
+       }
+
+       return B_OK;
+}
+
+
 status_t
 Extent::Init()
 {
@@ -46,16 +78,38 @@ Extent::Init()
        ASSERT(BlockType() == true);
        void* pointerToMap = DIR_DFORK_PTR(fInode->Buffer());
        FillMapEntry(pointerToMap);
+       ASSERT(fMap->br_blockcount == 1);
+               //TODO: This is always true for block directories
+               //If we use this implementation for leaf directories, this is 
not
+               //always true
+       status_t status = FillBlockBuffer();
+       ExtentDataHeader* header = (ExtentDataHeader*)fBlockBuffer;
+       if (B_BENDIAN_TO_HOST_INT32(header->magic) == DIR2_BLOCK_HEADER_MAGIC) {
+               status = B_OK;
+               TRACE("Extent:Init(): Block read successfully\n");
+       } else {
+               status = B_BAD_VALUE;
+               TRACE("Extent:Init(): Bad Block!\n");
+       }
 
-       return B_NOT_SUPPORTED;
+       return status;
 }
 
 
 ExtentBlockTail*
-Extent::BlockTail(ExtentDataHeader* header)
+Extent::BlockTail()
 {
        return (ExtentBlockTail*)
-               ((char*)header + fInode->DirBlockSize() - 
sizeof(ExtentBlockTail));
+               (fBlockBuffer + fInode->DirBlockSize() - 
sizeof(ExtentBlockTail));
+}
+
+
+uint32
+Extent::GetOffsetFromAddress(uint32 address)
+{
+       address = address * 8;
+               // block offset in eight bytes, hence multiple with 8
+       return address & (fInode->DirBlockSize() - 1);
 }
 
 
@@ -75,5 +129,128 @@ Extent::BlockType()
        if (fInode->Size() != fInode->DirBlockSize())
                status = false;
        return status;
+       //TODO: Checks: Fileoffset must be 0 and
+       //length = directory block size / filesystem block size
+}
+
+
+int
+Extent::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
+}
+
+
+status_t
+Extent::GetNext(char* name, size_t* length, xfs_ino_t* ino)
+{
+       TRACE("Extend::GetNext\n");
+       void* entry = (void*)((ExtentDataHeader*)fBlockBuffer + 1);
+               // This could be an unused entry so we should check
+
+       int numberOfEntries = B_BENDIAN_TO_HOST_INT32(BlockTail()->count);
+       TRACE("numberOfEntries:(%d)\n", numberOfEntries);
+
+       for (int i = 0; i < numberOfEntries; i++) {
+               TRACE("i:(%d)\n", i);
+               ExtentUnusedEntry* unusedEntry = (ExtentUnusedEntry*)entry;
+
+               if (B_BENDIAN_TO_HOST_INT16(unusedEntry->freetag) == 
DIR2_FREE_TAG) {
+                       TRACE("Unused entry found\n");
+                       entry = (void*)
+                               ((char*)entry + 
B_BENDIAN_TO_HOST_INT16(unusedEntry->length));
+                       continue;
+               }
+               ExtentDataEntry* dataEntry = (ExtentDataEntry*) entry;
+
+               uint16 currentOffset = (char*)dataEntry - fBlockBuffer;
+               TRACE("GetNext: fOffset:(%d), currentOffset:(%d)\n",
+                       fOffset, currentOffset);
+
+               if (fOffset >= currentOffset) {
+                       entry = (void*)((char*)entry + 
EntrySize(dataEntry->namelen));
+                       continue;
+               }
+
+               if (dataEntry->namelen > *length)
+                               return B_BUFFER_OVERFLOW;
+
+               fOffset = currentOffset;
+               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
+Extent::Lookup(const char* name, size_t length, xfs_ino_t* ino)
+{
+       TRACE("Extent: Lookup\n");
+       TRACE("Name: %s\n", name);
+       uint32 hashValueOfRequest = hashfunction(name, length);
+       TRACE("Hashval:(%ld)\n", hashValueOfRequest);
+       ExtentBlockTail* blockTail = BlockTail();
+       ExtentLeafEntry* leafEntry = BlockFirstLeaf(blockTail);
+
+       int numberOfLeafEntries = B_BENDIAN_TO_HOST_INT32(blockTail->count);
+       int left = 0;
+       int mid;
+       int right = numberOfLeafEntries - 1;
+
+       /*
+       * 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 offset = GetOffsetFromAddress(address);
+               TRACE("offset:(%d)\n", offset);
+               ExtentDataEntry* entry = (ExtentDataEntry*)(fBlockBuffer + 
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/Extent.h 
b/src/add-ons/kernel/file_systems/xfs/Extent.h
index 39b4d28025..3f3d6012c0 100644
--- a/src/add-ons/kernel/file_systems/xfs/Extent.h
+++ b/src/add-ons/kernel/file_systems/xfs/Extent.h
@@ -12,9 +12,13 @@
 
 #define DIR2_BLOCK_HEADER_MAGIC 0x58443242
        // for v4 system
+#define DIR2_FREE_TAG 0xffff
 #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()))
+
 
 
 // xfs_exntst_t
@@ -97,10 +101,12 @@ public:
                        status_t                        Init();
                        bool                            BlockType();
                        void                            FillMapEntry(void* 
pointerToMap);
-                       ExtentDataHeader*       BlockHeader();
-                       ExtentBlockTail*        BlockTail(ExtentDataHeader* 
header);
+                       status_t                        FillBlockBuffer();
+                       ExtentBlockTail*        BlockTail();
                        ExtentLeafEntry*        BlockFirstLeaf(ExtentBlockTail* 
tail);
                        xfs_ino_t                       GetIno();
+                       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,
@@ -108,6 +114,7 @@ public:
 private:
                        Inode*                          fInode;
                        ExtentMapEntry*         fMap;
+                       uint32                          fOffset;
                        char*                           fBlockBuffer;
                                // This isn't inode data. It holds the 
directory block.
 };
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp 
b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
index f855443e77..78d4a6ebea 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
@@ -160,6 +160,13 @@ Inode::Init()
 }
 
 
+bool
+Inode::HasFileTypeField() const
+{
+       return fVolume->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE;
+}
+
+
 status_t
 Inode::GetFromDisk()
 {
@@ -209,17 +216,21 @@ Inode::~Inode()
 }
 
 
+/*
+ * Basically take 4 characters at a time as long as you can, and xor with
+ * previous hashVal after rotating 4 bits of hashVal. Likewise, continue
+ * xor and rotating. This is quite a generic hash function.
+*/
 uint32
 hashfunction(const char* name, int length)
 {
        uint32 hashVal = 0;
-
        int lengthCovered = 0;
        int index = 0;
        if (length >= 4) {
-               for (; index <= length; index+=4)
+               for (;index < length && (length - index) >= 4; index += 4)
                {
-                       lengthCovered = index;
+                       lengthCovered += 4;
                        hashVal = (name[index] << 21) ^ (name[index+1] << 14)
                                ^ (name[index+2] << 7) ^ (name[index+3] << 0)
                                ^ ((hashVal << 28) | (hashVal >> (4)));
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.h 
b/src/add-ons/kernel/file_systems/xfs/Inode.h
index 7a1f16ff66..6bf4c9f8e1 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.h
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.h
@@ -178,6 +178,7 @@ public:
 
                        uint32                          UserId() const { return 
fNode->UserId(); }
                        uint32                          GroupId() const { 
return fNode->GroupId(); }
+                       bool                            HasFileTypeField() 
const;
 
 private:
                        status_t                        GetFromDisk();
diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp 
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
index 3e34062c6e..ff3f6619e5 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
@@ -22,20 +22,10 @@ ShortDirectory::~ShortDirectory()
 }
 
 
-bool
-ShortDirectory::HasFileTypeField()
-{
-       if (fInode->GetVolume()->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE)
-               return true;
-       else
-               return false;
-}
-
-
 uint8
 ShortDirectory::GetFileType(ShortFormEntry* entry)
 {
-       ASSERT(HasFileTypeField() == true);
+       ASSERT(fInode->HasFileTypeField() == true);
        return entry->name[entry->namelen];
 }
 
@@ -70,7 +60,7 @@ ShortDirectory::GetIno(ShortFormInodeUnion* inum)
 xfs_ino_t
 ShortDirectory::GetEntryIno(ShortFormEntry* entry)
 {
-       if (HasFileTypeField())
+       if (fInode->HasFileTypeField())
                return GetIno((ShortFormInodeUnion*)(entry->name
                                + entry->namelen + sizeof(uint8)));
        else
@@ -82,7 +72,7 @@ size_t
 ShortDirectory::EntrySize(int namelen)
 {
        return sizeof(ShortFormEntry) + namelen
-                       + (HasFileTypeField()? sizeof(uint8) : 0)
+                       + (fInode->HasFileTypeField()? sizeof(uint8) : 0)
                        + (fHeader->i8count? sizeof(uint64):sizeof(uint32));
 }
 
diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h 
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
index 7507d3878b..316a3bda71 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
@@ -56,7 +56,6 @@ public:
                                                                
ShortDirectory(Inode* inode);
                                                                
~ShortDirectory();
                        size_t                          HeaderSize();
-                       bool                            HasFileTypeField();
                        uint8                           
GetFileType(ShortFormEntry* entry);
                        ShortFormEntry*         FirstEntry();
                        xfs_ino_t                       
GetIno(ShortFormInodeUnion* inum);


Other related posts:

  • » [haiku-commits] haiku: hrev54636 - src/add-ons/kernel/file_systems/xfs - waddlesplash