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:
CruxBox
2020-06-15 06:44:23 +00:00
committed by Adrien Destugues
parent 4814d0aa44
commit 406d14d4ce
10 changed files with 520 additions and 146 deletions
@@ -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();
}
+38 -26
View File
@@ -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;
}
+146
View File
@@ -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
+16 -16
View File
@@ -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 ] ;
+34 -10
View File
@@ -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
+70 -6
View File
@@ -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()
{
+35 -58
View File
@@ -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) ;