xfs: Reading Inodes
This patch successfully reads inodes. There are also some style fixes. The inodes aren't published and some useful hooks are yet to implement. Change-Id: I73e6c68f1c2177871fbd0b241a67826aea1b17be Reviewed-on: https://review.haiku-os.org/c/haiku/+/2738 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
4814d0aa44
commit
406d14d4ce
@@ -1,6 +1,13 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "BPlusTree.h"
|
||||
|
||||
void bplustree_short_block::SwapEndian()
|
||||
|
||||
void
|
||||
bplustree_short_block::SwapEndian()
|
||||
{
|
||||
bb_magic = B_BENDIAN_TO_HOST_INT32(bb_magic);
|
||||
bb_level = B_BENDIAN_TO_HOST_INT16(bb_level);
|
||||
@@ -10,7 +17,8 @@ void bplustree_short_block::SwapEndian()
|
||||
}
|
||||
|
||||
|
||||
void bplustree_long_block::SwapEndian()
|
||||
void
|
||||
bplustree_long_block::SwapEndian()
|
||||
{
|
||||
bb_magic = B_BENDIAN_TO_HOST_INT32(bb_magic);
|
||||
bb_level = B_BENDIAN_TO_HOST_INT16(bb_level);
|
||||
@@ -20,70 +28,100 @@ void bplustree_long_block::SwapEndian()
|
||||
}
|
||||
|
||||
|
||||
void xfs_alloc_rec::SwapEndian()
|
||||
void
|
||||
xfs_alloc_rec::SwapEndian()
|
||||
{
|
||||
ar_startblock = B_BENDIAN_TO_HOST_INT32(ar_startblock);
|
||||
ar_blockcount = B_BENDIAN_TO_HOST_INT32(ar_blockcount);
|
||||
}
|
||||
|
||||
|
||||
uint32 BPlusTree::BlockSize(){
|
||||
uint32
|
||||
BPlusTree::BlockSize()
|
||||
{
|
||||
return fVolume.SuperBlock().BlockSize();
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::RecordSize(){
|
||||
int
|
||||
BPlusTree::RecordSize()
|
||||
{
|
||||
if (fRecType == ALLOC_FLAG)
|
||||
return XFS_ALLOC_REC_SIZE;
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::MaxRecords(bool leaf){
|
||||
int
|
||||
BPlusTree::MaxRecords(bool leaf)
|
||||
{
|
||||
int blockLen = BlockSize();
|
||||
|
||||
|
||||
if (fPtrType == SHORT_BLOCK_FLAG)
|
||||
blockLen - XFS_BTREE_SBLOCK_SIZE;
|
||||
|
||||
if (leaf){
|
||||
if (leaf) {
|
||||
if (fRecType == ALLOC_FLAG)
|
||||
return blockLen/sizeof(xfs_alloc_rec_t);
|
||||
}
|
||||
else {
|
||||
if (fKeyType) == ALLOC_FLAG){
|
||||
return blockLen/(sizeof(xfs_alloc_key_t)
|
||||
return blockLen / sizeof(xfs_alloc_rec_t);
|
||||
} else {
|
||||
if (fKeyType == ALLOC_FLAG) {
|
||||
return blockLen / (sizeof(xfs_alloc_key_t)
|
||||
+ sizeof(xfs_alloc_ptr_t));
|
||||
}
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::KeyLen(){
|
||||
if (fKeyType == ALLOC_FLAG) return XFS_ALLOC_REC_SIZE;
|
||||
int
|
||||
BPlusTree::KeyLen()
|
||||
{
|
||||
if (fKeyType == ALLOC_FLAG)
|
||||
return XFS_ALLOC_REC_SIZE;
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::BlockLen(){
|
||||
if(fPtrType == LONG_BLOCK_FLAG) return XFS_BTREE_LBLOCK_SIZE;
|
||||
else return XFS_BTREE_SBLOCK_SIZE;
|
||||
int
|
||||
BPlusTree::BlockLen()
|
||||
{
|
||||
if (fPtrType == LONG_BLOCK_FLAG)
|
||||
return XFS_BTREE_LBLOCK_SIZE;
|
||||
if (fPtrType == SHORT_BLOCK_FLAG)
|
||||
return XFS_BTREE_SBLOCK_SIZE;
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::PtrLen(){
|
||||
if(fPtrType == LONG_BLOCK_FLAG) return sizeof(uint64);
|
||||
else return sizeof(uint32);
|
||||
int
|
||||
BPlusTree::PtrLen()
|
||||
{
|
||||
if (fPtrType == LONG_BLOCK_FLAG)
|
||||
return sizeof(uint64);
|
||||
else
|
||||
return sizeof(uint32);
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::RecordOffset(int pos){
|
||||
return BlockLen() + (pos-1)*RecordSize();
|
||||
int
|
||||
BPlusTree::RecordOffset(int pos)
|
||||
{
|
||||
return BlockLen() + (pos - 1) * RecordSize();
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::KeyOffset(int pos){
|
||||
return BlockLen() + (pos-1)*KeyLen();
|
||||
int
|
||||
BPlusTree::KeyOffset(int pos)
|
||||
{
|
||||
return BlockLen() + (pos - 1) * KeyLen();
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::PtrOffset(int pos, int level){
|
||||
return BlockLen() + MaxRecords(level>0)*KeyLen() + (pos-1)*PtrLen();
|
||||
int
|
||||
BPlusTree::PtrOffset(int pos, int level)
|
||||
{
|
||||
return BlockLen() + MaxRecords(level > 0) * KeyLen()
|
||||
+ (pos - 1) * PtrLen();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BPLUS_TREE_H_
|
||||
#define _BPLUS_TREE_H_
|
||||
|
||||
@@ -11,23 +16,47 @@
|
||||
/* Header for Short Format btree */
|
||||
#define XFS_BTREE_SBLOCK_SIZE 18
|
||||
|
||||
/* Header for Long Format btree */
|
||||
#define XFS_BTREE_LBLOCK_SIZE 24
|
||||
|
||||
|
||||
/*
|
||||
* Headers are the "nodes" really and are called "blocks". The records, keys and
|
||||
* pts are calculated using helpers
|
||||
*/
|
||||
|
||||
struct bplustree_short_block {
|
||||
void SwapEndian();
|
||||
|
||||
uint32 Magic()
|
||||
{ return bb_magic; }
|
||||
|
||||
uint16 Level()
|
||||
{ return bb_level; }
|
||||
|
||||
uint16 NumRecs()
|
||||
{ return bb_numrecs; }
|
||||
|
||||
xfs_alloc_ptr_t Left()
|
||||
{ return bb_leftsib; }
|
||||
|
||||
xfs_alloc_ptr_t Right()
|
||||
{ return bb_rightsib;}
|
||||
|
||||
uint32 bb_magic;
|
||||
uint16 bb_level;
|
||||
uint16 bb_numrecs;
|
||||
uint32 bb_leftsib;
|
||||
uint32 bb_rightsib;
|
||||
}
|
||||
|
||||
|
||||
struct bplustree_long_block {
|
||||
void SwapEndian();
|
||||
|
||||
uint32 Magic()
|
||||
{ return bb_magic; }
|
||||
|
||||
|
||||
uint16 Level()
|
||||
{ return bb_level; }
|
||||
|
||||
@@ -39,43 +68,18 @@ struct bplustree_short_block {
|
||||
|
||||
xfs_alloc_ptr_t Right()
|
||||
{ return bb_rightsib;}
|
||||
}
|
||||
|
||||
|
||||
/* Header for Long Format btree */
|
||||
#define XFS_BTREE_LBLOCK_SIZE 24
|
||||
struct bplustree_long_block {
|
||||
uint32 bb_magic;
|
||||
uint16 bb_level;
|
||||
uint16 bb_numrecs;
|
||||
uint64 bb_leftsib;
|
||||
uint64 bb_rightsib;
|
||||
|
||||
void SwapEndian();
|
||||
|
||||
uint32 Magic()
|
||||
{ return bb_magic; }
|
||||
|
||||
uint16 Level()
|
||||
{ return bb_level; }
|
||||
|
||||
uint16 NumRecs()
|
||||
{ return bb_numrecs; }
|
||||
|
||||
xfs_alloc_ptr_t Left()
|
||||
{ return bb_leftsib; }
|
||||
|
||||
xfs_alloc_ptr_t Right()
|
||||
{ return bb_rightsib;}
|
||||
}
|
||||
|
||||
|
||||
/* Array of these records in the leaf node along with above headers */
|
||||
#define XFS_ALLOC_REC_SIZE 8
|
||||
typedef struct xfs_alloc_rec {
|
||||
uint32 ar_startblock;
|
||||
uint32 ar_blockcount;
|
||||
|
||||
void SwapEndian();
|
||||
|
||||
uint32 StartBlock()
|
||||
@@ -84,6 +88,9 @@ typedef struct xfs_alloc_rec {
|
||||
uint32 BlockCount()
|
||||
{ return ar_blockcount; }
|
||||
|
||||
uint32 ar_startblock;
|
||||
uint32 ar_blockcount;
|
||||
|
||||
} xfs_alloc_rec_t, xfs_alloc_key_t;
|
||||
|
||||
// Swap Endians while returning itself
|
||||
@@ -99,14 +106,17 @@ union btree_ptr {
|
||||
bplustree_short_block fShortBlock;
|
||||
}
|
||||
|
||||
|
||||
union btree_key {
|
||||
xfs_alloc_key_t fAlloc;
|
||||
}
|
||||
|
||||
|
||||
union btree_rec {
|
||||
xfs_alloc_rec_t fAlloc;
|
||||
}
|
||||
|
||||
|
||||
class BPlusTree {
|
||||
public:
|
||||
uint32 BlockSize();
|
||||
@@ -128,4 +138,6 @@ class BPlusTree {
|
||||
int fPtrType;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "Inode.h"
|
||||
|
||||
|
||||
void
|
||||
xfs_inode::SwapEndian()
|
||||
{
|
||||
di_magic = B_BENDIAN_TO_HOST_INT16(di_magic);
|
||||
di_mode = B_BENDIAN_TO_HOST_INT16(di_mode);
|
||||
di_onlink = B_BENDIAN_TO_HOST_INT16(di_onlink);
|
||||
di_uid = B_BENDIAN_TO_HOST_INT32(di_uid);
|
||||
di_gid = B_BENDIAN_TO_HOST_INT32(di_gid);
|
||||
di_nlink = B_BENDIAN_TO_HOST_INT32(di_nlink);
|
||||
di_projid = B_BENDIAN_TO_HOST_INT16(di_projid);
|
||||
di_flushiter = B_BENDIAN_TO_HOST_INT16(di_flushiter);
|
||||
di_atime.t_sec = B_BENDIAN_TO_HOST_INT32(di_atime.t_sec);
|
||||
di_atime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_atime.t_nsec);
|
||||
di_mtime.t_sec = B_BENDIAN_TO_HOST_INT32(di_mtime.t_sec);
|
||||
di_mtime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_mtime.t_nsec);
|
||||
di_ctime.t_sec = B_BENDIAN_TO_HOST_INT32(di_ctime.t_sec);
|
||||
di_ctime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_ctime.t_nsec);
|
||||
di_size = B_BENDIAN_TO_HOST_INT64(di_size);
|
||||
di_nblocks = B_BENDIAN_TO_HOST_INT64(di_nblocks);
|
||||
di_extsize = B_BENDIAN_TO_HOST_INT32(di_extsize);
|
||||
di_nextents = B_BENDIAN_TO_HOST_INT32(di_nextents);
|
||||
di_anextents = B_BENDIAN_TO_HOST_INT16(di_anextents);
|
||||
di_dmevmask = B_BENDIAN_TO_HOST_INT32(di_dmevmask);
|
||||
di_dmstate = B_BENDIAN_TO_HOST_INT16(di_dmstate);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
mode_t
|
||||
xfs_inode::Mode()
|
||||
{
|
||||
return di_mode;
|
||||
}
|
||||
|
||||
|
||||
Inode::Inode(Volume* volume, xfs_ino_t id)
|
||||
{
|
||||
fVolume = volume;
|
||||
fId = id;
|
||||
fNode = new(std::nothrow) xfs_inode_t;
|
||||
|
||||
uint16 inodeSize = volume->InodeSize();
|
||||
fBuffer = new(std::nothrow) char[inodeSize];
|
||||
|
||||
status_t status = GetFromDisk();
|
||||
if (status == B_OK) {
|
||||
status = InitCheck();
|
||||
if (status) {
|
||||
TRACE("Inode successfully read!");
|
||||
} else {
|
||||
TRACE("Inode wasn't read successfully!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
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());
|
||||
// AG relative ino #
|
||||
xfs_agblock_t agBlock = INO_TO_AGBLOCK(agInodeNo, fVolume);
|
||||
// AG relative block number
|
||||
xfs_off_t offset = INO_TO_OFFSET(fId, fVolume);
|
||||
// Offset into the block
|
||||
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_fsblock_t blockToRead =
|
||||
FSB_TO_BB(fVolume->BlockLog(), ((uint64)(agNo * agBlocks) + agBlock));
|
||||
|
||||
xfs_daddr_t readPos = blockToRead*(BBLOCKSIZE) + offset;
|
||||
|
||||
if (read_pos(fd, readPos, fBuffer, len) != len) {
|
||||
ERROR("Inode::Inode(): IO Error");
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
|
||||
memcpy(fNode, fBuffer, INODE_CORE_UNLINKED_SIZE);
|
||||
fNode->SwapEndian();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Inode::InitCheck()
|
||||
{
|
||||
return fNode->di_magic == INODE_MAGIC;
|
||||
}
|
||||
|
||||
|
||||
Inode::~Inode()
|
||||
{
|
||||
delete fBuffer;
|
||||
delete fNode;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* 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 DATA_FORK_OFFSET 0x64
|
||||
|
||||
#define INO_MASK(x) ((1ULL << (x)) - 1)
|
||||
// Gets 2^x - 1
|
||||
#define INO_TO_AGNO(id, volume) (xfs_agnumber_t)id >> (volume->AgInodeBits())
|
||||
// Gets AG number from inode number
|
||||
#define INO_TO_AGINO(id, bits) (uint32) id & INO_MASK(bits);
|
||||
// Gets the AG relative inode number
|
||||
#define INO_TO_AGBLOCK(id, volume) \
|
||||
(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()))
|
||||
// Gets the offset into the block from the inode number
|
||||
|
||||
|
||||
typedef struct xfs_timestamp
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
/*
|
||||
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();
|
||||
void DirIsV2(); //TODO
|
||||
mode_t Mode();
|
||||
void GetModificationTime();
|
||||
int8 Format(); // The format of the inode
|
||||
|
||||
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;
|
||||
|
||||
uint32 di_next_unlinked;
|
||||
} xfs_inode_t;
|
||||
|
||||
|
||||
class Inode
|
||||
{
|
||||
public:
|
||||
Inode(Volume* volume, xfs_ino_t id);
|
||||
~Inode();
|
||||
bool InitCheck();
|
||||
bool IsDirectory() const
|
||||
{ return S_ISDIR(Mode()); }
|
||||
|
||||
bool IsFile() const
|
||||
{ return S_ISREG(Mode()); }
|
||||
|
||||
bool IsSymLink() const
|
||||
{ return S_ISLNK(Mode()); }
|
||||
|
||||
mode_t Mode() const { return fNode->Mode(); }
|
||||
|
||||
Volume* GetVolume() { return fVolume;}
|
||||
|
||||
int8 Format() { return fNode->Format(); }
|
||||
|
||||
bool IsLocal() { return Format() == XFS_DINODE_FMT_LOCAL; }
|
||||
|
||||
#if 0
|
||||
int32 Flags() const { return fNode->Flags(); }
|
||||
|
||||
off_t Size() const { return fNode->Size(); }
|
||||
|
||||
void GetChangeTime(xfs_timestamp_t *stamp) const
|
||||
{ fNode.GetChangeTime(stamp, fHasExtraAttributes); }
|
||||
|
||||
void GetModificationTime(xfs_timestamp_t *stamp) const
|
||||
{ fNode.GetModificationTime(stamp,
|
||||
fHasExtraAttributes); }
|
||||
|
||||
void GetCreationTime(xfs_timestamp_t *stamp) const
|
||||
{ fNode.GetCreationTime(stamp,
|
||||
fHasExtraAttributes); }
|
||||
|
||||
void GetAccessTime(xfs_timestamp_t *stamp) const
|
||||
{ fNode.GetAccessTime(stamp, fHasExtraAttributes); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
status_t GetFromDisk();
|
||||
xfs_inode_t* fNode;
|
||||
xfs_ino_t fId;
|
||||
Volume* fVolume;
|
||||
char* fBuffer; // Contains the disk inode in BE format
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,13 +2,13 @@ SubDir HAIKU_TOP src add-ons kernel file_systems xfs ;
|
||||
|
||||
# set some additional defines
|
||||
{
|
||||
local defines =
|
||||
XFS_DEBUGGER_COMMANDS
|
||||
;
|
||||
local defines =
|
||||
XFS_DEBUGGER_COMMANDS
|
||||
;
|
||||
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) ;
|
||||
SubDirC++Flags $(defines) ;
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) ;
|
||||
SubDirC++Flags $(defines) ;
|
||||
}
|
||||
|
||||
UsePrivateHeaders [ FDirName kernel util ] ;
|
||||
@@ -20,23 +20,23 @@ DEFINES += DEBUG_APP="\\\"xfs\\\"" ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
||||
|
||||
local xfsSources =
|
||||
DeviceOpener.cpp
|
||||
xfs.cpp
|
||||
Volume.cpp
|
||||
kernel_cpp.cpp
|
||||
kernel_interface.cpp
|
||||
;
|
||||
Inode.cpp
|
||||
kernel_cpp.cpp
|
||||
kernel_interface.cpp
|
||||
Volume.cpp
|
||||
xfs.cpp
|
||||
;
|
||||
KernelAddon xfs :
|
||||
$(xfsSources)
|
||||
:
|
||||
$(xfsSources)
|
||||
:
|
||||
libuuid_kernel.a
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles $(xfsSources) ]
|
||||
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems xfs ] ;
|
||||
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems xfs ] ;
|
||||
|
||||
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 ] ;
|
||||
@@ -1,14 +1,18 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _VOLUME_H_
|
||||
#define _VOLUME_H_
|
||||
|
||||
#include "xfs.h"
|
||||
|
||||
extern fs_volume_ops gxfsVolumeOps;
|
||||
|
||||
/* Converting the FS Blocks to Basic Blocks */
|
||||
#define FSBSHIFT(fsBlockLog) (fsBlockLog - BBLOCKLOG);
|
||||
#define FSB_TO_BB(fsBlockLog, x) x << FSBSHIFT(fsBlockLog);
|
||||
|
||||
enum volume_flags {
|
||||
VOLUME_READ_ONLY = 0x0001
|
||||
};
|
||||
@@ -38,15 +42,35 @@ public:
|
||||
XfsSuperBlock& SuperBlock() { return fSuperBlock; }
|
||||
int Device() const { return fDevice; }
|
||||
|
||||
static status_t Identify(int fd, XfsSuperBlock *superBlock);
|
||||
static status_t Identify(int fd, XfsSuperBlock *superBlock);
|
||||
|
||||
uint32 BlockSize() { return fSuperBlock.BlockSize(); }
|
||||
|
||||
uint8 BlockLog() { return fSuperBlock.BlockLog(); }
|
||||
|
||||
uint32 DirBlockSize()
|
||||
{ return fSuperBlock.DirBlockSize(); }
|
||||
|
||||
uint8 AgInodeBits()
|
||||
{ return fSuperBlock.AgInodeBits(); }
|
||||
|
||||
uint8 AgBlocksLog()
|
||||
{ return fSuperBlock.AgBlocksLog(); }
|
||||
|
||||
uint8 InodesPerBlkLog()
|
||||
{ return fSuperBlock.InodesPerBlkLog(); }
|
||||
|
||||
off_t Root() const { return fSuperBlock.Root(); }
|
||||
|
||||
uint16 InodeSize() { return fSuperBlock.InodeSize(); }
|
||||
|
||||
xfs_agnumber_t AgCount() { return fSuperBlock.AgCount(); }
|
||||
|
||||
xfs_agblock_t AgBlocks() { return fSuperBlock.AgBlocks(); }
|
||||
|
||||
#if 0
|
||||
off_t NumBlocks() const
|
||||
{ return fSuperBlock.NumBlocks(); }
|
||||
|
||||
off_t Root() const { return fSuperBlock.rootino; }
|
||||
|
||||
static status_t Identify(int fd, SuperBlock *superBlock);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -54,7 +78,7 @@ protected:
|
||||
int fDevice;
|
||||
XfsSuperBlock fSuperBlock;
|
||||
char fName[32]; /* filesystem name */
|
||||
|
||||
|
||||
uint32 fDeviceBlockSize;
|
||||
mutex fLock;
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ extern "C"
|
||||
#include <NodeMonitor.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <TypeConstants.h>
|
||||
#include <sys/stat.h>
|
||||
#endif // !FS_SHELL
|
||||
|
||||
#endif // _SYSTEM_DEPENDENCIES
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "xfs.h"
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
bool
|
||||
XfsSuperBlock::IsValid()
|
||||
{
|
||||
if (sb_magicnum != XFS_SB_MAGIC) return false;
|
||||
if (sb_magicnum != XFS_SB_MAGIC)
|
||||
return false;
|
||||
|
||||
if (BBLOCKSIZE > sb_blocksize){
|
||||
if (BBLOCKSIZE > sb_blocksize) {
|
||||
ERROR("Basic block is less than 512 bytes!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,6 +28,41 @@ XfsSuperBlock::BlockSize()
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::BlockLog()
|
||||
{
|
||||
return sb_blocklog;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
XfsSuperBlock::DirBlockSize()
|
||||
{
|
||||
return BlockSize() * (1 << sb_dirblklog);
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::AgInodeBits()
|
||||
{
|
||||
return AgBlocksLog() + InodesPerBlkLog();
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::InodesPerBlkLog()
|
||||
{
|
||||
return sb_inopblog;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::AgBlocksLog()
|
||||
{
|
||||
return sb_agblklog;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
XfsSuperBlock::Size()
|
||||
{
|
||||
@@ -34,6 +70,13 @@ XfsSuperBlock::Size()
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
XfsSuperBlock::InodeSize()
|
||||
{
|
||||
return sb_inodesize;
|
||||
}
|
||||
|
||||
|
||||
xfs_rfsblock_t
|
||||
XfsSuperBlock::TotalBlocks()
|
||||
{
|
||||
@@ -69,6 +112,27 @@ XfsSuperBlock::Name()
|
||||
}
|
||||
|
||||
|
||||
xfs_ino_t
|
||||
XfsSuperBlock::Root() const
|
||||
{
|
||||
return sb_rootino;
|
||||
}
|
||||
|
||||
|
||||
xfs_agnumber_t
|
||||
XfsSuperBlock::AgCount()
|
||||
{
|
||||
return sb_agcount;
|
||||
}
|
||||
|
||||
|
||||
xfs_agblock_t
|
||||
XfsSuperBlock::AgBlocks()
|
||||
{
|
||||
return sb_agblocks;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XfsSuperBlock::SwapEndian()
|
||||
{
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* 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.
|
||||
*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_
|
||||
@@ -15,10 +17,15 @@ except for log items which are formatted in host order.
|
||||
#include "system_dependencies.h"
|
||||
#include "xfs_types.h"
|
||||
|
||||
|
||||
extern fs_vnode_ops gxfsVnodeOps;
|
||||
extern fs_volume_ops gxfsVolumeOps;
|
||||
|
||||
|
||||
#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 BBLOCKSIZE 1 << BBLOCKLOG /* The size of a basic block should be 512 */
|
||||
|
||||
|
||||
/* Version 4 superblock definition */
|
||||
@@ -29,12 +36,21 @@ 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();
|
||||
|
||||
private:
|
||||
|
||||
@@ -85,11 +101,12 @@ private:
|
||||
uint32 sb_features2;
|
||||
};
|
||||
|
||||
/*
|
||||
These flags indicate features introduced over time.
|
||||
|
||||
If the lower nibble of sb_versionnum >=4 then the following features are
|
||||
checked. If it's equal to 5, it's version 5.
|
||||
/*
|
||||
*These flags indicate features introduced over time.
|
||||
*
|
||||
*If the lower nibble of sb_versionnum >=4 then the following features are
|
||||
*checked. If it's equal to 5, it's version 5.
|
||||
*/
|
||||
|
||||
#define XFS_SB_VERSION_ATTRBIT 0x0010
|
||||
@@ -104,6 +121,7 @@ private:
|
||||
#define XFS_SB_VERSION_DIRV2BIT 0x2000
|
||||
#define XFS_SB_VERSION_MOREBITSBIT 0x4000
|
||||
|
||||
|
||||
/*
|
||||
Superblock quota flags - sb_qflags
|
||||
*/
|
||||
@@ -119,65 +137,24 @@ Superblock quota flags - sb_qflags
|
||||
#define XFS_PQUOTA_ENFD 0x0200
|
||||
#define XFS_PQUOTA_CHKD 0x0400
|
||||
|
||||
|
||||
/*
|
||||
Superblock flags - sb_flags
|
||||
*/
|
||||
#define XFS_SBF_READONLY 0x1
|
||||
|
||||
|
||||
/*
|
||||
Extended v4 Superblock flags - sb_features2
|
||||
*/
|
||||
|
||||
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT \
|
||||
0x0001 /*update global free space \
|
||||
and inode on clean unmount*/
|
||||
#define XFS_SB_VERSION2_ATTR2BIT \
|
||||
0x0002 /* optimises the inode layout of ext-attr */
|
||||
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x0001
|
||||
// update global free space and inode on clean unmount
|
||||
#define XFS_SB_VERSION2_ATTR2BIT 0x0002
|
||||
// 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
|
||||
|
||||
|
||||
/* AG Free Space Block */
|
||||
|
||||
/*
|
||||
index 0 for free space B+Tree indexed by block number
|
||||
index 1 for free space B+Tree indexed by extent size
|
||||
|
||||
Version 5 has XFS_BT_NUM_AGF defined as 3. This is because the index 2 is
|
||||
for reverse-mapped B+Trees. I have spare0/1 defined here instead.
|
||||
*/
|
||||
|
||||
#define XFS_BTNUM_AGF 2
|
||||
#define XFS_AG_MAGICNUM 0x58414746
|
||||
class AGFreeSpace{
|
||||
public:
|
||||
//TODO:
|
||||
void SwapEndian();
|
||||
private:
|
||||
uint32 magicnum;
|
||||
uint32 versionnum; // should be set to 1
|
||||
uint32 seqno; // defines the ag number for the sector
|
||||
uint32 length; // size of ag in fs blocks
|
||||
uint32 roots[XFS_BTNUM_AGF]; // roots of trees
|
||||
uint32 spare0; //spare
|
||||
uint32 levels[XFS_BTNUM_AGF]; // tree levels
|
||||
uint32 spare1; //spare
|
||||
uint32 flfirst; // index to first free list block
|
||||
uint32 fllast; // index to last free list block
|
||||
uint32 flcount; // number of blocks in freelist
|
||||
uint32 freeblks; // current num of free blocks in AG
|
||||
uint32 longest; // no.of blocks of longest
|
||||
// contiguous free space in the AG
|
||||
|
||||
/*number of blocks used for the free space B+trees.
|
||||
This is only used if the XFS_SB_VERSION2_LAZYSBCOUNTBIT
|
||||
bit is set in sb_features2
|
||||
*/
|
||||
|
||||
uint32 btreeblks;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,10 +39,10 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||
|
||||
local xfsSource =
|
||||
DeviceOpener.cpp
|
||||
xfs.cpp
|
||||
Volume.cpp
|
||||
Inode.cpp
|
||||
kernel_interface.cpp
|
||||
Volume.cpp
|
||||
xfs.cpp
|
||||
;
|
||||
|
||||
BuildPlatformMergeObject <build>xfs_shell.o : $(xfsSource) ;
|
||||
|
||||
Reference in New Issue
Block a user