xfs: An attempt to read block directories
Map entries can be read, most structures are in place. Next is to actually work with the directory block. Change-Id: I700ee2e003bdef97838b1f06a95e53a5e4293658 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2981 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
a060fa968e
commit
9593c05ac5
@@ -9,7 +9,7 @@
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
// #define TRACE_XFS
|
||||
#define TRACE_XFS
|
||||
#ifdef TRACE_XFS
|
||||
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
||||
#define ASSERT(x) \
|
||||
|
||||
@@ -30,6 +30,14 @@ DirectoryIterator::Init()
|
||||
return B_NO_MEMORY;
|
||||
return B_OK;
|
||||
}
|
||||
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
|
||||
// TODO: Only working with Block directories, not leaf.
|
||||
fExtentDir = new(std::nothrow) Extent(fInode);
|
||||
if (fExtentDir == NULL)
|
||||
return B_NO_MEMORY;
|
||||
status_t status = fExtentDir->Init();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Return B_OK so even if the shortform directory has an extent directory
|
||||
* we can atleast still list the shortform directory
|
||||
@@ -87,6 +95,10 @@ DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino)
|
||||
//TODO: Reading from extent based dirs
|
||||
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
|
||||
TRACE("Iterator:Lookup: EXTENTS");
|
||||
#if 0
|
||||
status_t status = fExtentDir->Lookup(name, length, ino);
|
||||
return status;
|
||||
#endif
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define _DIRECTORY_H_
|
||||
|
||||
|
||||
#include "Extent.h"
|
||||
#include "Inode.h"
|
||||
#include "ShortDirectory.h"
|
||||
|
||||
@@ -29,6 +30,8 @@ private:
|
||||
Inode* fInode;
|
||||
ShortDirectory* fShortDir;
|
||||
// Short form Directory type
|
||||
Extent* fExtentDir;
|
||||
// Extent form Directory type
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Extent.h"
|
||||
|
||||
|
||||
Extent::Extent(Inode* inode)
|
||||
:
|
||||
fInode(inode)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Extent::FillMapEntry(void* pointerToMap)
|
||||
{
|
||||
uint64 firstHalf = *((uint64*)pointerToMap);
|
||||
uint64 secondHalf = *((uint64*)pointerToMap + 1);
|
||||
//dividing the 128 bits into 2 parts.
|
||||
firstHalf = B_BENDIAN_TO_HOST_INT64(firstHalf);
|
||||
secondHalf = B_BENDIAN_TO_HOST_INT64(secondHalf);
|
||||
fMap->br_state = (firstHalf >> 63);
|
||||
fMap->br_startoff = (firstHalf & MASK(63)) >> 9;
|
||||
fMap->br_startblock = ((firstHalf & MASK(9)) << 43) | (secondHalf >> 21);
|
||||
fMap->br_blockcount = (secondHalf & MASK(21));
|
||||
TRACE("Extent::Init: startoff:(%ld), startblock:(%ld), blockcount:(%ld),"
|
||||
"state:(%d)\n",
|
||||
fMap->br_startoff,
|
||||
fMap->br_startblock,
|
||||
fMap->br_blockcount,
|
||||
fMap->br_state
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Extent::Init()
|
||||
{
|
||||
fMap = new(std::nothrow) ExtentMapEntry;
|
||||
if (fMap == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
ASSERT(BlockType() == true);
|
||||
void* pointerToMap = DIR_DFORK_PTR(fInode->Buffer());
|
||||
FillMapEntry(pointerToMap);
|
||||
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
ExtentBlockTail*
|
||||
Extent::BlockTail(ExtentDataHeader* header)
|
||||
{
|
||||
return (ExtentBlockTail*)
|
||||
((char*)header + fInode->DirBlockSize() - sizeof(ExtentBlockTail));
|
||||
}
|
||||
|
||||
|
||||
ExtentLeafEntry*
|
||||
Extent::BlockFirstLeaf(ExtentBlockTail* tail)
|
||||
{
|
||||
return (ExtentLeafEntry*)tail - B_BENDIAN_TO_HOST_INT32(tail->count);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Extent::BlockType()
|
||||
{
|
||||
bool status = true;
|
||||
if (fInode->NoOfBlocks() != 1)
|
||||
status = false;
|
||||
if (fInode->Size() != fInode->DirBlockSize())
|
||||
status = false;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _EXTENT_H_
|
||||
#define _EXTENT_H_
|
||||
|
||||
|
||||
#include "Inode.h"
|
||||
#include "system_dependencies.h"
|
||||
|
||||
|
||||
#define DIR2_BLOCK_HEADER_MAGIC 0x58443242
|
||||
// for v4 system
|
||||
#define XFS_DIR2_DATA_FD_COUNT 3
|
||||
#define EXTENT_REC_SIZE 128
|
||||
#define MASK(n) ((1UL << n) - 1)
|
||||
|
||||
|
||||
// xfs_exntst_t
|
||||
enum ExtentState {
|
||||
XFS_EXT_NORM,
|
||||
XFS_EXT_UNWRITTEN,
|
||||
XFS_EXT_INVALID
|
||||
};
|
||||
|
||||
|
||||
// xfs_dir2_data_free_t
|
||||
struct FreeRegion {
|
||||
uint16 offset;
|
||||
uint16 length;
|
||||
};
|
||||
|
||||
|
||||
// xfs_dir2_data_hdr_t
|
||||
struct ExtentDataHeader {
|
||||
uint32 magic;
|
||||
FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT];
|
||||
};
|
||||
|
||||
|
||||
// xfs_dir2_data_entry_t
|
||||
struct ExtentDataEntry {
|
||||
xfs_ino_t inumber;
|
||||
uint8 namelen;
|
||||
uint8 name[];
|
||||
|
||||
// Followed by a file type (8bit) if applicable and a 16bit tag
|
||||
// tag is the offset from start of the block
|
||||
};
|
||||
|
||||
|
||||
// xfs_dir2_data_unused_t
|
||||
struct ExtentUnusedEntry {
|
||||
uint16 freetag;
|
||||
// takes the value 0xffff
|
||||
uint16 length;
|
||||
// freetag+length overrides the inumber of an entry
|
||||
uint16 tag;
|
||||
};
|
||||
|
||||
|
||||
// xfs_dir2_leaf_entry_t
|
||||
struct ExtentLeafEntry {
|
||||
uint32 hashval;
|
||||
uint32 address;
|
||||
// offset into block after >> 3
|
||||
};
|
||||
|
||||
|
||||
// xfs_dir2_block_tail_t
|
||||
struct ExtentBlockTail {
|
||||
uint32 count;
|
||||
// # of entries in leaf
|
||||
uint32 stale;
|
||||
// # of free leaf entries
|
||||
};
|
||||
|
||||
|
||||
struct ExtentMapEntry {
|
||||
xfs_fileoff_t br_startoff;
|
||||
// logical file block offset
|
||||
xfs_fsblock_t br_startblock;
|
||||
// absolute block number
|
||||
xfs_filblks_t br_blockcount;
|
||||
// # of blocks
|
||||
uint8 br_state;
|
||||
// state of the extent
|
||||
};
|
||||
|
||||
|
||||
class Extent
|
||||
{
|
||||
public:
|
||||
Extent(Inode* inode);
|
||||
~Extent();
|
||||
status_t Init();
|
||||
bool BlockType();
|
||||
void FillMapEntry(void* pointerToMap);
|
||||
ExtentDataHeader* BlockHeader();
|
||||
ExtentBlockTail* BlockTail(ExtentDataHeader* header);
|
||||
ExtentLeafEntry* BlockFirstLeaf(ExtentBlockTail* tail);
|
||||
xfs_ino_t GetIno();
|
||||
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;
|
||||
ExtentMapEntry* fMap;
|
||||
char* fBlockBuffer;
|
||||
// This isn't inode data. It holds the directory block.
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -175,7 +175,8 @@ Inode::GetFromDisk()
|
||||
// Inode len to read (size of inode)
|
||||
|
||||
TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d),"
|
||||
"Offset: (%d), len: (%d)\n", agNo, agInodeNo, agBlock, offset, len);
|
||||
"Offset: (%d), len: (%d)\n", agNo,
|
||||
agRelativeInodeNo, agBlock, offset, len);
|
||||
|
||||
if (agNo > fVolume->AgCount()) {
|
||||
ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
|
||||
@@ -206,3 +207,38 @@ Inode::~Inode()
|
||||
delete fBuffer;
|
||||
delete fNode;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
hashfunction(const char* name, int length)
|
||||
{
|
||||
uint32 hashVal = 0;
|
||||
|
||||
int lengthCovered = 0;
|
||||
int index = 0;
|
||||
if (length >= 4) {
|
||||
for (; index <= length; index+=4)
|
||||
{
|
||||
lengthCovered = index;
|
||||
hashVal = (name[index] << 21) ^ (name[index+1] << 14)
|
||||
^ (name[index+2] << 7) ^ (name[index+3] << 0)
|
||||
^ ((hashVal << 28) | (hashVal >> (4)));
|
||||
}
|
||||
}
|
||||
|
||||
int leftToCover = length - lengthCovered;
|
||||
if (leftToCover == 3) {
|
||||
hashVal = (name[index] << 14) ^ (name[index+1] << 7)
|
||||
^ (name[index+2] << 0) ^ ((hashVal << 21) | (hashVal >> (11)));
|
||||
}
|
||||
if (leftToCover == 2) {
|
||||
hashVal = (name[index] << 7) ^ (name[index+1] << 0)
|
||||
^ ((hashVal << 14) | (hashVal >> (32 - 14)));
|
||||
}
|
||||
if (leftToCover == 1) {
|
||||
hashVal = (name[index] << 0)
|
||||
^ ((hashVal << 7) | (hashVal >> (32 - 7)));
|
||||
}
|
||||
|
||||
return hashVal;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0
|
||||
|
||||
|
||||
uint32
|
||||
hashfunction(const char* name, int length);
|
||||
|
||||
|
||||
struct xfs_timestamp_t {
|
||||
int32 t_sec;
|
||||
int32 t_nsec;
|
||||
@@ -159,6 +163,9 @@ public:
|
||||
|
||||
xfs_fsize_t Size() const { return fNode->Size(); }
|
||||
|
||||
uint32 DirBlockSize() const
|
||||
{ return fVolume->DirBlockSize(); }
|
||||
|
||||
void GetChangeTime(struct timespec& timestamp) const
|
||||
{ fNode->GetChangeTime(timestamp); }
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
||||
local xfsSources =
|
||||
DeviceOpener.cpp
|
||||
Directory.cpp
|
||||
Extent.cpp
|
||||
Inode.cpp
|
||||
kernel_cpp.cpp
|
||||
kernel_interface.cpp
|
||||
@@ -42,4 +43,4 @@ SEARCH on [ FGristFiles DeviceOpener.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
|
||||
|
||||
SEARCH on [ FGristFiles kernel_cpp.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||
|
||||
@@ -152,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());
|
||||
TRACE("(%ld)\n", inode->ID());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
|
||||
return status;
|
||||
}
|
||||
|
||||
TRACE("XFS_LOOKUP: ID: (%d)\n", *_vnodeID);
|
||||
TRACE("XFS_LOOKUP: ID: (%ld)\n", *_vnodeID);
|
||||
status = get_vnode(volume->FSVolume(), *_vnodeID, NULL);
|
||||
TRACE("get_vnode status: (%d)\n", status);
|
||||
return status;
|
||||
@@ -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: id: (%d)\n", inode->ID());
|
||||
TRACE("XFS_READ_STAT: id: (%ld)\n", inode->ID());
|
||||
stat->st_dev = inode->GetVolume()->ID();
|
||||
stat->st_ino = inode->ID();
|
||||
stat->st_nlink = 1;
|
||||
@@ -351,7 +351,7 @@ static status_t
|
||||
xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie)
|
||||
{
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
TRACE("XFS_OPEN_DIR: (%d)\n", inode->ID());
|
||||
TRACE("XFS_OPEN_DIR: (%ld)\n", inode->ID());
|
||||
|
||||
if (!inode->IsDirectory())
|
||||
return B_NOT_A_DIRECTORY;
|
||||
|
||||
@@ -29,10 +29,9 @@ typedef uint32 xfs_dablk_t; // block number for directories
|
||||
typedef uint32 xfs_dahash_t; // hash of a directory file name
|
||||
// or extended attribute name
|
||||
typedef uint64 xfs_fsblock_t; // filesystem block number combining AG number
|
||||
// and block offset into the AG
|
||||
typedef uint64 xfs_rfsblock_t; // raw filesystem block number
|
||||
typedef uint64 xfs_rtblock_t; // extent number in the real-time sub-volume
|
||||
typedef uint64 xfs_filoff_t; // block offset into a file
|
||||
typedef uint64 xfs_fileoff_t; // block offset into a file
|
||||
typedef uint64 xfs_filblks_t; // block count for a file
|
||||
typedef int64 xfs_fsize_t; // byte size of a file
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||
local xfsSource =
|
||||
DeviceOpener.cpp
|
||||
Directory.cpp
|
||||
Extent.cpp
|
||||
Inode.cpp
|
||||
kernel_interface.cpp
|
||||
ShortDirectory.cpp
|
||||
|
||||
Reference in New Issue
Block a user