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"
|
#include "BPlusTree.h"
|
||||||
|
|
||||||
void bplustree_short_block::SwapEndian()
|
|
||||||
|
void
|
||||||
|
bplustree_short_block::SwapEndian()
|
||||||
{
|
{
|
||||||
bb_magic = B_BENDIAN_TO_HOST_INT32(bb_magic);
|
bb_magic = B_BENDIAN_TO_HOST_INT32(bb_magic);
|
||||||
bb_level = B_BENDIAN_TO_HOST_INT16(bb_level);
|
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_magic = B_BENDIAN_TO_HOST_INT32(bb_magic);
|
||||||
bb_level = B_BENDIAN_TO_HOST_INT16(bb_level);
|
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_startblock = B_BENDIAN_TO_HOST_INT32(ar_startblock);
|
||||||
ar_blockcount = B_BENDIAN_TO_HOST_INT32(ar_blockcount);
|
ar_blockcount = B_BENDIAN_TO_HOST_INT32(ar_blockcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32 BPlusTree::BlockSize(){
|
uint32
|
||||||
|
BPlusTree::BlockSize()
|
||||||
|
{
|
||||||
return fVolume.SuperBlock().BlockSize();
|
return fVolume.SuperBlock().BlockSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BPlusTree::RecordSize(){
|
int
|
||||||
|
BPlusTree::RecordSize()
|
||||||
|
{
|
||||||
if (fRecType == ALLOC_FLAG)
|
if (fRecType == ALLOC_FLAG)
|
||||||
return XFS_ALLOC_REC_SIZE;
|
return XFS_ALLOC_REC_SIZE;
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BPlusTree::MaxRecords(bool leaf){
|
int
|
||||||
|
BPlusTree::MaxRecords(bool leaf)
|
||||||
|
{
|
||||||
int blockLen = BlockSize();
|
int blockLen = BlockSize();
|
||||||
|
|
||||||
if (fPtrType == SHORT_BLOCK_FLAG)
|
if (fPtrType == SHORT_BLOCK_FLAG)
|
||||||
blockLen - XFS_BTREE_SBLOCK_SIZE;
|
blockLen - XFS_BTREE_SBLOCK_SIZE;
|
||||||
|
|
||||||
if (leaf){
|
if (leaf) {
|
||||||
if (fRecType == ALLOC_FLAG)
|
if (fRecType == ALLOC_FLAG)
|
||||||
return blockLen/sizeof(xfs_alloc_rec_t);
|
return blockLen / sizeof(xfs_alloc_rec_t);
|
||||||
}
|
} else {
|
||||||
else {
|
if (fKeyType == ALLOC_FLAG) {
|
||||||
if (fKeyType) == ALLOC_FLAG){
|
return blockLen / (sizeof(xfs_alloc_key_t)
|
||||||
return blockLen/(sizeof(xfs_alloc_key_t)
|
|
||||||
+ sizeof(xfs_alloc_ptr_t));
|
+ sizeof(xfs_alloc_ptr_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BPlusTree::KeyLen(){
|
int
|
||||||
if (fKeyType == ALLOC_FLAG) return XFS_ALLOC_REC_SIZE;
|
BPlusTree::KeyLen()
|
||||||
|
{
|
||||||
|
if (fKeyType == ALLOC_FLAG)
|
||||||
|
return XFS_ALLOC_REC_SIZE;
|
||||||
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BPlusTree::BlockLen(){
|
int
|
||||||
if(fPtrType == LONG_BLOCK_FLAG) return XFS_BTREE_LBLOCK_SIZE;
|
BPlusTree::BlockLen()
|
||||||
else return XFS_BTREE_SBLOCK_SIZE;
|
{
|
||||||
|
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(){
|
int
|
||||||
if(fPtrType == LONG_BLOCK_FLAG) return sizeof(uint64);
|
BPlusTree::PtrLen()
|
||||||
else return sizeof(uint32);
|
{
|
||||||
|
if (fPtrType == LONG_BLOCK_FLAG)
|
||||||
|
return sizeof(uint64);
|
||||||
|
else
|
||||||
|
return sizeof(uint32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BPlusTree::RecordOffset(int pos){
|
int
|
||||||
return BlockLen() + (pos-1)*RecordSize();
|
BPlusTree::RecordOffset(int pos)
|
||||||
|
{
|
||||||
|
return BlockLen() + (pos - 1) * RecordSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BPlusTree::KeyOffset(int pos){
|
int
|
||||||
return BlockLen() + (pos-1)*KeyLen();
|
BPlusTree::KeyOffset(int pos)
|
||||||
|
{
|
||||||
|
return BlockLen() + (pos - 1) * KeyLen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BPlusTree::PtrOffset(int pos, int level){
|
int
|
||||||
return BlockLen() + MaxRecords(level>0)*KeyLen() + (pos-1)*PtrLen();
|
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_
|
#ifndef _BPLUS_TREE_H_
|
||||||
#define _BPLUS_TREE_H_
|
#define _BPLUS_TREE_H_
|
||||||
|
|
||||||
@@ -11,23 +16,47 @@
|
|||||||
/* Header for Short Format btree */
|
/* Header for Short Format btree */
|
||||||
#define XFS_BTREE_SBLOCK_SIZE 18
|
#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
|
* Headers are the "nodes" really and are called "blocks". The records, keys and
|
||||||
* pts are calculated using helpers
|
* pts are calculated using helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct bplustree_short_block {
|
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;
|
uint32 bb_magic;
|
||||||
uint16 bb_level;
|
uint16 bb_level;
|
||||||
uint16 bb_numrecs;
|
uint16 bb_numrecs;
|
||||||
uint32 bb_leftsib;
|
uint32 bb_leftsib;
|
||||||
uint32 bb_rightsib;
|
uint32 bb_rightsib;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct bplustree_long_block {
|
||||||
void SwapEndian();
|
void SwapEndian();
|
||||||
|
|
||||||
uint32 Magic()
|
uint32 Magic()
|
||||||
{ return bb_magic; }
|
{ return bb_magic; }
|
||||||
|
|
||||||
uint16 Level()
|
uint16 Level()
|
||||||
{ return bb_level; }
|
{ return bb_level; }
|
||||||
|
|
||||||
@@ -39,43 +68,18 @@ struct bplustree_short_block {
|
|||||||
|
|
||||||
xfs_alloc_ptr_t Right()
|
xfs_alloc_ptr_t Right()
|
||||||
{ return bb_rightsib;}
|
{ return bb_rightsib;}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Header for Long Format btree */
|
|
||||||
#define XFS_BTREE_LBLOCK_SIZE 24
|
|
||||||
struct bplustree_long_block {
|
|
||||||
uint32 bb_magic;
|
uint32 bb_magic;
|
||||||
uint16 bb_level;
|
uint16 bb_level;
|
||||||
uint16 bb_numrecs;
|
uint16 bb_numrecs;
|
||||||
uint64 bb_leftsib;
|
uint64 bb_leftsib;
|
||||||
uint64 bb_rightsib;
|
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 */
|
/* Array of these records in the leaf node along with above headers */
|
||||||
#define XFS_ALLOC_REC_SIZE 8
|
#define XFS_ALLOC_REC_SIZE 8
|
||||||
typedef struct xfs_alloc_rec {
|
typedef struct xfs_alloc_rec {
|
||||||
uint32 ar_startblock;
|
|
||||||
uint32 ar_blockcount;
|
|
||||||
|
|
||||||
void SwapEndian();
|
void SwapEndian();
|
||||||
|
|
||||||
uint32 StartBlock()
|
uint32 StartBlock()
|
||||||
@@ -84,6 +88,9 @@ typedef struct xfs_alloc_rec {
|
|||||||
uint32 BlockCount()
|
uint32 BlockCount()
|
||||||
{ return ar_blockcount; }
|
{ return ar_blockcount; }
|
||||||
|
|
||||||
|
uint32 ar_startblock;
|
||||||
|
uint32 ar_blockcount;
|
||||||
|
|
||||||
} xfs_alloc_rec_t, xfs_alloc_key_t;
|
} xfs_alloc_rec_t, xfs_alloc_key_t;
|
||||||
|
|
||||||
// Swap Endians while returning itself
|
// Swap Endians while returning itself
|
||||||
@@ -99,14 +106,17 @@ union btree_ptr {
|
|||||||
bplustree_short_block fShortBlock;
|
bplustree_short_block fShortBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
union btree_key {
|
union btree_key {
|
||||||
xfs_alloc_key_t fAlloc;
|
xfs_alloc_key_t fAlloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
union btree_rec {
|
union btree_rec {
|
||||||
xfs_alloc_rec_t fAlloc;
|
xfs_alloc_rec_t fAlloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class BPlusTree {
|
class BPlusTree {
|
||||||
public:
|
public:
|
||||||
uint32 BlockSize();
|
uint32 BlockSize();
|
||||||
@@ -128,4 +138,6 @@ class BPlusTree {
|
|||||||
int fPtrType;
|
int fPtrType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#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
|
# set some additional defines
|
||||||
{
|
{
|
||||||
local defines =
|
local defines =
|
||||||
XFS_DEBUGGER_COMMANDS
|
XFS_DEBUGGER_COMMANDS
|
||||||
;
|
;
|
||||||
|
|
||||||
defines = [ FDefines $(defines) ] ;
|
defines = [ FDefines $(defines) ] ;
|
||||||
SubDirCcFlags $(defines) ;
|
SubDirCcFlags $(defines) ;
|
||||||
SubDirC++Flags $(defines) ;
|
SubDirC++Flags $(defines) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName kernel util ] ;
|
UsePrivateHeaders [ FDirName kernel util ] ;
|
||||||
@@ -20,23 +20,23 @@ DEFINES += DEBUG_APP="\\\"xfs\\\"" ;
|
|||||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
||||||
|
|
||||||
local xfsSources =
|
local xfsSources =
|
||||||
DeviceOpener.cpp
|
Inode.cpp
|
||||||
xfs.cpp
|
kernel_cpp.cpp
|
||||||
Volume.cpp
|
kernel_interface.cpp
|
||||||
kernel_cpp.cpp
|
Volume.cpp
|
||||||
kernel_interface.cpp
|
xfs.cpp
|
||||||
;
|
;
|
||||||
KernelAddon xfs :
|
KernelAddon xfs :
|
||||||
$(xfsSources)
|
$(xfsSources)
|
||||||
:
|
:
|
||||||
libuuid_kernel.a
|
libuuid_kernel.a
|
||||||
;
|
;
|
||||||
|
|
||||||
SEARCH on [ FGristFiles $(xfsSources) ]
|
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 ]
|
SEARCH on [ FGristFiles DeviceOpener.cpp ]
|
||||||
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
|
= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
|
||||||
|
|
||||||
SEARCH on [ FGristFiles kernel_cpp.cpp ]
|
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]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _VOLUME_H_
|
#ifndef _VOLUME_H_
|
||||||
#define _VOLUME_H_
|
#define _VOLUME_H_
|
||||||
|
|
||||||
#include "xfs.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 {
|
enum volume_flags {
|
||||||
VOLUME_READ_ONLY = 0x0001
|
VOLUME_READ_ONLY = 0x0001
|
||||||
};
|
};
|
||||||
@@ -38,15 +42,35 @@ public:
|
|||||||
XfsSuperBlock& SuperBlock() { return fSuperBlock; }
|
XfsSuperBlock& SuperBlock() { return fSuperBlock; }
|
||||||
int Device() const { return fDevice; }
|
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
|
#if 0
|
||||||
off_t NumBlocks() const
|
off_t NumBlocks() const
|
||||||
{ return fSuperBlock.NumBlocks(); }
|
{ return fSuperBlock.NumBlocks(); }
|
||||||
|
|
||||||
off_t Root() const { return fSuperBlock.rootino; }
|
|
||||||
|
|
||||||
static status_t Identify(int fd, SuperBlock *superBlock);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -54,7 +78,7 @@ protected:
|
|||||||
int fDevice;
|
int fDevice;
|
||||||
XfsSuperBlock fSuperBlock;
|
XfsSuperBlock fSuperBlock;
|
||||||
char fName[32]; /* filesystem name */
|
char fName[32]; /* filesystem name */
|
||||||
|
|
||||||
uint32 fDeviceBlockSize;
|
uint32 fDeviceBlockSize;
|
||||||
mutex fLock;
|
mutex fLock;
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ extern "C"
|
|||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#endif // !FS_SHELL
|
#endif // !FS_SHELL
|
||||||
|
|
||||||
#endif // _SYSTEM_DEPENDENCIES
|
#endif // _SYSTEM_DEPENDENCIES
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xfs.h"
|
#include "xfs.h"
|
||||||
|
|
||||||
@@ -9,13 +9,14 @@
|
|||||||
bool
|
bool
|
||||||
XfsSuperBlock::IsValid()
|
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!");
|
ERROR("Basic block is less than 512 bytes!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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
|
uint32
|
||||||
XfsSuperBlock::Size()
|
XfsSuperBlock::Size()
|
||||||
{
|
{
|
||||||
@@ -34,6 +70,13 @@ XfsSuperBlock::Size()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16
|
||||||
|
XfsSuperBlock::InodeSize()
|
||||||
|
{
|
||||||
|
return sb_inodesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
xfs_rfsblock_t
|
xfs_rfsblock_t
|
||||||
XfsSuperBlock::TotalBlocks()
|
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
|
void
|
||||||
XfsSuperBlock::SwapEndian()
|
XfsSuperBlock::SwapEndian()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Important:
|
*Important:
|
||||||
All fields in XFS metadata structures are in big-endian byte order
|
*All fields in XFS metadata structures are in big-endian byte order
|
||||||
except for log items which are formatted in host order.
|
*except for log items which are formatted in host order.
|
||||||
|
*
|
||||||
|
*This file contains all global structure definitions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _XFS_SB_H_
|
#ifndef _XFS_SB_H_
|
||||||
@@ -15,10 +17,15 @@ except for log items which are formatted in host order.
|
|||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
#include "xfs_types.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_MAGIC 0x58465342 /* Identifies XFS. "XFSB" */
|
||||||
#define XFS_SB_MAXSIZE 512
|
#define XFS_SB_MAXSIZE 512
|
||||||
#define BBLOCKLOG 9 /* Log of block size should be 9 */
|
#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 */
|
/* Version 4 superblock definition */
|
||||||
@@ -29,12 +36,21 @@ public:
|
|||||||
bool IsValid();
|
bool IsValid();
|
||||||
char* Name();
|
char* Name();
|
||||||
uint32 BlockSize();
|
uint32 BlockSize();
|
||||||
|
uint8 BlockLog();
|
||||||
|
uint32 DirBlockSize(); // maximum 65536
|
||||||
|
uint8 AgInodeBits();
|
||||||
|
uint8 InodesPerBlkLog();
|
||||||
|
uint8 AgBlocksLog();
|
||||||
xfs_rfsblock_t TotalBlocks();
|
xfs_rfsblock_t TotalBlocks();
|
||||||
xfs_rfsblock_t TotalBlocksWithLog();
|
xfs_rfsblock_t TotalBlocksWithLog();
|
||||||
uint64 FreeBlocks();
|
uint64 FreeBlocks();
|
||||||
uint64 UsedBlocks();
|
uint64 UsedBlocks();
|
||||||
uint32 Size();
|
uint32 Size();
|
||||||
|
uint16 InodeSize();
|
||||||
void SwapEndian();
|
void SwapEndian();
|
||||||
|
xfs_ino_t Root() const;
|
||||||
|
xfs_agnumber_t AgCount();
|
||||||
|
xfs_agblock_t AgBlocks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -85,11 +101,12 @@ private:
|
|||||||
uint32 sb_features2;
|
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
|
#define XFS_SB_VERSION_ATTRBIT 0x0010
|
||||||
@@ -104,6 +121,7 @@ private:
|
|||||||
#define XFS_SB_VERSION_DIRV2BIT 0x2000
|
#define XFS_SB_VERSION_DIRV2BIT 0x2000
|
||||||
#define XFS_SB_VERSION_MOREBITSBIT 0x4000
|
#define XFS_SB_VERSION_MOREBITSBIT 0x4000
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Superblock quota flags - sb_qflags
|
Superblock quota flags - sb_qflags
|
||||||
*/
|
*/
|
||||||
@@ -119,65 +137,24 @@ Superblock quota flags - sb_qflags
|
|||||||
#define XFS_PQUOTA_ENFD 0x0200
|
#define XFS_PQUOTA_ENFD 0x0200
|
||||||
#define XFS_PQUOTA_CHKD 0x0400
|
#define XFS_PQUOTA_CHKD 0x0400
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Superblock flags - sb_flags
|
Superblock flags - sb_flags
|
||||||
*/
|
*/
|
||||||
#define XFS_SBF_READONLY 0x1
|
#define XFS_SBF_READONLY 0x1
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Extended v4 Superblock flags - sb_features2
|
Extended v4 Superblock flags - sb_features2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT \
|
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x0001
|
||||||
0x0001 /*update global free space \
|
// update global free space and inode on clean unmount
|
||||||
and inode on clean unmount*/
|
#define XFS_SB_VERSION2_ATTR2BIT 0x0002
|
||||||
#define XFS_SB_VERSION2_ATTR2BIT \
|
// optimises the inode layout of ext-attr
|
||||||
0x0002 /* optimises the inode layout of ext-attr */
|
|
||||||
#define XFS_SB_VERSION2_PARENTBIT 0x0004 /* Parent pointers */
|
#define XFS_SB_VERSION2_PARENTBIT 0x0004 /* Parent pointers */
|
||||||
#define XFS_SB_VERSION2_PROJID32BIT 0x0008 /* 32-bit project id */
|
#define XFS_SB_VERSION2_PROJID32BIT 0x0008 /* 32-bit project id */
|
||||||
#define XFS_SB_VERSION2_CRCBIT 0x0010 /* Metadata checksumming */
|
#define XFS_SB_VERSION2_CRCBIT 0x0010 /* Metadata checksumming */
|
||||||
#define XFS_SB_VERSION2_FTYPE 0x0020
|
#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
|
#endif
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ;
|
|||||||
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||||
|
|
||||||
local xfsSource =
|
local xfsSource =
|
||||||
DeviceOpener.cpp
|
Inode.cpp
|
||||||
xfs.cpp
|
|
||||||
Volume.cpp
|
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
|
Volume.cpp
|
||||||
|
xfs.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
BuildPlatformMergeObject <build>xfs_shell.o : $(xfsSource) ;
|
BuildPlatformMergeObject <build>xfs_shell.o : $(xfsSource) ;
|
||||||
|
|||||||
Reference in New Issue
Block a user