diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h b/src/add-ons/kernel/file_systems/xfs/Debug.h index bc41c80b0e..ec5a36b935 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@gmail.com. + * Copyright 2011, Jérôme Duval, korli@users.berlios.de. + * Copyright 2008-2014, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2005-2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com - * 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,11 @@ // #define TRACE_XFS #ifdef TRACE_XFS #define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x) +#define ASSERT(x) \ + { if (!(x)) kernel_debugger("xfs: 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/Directory.cpp b/src/add-ons/kernel/file_systems/xfs/Directory.cpp index 3b8c06ef3c..ad825ec886 100644 --- a/src/add-ons/kernel/file_systems/xfs/Directory.cpp +++ b/src/add-ons/kernel/file_systems/xfs/Directory.cpp @@ -50,6 +50,7 @@ DirectoryIterator::Init() return B_BAD_VALUE; } + status_t DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino) { diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp b/src/add-ons/kernel/file_systems/xfs/Inode.cpp index 98a40ceb29..787ccd6bfa 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::GetFromDisk() uint32 len = fVolume->InodeSize(); // Inode len to read (size of inode) + 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 @@ Inode::GetFromDisk() xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(), ((uint64)(agNo * numberOfBlocksInAg) + agBlock)); - xfs_daddr_t readPos = blockToRead*(BASICBLOCKSIZE) + offset; + xfs_daddr_t readPos = blockToRead * (BASICBLOCKSIZE) + offset * len; if (read_pos(fVolume->Device(), 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 2d794f94c2..d891c8ef09 100644 --- a/src/add-ons/kernel/file_systems/xfs/Inode.h +++ b/src/add-ons/kernel/file_systems/xfs/Inode.h @@ -30,9 +30,10 @@ // 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) (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 b9e37ea9fc..3e34062c6e 100644 --- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp +++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp @@ -12,8 +12,8 @@ ShortDirectory::ShortDirectory(Inode* inode) fInode(inode), fTrack(0) { - memcpy(&fHeader, - DIR_DFORK_PTR(fInode->Buffer()), sizeof(xfs_dir2_sf_hdr_t)); + + fHeader = (ShortFormHeader*)(DIR_DFORK_PTR(fInode->Buffer())); } @@ -22,20 +22,76 @@ ShortDirectory::~ShortDirectory() } -xfs_ino_t -ShortDirectory::GetParentIno() +bool +ShortDirectory::HasFileTypeField() { - TRACE("GetParentIno: \n"); - if (fHeader.i8count > 0) - 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(ShortFormEntry* entry) +{ + ASSERT(HasFileTypeField() == true); + return entry->name[entry->namelen]; +} + + +ShortFormEntry* +ShortDirectory::FirstEntry() +{ + return (ShortFormEntry*) ((char*) fHeader + HeaderSize()); +} + + +size_t +ShortDirectory::HeaderSize() +{ + if (fHeader->i8count) + return sizeof(ShortFormHeader); + else + return sizeof(ShortFormHeader) - sizeof(uint32); +} + + +xfs_ino_t +ShortDirectory::GetIno(ShortFormInodeUnion* 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(ShortFormEntry* entry) +{ + if (HasFileTypeField()) + return GetIno((ShortFormInodeUnion*)(entry->name + + entry->namelen + sizeof(uint8))); + else + return GetIno((ShortFormInodeUnion*)(entry->name + entry->namelen)); +} + + +size_t +ShortDirectory::EntrySize(int namelen) +{ + return sizeof(ShortFormEntry) + namelen + + (HasFileTypeField()? sizeof(uint8) : 0) + + (fHeader->i8count? sizeof(uint64):sizeof(uint32)); } status_t ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino) { + TRACE("ShortDirectory::Lookup\n"); + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { xfs_ino_t rootIno = fInode->GetVolume()->Root(); if (strcmp(name, ".") == 0 || (rootIno == fInode->ID())) { @@ -43,13 +99,27 @@ ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino) 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; + ShortFormEntry* entry = FirstEntry(); + TRACE("Length of first entry: (%d),offset of first entry:" + "(%d)\n", entry->namelen, B_BENDIAN_TO_HOST_INT16(entry->offset.i)); + + int status; + for (int i = 0; i < fHeader->count; i++) { + status = strncmp(name, (char*)entry->name, entry->namelen); + if (status == 0) { + *ino = GetEntryIno(entry); + return B_OK; + } + entry = (ShortFormEntry*) + ((char*) entry + EntrySize(entry->namelen)); + } + + return B_ENTRY_NOT_FOUND; } @@ -73,12 +143,35 @@ ShortDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino) 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); return B_OK; } - // TODO: Now iterate through sf entries - return B_NOT_SUPPORTED; + ShortFormEntry* 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 = (ShortFormEntry*)((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 b17f6ed8d6..7507d3878b 100644 --- a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h +++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h @@ -5,52 +5,49 @@ #ifndef __SHORT_DIR_H__ #define __SHORT_DIR_H__ + #include "Inode.h" -struct xfs_dir2_sf_off_t { uint8 i[2]; }; - //offset into the literal area +/* + * offset into the literal area + * xfs_dir2_sf_off_t + */ +struct ShortFormOffset { + uint16 i; +} __attribute__((packed)); -union xfs_dir2_inou_t { +//xfs_dir2_inou_t +union ShortFormInodeUnion { uint64 i8; uint32 i4; -}; +} __attribute__((packed)); -// Short form directory header -struct xfs_dir2_sf_hdr_t { +// xfs_dir2_sf_hdr_t +struct ShortFormHeader { uint8 count; // number of entries uint8 i8count; // # of 64bit inode entries - xfs_dir2_inou_t parent; + ShortFormInodeUnion parent; // absolute inode # of parent -}; +} __attribute__((packed)); -/* - *The xfs_dir2_sf_entry is split into - * two parts because the entries size is variable - */ -struct xfs_dir2_sf_entry_t { +//xfs_dir2_sf_entry_t +struct ShortFormEntry { uint8 namelen; // length of the name, in bytes - xfs_dir2_sf_off_t offset; + ShortFormOffset offset; // offset tag, for directory iteration uint8 name[]; // name of directory entry -}; - - -union xfs_dir2_sf_entry_inum_t { - struct xfs_ftype_inum{ - uint8 ftype; - xfs_dir2_inou_t inumber; - }; - struct xfs_inum{ - xfs_dir2_inou_t inumber; - }; -}; +/* + * Following will be a single byte file type variable + * and inode number (64bits or 32 bits) + */ +} __attribute__((packed)); class ShortDirectory @@ -58,21 +55,24 @@ class ShortDirectory public: ShortDirectory(Inode* inode); ~ShortDirectory(); + size_t HeaderSize(); + bool HasFileTypeField(); + uint8 GetFileType(ShortFormEntry* entry); + ShortFormEntry* FirstEntry(); + xfs_ino_t GetIno(ShortFormInodeUnion* inum); + xfs_ino_t GetEntryIno(ShortFormEntry* entry); + size_t EntrySize(int namelen); 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; - // offset into the literal area + ShortFormHeader* fHeader; + uint16 fLastEntryOffset; + // offset into the literal area uint8 fTrack; - // Takes the values 0, 1 or 2 only - + // Takes the values 0, 1 or 2 }; - -#endif \ No newline at end of file +#endif diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.h b/src/add-ons/kernel/file_systems/xfs/Volume.h index bd69abfdec..46631fc580 100644 --- a/src/add-ons/kernel/file_systems/xfs/Volume.h +++ b/src/add-ons/kernel/file_systems/xfs/Volume.h @@ -79,6 +79,9 @@ public: 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 309dd15fde..1eabf9e8eb 100644 --- a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp @@ -249,7 +249,7 @@ static status_t 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 6200c182ef..2c3f90ef8a 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 @@ XfsSuperBlock::IsValid() const 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 135c63d30d..603dc7274f 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 @@ public: 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 @@ Superblock quota flags - sb_qflags 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