[haiku-commits] Change in haiku[master]: xfs: Read Block directories

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 5 Jul 2020 21:01:02 +0000

From Shubham Bhagat <shubhambhagat111@xxxxxxxxx>:

Shubham Bhagat has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/2992 ;)


Change subject: xfs: Read Block directories
......................................................................

xfs: Read Block directories

Block directories can now be read.
---
M src/add-ons/kernel/file_systems/xfs/Debug.h
M src/add-ons/kernel/file_systems/xfs/Directory.cpp
M src/add-ons/kernel/file_systems/xfs/Extent.cpp
M src/add-ons/kernel/file_systems/xfs/Extent.h
M src/add-ons/kernel/file_systems/xfs/Inode.cpp
M src/add-ons/kernel/file_systems/xfs/Inode.h
M src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
M src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
8 files changed, 206 insertions(+), 30 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/92/2992/1

diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h 
b/src/add-ons/kernel/file_systems/xfs/Debug.h
index ac7413c..ec5a36b 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 1f8a964..dacfd4f 100644
--- a/src/add-ons/kernel/file_systems/xfs/Directory.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Directory.cpp
@@ -70,7 +70,8 @@
        //TODO: Reading from extent based directories
        if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
                TRACE("Iterator:GetNext: EXTENTS");
-               return B_NOT_SUPPORTED;
+               status_t status = fExtentDir->GetNext(name, length, ino);
+               return status;
        }

        //TODO: Reading from B+Trees based directories
@@ -95,11 +96,8 @@
        //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_t 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 106c737..f162dd8 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)
 {
 }

@@ -37,6 +38,30 @@


 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();
+       uint64 blockToRead = FSBLOCKS_TO_BASICBLOCKS(volume->BlockLog(), 
fMap->br_startblock);
+       uint64 readPos = blockToRead * (BASICBLOCKSIZE) + fMap->br_startoff;
+
+       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()
 {
        fMap = new(std::nothrow) ExtentMapEntry;
@@ -46,16 +71,40 @@
        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;
+       TRACE("Number of entries: (%d)\n", 
B_BENDIAN_TO_HOST_INT32(BlockTail()->count));
+
+       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 +124,130 @@
        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)
+{
+       int retVal= sizeof(xfs_ino_t) + sizeof(uint8) + len + sizeof(uint16)
+               + fInode->HasFileTypeField() * sizeof(uint8);
+                       // uint16 is for the tag
+       return (retVal + 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;
+       bool status = false;
+
+       while (left < right) {
+               // Trying to find the lowerbound of hashValueOfRequest
+               mid = (left+right)/2;
+               uint32 hashval = 
B_BENDIAN_TO_HOST_INT32(leafEntry[mid].hashval);
+               if (hashval >= hashValueOfRequest) {
+                       status = true;
+                       right = mid;
+                       continue;
+               }
+               if (hashval < hashValueOfRequest) {
+                       left = mid+1;
+               }
+       }
+       TRACE("left:(%d), right:(%d)\n", left, right);
+
+       if (status == false) {
+               TRACE("Entry not found\n");
+               return B_ENTRY_NOT_FOUND;
+       }
+
+       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++;
+       }
+
+       TRACE("Entry not found 2\n");
+
+       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 39b4d28..f126eaf 100644
--- a/src/add-ons/kernel/file_systems/xfs/Extent.h
+++ b/src/add-ons/kernel/file_systems/xfs/Extent.h
@@ -12,6 +12,7 @@

 #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)
@@ -97,10 +98,12 @@
                        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);
                        status_t                        GetNext(char* name, 
size_t* length,
                                                                        
xfs_ino_t* ino);
                        status_t                        Lookup(const char* 
name, size_t length,
@@ -108,6 +111,7 @@
 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 f855443..fc45702 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
@@ -160,6 +160,16 @@
 }


+bool
+Inode::HasFileTypeField()
+{
+       if (fVolume->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE)
+               return true;
+       else
+               return false;
+}
+
+
 status_t
 Inode::GetFromDisk()
 {
@@ -212,14 +222,14 @@
 uint32
 hashfunction(const char* name, int length)
 {
+       TRACE("name: %s, length: %d\n", name, length);
        uint32 hashVal = 0;
-
        int lengthCovered = 0;
        int index = 0;
        if (length >= 4) {
-               for (; index <= length; index+=4)
+               for (; index < length and (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 7a1f16f..3fb29a4 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 @@

                        uint32                          UserId() const { return 
fNode->UserId(); }
                        uint32                          GroupId() const { 
return fNode->GroupId(); }
+                       bool                            HasFileTypeField();

 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 3e34062..ff3f661 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 @@
 }


-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 @@
 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 @@
 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 7507d38..316a3bd 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 @@
                                                                
ShortDirectory(Inode* inode);
                                                                
~ShortDirectory();
                        size_t                          HeaderSize();
-                       bool                            HasFileTypeField();
                        uint8                           
GetFileType(ShortFormEntry* entry);
                        ShortFormEntry*         FirstEntry();
                        xfs_ino_t                       
GetIno(ShortFormInodeUnion* inum);

--
To view, visit https://review.haiku-os.org/c/haiku/+/2992
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I9aa898638e6ac39cb903f2dd58cd184785e1a06b
Gerrit-Change-Number: 2992
Gerrit-PatchSet: 1
Gerrit-Owner: Shubham Bhagat <shubhambhagat111@xxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: xfs: Read Block directories - Gerrit