[haiku-commits] Change in haiku[master]: xfs : version 3 Inodes and shortform directory

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 24 Jun 2022 09:22:17 +0000

From Raghav Sharma <raghavself28@xxxxxxxxx>:

Raghav Sharma has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/5396 ;)


Change subject: xfs : version 3 Inodes and shortform directory
......................................................................

xfs : version 3 Inodes and shortform directory

- Implemented xfs v5 inodes (known as v3 inodes) and necessary metadata 
integrity checks

- Implemented correct data fork pointer which handles both xfs v4 and v5 
directories

- We can now read inodes and shortform directories for both xfs versions 
completely fine

Change-Id: I8a75ec1dc663d567d3bf6db64be4a27b55d709b3
---
M src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp
M src/add-ons/kernel/file_systems/xfs/Extent.cpp
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/LeafDirectory.cpp
M src/add-ons/kernel/file_systems/xfs/Node.cpp
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
12 files changed, 428 insertions(+), 31 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/96/5396/1

diff --git a/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp 
b/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp
index 819e50f..8d23ff7 100644
--- a/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp
@@ -32,7 +32,8 @@
        }

        memcpy((void*)fRoot,
-               DIR_DFORK_PTR(fInode->Buffer()), sizeof(BlockInDataFork));
+               DIR_DFORK_PTR(fInode->Buffer(),fInode->CoreInodeSize()),
+                                       sizeof(BlockInDataFork));

        for (int i = 0; i < MAX_TREE_DEPTH; i++) {
                fPathForLeaves[i].blockData = NULL;
@@ -85,7 +86,7 @@
                lengthOfDataFork = fInode->ForkOffset() << 3;
        if (fInode->ForkOffset() == 0) {
                lengthOfDataFork = fInode->GetVolume()->InodeSize()
-                       - INODE_CORE_UNLINKED_SIZE;
+                       - fInode->CoreInodeSize();
        }

        lengthOfDataFork -= sizeof(BlockInDataFork);
@@ -122,7 +123,8 @@
 TreeDirectory::GetPtrFromRoot(int pos)
 {
        return (TreePointer*)
-               ((char*)DIR_DFORK_PTR(fInode->Buffer()) + 
GetPtrOffsetIntoRoot(pos));
+               ((char*)DIR_DFORK_PTR(fInode->Buffer(),fInode->CoreInodeSize())
+                       + GetPtrOffsetIntoRoot(pos));
 }


@@ -146,7 +148,7 @@
 TreeDirectory::GetKeyFromRoot(int pos)
 {
        off_t offset = (pos - 1) * KeySize();
-       char* base = (char*)DIR_DFORK_PTR(fInode->Buffer())
+       char* base = 
(char*)DIR_DFORK_PTR(fInode->Buffer(),fInode->CoreInodeSize())
                + sizeof(BlockInDataFork);
        return (TreeKey*) (base + offset);
 }
diff --git a/src/add-ons/kernel/file_systems/xfs/Extent.cpp 
b/src/add-ons/kernel/file_systems/xfs/Extent.cpp
index dbe4023..96c9ce2 100644
--- a/src/add-ons/kernel/file_systems/xfs/Extent.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Extent.cpp
@@ -70,7 +70,7 @@
                return B_NO_MEMORY;

        ASSERT(IsBlockType() == true);
-       void* pointerToMap = DIR_DFORK_PTR(fInode->Buffer());
+       void* pointerToMap = 
DIR_DFORK_PTR(fInode->Buffer(),fInode->CoreInodeSize());
        FillMapEntry(pointerToMap);
        ASSERT(fMap->br_blockcount == 1);
                //TODO: This is always true for block directories
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp 
b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
index a99d89a..99564f7 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2022, Raghav Sharma, raghavself28@xxxxxxxxx
  * Copyright 2020, Shubham Bhagat, shubhambhagat111@xxxxxxxxx
  * All rights reserved. Distributed under the terms of the MIT License.
  */
@@ -6,6 +7,7 @@

 #include "Inode.h"
 #include "BPlusTree.h"
+#include "Checksum.h"

 void
 xfs_inode_t::SwapEndian()
@@ -34,6 +36,13 @@
        di_flags = B_BENDIAN_TO_HOST_INT16(di_flags);
        di_gen = B_BENDIAN_TO_HOST_INT32(di_gen);
        di_next_unlinked = B_BENDIAN_TO_HOST_INT32(di_next_unlinked);
+       di_changecount = B_BENDIAN_TO_HOST_INT64(di_changecount);
+       di_lsn = B_BENDIAN_TO_HOST_INT64(di_lsn);
+       di_flags2 = B_BENDIAN_TO_HOST_INT64(di_flags2);
+       di_cowextsize = B_BENDIAN_TO_HOST_INT64(di_cowextsize);
+       di_crtime.t_sec = B_BENDIAN_TO_HOST_INT32(di_crtime.t_sec);
+       di_crtime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_crtime.t_nsec);
+       di_ino = B_BENDIAN_TO_HOST_INT64(di_ino);
 }


@@ -103,6 +112,14 @@
 }


+void
+xfs_inode_t::GetCreationTime(struct timespec& stamp)
+{
+       stamp.tv_sec = di_crtime.t_sec;
+       stamp.tv_nsec = di_crtime.t_nsec;
+}
+
+
 uint32
 xfs_inode_t::NLink() const
 {
@@ -148,6 +165,201 @@
 }


+//Convert inode mode to directory entry filetype
+unsigned char
+Inode::XfsModeToFtype() const
+{
+       switch (Mode() & S_IFMT) {
+       case S_IFREG:
+               return XFS_DIR3_FT_REG_FILE;
+       case S_IFDIR:
+               return XFS_DIR3_FT_DIR;
+       case S_IFCHR:
+               return XFS_DIR3_FT_CHRDEV;
+       case S_IFBLK:
+               return XFS_DIR3_FT_BLKDEV;
+       case S_IFIFO:
+               return XFS_DIR3_FT_FIFO;
+       case S_IFSOCK:
+               return XFS_DIR3_FT_SOCK;
+       case S_IFLNK:
+               return XFS_DIR3_FT_SYMLINK;
+       default:
+               return XFS_DIR3_FT_UNKNOWN;
+       }
+}
+
+bool
+Inode::VerifyFork(int WhichFork) const
+{
+       uint32 di_nextents = XFS_DFORK_NEXTENTS(fNode, WhichFork);
+
+       switch (XFS_DFORK_FORMAT(fNode, WhichFork)) {
+       case XFS_DINODE_FMT_LOCAL:
+               if (WhichFork == XFS_DATA_FORK) {
+                       if (S_ISREG(Mode()))
+                               return false;
+                       if (Size() > DFORK_SIZE(fNode, fVolume, WhichFork))
+                               return false;
+               }
+               if (di_nextents)
+                       return false;
+               break;
+       case XFS_DINODE_FMT_EXTENTS:
+               if (di_nextents > DFORK_MAXEXT(fNode, fVolume, WhichFork))
+                       return false;
+               break;
+       case XFS_DINODE_FMT_BTREE:
+               if (WhichFork == XFS_ATTR_FORK) {
+                       if (di_nextents > MAXAEXTNUM)
+                               return false;
+               } else if (di_nextents > MAXEXTNUM) {
+                       return false;
+               }
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+
+bool
+Inode::VerifyForkoff() const
+{
+       switch(Format()) {
+               case XFS_DINODE_FMT_DEV:
+                       if (fNode->di_forkoff != (ROUNDUP(sizeof(uint32), 8) >> 
3))
+                       return false;
+               break;
+               case XFS_DINODE_FMT_LOCAL:
+               case XFS_DINODE_FMT_EXTENTS:
+               case XFS_DINODE_FMT_BTREE:
+                       if (fNode->di_forkoff >= (LITINO(fVolume) >> 3))
+                               return false;
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+
+
+bool
+Inode::VerifyInode() const
+{
+       if(fNode->di_magic != INODE_MAGIC) {
+               ERROR("Bad inode magic number");
+               return false;
+       }
+
+       // check if inode version is valid
+       if(fNode->Version() > 3 || fNode->Version() < 1) {
+               ERROR("Bad inode version");
+               return false;
+       }
+
+       // verify version 3 inodes first
+       if(fNode->Version() == 3) {
+
+               if(!HAS_V3INODES(fVolume)) {
+                       ERROR("xfs v4 doesn't have v3 inodes");
+                       return false;
+               }
+
+               if(!xfs_verify_cksum(fBuffer, fVolume->InodeSize(), 
INODE_CRC_OFF)) {
+                       ERROR("Inode is corrupted");
+                       return false;
+               }
+
+               if(fNode->di_ino != fId) {
+                       ERROR("Incorrect inode number");
+                       return false;
+               }
+
+               // TODO : uuid verification
+       }
+
+       if(fNode->di_size & (1ULL << 63)) {
+               ERROR("Invalid EOF of inode");
+               return false;
+       }
+
+       if (Mode() && XfsModeToFtype() == XFS_DIR3_FT_UNKNOWN) {
+                ERROR("Entry points to an unknown inode type");
+                return false;
+       }
+
+       if(!VerifyForkoff()) {
+               ERROR("Invalid inode fork offset");
+               return false;
+       }
+
+       // Check for appropriate data fork formats for the mode
+       switch (Mode() & S_IFMT) {
+       case S_IFIFO:
+       case S_IFCHR:
+       case S_IFBLK:
+       case S_IFSOCK:
+               if (fNode->di_format != XFS_DINODE_FMT_DEV)
+                       return false;
+               break;
+       case S_IFREG:
+       case S_IFLNK:
+       case S_IFDIR:
+               if (!VerifyFork(XFS_DATA_FORK)) {
+                       ERROR("Invalid data fork in inode");
+                       return false;
+               }
+               break;
+       case 0:
+               // Uninitialized inode is fine
+               break;
+       default:
+               return false;
+       }
+
+       if (fNode->di_forkoff) {
+               if (!VerifyFork(XFS_ATTR_FORK)) {
+                       ERROR("Invalid attribute fork in inode");
+                       return false;
+               }
+       }
+       else {
+               /*
+                       If there is no fork offset, this may be a freshly-made 
inode
+                       in a new disk cluster, in which case di_aformat is 
zeroed.
+                       Otherwise, such an inode must be in EXTENTS format; 
this goes
+                       for freed inodes as well.
+                */
+               switch (fNode->di_aformat) {
+               case 0:
+               case XFS_DINODE_FMT_EXTENTS:
+                       break;
+               default:
+                       return false;
+               }
+
+               if (fNode->di_anextents)
+                       return false;
+       }
+
+       // TODO : Add reflink and big-timestamps check using di_flags2
+
+       return true;
+}
+
+
+uint32
+Inode::CoreInodeSize() const
+{
+       if (Version() == 3)
+               return sizeof(struct xfs_inode_t);
+
+       return offsetof(struct xfs_inode_t, di_crc);
+}
+
 status_t
 Inode::Init()
 {
@@ -162,7 +374,7 @@

        status_t status = GetFromDisk();
        if (status == B_OK) {
-               if (fNode->di_magic == INODE_MAGIC) {
+               if (VerifyInode()) {
                        TRACE("Init(): Inode successfully read.\n");
                        status = B_OK;
                } else {
@@ -186,7 +398,11 @@
 bool
 Inode::HasFileTypeField() const
 {
-       return fVolume->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE;
+       if(fNode->Version() == 3 && fVolume->XfsHasIncompatFeature()
+                       || fVolume->SuperBlockFeatures2() & 
XFS_SB_VERSION2_FTYPE)
+               return true;
+
+       return false;
 }


@@ -219,7 +435,7 @@
 Inode::ReadExtentsFromExtentBasedInode()
 {
        fExtents = new(std::nothrow) ExtentMapEntry[DataExtentsCount()];
-       char* dataStart = (char*) DIR_DFORK_PTR(Buffer());
+       char* dataStart = (char*) DIR_DFORK_PTR(Buffer(),CoreInodeSize());
        uint64 wrappedExtent[2];
        for (int i = 0; i < DataExtentsCount(); i++) {
                wrappedExtent[0] = *(uint64*)(dataStart);
@@ -239,7 +455,7 @@
                lengthOfDataFork = ForkOffset() << 3;
        else if(ForkOffset() == 0) {
                lengthOfDataFork = GetVolume()->InodeSize()
-                       - INODE_CORE_UNLINKED_SIZE;
+                       - CoreInodeSize();
        }

        lengthOfDataFork -= sizeof(BlockInDataFork);
@@ -260,7 +476,7 @@
 Inode::GetPtrFromRoot(int pos)
 {
        return (TreePointer*)
-               ((char*)DIR_DFORK_PTR(Buffer()) + GetPtrOffsetIntoRoot(pos));
+               ((char*)DIR_DFORK_PTR(Buffer(),CoreInodeSize()) + 
GetPtrOffsetIntoRoot(pos));
 }


@@ -342,7 +558,7 @@
        if (root == NULL)
                return B_NO_MEMORY;
        memcpy((void*)root,
-               DIR_DFORK_PTR(Buffer()), sizeof(BlockInDataFork));
+               DIR_DFORK_PTR(Buffer(),CoreInodeSize()), 
sizeof(BlockInDataFork));

        size_t maxRecords = MaxRecordsPossibleInTreeRoot();
        TRACE("Maxrecords: (%" B_PRIuSIZE ")\n", maxRecords);
@@ -550,7 +766,8 @@
                return B_IO_ERROR;
        }

-       memcpy(fNode, fBuffer, INODE_CORE_UNLINKED_SIZE);
+       memcpy(fNode, fBuffer, 176);
+
        fNode->SwapEndian();

        return B_OK;
diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.h 
b/src/add-ons/kernel/file_systems/xfs/Inode.h
index 052a8af..1902ca7 100644
--- a/src/add-ons/kernel/file_systems/xfs/Inode.h
+++ b/src/add-ons/kernel/file_systems/xfs/Inode.h
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2022, Raghav Sharma, raghavself28@xxxxxxxxx
  * Copyright 2020, Shubham Bhagat, shubhambhagat111@xxxxxxxxx
  * All rights reserved. Distributed under the terms of the MIT License.
  */
@@ -14,11 +15,38 @@
 #define INODE_MAGIC 0x494e
 #define INODE_MINSIZE_LOG 8
 #define INODE_MAXSIZE_LOG 11
-#define INODE_CORE_SIZE 96
-#define INODE_CORE_UNLINKED_SIZE 100
-       // Inode core but with unlinked pointer
-#define DATA_FORK_OFFSET 0x64
-       // For v4 FS
+#define        INODE_MIN_SIZE  (1 << INODE_MINSIZE_LOG)
+#define        INODE_MAX_SIZE  (1 << INODE_MAXSIZE_LOG)
+#define INODE_CRC_OFF offsetof(struct xfs_inode_t, di_crc)
+#define        MAXAEXTNUM      ((xfs_aextnum_t)0x7fff)
+#define        MAXEXTNUM       ((xfs_extnum_t)0x7fffffff)
+
+// Does fs volume has v3 inodes?
+#define HAS_V3INODES(volume) \
+       (XFS_SB_VERSION_NUM(volume->SuperBlock()) == 5 ? \
+               1 : 0 )
+
+// Inode size for given fs
+#define DINODE_SIZE(volume) \
+       (HAS_V3INODES(volume) ? \
+               sizeof(struct xfs_inode_t) : \
+               offsetof(struct xfs_inode_t, di_crc))
+#define LITINO(volume) \
+       ((volume)->InodeSize() - DINODE_SIZE(volume))
+
+// inode data and attribute fork sizes
+#define DFORK_BOFF(ino)                ((int)((ino)->di_forkoff << 3))
+
+#define DFORK_DSIZE(ino,volume) \
+       ((ino)->di_forkoff ? DFORK_BOFF(ino) : LITINO(volume))
+#define DFORK_ASIZE(ino,volume) \
+       ((ino)->di_forkoff ? LITINO(volume) - DFORK_BOFF(ino) : 0)
+#define DFORK_SIZE(ino,volume,w) \
+       ((w) == XFS_DATA_FORK ? \
+               DFORK_DSIZE(ino, volume) : \
+               DFORK_ASIZE(ino, volume))
+
+
 #define INO_MASK(x)            ((1ULL << (x)) - 1)
        // Gets 2^x - 1
 #define INO_TO_AGNO(id, volume)        (xfs_agnumber_t)id >> 
(volume->AgInodeBits())
@@ -31,12 +59,16 @@
        // Gets the AG relative block number that contains inode
 #define INO_TO_BLOCKOFFSET(id, volume) (id & 
INO_MASK(volume->InodesPerBlkLog()))
        // Gets the offset into the block from the inode number
-#define DIR_DFORK_PTR(dir_ino_ptr) (void*) \
+
+// Data and attribute fork pointers
+#define DIR_DFORK_PTR(dir_ino_ptr,DATA_FORK_OFFSET) (void*) \
                ((char*) dir_ino_ptr + DATA_FORK_OFFSET)
-#define DIR_AFORK_PTR(dir_ino_ptr, forkoff) \
-                                       
(void*)((char*)DIR_DFORK_PTR(dir_ino_ptr) + \
+#define DIR_AFORK_PTR(dir_ino_ptr, DATA_FORK_OFFSET, forkoff) \
+                                       
(void*)((char*)DIR_DFORK_PTR(dir_ino_ptr, DATA_FORK_OFFSET) + \
                                        (((uint32)forkoff)<<3))
+
 #define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0
+
 #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()))
@@ -44,6 +76,25 @@
        ((n) >> (volume->BlockLog()))
 #define BLOCKOFFSET_FROM_POSITION(n, inode) ((n) & (inode->BlockSize() - 1))

+#define        MAXINUMBER              ((xfs_ino_t)((1ULL << 56) - 1ULL))
+
+// Inode fork identifiers
+#define        XFS_DATA_FORK   0
+#define        XFS_ATTR_FORK   1
+
+#define XFS_DFORK_FORMAT(ino, w) \
+       ((w) == XFS_DATA_FORK ? \
+               (ino)->di_format : \
+               (ino)->di_aformat)
+
+#define XFS_DFORK_NEXTENTS(ino, w) \
+       ((w) == XFS_DATA_FORK ? \
+               (ino)->di_nextents : \
+               (ino)->di_anextents)
+
+#define DFORK_MAXEXT(ino, volume, w) \
+       (DFORK_SIZE(ino, volume, w) / (2*sizeof(uint64)))
+

 // xfs_bmdr_block
 struct BlockInDataFork {
@@ -102,6 +153,33 @@
                        // Not used
 };

+
+#define XFS_INODE_FORMAT_STR \
+       { XFS_DINODE_FMT_DEV,           "dev" }, \
+       { XFS_DINODE_FMT_LOCAL,         "local" }, \
+       { XFS_DINODE_FMT_EXTENTS,       "extent" }, \
+       { XFS_DINODE_FMT_BTREE,         "btree" }, \
+       { XFS_DINODE_FMT_UUID,          "uuid" }
+
+
+/*
+       Dirents in version 3 directories have a file type field. Additions to 
this
+       list are an on-disk format change, requiring feature bits. Valid values
+       are as follows:
+*/
+#define XFS_DIR3_FT_UNKNOWN            0
+#define XFS_DIR3_FT_REG_FILE   1
+#define XFS_DIR3_FT_DIR                        2
+#define XFS_DIR3_FT_CHRDEV             3
+#define XFS_DIR3_FT_BLKDEV             4
+#define XFS_DIR3_FT_FIFO               5
+#define XFS_DIR3_FT_SOCK               6
+#define XFS_DIR3_FT_SYMLINK            7
+#define XFS_DIR3_FT_WHT                        8
+
+#define XFS_DIR3_FT_MAX                        9
+
+
 /*
  * The xfs_ino_t is the same for all types of inodes, the data and attribute
  * fork might be different and that is to be handled accordingly.
@@ -114,6 +192,8 @@
                                                                        
timestamp);
                        void                            GetChangeTime(struct 
timespec& timestamp);
                        void                            GetAccessTime(struct 
timespec& timestamp);
+                       void                            GetCreationTime(struct 
timespec& timestamp);
+
                        int8                            Format() const;
                                // The format of the inode
                        xfs_fsize_t                     Size() const;
@@ -160,17 +240,97 @@
                        uint16                          di_flags;
                        uint32                          di_gen;
                        uint32                          di_next_unlinked;
+
+                       // XFS Version 5
+
+                       uint32                          di_crc;
+                       uint64                          di_changecount;
+                       uint64                          di_lsn;
+                       uint64                          di_flags2;
+                       uint32                          di_cowextsize;
+                       uint8                           di_pad2[12];
+
+                       // fields only written to during inode creation
+
+                       xfs_timestamp_t         di_crtime;
+                       uint64                          di_ino;
+                       uuid_t                          di_uuid;
 };


+// Values for di_flags
+#define XFS_DIFLAG_REALTIME_BIT  0     // file's blocks come from rt area
+#define XFS_DIFLAG_PREALLOC_BIT  1     // file space has been preallocated
+#define XFS_DIFLAG_NEWRTBM_BIT   2     // for rtbitmap inode, new format
+#define XFS_DIFLAG_IMMUTABLE_BIT 3     // inode is immutable
+#define XFS_DIFLAG_APPEND_BIT    4     // inode is append-only
+#define XFS_DIFLAG_SYNC_BIT      5     // inode is written synchronously
+#define XFS_DIFLAG_NOATIME_BIT   6     // do not update atime
+#define XFS_DIFLAG_NODUMP_BIT    7     // do not dump
+#define XFS_DIFLAG_RTINHERIT_BIT 8     // create with realtime bit set
+#define XFS_DIFLAG_PROJINHERIT_BIT   9 // create with parents projid
+#define XFS_DIFLAG_NOSYMLINKS_BIT   10 // disallow symlink creation
+#define XFS_DIFLAG_EXTSIZE_BIT      11 // inode extent size allocator hint
+#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 // inherit inode extent size
+#define XFS_DIFLAG_NODEFRAG_BIT     13 // do not reorganize/defragment
+#define XFS_DIFLAG_FILESTREAM_BIT   14  // use filestream allocator
+
+#define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
+#define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
+#define XFS_DIFLAG_NEWRTBM       (1 << XFS_DIFLAG_NEWRTBM_BIT)
+#define XFS_DIFLAG_IMMUTABLE     (1 << XFS_DIFLAG_IMMUTABLE_BIT)
+#define XFS_DIFLAG_APPEND        (1 << XFS_DIFLAG_APPEND_BIT)
+#define XFS_DIFLAG_SYNC          (1 << XFS_DIFLAG_SYNC_BIT)
+#define XFS_DIFLAG_NOATIME       (1 << XFS_DIFLAG_NOATIME_BIT)
+#define XFS_DIFLAG_NODUMP        (1 << XFS_DIFLAG_NODUMP_BIT)
+#define XFS_DIFLAG_RTINHERIT     (1 << XFS_DIFLAG_RTINHERIT_BIT)
+#define XFS_DIFLAG_PROJINHERIT   (1 << XFS_DIFLAG_PROJINHERIT_BIT)
+#define XFS_DIFLAG_NOSYMLINKS    (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
+#define XFS_DIFLAG_EXTSIZE       (1 << XFS_DIFLAG_EXTSIZE_BIT)
+#define XFS_DIFLAG_EXTSZINHERIT  (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
+#define XFS_DIFLAG_NODEFRAG      (1 << XFS_DIFLAG_NODEFRAG_BIT)
+#define XFS_DIFLAG_FILESTREAM    (1 << XFS_DIFLAG_FILESTREAM_BIT)
+
+#define XFS_DIFLAG_ANY \
+       (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
+        XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
+        XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
+        XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
+        XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM)
+
+/*
+       Values for di_flags2 These start by being exposed to userspace in the 
upper
+       16 bits of the XFS_XFLAG_S range.
+*/
+#define XFS_DIFLAG2_DAX_BIT    0       // use DAX for this inode
+#define XFS_DIFLAG2_REFLINK_BIT        1       // file's blocks may be shared
+#define XFS_DIFLAG2_COWEXTSIZE_BIT 2  // copy on write extent size hint
+#define XFS_DIFLAG2_BIGTIME_BIT        3       // big timestamps
+
+#define XFS_DIFLAG2_DAX                (1 << XFS_DIFLAG2_DAX_BIT)
+#define XFS_DIFLAG2_REFLINK     (1 << XFS_DIFLAG2_REFLINK_BIT)
+#define XFS_DIFLAG2_COWEXTSIZE  (1 << XFS_DIFLAG2_COWEXTSIZE_BIT)
+#define XFS_DIFLAG2_BIGTIME    (1 << XFS_DIFLAG2_BIGTIME_BIT)
+
+#define XFS_DIFLAG2_ANY \
+       (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \
+        XFS_DIFLAG2_BIGTIME)
+
 class Inode {
 public:
                                                                Inode(Volume* 
volume, xfs_ino_t id);
                                                                ~Inode();
+
                        status_t                        Init();

                        xfs_ino_t                       ID() const { return 
fId; }

+                       bool                            VerifyInode() const;
+
+                       bool                            VerifyForkoff() const;
+
+                       bool                            VerifyFork(int 
WhichFork) const;
+
                        bool                            IsDirectory() const
                                                                        { 
return S_ISDIR(Mode()); }

@@ -209,6 +369,8 @@
                        uint32                          BlockSize() const
                                                                        { 
return fVolume->BlockSize(); }

+                       uint32                          CoreInodeSize() const;
+
                        void                            GetChangeTime(struct 
timespec& timestamp) const
                                                                { 
fNode->GetChangeTime(timestamp); }

@@ -219,6 +381,10 @@
                        void                            GetAccessTime(struct 
timespec& timestamp) const
                                                                { 
fNode->GetAccessTime(timestamp); }

+                       void                            GetCreationTime(struct 
timespec& timestamp) const
+                                                               { 
fNode->GetCreationTime(timestamp); }
+
+                       unsigned char           XfsModeToFtype() const;
                        status_t                        CheckPermissions(int 
accessMode) const;
                        uint32                          UserId() const { return 
fNode->UserId(); }
                        uint32                          GroupId() const { 
return fNode->GroupId(); }
diff --git a/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp 
b/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp
index 7359a93..7c8b1c3 100644
--- a/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/LeafDirectory.cpp
@@ -74,7 +74,7 @@
 void
 LeafDirectory::FillMapEntry(int num, ExtentMapEntry* fMap)
 {
-       void* directoryFork = DIR_DFORK_PTR(fInode->Buffer());
+       void* directoryFork = DIR_DFORK_PTR(fInode->Buffer(), 
fInode->CoreInodeSize());

        uint64* pointerToMap = (uint64*)((char*)directoryFork + num * 
EXTENT_SIZE);
        uint64 firstHalf = pointerToMap[0];
diff --git a/src/add-ons/kernel/file_systems/xfs/Node.cpp 
b/src/add-ons/kernel/file_systems/xfs/Node.cpp
index c2f983d..77cf1ef 100644
--- a/src/add-ons/kernel/file_systems/xfs/Node.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/Node.cpp
@@ -62,7 +62,7 @@
 void
 NodeDirectory::FillMapEntry(int num, ExtentMapEntry* fMap)
 {
-       void* directoryFork = DIR_DFORK_PTR(fInode->Buffer());
+       void* directoryFork = 
DIR_DFORK_PTR(fInode->Buffer(),fInode->CoreInodeSize());
        void* pointerToMap = (void*)((char*)directoryFork + num * EXTENT_SIZE);
        uint64 firstHalf = *((uint64*)pointerToMap);
        uint64 secondHalf = *((uint64*)pointerToMap + 1);
diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp 
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
index 50b8e11..4224636 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp
@@ -12,8 +12,7 @@
        fInode(inode),
        fTrack(0)
 {
-
-       fHeader = (ShortFormHeader*)(DIR_DFORK_PTR(fInode->Buffer()));
+       fHeader = 
(ShortFormHeader*)(DIR_DFORK_PTR(fInode->Buffer(),fInode->CoreInodeSize()));
 }


@@ -72,8 +71,8 @@
 ShortDirectory::EntrySize(int namelen)
 {
        return sizeof(ShortFormEntry) + namelen
-                       + (fInode->HasFileTypeField()? sizeof(uint8) : 0)
-                       + (fHeader->i8count? sizeof(uint64):sizeof(uint32));
+                       + (fInode->HasFileTypeField() ? sizeof(uint8) : 0)
+                       + (fHeader->i8count ? sizeof(uint64) : sizeof(uint32));
 }


@@ -155,7 +154,6 @@
                        name[entry->namelen] = '\0';
                        *length = entry->namelen + 1;
                        *ino = GetEntryIno(entry);
-
                        TRACE("Entry found. Name: (%s), Length: (%" B_PRIuSIZE 
"),ino: (%" B_PRIu64 ")\n",
                                name,*length, *ino);
                        return B_OK;
diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h 
b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
index 316a3bd..bf95e98 100644
--- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
+++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h
@@ -43,6 +43,7 @@
                                // offset tag, for directory iteration
                        uint8                           name[];
                                // name of directory entry
+
 /*
  * Following will be a single byte file type variable
  * and inode number (64bits or 32 bits)
diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.h 
b/src/add-ons/kernel/file_systems/xfs/Volume.h
index a213451..8baf31f 100644
--- a/src/add-ons/kernel/file_systems/xfs/Volume.h
+++ b/src/add-ons/kernel/file_systems/xfs/Volume.h
@@ -85,6 +85,9 @@
                        uint32                          SuperBlockFeatures2() 
const
                                                                        { 
return fSuperBlock.Features2(); }

+                       bool                            XfsHasIncompatFeature() 
const
+                                                                       { 
return fSuperBlock.XfsHasIncompatFeature(); }
+
        #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 9aec919..0d200f5 100644
--- a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp
@@ -251,11 +251,13 @@
        inode->GetModificationTime(stat->st_mtim);
        inode->GetChangeTime(stat->st_ctim);

-       /* TODO: Can we obtain the Creation Time in v4 system? */
-       inode->GetChangeTime(stat->st_crtim);
+       // Only version 3 Inodes has creation time
+       if(inode->Version() == 3)
+               inode->GetCreationTime(stat->st_crtim);
+       else
+               inode->GetChangeTime(stat->st_crtim);

        return B_OK;
-
 }
 

diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.cpp 
b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
index 2f43f88..2eb631c 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.cpp
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.cpp
@@ -154,6 +154,13 @@
 }


+bool
+XfsSuperBlock::XfsHasIncompatFeature() const
+{
+       return sb_features_incompat & XFS_SB_FEAT_INCOMPAT_FTYPE != 0;
+}
+
+
 uint16
 XfsSuperBlock::Version() const
 {
diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.h 
b/src/add-ons/kernel/file_systems/xfs/xfs.h
index e132fe6..813213f 100644
--- a/src/add-ons/kernel/file_systems/xfs/xfs.h
+++ b/src/add-ons/kernel/file_systems/xfs/xfs.h
@@ -39,7 +39,7 @@
 #define XFS_OPEN_MODE_USER_MASK 0x7fffffff
 #define        XFS_SB_VERSION_NUMBITS  0x000f
 #define        XFS_SB_VERSION_ALLFBITS 0xfff0
-#define        XFS_SB_VERSION_NUM(sb)  ((sb)->sb_versionnum & 
XFS_SB_VERSION_NUMBITS)
+#define        XFS_SB_VERSION_NUM(sb)  ((sb).Version() & 
XFS_SB_VERSION_NUMBITS)

 /*
        Inode minimum and maximum sizes.
@@ -73,6 +73,7 @@
                        bool                            IsValid() const;
                        bool                            IsValidVersion() const;
                        bool                            IsValidFeatureMask() 
const;
+                       bool                            XfsHasIncompatFeature() 
const;
                        const char*                     Name() const;
                        uint32                          BlockSize() const;
                        uint8                           BlockLog() const;

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

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I8a75ec1dc663d567d3bf6db64be4a27b55d709b3
Gerrit-Change-Number: 5396
Gerrit-PatchSet: 1
Gerrit-Owner: Raghav Sharma <raghavself28@xxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: xfs : version 3 Inodes and shortform directory - Gerrit