From 7e1b5cf8099ce814ddf190e119d83496abaf8c72 Mon Sep 17 00:00:00 2001 From: CruxBox Date: Sun, 14 Jun 2020 01:42:13 +0530 Subject: [PATCH] xfs: An attempt at reading shortform dir This patch gets read_dir, lookup and few others to work. Entries cannot be listed yet except the root. Change-Id: Ic4b7b61a794a1b75849e45777a383b3315b15aa8 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2915 Reviewed-by: Adrien Destugues --- .../kernel/file_systems/xfs/BPlusTree.cpp | 7 +- .../kernel/file_systems/xfs/BPlusTree.h | 39 ++- src/add-ons/kernel/file_systems/xfs/Debug.h | 2 +- .../kernel/file_systems/xfs/Directory.cpp | 99 ++++++++ .../kernel/file_systems/xfs/Directory.h | 35 +++ src/add-ons/kernel/file_systems/xfs/Inode.cpp | 90 +++---- src/add-ons/kernel/file_systems/xfs/Inode.h | 231 ++++++++++-------- src/add-ons/kernel/file_systems/xfs/Jamfile | 3 + .../file_systems/xfs/ShortDirectory.cpp | 84 +++++++ .../kernel/file_systems/xfs/ShortDirectory.h | 78 ++++++ .../kernel/file_systems/xfs/Volume.cpp | 26 +- src/add-ons/kernel/file_systems/xfs/Volume.h | 52 ++-- .../file_systems/xfs/kernel_interface.cpp | 121 +++++++-- src/add-ons/kernel/file_systems/xfs/xfs.cpp | 43 ++-- src/add-ons/kernel/file_systems/xfs/xfs.h | 161 ++++++------ .../kernel/file_systems/xfs/xfs_shell/Jamfile | 3 + 16 files changed, 760 insertions(+), 314 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/xfs/Directory.cpp create mode 100644 src/add-ons/kernel/file_systems/xfs/Directory.h create mode 100644 src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp create mode 100644 src/add-ons/kernel/file_systems/xfs/ShortDirectory.h diff --git a/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp b/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp index 07432a11d8..b14f869cc3 100644 --- a/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp +++ b/src/add-ons/kernel/file_systems/xfs/BPlusTree.cpp @@ -1,7 +1,8 @@ /* -* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com -* All rights reserved. Distributed under the terms of the MIT License. -*/ + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + #include "BPlusTree.h" diff --git a/src/add-ons/kernel/file_systems/xfs/BPlusTree.h b/src/add-ons/kernel/file_systems/xfs/BPlusTree.h index 7156e7a2bb..371a4f4411 100644 --- a/src/add-ons/kernel/file_systems/xfs/BPlusTree.h +++ b/src/add-ons/kernel/file_systems/xfs/BPlusTree.h @@ -1,30 +1,28 @@ /* -* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com -* All rights reserved. Distributed under the terms of the MIT License. -*/ - + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ #ifndef _BPLUS_TREE_H_ #define _BPLUS_TREE_H_ #include "system_dependencies.h" + /* Allocation B+ Tree Format */ -#define XFS_ABTB_MAGICNUM 0x41425442 // For block offset B+Tree -#define XFS_ABTC_MAGICNUM 0x41425443 // For block count B+ Tree - - -/* Header for Short Format btree */ +#define XFS_ABTB_MAGICNUM 0x41425442 + // For block offset B+Tree +#define XFS_ABTC_MAGICNUM 0x41425443 + // For block count B+ Tree #define XFS_BTREE_SBLOCK_SIZE 18 - -/* Header for Long Format btree */ + // Header for Short Format btree #define XFS_BTREE_LBLOCK_SIZE 24 + // Header for Long Format btree /* -* Headers are the "nodes" really and are called "blocks". The records, keys and -* pts are calculated using helpers -*/ - + * Headers are the "nodes" really and are called "blocks". The records, keys + * and ptrs are calculated using helpers + */ struct bplustree_short_block { void SwapEndian(); @@ -93,11 +91,11 @@ typedef struct xfs_alloc_rec { } xfs_alloc_rec_t, xfs_alloc_key_t; -// Swap Endians while returning itself -typedef uint32 xfs_alloc_ptr_t; // Node pointers, AG relative block pointer + +typedef uint32 xfs_alloc_ptr_t; + // Node pointers, AG relative block pointer #define ALLOC_FLAG 0x1 - #define LONG_BLOCK_FLAG 0x1 #define SHORT_BLOCK_FLAG 0x2 @@ -118,7 +116,7 @@ union btree_rec { class BPlusTree { - public: +public: uint32 BlockSize(); int RecordSize(); int MaxRecords(bool leaf); @@ -129,7 +127,7 @@ class BPlusTree { int KeyOffset(int pos); // get the pos'th key int PtrOffset(int pos); // get the pos'th ptr - private: +private: Volume* fVolume; xfs_agnumber_t fAgnumber; btree_ptr* fRoot; @@ -140,4 +138,3 @@ class BPlusTree { #endif - diff --git a/src/add-ons/kernel/file_systems/xfs/Debug.h b/src/add-ons/kernel/file_systems/xfs/Debug.h index 6ab16012bc..bc41c80b0e 100644 --- a/src/add-ons/kernel/file_systems/xfs/Debug.h +++ b/src/add-ons/kernel/file_systems/xfs/Debug.h @@ -5,7 +5,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) #else diff --git a/src/add-ons/kernel/file_systems/xfs/Directory.cpp b/src/add-ons/kernel/file_systems/xfs/Directory.cpp new file mode 100644 index 0000000000..3b8c06ef3c --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Directory.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + + +#include "Directory.h" + + +DirectoryIterator::DirectoryIterator(Inode* inode) +{ + fInode = inode; + fShortDir = NULL; +} + + +DirectoryIterator::~DirectoryIterator() +{ + delete fShortDir; +} + + +status_t +DirectoryIterator::Init() +{ + if (fInode->Format() == XFS_DINODE_FMT_LOCAL) + { + fShortDir = new(std::nothrow) ShortDirectory(fInode); + if (fShortDir == NULL) + return B_NO_MEMORY; + return B_OK; + } + + /* Return B_OK so even if the shortform directory has an extent directory + * we can atleast still list the shortform directory + */ + + //TODO: Reading from extent based directories + if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) { + TRACE("Iterator:GetNext: EXTENTS"); + return B_OK; + } + + //TODO: Reading from B+Trees based directories + if (fInode->Format() == XFS_DINODE_FMT_BTREE) { + TRACE("Iterator:GetNext: B+TREE"); + return B_OK; + } + + return B_BAD_VALUE; +} + +status_t +DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino) +{ + if (fInode->Format() == XFS_DINODE_FMT_LOCAL) { + status_t 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; + } + + //TODO: Reading from B+Trees based directories + if (fInode->Format() == XFS_DINODE_FMT_BTREE) { + TRACE("Iterator:GetNext: B+TREE"); + return B_NOT_SUPPORTED; + } + + // Only reaches here if Inode is a device or is corrupt. + return B_BAD_VALUE; +} + + +status_t +DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino) +{ + if (fInode->Format() == XFS_DINODE_FMT_LOCAL) { + status_t 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"); + return B_NOT_SUPPORTED; + } + + //TODO: Reading from B+Tree based dirs + if (fInode->Format() == XFS_DINODE_FMT_BTREE) { + TRACE("Iterator:Lookup: B+TREE"); + return B_NOT_SUPPORTED; + } + + return B_BAD_VALUE; +} diff --git a/src/add-ons/kernel/file_systems/xfs/Directory.h b/src/add-ons/kernel/file_systems/xfs/Directory.h new file mode 100644 index 0000000000..fd0e3bec6b --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/Directory.h @@ -0,0 +1,35 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _DIRECTORY_H_ +#define _DIRECTORY_H_ + + +#include "Inode.h" +#include "ShortDirectory.h" + + +/* + * This class should act as a layer between any kind of directory + * and the kernel interface + */ +class DirectoryIterator { +public: + DirectoryIterator(Inode* inode); + ~DirectoryIterator(); + status_t Init(); + bool IsLocalDir() { return fInode->IsLocal(); } + status_t GetNext(char* name, size_t* length, + xfs_ino_t* ino); + status_t Lookup(const char* name, size_t length, + xfs_ino_t* id); + +private: + Inode* fInode; + ShortDirectory* fShortDir; + // Short form Directory type +}; + + +#endif diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.cpp b/src/add-ons/kernel/file_systems/xfs/Inode.cpp index 61823765fd..98a40ceb29 100644 --- a/src/add-ons/kernel/file_systems/xfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/xfs/Inode.cpp @@ -1,13 +1,14 @@ /* -* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com -* All rights reserved. Distributed under the terms of the MIT License. -*/ + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + #include "Inode.h" void -xfs_inode::SwapEndian() +xfs_inode_t::SwapEndian() { di_magic = B_BENDIAN_TO_HOST_INT16(di_magic); di_mode = B_BENDIAN_TO_HOST_INT16(di_mode); @@ -37,42 +38,42 @@ xfs_inode::SwapEndian() xfs_rfsblock_t -xfs_inode::NoOfBlocks() const +xfs_inode_t::NoOfBlocks() const { return di_nblocks; } xfs_fsize_t -xfs_inode::Size() const +xfs_inode_t::Size() const { return di_size; } mode_t -xfs_inode::Mode() +xfs_inode_t::Mode() const { return di_mode; } uint32 -xfs_inode::UserId() +xfs_inode_t::UserId() const { return di_uid; } uint32 -xfs_inode::GroupId() +xfs_inode_t::GroupId() const { return di_gid; } void -xfs_inode::GetModificationTime(struct timespec& stamp) +xfs_inode_t::GetModificationTime(struct timespec& stamp) { stamp.tv_sec = di_mtime.t_sec; stamp.tv_nsec = di_mtime.t_nsec; @@ -80,7 +81,7 @@ xfs_inode::GetModificationTime(struct timespec& stamp) void -xfs_inode::GetAccessTime(struct timespec& stamp) +xfs_inode_t::GetAccessTime(struct timespec& stamp) { stamp.tv_sec = di_atime.t_sec; stamp.tv_nsec = di_atime.t_nsec; @@ -88,7 +89,7 @@ xfs_inode::GetAccessTime(struct timespec& stamp) void -xfs_inode::GetChangeTime(struct timespec& stamp) +xfs_inode_t::GetChangeTime(struct timespec& stamp) { stamp.tv_sec = di_ctime.t_sec; stamp.tv_nsec = di_ctime.t_nsec; @@ -96,51 +97,66 @@ xfs_inode::GetChangeTime(struct timespec& stamp) uint32 -xfs_inode::NLink() +xfs_inode_t::NLink() const { return di_nlink; } int8 -xfs_inode::Version() +xfs_inode_t::Version() const { return di_version; } uint16 -xfs_inode::Flags() +xfs_inode_t::Flags() const { return di_flags; } int8 -xfs_inode::Format() +xfs_inode_t::Format() const { return di_format; } Inode::Inode(Volume* volume, xfs_ino_t id) + : + fVolume(volume), + fId(id) { - fVolume = volume; - fId = id; - fNode = new(std::nothrow) xfs_inode_t; - uint16 inodeSize = volume->InodeSize(); +} + + +status_t +Inode::Init() +{ + fNode = new(std::nothrow) xfs_inode_t; + if (fNode == NULL) + return B_NO_MEMORY; + + uint16 inodeSize = fVolume->InodeSize(); fBuffer = new(std::nothrow) char[inodeSize]; + if (fBuffer == NULL) + return B_NO_MEMORY; status_t status = GetFromDisk(); if (status == B_OK) { - status = InitCheck(); - if (status) { - TRACE("Inode successfully read!"); + if (fNode->di_magic == INODE_MAGIC) { + TRACE("Init(): Inode successfully read.\n"); + status = B_OK; } else { - TRACE("Inode wasn't read successfully!"); + TRACE("Init(): Inode wasn't read successfully!\n"); + status = B_BAD_VALUE; } } + + return status; } @@ -149,29 +165,28 @@ Inode::GetFromDisk() { xfs_agnumber_t agNo = INO_TO_AGNO(fId, fVolume); // Get the AG number from the inode - uint32 agInodeNo = INO_TO_AGINO(fId, fVolume->AgInodeBits()); + uint32 agRelativeInodeNo = INO_TO_AGINO(fId, fVolume->AgInodeBits()); // AG relative ino # - xfs_agblock_t agBlock = INO_TO_AGBLOCK(agInodeNo, fVolume); + xfs_agblock_t agBlock = INO_TO_AGBLOCK(agRelativeInodeNo, fVolume); // AG relative block number - xfs_off_t offset = INO_TO_OFFSET(fId, fVolume); - // Offset into the block + xfs_off_t offset = INO_TO_BLOCKOFFSET(fId, fVolume); + // Offset into the block1 uint32 len = fVolume->InodeSize(); // Inode len to read (size of inode) - int fd = fVolume->Device(); if (agNo > fVolume->AgCount()) { ERROR("Inode::GetFromDisk : AG Number more than number of AGs"); return B_ENTRY_NOT_FOUND; } - xfs_agblock_t agBlocks = fVolume->AgBlocks(); + xfs_agblock_t numberOfBlocksInAg = fVolume->AgBlocks(); - xfs_fsblock_t blockToRead = - FSB_TO_BB(fVolume->BlockLog(), ((uint64)(agNo * agBlocks) + agBlock)); + xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(), + ((uint64)(agNo * numberOfBlocksInAg) + agBlock)); - xfs_daddr_t readPos = blockToRead*(BBLOCKSIZE) + offset; + xfs_daddr_t readPos = blockToRead*(BASICBLOCKSIZE) + offset; - if (read_pos(fd, readPos, fBuffer, len) != len) { + if (read_pos(fVolume->Device(), readPos, fBuffer, len) != len) { ERROR("Inode::Inode(): IO Error"); return B_IO_ERROR; } @@ -183,13 +198,6 @@ Inode::GetFromDisk() } -bool -Inode::InitCheck() -{ - return fNode->di_magic == INODE_MAGIC; -} - - Inode::~Inode() { delete fBuffer; diff --git a/src/add-ons/kernel/file_systems/xfs/Inode.h b/src/add-ons/kernel/file_systems/xfs/Inode.h index 5241c291ea..2d794f94c2 100644 --- a/src/add-ons/kernel/file_systems/xfs/Inode.h +++ b/src/add-ons/kernel/file_systems/xfs/Inode.h @@ -1,22 +1,23 @@ /* -* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com -* All rights reserved. Distributed under the terms of the MIT License. -*/ - + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ #ifndef _INODE_H_ #define _INODE_H_ - #include "system_dependencies.h" #include "Volume.h" #include "xfs_types.h" #define INODE_MAGIC 0x494e -#define INODE_CORE_SIZE 96 // For v4 FS -#define INODE_CORE_UNLINKED_SIZE 100 //For v4 FS +#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 INO_MASK(x) ((1ULL << (x)) - 1) // Gets 2^x - 1 #define INO_TO_AGNO(id, volume) (xfs_agnumber_t)id >> (volume->AgInodeBits()) @@ -27,132 +28,156 @@ (id >> (volume->InodesPerBlkLog())) \ & (INO_MASK(volume->AgBlocksLog())) // Gets the AG relative block number that contains inode -#define INO_TO_OFFSET(id, volume) (id & INO_MASK(volume->InodesPerBlkLog())) +#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_AFORK_PTR(dir_ino_ptr) \ + (XFS_DFORK_PTR + \ + ((uint32)dir_ino_ptr->di_forkoff<<3)) +#define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0 -typedef struct xfs_timestamp -{ +struct xfs_timestamp_t { int32 t_sec; int32 t_nsec; -} xfs_timestamp_t; +}; -typedef enum xfs_dinode_fmt -{ - XFS_DINODE_FMT_DEV, // For devices - XFS_DINODE_FMT_LOCAL, // For Directories and links - XFS_DINODE_FMT_EXTENTS, // For large number of extents - XFS_DINODE_FMT_BTREE, // Extents and Directories - XFS_DINODE_FMT_UUID, // Not used -} xfs_dinode_fmt_t; - +enum xfs_dinode_fmt_t { + XFS_DINODE_FMT_DEV, + // For devices + XFS_DINODE_FMT_LOCAL, + // For Directories and links + XFS_DINODE_FMT_EXTENTS, + // For large number of extents + XFS_DINODE_FMT_BTREE, + // Extents and Directories + XFS_DINODE_FMT_UUID, + // Not used +}; /* - 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. -*/ -typedef struct xfs_inode -{ - void SwapEndian(); - int8 Version(); //TODO - mode_t Mode(); - void GetModificationTime(struct timespec& timestamp); - void GetChangeTime(struct timespec& timestamp); - void GetAccessTime(struct timespec& timestamp); - int8 Format(); // The format of the inode - xfs_fsize_t Size() const; // TODO - xfs_rfsblock_t NoOfBlocks() const; - uint32 NLink(); - uint16 Flags(); - uint32 UserId(); - uint32 GroupId(); + * 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. + */ +struct xfs_inode_t { + void SwapEndian(); + int8 Version() const; + //TODO: Check + mode_t Mode() const; + void GetModificationTime(struct timespec& + timestamp); + void GetChangeTime(struct timespec& timestamp); + void GetAccessTime(struct timespec& timestamp); + int8 Format() const; + // The format of the inode + xfs_fsize_t Size() const; + xfs_rfsblock_t NoOfBlocks() const; + uint32 NLink() const; + uint16 Flags() const; + uint32 UserId() const; + uint32 GroupId() const; - uint16 di_magic; - uint16 di_mode; // uses standard S_Ixxx - int8 di_version; // 1 or 2 - int8 di_format; - uint16 di_onlink; - uint32 di_uid; - uint32 di_gid; - uint32 di_nlink; - uint16 di_projid; - uint8 di_pad[8]; - uint16 di_flushiter; - xfs_timestamp_t di_atime; - xfs_timestamp_t di_mtime; - xfs_timestamp_t di_ctime; - xfs_fsize_t di_size; // size in bytes or length if link - xfs_rfsblock_t di_nblocks; // blocks used including metadata - // extended attributes not included - xfs_extlen_t di_extsize; // extent size - xfs_extnum_t di_nextents; // number of data extents - xfs_aextnum_t di_anextents; // number of EA extents - uint8 di_forkoff; // decides where di_a starts - int8 di_aformat; // similar to di_format - uint32 di_dmevmask; - uint16 di_dmstate; - uint16 di_flags; - uint32 di_gen; + uint16 di_magic; + uint16 di_mode; + // uses standard S_Ixxx + int8 di_version; + //This either would be 1 or 2 + int8 di_format; + uint16 di_onlink; + uint32 di_uid; + uint32 di_gid; + uint32 di_nlink; + uint16 di_projid; + uint8 di_pad[8]; + uint16 di_flushiter; + xfs_timestamp_t di_atime; + xfs_timestamp_t di_mtime; + xfs_timestamp_t di_ctime; + xfs_fsize_t di_size; + // size in bytes or length if link + xfs_rfsblock_t di_nblocks; + // blocks used including metadata + // extended attributes not included + xfs_extlen_t di_extsize; + // extent size + xfs_extnum_t di_nextents; + // number of data extents + xfs_aextnum_t di_anextents; + // number of EA extents + uint8 di_forkoff; + // decides where di_a starts + int8 di_aformat; + // similar to di_format + uint32 di_dmevmask; + uint16 di_dmstate; + uint16 di_flags; + uint32 di_gen; - uint32 di_next_unlinked; -} xfs_inode_t; + uint32 di_next_unlinked; +}; -class Inode -{ - public: - Inode(Volume* volume, xfs_ino_t id); - ~Inode(); - bool InitCheck(); +class Inode { +public: + Inode(Volume* volume, xfs_ino_t id); + ~Inode(); + status_t Init(); - xfs_ino_t ID() const { return fId; } + xfs_ino_t ID() const { return fId; } - bool IsDirectory() const - { return S_ISDIR(Mode()); } + bool IsDirectory() const + { return S_ISDIR(Mode()); } - bool IsFile() const - { return S_ISREG(Mode()); } + bool IsFile() const + { return S_ISREG(Mode()); } - bool IsSymLink() const - { return S_ISLNK(Mode()); } + bool IsSymLink() const + { return S_ISLNK(Mode()); } - mode_t Mode() const { return fNode->Mode(); } + mode_t Mode() const { return fNode->Mode(); } - Volume* GetVolume() { return fVolume;} + Volume* GetVolume() { return fVolume;} - int8 Format() { return fNode->Format(); } + int8 Format() const { return fNode->Format(); } - bool IsLocal() { return Format() == XFS_DINODE_FMT_LOCAL; } + bool IsLocal() const + { return + Format() == XFS_DINODE_FMT_LOCAL; } - uint32 NLink() { return fNode->NLink(); } + uint32 NLink() const { return fNode->NLink(); } - int8 Version() { return fNode->Version(); } + int8 Version() const { return fNode->Version(); } - xfs_fsize_t Size() const { return fNode->Size(); } + xfs_rfsblock_t NoOfBlocks() const + { return fNode->NoOfBlocks(); } - xfs_rfsblock_t NoOfBlocks() const { return fNode->NoOfBlocks(); } + char* Buffer() { return fBuffer; } - int16 Flags() const { return fNode->Flags(); } + int16 Flags() const { return fNode->Flags(); } - void GetChangeTime(struct timespec& timestamp) const - { fNode->GetChangeTime(timestamp); } + xfs_fsize_t Size() const { return fNode->Size(); } - void GetModificationTime(struct timespec& timestamp) const - { fNode->GetModificationTime(timestamp); } + void GetChangeTime(struct timespec& timestamp) const + { fNode->GetChangeTime(timestamp); } - void GetAccessTime(struct timespec& timestamp) const - { fNode->GetAccessTime(timestamp); } + void GetModificationTime(struct timespec& timestamp) + const + { fNode->GetModificationTime(timestamp); } - private: - uint32 UserId() { return fNode->UserId(); } - uint32 GroupId() { return fNode->GroupId(); } + void GetAccessTime(struct timespec& timestamp) const + { fNode->GetAccessTime(timestamp); } - status_t GetFromDisk(); - xfs_inode_t* fNode; - xfs_ino_t fId; - Volume* fVolume; - char* fBuffer; // Contains the disk inode in BE format + uint32 UserId() const { return fNode->UserId(); } + uint32 GroupId() const { return fNode->GroupId(); } + +private: + status_t GetFromDisk(); + xfs_inode_t* fNode; + xfs_ino_t fId; + Volume* fVolume; + char* fBuffer; + // Contains the disk inode in BE format }; #endif diff --git a/src/add-ons/kernel/file_systems/xfs/Jamfile b/src/add-ons/kernel/file_systems/xfs/Jamfile index 1a6803e53e..0509ce2e83 100644 --- a/src/add-ons/kernel/file_systems/xfs/Jamfile +++ b/src/add-ons/kernel/file_systems/xfs/Jamfile @@ -20,9 +20,12 @@ DEFINES += DEBUG_APP="\\\"xfs\\\"" ; UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ; local xfsSources = + DeviceOpener.cpp + Directory.cpp Inode.cpp kernel_cpp.cpp kernel_interface.cpp + ShortDirectory.cpp Volume.cpp xfs.cpp ; diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp new file mode 100644 index 0000000000..b9e37ea9fc --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.cpp @@ -0,0 +1,84 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + + +#include "ShortDirectory.h" + + +ShortDirectory::ShortDirectory(Inode* inode) + : + fInode(inode), + fTrack(0) +{ + memcpy(&fHeader, + DIR_DFORK_PTR(fInode->Buffer()), sizeof(xfs_dir2_sf_hdr_t)); +} + + +ShortDirectory::~ShortDirectory() +{ +} + + +xfs_ino_t +ShortDirectory::GetParentIno() +{ + TRACE("GetParentIno: \n"); + if (fHeader.i8count > 0) + return B_BENDIAN_TO_HOST_INT64(fHeader.parent.i8); + else + return B_BENDIAN_TO_HOST_INT32(fHeader.parent.i4); +} + + +status_t +ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino) +{ + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + xfs_ino_t rootIno = fInode->GetVolume()->Root(); + if (strcmp(name, ".") == 0 || (rootIno == fInode->ID())) { + *ino = fInode->ID(); + TRACE("ShortDirectory:Lookup: name: \".\" ino: (%d)\n", *ino); + return B_OK; + } + *ino = GetParentIno(); + TRACE("Parent: (%d)\n", *ino); + return B_OK; + } + + //TODO: Other entries + return B_NOT_SUPPORTED; +} + + +status_t +ShortDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino) +{ + if (fTrack == 0) { + // Return '.' + if (*length < 2) + return B_BUFFER_OVERFLOW; + *length = 2; + strlcpy(name, ".", *length + 1); + *ino = fInode->ID(); + fTrack = 1; + TRACE("ShortDirectory:GetNext: name: \".\" ino: (%d)\n", *ino); + return B_OK; + } + if (fTrack == 1) { + // Return '..' + if (*length < 3) + return B_BUFFER_OVERFLOW; + *length = 3; + strlcpy(name, "..", *length + 1); + *ino = GetParentIno(); + fTrack = 2; + TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n", *ino); + return B_OK; + } + + // TODO: Now iterate through sf entries + return B_NOT_SUPPORTED; +} diff --git a/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h new file mode 100644 index 0000000000..b17f6ed8d6 --- /dev/null +++ b/src/add-ons/kernel/file_systems/xfs/ShortDirectory.h @@ -0,0 +1,78 @@ +/* + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ +#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 + +union xfs_dir2_inou_t { + uint64 i8; + uint32 i4; +}; + + +// Short form directory header +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 +}; + + +/* + *The xfs_dir2_sf_entry is split into + * two parts because the entries size is variable + */ +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 +}; + + +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; + }; +}; + + +class ShortDirectory +{ +public: + ShortDirectory(Inode* inode); + ~ShortDirectory(); + 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 + uint8 fTrack; + // Takes the values 0, 1 or 2 only + +}; + + +#endif \ No newline at end of file diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.cpp b/src/add-ons/kernel/file_systems/xfs/Volume.cpp index aa6d14ce00..e63bd5164f 100644 --- a/src/add-ons/kernel/file_systems/xfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/xfs/Volume.cpp @@ -3,12 +3,15 @@ * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com * All rights reserved. Distributed under the terms of the MIT License. */ + + #include "Volume.h" -#include "DeviceOpener.h" + +#include "Inode.h" Volume::Volume(fs_volume *volume) - : fFSVolume(volume) + : fFSVolume(volume) { fFlags = 0; mutex_init(&fLock, "xfs volume"); @@ -24,7 +27,7 @@ Volume::~Volume() bool -Volume::IsValidSuperBlock() +Volume::IsValidSuperBlock() const { return fSuperBlock.IsValid(); } @@ -65,7 +68,7 @@ Volume::Mount(const char *deviceName, uint32 flags) DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0 ? O_RDONLY - : O_RDWR); + : O_RDWR); fDevice = opener.Device(); if (fDevice < B_OK) { ERROR("Volume::Mount(): couldn't open device\n"); @@ -92,6 +95,21 @@ Volume::Mount(const char *deviceName, uint32 flags) } opener.Keep(); + + //publish the root inode + Inode* rootInode = new(std::nothrow) Inode(this, Root()); + if (rootInode == NULL) + return B_NO_MEMORY; + + status = rootInode->Init(); + if (status != B_OK) + return status; + + status = publish_vnode(FSVolume(), Root(), + (void*)rootInode, &gxfsVnodeOps, rootInode->Mode(), 0); + if (status != B_OK) + return B_BAD_VALUE; + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/xfs/Volume.h b/src/add-ons/kernel/file_systems/xfs/Volume.h index 1a9be65efe..bd69abfdec 100644 --- a/src/add-ons/kernel/file_systems/xfs/Volume.h +++ b/src/add-ons/kernel/file_systems/xfs/Volume.h @@ -1,17 +1,19 @@ /* -* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com -* All rights reserved. Distributed under the terms of the MIT License. -*/ - + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ #ifndef _VOLUME_H_ #define _VOLUME_H_ + +#include + #include "xfs.h" -/* Converting the FS Blocks to Basic Blocks */ -#define FSBSHIFT(fsBlockLog) (fsBlockLog - BBLOCKLOG); -#define FSB_TO_BB(fsBlockLog, x) x << FSBSHIFT(fsBlockLog); +#define FSBLOCK_SHIFT(fsBlockLog) (fsBlockLog - BASICBLOCKLOG); +#define FSBLOCKS_TO_BASICBLOCKS(fsBlockLog, x) x << FSBLOCK_SHIFT(fsBlockLog); + // Converting the FS Blocks to Basic Blocks enum volume_flags { VOLUME_READ_ONLY = 0x0001 @@ -28,15 +30,16 @@ public: status_t Initialize(int fd, const char *label, uint32 blockSize, uint32 sectorSize); - bool IsValidSuperBlock(); + bool IsValidSuperBlock() const; bool IsReadOnly() const - { return (fFlags & VOLUME_READ_ONLY) != 0; } + { return + (fFlags & VOLUME_READ_ONLY) != 0; } dev_t ID() const { return fFSVolume ? fFSVolume->id : -1; } fs_volume* FSVolume() const { return fFSVolume; } - char* Name() + const char* Name() const { return fSuperBlock.Name(); } XfsSuperBlock& SuperBlock() { return fSuperBlock; } @@ -44,29 +47,37 @@ public: static status_t Identify(int fd, XfsSuperBlock *superBlock); - uint32 BlockSize() { return fSuperBlock.BlockSize(); } + uint32 BlockSize() const + { return fSuperBlock.BlockSize(); } - uint8 BlockLog() { return fSuperBlock.BlockLog(); } + uint8 BlockLog() const + { return fSuperBlock.BlockLog(); } - uint32 DirBlockSize() + uint32 DirBlockSize() const { return fSuperBlock.DirBlockSize(); } - uint8 AgInodeBits() + uint8 AgInodeBits() const { return fSuperBlock.AgInodeBits(); } - uint8 AgBlocksLog() + uint8 AgBlocksLog() const { return fSuperBlock.AgBlocksLog(); } - uint8 InodesPerBlkLog() + uint8 InodesPerBlkLog() const { return fSuperBlock.InodesPerBlkLog(); } off_t Root() const { return fSuperBlock.Root(); } - uint16 InodeSize() { return fSuperBlock.InodeSize(); } + uint16 InodeSize() const + { return fSuperBlock.InodeSize(); } - xfs_agnumber_t AgCount() { return fSuperBlock.AgCount(); } + xfs_agnumber_t AgCount() const + { return fSuperBlock.AgCount(); } - xfs_agblock_t AgBlocks() { return fSuperBlock.AgBlocks(); } + xfs_agblock_t AgBlocks() const + { return fSuperBlock.AgBlocks(); } + + uint8 SuperBlockFlags() const + { return fSuperBlock.Flags(); } #if 0 off_t NumBlocks() const @@ -77,7 +88,8 @@ protected: fs_volume* fFSVolume; int fDevice; XfsSuperBlock fSuperBlock; - char fName[32]; /* filesystem name */ + char fName[32]; + // Filesystem name uint32 fDeviceBlockSize; mutex fLock; 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 fef7c6f4da..309dd15fde 100644 --- a/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/xfs/kernel_interface.cpp @@ -1,9 +1,12 @@ /* -* Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. -* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com -* All rights reserved. Distributed under the terms of the MIT License. -*/ + * Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ + + #include "system_dependencies.h" +#include "Directory.h" #include "Inode.h" #include "Volume.h" @@ -86,16 +89,6 @@ xfs_mount(fs_volume *_volume, const char *device, uint32 flags, return status; } - //publish the root inode - Inode* rootInode = new(std::nothrow) Inode(volume, volume->Root()); - if (rootInode != NULL) { - status = publish_vnode(volume->FSVolume(), volume->Root(), - (void*)rootInode, &gxfsVnodeOps, rootInode->Mode(), 0); - - if (status!=B_OK) - return B_BAD_VALUE; - } - *_rootID = volume->Root(); return B_OK; } @@ -116,6 +109,7 @@ xfs_unmount(fs_volume *_volume) static status_t xfs_read_fs_info(fs_volume *_volume, struct fs_info *info) { + TRACE("XFS_READ_FS_INFO:\n"); Volume* volume = (Volume*)_volume->private_volume; info->flags = B_FS_IS_READONLY @@ -140,15 +134,15 @@ static status_t xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type, uint32 *_flags, bool reenter) { + TRACE("XFS_GET_VNODE:\n"); Volume* volume = (Volume*)_volume->private_volume; Inode* inode = new(std::nothrow) Inode(volume, id); - if (inode == NULL) return B_NO_MEMORY; - status_t status = inode->InitCheck(); - if (status == false) { + status_t status = inode->Init(); + if (status != B_OK) { delete inode; ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status)); return B_NO_INIT; @@ -158,7 +152,7 @@ xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type, _node->ops = &gxfsVnodeOps; *_type = inode->Mode(); *_flags = 0; - + TRACE("(%d)\n", inode->ID()); return B_OK; } @@ -166,7 +160,9 @@ xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type, static status_t xfs_put_vnode(fs_volume *_volume, fs_vnode *_node, bool reenter) { - return B_NOT_SUPPORTED; + TRACE("XFS_PUT_VNODE:\n"); + delete (Inode*)_node->private_node; + return B_OK; } @@ -208,7 +204,36 @@ static status_t xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, ino_t *_vnodeID) { - return B_NOT_SUPPORTED; + TRACE("XFS_LOOKUP: %p (%s)\n", name, name); + Volume* volume = (Volume*)_volume->private_volume; + Inode* directory = (Inode*)_directory->private_node; + + if (!directory->IsDirectory()) + return B_NOT_A_DIRECTORY; + + //TODO: pretend everything is accessible. We should actually checking + //for permission here. + DirectoryIterator* iterator = + new(std::nothrow) DirectoryIterator(directory); + if (iterator == NULL) + return B_NO_MEMORY; + + status_t status = iterator->Init(); + if (status != B_OK) { + delete iterator; + return status; + } + + status = iterator->Lookup(name, strlen(name), (xfs_ino_t*)_vnodeID); + if (status != B_OK) { + delete iterator; + return status; + } + + TRACE("XFS_LOOKUP: ID: (%d)\n", *_vnodeID); + status = get_vnode(volume->FSVolume(), *_vnodeID, NULL); + TRACE("get_vnode status: (%d)\n", status); + return status; } @@ -224,6 +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()); stat->st_dev = inode->GetVolume()->ID(); stat->st_ino = inode->ID(); stat->st_nlink = 1; @@ -234,7 +260,7 @@ xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) stat->st_mode = inode->Mode(); stat->st_type = 0; // TODO - stat->st_size = inode->GetVolume()->InodeSize(); + stat->st_size = inode->Size(); stat->st_blocks = inode->NoOfBlocks(); inode->GetAccessTime(stat->st_atim); @@ -282,7 +308,9 @@ xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie) static status_t xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode) { - return B_NOT_SUPPORTED; + //TODO: pretend everything is accessible. We should actually checking + //for permission here. + return B_OK; } @@ -322,7 +350,20 @@ xfs_remove_dir(fs_volume *_volume, fs_vnode *_directory, const char *name) static status_t xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie) { - return B_NOT_SUPPORTED; + Inode* inode = (Inode*)_node->private_node; + TRACE("XFS_OPEN_DIR: (%d)\n", inode->ID()); + + if (!inode->IsDirectory()) + return B_NOT_A_DIRECTORY; + + DirectoryIterator* iterator = new(std::nothrow) DirectoryIterator(inode); + if (iterator == NULL) { + delete iterator; + return B_NO_MEMORY; + } + status_t status = iterator->Init(); + *_cookie = iterator; + return status; } @@ -330,7 +371,39 @@ static status_t xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { - return B_NOT_SUPPORTED; + TRACE("XFS_READ_DIR\n"); + DirectoryIterator* iterator = (DirectoryIterator*)_cookie; + Volume* volume = (Volume*)_volume->private_volume; + + uint32 maxCount = *_num; + uint32 count = 0; + + while (count < maxCount and (bufferSize > sizeof(struct dirent))) { + size_t length = bufferSize - sizeof(struct dirent) + 1; + xfs_ino_t ino; + + status_t status = iterator->GetNext(dirent->d_name, &length, &ino); + if (status == B_ENTRY_NOT_FOUND) + break; + if (status == B_BUFFER_OVERFLOW) { + if (count == 0) + return status; + break; + } + if (status != B_OK) + return status; + + dirent->d_dev = volume->ID(); + dirent->d_ino = ino; + dirent->d_reclen = sizeof(dirent) + length; + bufferSize -= dirent->d_reclen; + dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen); + count++; + } + + *_num = count; + TRACE("Count: (%d)\n", count); + 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 763d66fb37..6200c182ef 100644 --- a/src/add-ons/kernel/file_systems/xfs/xfs.cpp +++ b/src/add-ons/kernel/file_systems/xfs/xfs.cpp @@ -6,13 +6,20 @@ #include "xfs.h" +uint8 +XfsSuperBlock::Flags() const +{ + return sb_flags; +} + + bool -XfsSuperBlock::IsValid() +XfsSuperBlock::IsValid() const { if (sb_magicnum != XFS_SB_MAGIC) return false; - if (BBLOCKSIZE > sb_blocksize) { + if (BASICBLOCKSIZE > sb_blocksize) { ERROR("Basic block is less than 512 bytes!"); return false; } @@ -22,91 +29,91 @@ XfsSuperBlock::IsValid() uint32 -XfsSuperBlock::BlockSize() +XfsSuperBlock::BlockSize() const { return sb_blocksize; } uint8 -XfsSuperBlock::BlockLog() +XfsSuperBlock::BlockLog() const { return sb_blocklog; } uint32 -XfsSuperBlock::DirBlockSize() +XfsSuperBlock::DirBlockSize() const { return BlockSize() * (1 << sb_dirblklog); } uint8 -XfsSuperBlock::AgInodeBits() +XfsSuperBlock::AgInodeBits() const { return AgBlocksLog() + InodesPerBlkLog(); } uint8 -XfsSuperBlock::InodesPerBlkLog() +XfsSuperBlock::InodesPerBlkLog() const { return sb_inopblog; } uint8 -XfsSuperBlock::AgBlocksLog() +XfsSuperBlock::AgBlocksLog() const { return sb_agblklog; } uint32 -XfsSuperBlock::Size() +XfsSuperBlock::Size() const { return XFS_SB_MAXSIZE; } uint16 -XfsSuperBlock::InodeSize() +XfsSuperBlock::InodeSize() const { return sb_inodesize; } xfs_rfsblock_t -XfsSuperBlock::TotalBlocks() +XfsSuperBlock::TotalBlocks() const { return sb_dblocks; } xfs_rfsblock_t -XfsSuperBlock::TotalBlocksWithLog() +XfsSuperBlock::TotalBlocksWithLog() const { return TotalBlocks() + sb_logblocks; } uint64 -XfsSuperBlock::FreeBlocks() +XfsSuperBlock::FreeBlocks() const { return sb_fdblocks; } uint64 -XfsSuperBlock::UsedBlocks() +XfsSuperBlock::UsedBlocks() const { return TotalBlocks() - FreeBlocks(); } -char* -XfsSuperBlock::Name() +const char* +XfsSuperBlock::Name() const { return sb_fname; } @@ -120,14 +127,14 @@ XfsSuperBlock::Root() const xfs_agnumber_t -XfsSuperBlock::AgCount() +XfsSuperBlock::AgCount() const { return sb_agcount; } xfs_agblock_t -XfsSuperBlock::AgBlocks() +XfsSuperBlock::AgBlocks() const { return sb_agblocks; } diff --git a/src/add-ons/kernel/file_systems/xfs/xfs.h b/src/add-ons/kernel/file_systems/xfs/xfs.h index b7d5ed4d30..135c63d30d 100644 --- a/src/add-ons/kernel/file_systems/xfs/xfs.h +++ b/src/add-ons/kernel/file_systems/xfs/xfs.h @@ -1,19 +1,19 @@ /* -* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com -* All rights reserved. Distributed under the terms of the MIT License. -*/ + * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com + * All rights reserved. Distributed under the terms of the MIT License. + */ /* -*Important: -*All fields in XFS metadata structures are in big-endian byte order -*except for log items which are formatted in host order. -* -*This file contains all global structure definitions. -*/ - + *Important: + *All fields in XFS metadata structures are in big-endian byte order + *except for log items which are formatted in host order. + * + *This file contains all global structure definitions. + */ #ifndef _XFS_SB_H_ #define _XFS_SB_H_ + #include "system_dependencies.h" #include "xfs_types.h" @@ -22,83 +22,86 @@ extern fs_vnode_ops gxfsVnodeOps; extern fs_volume_ops gxfsVolumeOps; -#define XFS_SB_MAGIC 0x58465342 /* Identifies XFS. "XFSB" */ +#define XFS_SB_MAGIC 0x58465342 + // Identifies XFS. "XFSB" #define XFS_SB_MAXSIZE 512 -#define BBLOCKLOG 9 /* Log of block size should be 9 */ -#define BBLOCKSIZE 1 << BBLOCKLOG /* The size of a basic block should be 512 */ +#define BASICBLOCKLOG 9 + // Log of block size should be 9 +#define BASICBLOCKSIZE 1 << BASICBLOCKLOG + // The size of a basic block should be 512 /* Version 4 superblock definition */ -class XfsSuperBlock -{ +class XfsSuperBlock { public: - bool IsValid(); - char* Name(); - uint32 BlockSize(); - uint8 BlockLog(); - uint32 DirBlockSize(); // maximum 65536 - uint8 AgInodeBits(); - uint8 InodesPerBlkLog(); - uint8 AgBlocksLog(); - xfs_rfsblock_t TotalBlocks(); - xfs_rfsblock_t TotalBlocksWithLog(); - uint64 FreeBlocks(); - uint64 UsedBlocks(); - uint32 Size(); - uint16 InodeSize(); - void SwapEndian(); - xfs_ino_t Root() const; - xfs_agnumber_t AgCount(); - xfs_agblock_t AgBlocks(); - + bool IsValid() const; + const char* Name() const; + uint32 BlockSize() const; + uint8 BlockLog() const; + uint32 DirBlockSize() const; + // maximum 65536 + uint8 AgInodeBits() const; + uint8 InodesPerBlkLog() const; + uint8 AgBlocksLog() const; + xfs_rfsblock_t TotalBlocks() const; + xfs_rfsblock_t TotalBlocksWithLog() const; + uint64 FreeBlocks() const; + uint64 UsedBlocks() const; + uint32 Size() const; + uint16 InodeSize() const; + void SwapEndian(); + xfs_ino_t Root() const; + xfs_agnumber_t AgCount() const; + xfs_agblock_t AgBlocks() const; + uint8 Flags() const; private: - uint32 sb_magicnum; - uint32 sb_blocksize; - xfs_rfsblock_t sb_dblocks; - xfs_rfsblock_t sb_rblocks; - xfs_rtblock_t sb_rextents; - uuid_t sb_uuid; - xfs_fsblock_t sb_logstart; - xfs_ino_t sb_rootino; - xfs_ino_t sb_rbmino; - xfs_ino_t sb_rsumino; - xfs_agblock_t sb_rextsize; - xfs_agblock_t sb_agblocks; - xfs_agnumber_t sb_agcount; - xfs_extlen_t sb_rbmblocks; - xfs_extlen_t sb_logblocks; - uint16 sb_versionnum; - uint16 sb_sectsize; - uint16 sb_inodesize; - uint16 sb_inopblock; - char sb_fname[12]; - uint8 sb_blocklog; - uint8 sb_sectlog; - uint8 sb_inodelog; - uint8 sb_inopblog; - uint8 sb_agblklog; - uint8 sb_rextslog; - uint8 sb_inprogress; - uint8 sb_imax_pct; - uint64 sb_icount; - uint64 sb_ifree; - uint64 sb_fdblocks; - uint64 sb_frextents; - xfs_ino_t sb_uquotino; - xfs_ino_t sb_gquotino; - uint16 sb_qflags; - uint8 sb_flags; - uint8 sb_shared_vn; - xfs_extlen_t sb_inoalignmt; - uint32 sb_unit; - uint32 sb_width; - uint8 sb_dirblklog; - uint8 sb_logsectlog; - uint16 sb_logsectsize; - uint32 sb_logsunit; - uint32 sb_features2; + uint32 sb_magicnum; + uint32 sb_blocksize; + xfs_rfsblock_t sb_dblocks; + xfs_rfsblock_t sb_rblocks; + xfs_rtblock_t sb_rextents; + uuid_t sb_uuid; + xfs_fsblock_t sb_logstart; + xfs_ino_t sb_rootino; + xfs_ino_t sb_rbmino; + xfs_ino_t sb_rsumino; + xfs_agblock_t sb_rextsize; + xfs_agblock_t sb_agblocks; + xfs_agnumber_t sb_agcount; + xfs_extlen_t sb_rbmblocks; + xfs_extlen_t sb_logblocks; + uint16 sb_versionnum; + uint16 sb_sectsize; + uint16 sb_inodesize; + uint16 sb_inopblock; + char sb_fname[12]; + uint8 sb_blocklog; + uint8 sb_sectlog; + uint8 sb_inodelog; + uint8 sb_inopblog; + uint8 sb_agblklog; + uint8 sb_rextslog; + uint8 sb_inprogress; + uint8 sb_imax_pct; + uint64 sb_icount; + uint64 sb_ifree; + uint64 sb_fdblocks; + uint64 sb_frextents; + xfs_ino_t sb_uquotino; + xfs_ino_t sb_gquotino; + uint16 sb_qflags; + uint8 sb_flags; + uint8 sb_shared_vn; + xfs_extlen_t sb_inoalignmt; + uint32 sb_unit; + uint32 sb_width; + uint8 sb_dirblklog; + uint8 sb_logsectlog; + uint16 sb_logsectsize; + uint32 sb_logsunit; + uint32 sb_features2; }; diff --git a/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile b/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile index 64b6177aca..c9fe209f6f 100644 --- a/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile +++ b/src/tests/add-ons/kernel/file_systems/xfs/xfs_shell/Jamfile @@ -39,8 +39,11 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ; UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ; local xfsSource = + DeviceOpener.cpp + Directory.cpp Inode.cpp kernel_interface.cpp + ShortDirectory.cpp Volume.cpp xfs.cpp ;