[haiku-commits] Change in haiku[master]: xfs: Read Short Form Directories

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 25 Jun 2020 16:24:25 +0000

From Shubham Bhagat <shubhambhagat111@xxxxxxxxx>:

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


Change subject: xfs: Read Short Form Directories
......................................................................

xfs: Read Short Form Directories

We can now read short form directories.
---
M src/add-ons/kernel/file_systems/xfs/Debug.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
M src/add-ons/kernel/file_systems/xfs/Volume.h
M src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
M src/add-ons/kernel/file_systems/xfs/xfs.cpp
M src/add-ons/kernel/file_systems/xfs/xfs.h
9 files changed, 194 insertions(+), 52 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/52/2952/1

diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h 
b/src/add-ons/kernel/file_systems/xfs/Debug.h
index bc41c80..51b5f70 100644
--- a/src/add-ons/kernel/file_systems/xfs/Debug.h
+++ b/src/add-ons/kernel/file_systems/xfs/Debug.h
@@ -1,6 +1,10 @@
 /*
+ * Copyright 2017, Chế Vũ Gia Hy, cvghy116@xxxxxxxxx.
+ * Copyright 2011, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Copyright 2008-2014, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2005-2007, Ingo Weinhold, bonefish@xxxxxxxxxxxxxxx.
  * Copyright 2020, Shubham Bhagat, shubhambhagat111@xxxxxxxxx
- * All rights reserved. Distributed under the terms of the MIT License.
+ * This file may be used under the terms of the MIT License.
  */
 #ifndef _DEBUG_H_
 #define _DEBUG_H_
@@ -8,8 +12,10 @@
 // #define TRACE_XFS
 #ifdef TRACE_XFS
 #define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
+#define ASSERT(x) { if (!(x)) kernel_debugger("btrfs: assert failed: " #x 
"\n"); }
 #else
 #define TRACE(x...) ;
+#define ASSERT(x) ;
 #endif
 #define ERROR(x...) dprintf("\n\33[34mxfs:\33[0m " x)

diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp 
b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
index a73cdd8..c653c87 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
@@ -174,6 +174,9 @@
                // Inode len to read (size of inode)
        int fd = fVolume->Device();

+       TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d), 
Offset: (%d), len: (%d)\n",
+               agNo, agInodeNo, agBlock, offset, len);
+
        if (agNo > fVolume->AgCount()) {
                ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
                return B_ENTRY_NOT_FOUND;
@@ -184,7 +187,7 @@
        xfs_fsblock_t blockToRead = FSB_TO_BB(fVolume->BlockLog(),
                ((uint64)(agNo * agBlocks) + agBlock));

-       xfs_daddr_t readPos = blockToRead*(BBLOCKSIZE) + offset;
+       xfs_daddr_t readPos = blockToRead*(BBLOCKSIZE) + offset*len;

        if (read_pos(fd, readPos, fBuffer, len) != len) {
                ERROR("Inode::Inode(): IO Error");
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.h 
b/src/add-ons/kernel/file_systems/xfs/Inode.h
index 948be5d..4b4757d 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.h
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.h
@@ -28,9 +28,9 @@
        // Gets the AG relative block number that contains inode
 #define INO_TO_OFFSET(id, volume) (id & INO_MASK(volume->InodesPerBlkLog()))
        // Gets the offset into the block from the inode number
-#define DIR_DFORK_PTR(dir_ino_ptr) (char*) dir_ino_ptr + DATA_FORK_OFFSET
+#define DIR_DFORK_PTR(dir_ino_ptr) (void*)((char*) dir_ino_ptr + 
DATA_FORK_OFFSET)
 #define DIR_AFORK_PTR(dir_ino_ptr) \
-                                       (XFS_DFORK_PTR + \
+                                       (void*)((char*)XFS_DFORK_PTR + \
                                        ((uint32)dir_ino_ptr->di_forkoff<<3))
 #define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0

diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp 
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
index 63c912e..b69a972 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
@@ -12,7 +12,7 @@
        fInode(inode),
        fTrack(0)
 {
-       memcpy(&fHeader, DIR_DFORK_PTR(fInode->Buffer()), 
sizeof(xfs_dir2_sf_hdr_t));
+       fHeader = (xfs_dir2_sf_hdr_t*)(DIR_DFORK_PTR(fInode->Buffer()));
 }


@@ -22,33 +22,121 @@
 }


-xfs_ino_t
-ShortDirectory::GetParentIno()
+bool
+ShortDirectory::HasFileTypeField()
 {
-       TRACE("GetParentIno: \n");
-       if (fHeader.i8count)
-               return B_BENDIAN_TO_HOST_INT64(fHeader.parent.i8);
+       if (fInode->GetVolume()->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE)
+               return true;
        else
-               return B_BENDIAN_TO_HOST_INT32(fHeader.parent.i4);
+               return false;
+}
+
+
+uint8
+ShortDirectory::GetFileType(xfs_dir2_sf_entry_t* entry)
+{
+       ASSERT(HasFileTypeField() == true);
+       return entry->name[entry->namelen];
+}
+
+
+xfs_dir2_sf_entry_t*
+ShortDirectory::FirstEntry()
+{
+       return (xfs_dir2_sf_entry_t*) ((char*) fHeader + HeaderSize());
+}
+
+
+size_t
+ShortDirectory::HeaderSize()
+{
+       if (fHeader->i8count)
+               return sizeof(xfs_dir2_sf_hdr_t);
+       else
+               return sizeof(xfs_dir2_sf_hdr_t) - sizeof(uint32);
+}
+
+
+xfs_ino_t
+ShortDirectory::GetIno(xfs_dir2_inou_t* inum)
+{
+       if (fHeader->i8count)
+               return B_BENDIAN_TO_HOST_INT64(inum->i8);
+       else
+               return B_BENDIAN_TO_HOST_INT32(inum->i4);
+}
+
+
+xfs_ino_t
+ShortDirectory::GetEntryIno(xfs_dir2_sf_entry_t* entry)
+{
+       if(HasFileTypeField())
+               return GetIno((xfs_dir2_inou_t*)(entry->name
+                               + entry->namelen + sizeof(uint8)));
+       else
+               return GetIno((xfs_dir2_inou_t*)(entry->name + entry->namelen));
+}
+
+
+size_t
+ShortDirectory::EntrySize(int namelen)
+{
+       return sizeof(xfs_dir2_sf_entry_t) + namelen
+                       + (HasFileTypeField()? sizeof(uint8) : 0)
+                       + (fHeader->i8count? sizeof(uint64):sizeof(uint32));
+}
+
+
+bool
+ShortDirectory::CompareName(const char* name, size_t length,
+       xfs_dir2_sf_entry_t* entry)
+{
+       if (length != entry->namelen)
+               return false;
+
+       bool status = true;
+       for (int i = 0; i < length; i++)
+       {
+               if(name[i] == entry->name[i])
+                       continue;
+               status = false;
+       }
+
+       return status;
 }


 status_t
 ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino)
 {
-       if (strcmp(name, ".") == 0 || strcmp(name, "..")) {
+       TRACE("ShortDirectory::Lookup\n");
+
+       if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
                xfs_ino_t rootIno = fInode->GetVolume()->Root();
-               if (strcmp(name, ".") || (rootIno == fInode->ID())) {
+               if (strcmp(name, ".") == 0 || (rootIno == fInode->ID())) {
                        *ino = fInode->ID();
                        TRACE("ShortDirectory:Lookup: name: \".\" ino: (%d)\n", 
*ino);
                        return B_OK;
                }
-               *ino = GetParentIno();
+               *ino = GetIno(&fHeader->parent);
                TRACE("Parent: (%d)\n", *ino);
                return B_OK;
        }
-       //TODO: Other entries
-       return B_NOT_SUPPORTED;
+
+       xfs_dir2_sf_entry_t* entry = FirstEntry();
+       TRACE("Length of first entry: (%d), offset of first entry: (%d)\n", 
entry->namelen,
+               B_BENDIAN_TO_HOST_INT16(entry->offset.i));
+
+       for (int i = 0; i < fHeader->count; i++) {
+               bool status = CompareName(name, length, entry);
+               if (status) {
+                       *ino = GetEntryIno(entry);
+                       return B_OK;
+               }
+               entry = (xfs_dir2_sf_entry_t*)((char*) entry + 
EntrySize(entry->namelen));
+       }
+
+       return B_ENTRY_NOT_FOUND;
 }


@@ -70,12 +158,35 @@
                        return B_BUFFER_OVERFLOW;
                *length = 3;
                strlcpy(name, "..", *length + 1);
-               *ino = GetParentIno();
+               *ino = GetIno(&fHeader->parent);
                fTrack = 2;
-               TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n", *ino);
+               // TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n", 
*ino);
                return B_OK;
        }

-       // TODO: Now iterate through sf entries
-       return B_NOT_SUPPORTED;
+       xfs_dir2_sf_entry_t* entry = FirstEntry();
+       TRACE("Length of first entry: (%d), offset of first entry: (%d)\n", 
entry->namelen,
+               B_BENDIAN_TO_HOST_INT16(entry->offset.i));
+
+       for(int i = 0; i < fHeader->count; i++)
+       {
+               uint16 curOffset = B_BENDIAN_TO_HOST_INT16(entry->offset.i);
+               if (curOffset > fLastEntryOffset) {
+
+                       if (entry->namelen > *length)
+                               return B_BUFFER_OVERFLOW;
+
+                       fLastEntryOffset = curOffset;
+                       memcpy(name, entry->name, entry->namelen);
+                       name[entry->namelen] = '\0';
+                       *length = entry->namelen + 1;
+                       *ino = GetEntryIno(entry);
+
+                       TRACE("Entry found. Name: (%s), Length: (%ld), ino: 
(%ld)\n", name, *length, *ino);
+                       return B_OK;
+               }
+               entry = (xfs_dir2_sf_entry_t*)((char*)entry + 
EntrySize(entry->namelen));
+       }
+
+       return B_ENTRY_NOT_FOUND;
 }
diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h 
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
index a6f47b5..635c2e1 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
@@ -8,41 +8,33 @@
 #include "Inode.h"


-typedef struct { uint8 i[2]; } xfs_dir2_sf_off_t; //offset into the literal 
area
-typedef union {
+struct xfs_dir2_sf_off_t{
+       uint16 i;
+} __attribute__((packed)); //offset into the literal area
+
+union xfs_dir2_inou_t{
        uint64          i8;
        uint32          i4;
-} xfs_dir2_inou_t;
+} __attribute__((packed));


 // Short form directory header
-typedef struct xfs_dir2_sf_hdr{
+struct xfs_dir2_sf_hdr_t{
        uint8                   count;          // number of entries
        uint8                   i8count;        // # of 64bit inode entries
        xfs_dir2_inou_t parent;         // absolute inode # of parent
-} xfs_dir2_sf_hdr_t;
+} __attribute__((packed));


-/*
- *The xfs_dir2_sf_entry is split into
- * two parts because the entries size is variable
- */
-typedef struct xfs_dir2_sf_entry {
+struct xfs_dir2_sf_entry_t {
        uint8                           namelen; // length of the name, in bytes
        xfs_dir2_sf_off_t       offset; // offset tag, for directory iteration
        uint8                           name[]; // name of directory entry
-} xfs_dir2_sf_entry_t;
-
-
-typedef union xfs_dir2_sf_entry_inum {
-       struct xfs_ftype_inum{
-               uint8                   ftype;
-               xfs_dir2_inou_t inumber;
-       };
-       struct xfs_inum{
-               xfs_dir2_inou_t inumber;
-       };
-} xfs_dir2_sf_entry_inum_t;
+       /*
+        * Following will be a single byte file type variable
+        * and inode number (64bits or 32 bits)
+        */
+} __attribute__((packed));


 class ShortDirectory
@@ -50,16 +42,24 @@
 public:
                                                                
ShortDirectory(Inode* inode);
                                                                
~ShortDirectory();
+                       size_t                          HeaderSize();
+                       bool                            HasFileTypeField();
+                       uint8                           
GetFileType(xfs_dir2_sf_entry_t* entry);
+                       xfs_dir2_sf_entry_t* FirstEntry();
+                       xfs_ino_t                       GetIno(xfs_dir2_inou_t* 
inum);
+                       xfs_ino_t                       
GetEntryIno(xfs_dir2_sf_entry_t* entry);
+                       size_t                          EntrySize(int namelen);
+                       bool                            CompareName(const char* 
name, size_t length,
+                                                                       
xfs_dir2_sf_entry_t* entry);
                        status_t                        GetNext(char* name, 
size_t* length,
                                                                        
xfs_ino_t* ino);
-                       xfs_ino_t                       GetParentIno();
                        status_t                        Lookup(const char* 
name, size_t length,
                                                                        
xfs_ino_t* id);

 private:
                        Inode*                          fInode;
-                       xfs_dir2_sf_hdr_t       fHeader;
-                       xfs_dir2_sf_off_t       fLastEntryOffset;
+                       xfs_dir2_sf_hdr_t*      fHeader;
+                       uint16                          fLastEntryOffset;
                        // offset into the literal area
                        uint8                           fTrack;
                        // Takes the values 0, 1 or 2
diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.h 
b/src/add-ons/kernel/file_systems/xfs/Volume.h
index 5683bc5..85abcbb 100644
--- a/src/add-ons/kernel/file_systems/xfs/Volume.h
+++ b/src/add-ons/kernel/file_systems/xfs/Volume.h
@@ -77,6 +77,9 @@
                        uint8                           SuperBlockFlags() const
                                                                        { 
return fSuperBlock.Flags(); }

+                       uint32                          SuperBlockFeatures2() 
const
+                                                                       { 
return fSuperBlock.Features2(); }
+
        #if 0
                        off_t                           NumBlocks() const
                                                                        { 
return fSuperBlock.NumBlocks(); }
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 ecbe4e5..6ea60d7 100644
--- a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
@@ -235,7 +235,7 @@
 xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
 {
        Inode* inode = (Inode*)_node->private_node;
-       TRACE("XFS_READ_STAT: root_id: (%d)\n", inode->ID());
+       // TRACE("XFS_READ_STAT: id: (%d)\n", inode->ID());
        stat->st_dev = inode->GetVolume()->ID();
        stat->st_ino = inode->ID();
        stat->st_nlink = 1;
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.cpp 
b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
index 9a3f207..6391392 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
@@ -24,10 +24,27 @@
                return false;
        }

+       // Checking version 4 file system
+       ASSERT((Version() & 0x000f) == 4)
+
        return true;
 }


+uint16
+XfsSuperBlock::Version() const
+{
+       return sb_versionnum;
+}
+
+
+uint32
+XfsSuperBlock::Features2() const
+{
+       return sb_features2;
+}
+
+
 uint32
 XfsSuperBlock::BlockSize() const
 {
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.h 
b/src/add-ons/kernel/file_systems/xfs/xfs.h
index b72a600..08e3d21 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.h
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.h
@@ -55,6 +55,8 @@
                        xfs_agnumber_t          AgCount() const;
                        xfs_agblock_t           AgBlocks() const;
                        uint8                           Flags() const;
+                       uint16                          Version() const;
+                       uint32                          Features2() const;
 private:

                        uint32                          sb_magicnum;
@@ -151,13 +153,13 @@
        Extended v4 Superblock flags - sb_features2
 */

-#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x0001
+#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000001
        // update global free space and inode on clean unmount
-#define XFS_SB_VERSION2_ATTR2BIT       0x0002
+#define XFS_SB_VERSION2_ATTR2BIT       0x00000002
        // optimises the inode layout of ext-attr
-#define XFS_SB_VERSION2_PARENTBIT 0x0004       /* Parent pointers */
-#define XFS_SB_VERSION2_PROJID32BIT 0x0008     /* 32-bit project id */
-#define XFS_SB_VERSION2_CRCBIT 0x0010          /* Metadata checksumming */
-#define XFS_SB_VERSION2_FTYPE 0x0020
+#define XFS_SB_VERSION2_PARENTBIT 0x00000010   /* Parent pointers */
+#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32-bit project id */
+#define XFS_SB_VERSION2_CRCBIT 0x00000100              /* Metadata 
checksumming */
+#define XFS_SB_VERSION2_FTYPE 0x00000200

 #endif

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

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

Other related posts:

  • » [haiku-commits] Change in haiku[master]: xfs: Read Short Form Directories - Gerrit