xfs: Init AG Free Space Management
Currently need to make the B+Tree for AG Free Space Management. The functions or the code for this task isn't complete. Sharing for reference. Change-Id: I1e29832b9645bd527962128a8c85b7ca24c7fd50 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2378 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
03f4263ea5
commit
eab542ef03
@@ -0,0 +1,89 @@
|
||||
#include "BPlusTree.h"
|
||||
|
||||
void bplustree_short_block::SwapEndian()
|
||||
{
|
||||
bb_magic = B_BENDIAN_TO_HOST_INT32(bb_magic);
|
||||
bb_level = B_BENDIAN_TO_HOST_INT16(bb_level);
|
||||
bb_numrecs = B_BENDIAN_TO_HOST_INT16(bb_numrecs);
|
||||
bb_leftsib = B_BENDIAN_TO_HOST_INT32(bb_leftsib);
|
||||
bb_rightsib = B_BENDIAN_TO_HOST_INT32(bb_rightsib);
|
||||
}
|
||||
|
||||
|
||||
void bplustree_long_block::SwapEndian()
|
||||
{
|
||||
bb_magic = B_BENDIAN_TO_HOST_INT32(bb_magic);
|
||||
bb_level = B_BENDIAN_TO_HOST_INT16(bb_level);
|
||||
bb_numrecs = B_BENDIAN_TO_HOST_INT16(bb_numrecs);
|
||||
bb_leftsib = B_BENDIAN_TO_HOST_INT64(bb_leftsib);
|
||||
bb_rightsib = B_BENDIAN_TO_HOST_INT64(bb_rightsib);
|
||||
}
|
||||
|
||||
|
||||
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(){
|
||||
return fVolume.SuperBlock().BlockSize();
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::RecordSize(){
|
||||
if (fRecType == ALLOC_FLAG)
|
||||
return XFS_ALLOC_REC_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::MaxRecords(bool leaf){
|
||||
int blockLen = BlockSize();
|
||||
|
||||
if (fPtrType == SHORT_BLOCK_FLAG)
|
||||
blockLen - XFS_BTREE_SBLOCK_SIZE;
|
||||
|
||||
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)
|
||||
+ sizeof(xfs_alloc_ptr_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::KeyLen(){
|
||||
if (fKeyType == ALLOC_FLAG) return XFS_ALLOC_REC_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::BlockLen(){
|
||||
if(fPtrType == LONG_BLOCK_FLAG) return XFS_BTREE_LBLOCK_SIZE;
|
||||
else return XFS_BTREE_SBLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
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::KeyOffset(int pos){
|
||||
return BlockLen() + (pos-1)*KeyLen();
|
||||
}
|
||||
|
||||
|
||||
int BPlusTree::PtrOffset(int pos, int level){
|
||||
return BlockLen() + MaxRecords(level>0)*KeyLen() + (pos-1)*PtrLen();
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
#ifndef _BPLUS_TREE_H_
|
||||
#define _BPLUS_TREE_H_
|
||||
|
||||
#include "system_dependencies.h"
|
||||
|
||||
/* Allocation B+ Tree Format */
|
||||
#define XFS_ABTB_MAGICNUM 0x41425442 // For block offset B+Tree
|
||||
#define XFS_ABTC_MAGICNUM 0x41425443 // For block count B+ Tree
|
||||
|
||||
|
||||
/* Header for Short Format btree */
|
||||
#define XFS_BTREE_SBLOCK_SIZE 18
|
||||
|
||||
/*
|
||||
* Headers are the "nodes" really and are called "blocks". The records, keys and
|
||||
* pts are calculated using helpers
|
||||
*/
|
||||
|
||||
struct bplustree_short_block {
|
||||
uint32 bb_magic;
|
||||
uint16 bb_level;
|
||||
uint16 bb_numrecs;
|
||||
uint32 bb_leftsib;
|
||||
uint32 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;}
|
||||
}
|
||||
|
||||
|
||||
/* 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()
|
||||
{ return ar_startblock; }
|
||||
|
||||
uint32 BlockCount()
|
||||
{ return ar_blockcount; }
|
||||
|
||||
} xfs_alloc_rec_t, xfs_alloc_key_t;
|
||||
|
||||
// Swap Endians while returning itself
|
||||
typedef uint32 xfs_alloc_ptr_t; // Node pointers, AG relative block pointer
|
||||
|
||||
#define ALLOC_FLAG 0x1
|
||||
|
||||
#define LONG_BLOCK_FLAG 0x1
|
||||
#define SHORT_BLOCK_FLAG 0x2
|
||||
|
||||
union btree_ptr {
|
||||
bplustree_long_block fLongBlock;
|
||||
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();
|
||||
int RecordSize();
|
||||
int MaxRecords(bool leaf);
|
||||
int KeyLen();
|
||||
int BlockLen();
|
||||
int PtrLen();
|
||||
int RecordOffset(int pos); // get the pos'th record
|
||||
int KeyOffset(int pos); // get the pos'th key
|
||||
int PtrOffset(int pos); // get the pos'th ptr
|
||||
|
||||
private:
|
||||
Volume* fVolume;
|
||||
xfs_agnumber_t fAgnumber;
|
||||
btree_ptr* fRoot;
|
||||
int fRecType;
|
||||
int fKeyType;
|
||||
int fPtrType;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -61,4 +61,4 @@ protected:
|
||||
uint32 fFlags;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,11 @@ XfsSuperBlock::IsValid()
|
||||
{
|
||||
if (sb_magicnum != XFS_SB_MAGIC) return false;
|
||||
|
||||
if (BBLOCKSIZE <= sb_blocksize){
|
||||
ERROR("Basic block is less than 512 bytes!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _XFS_SB_H_
|
||||
#define _XFS_SB_H_
|
||||
|
||||
@@ -11,7 +17,8 @@
|
||||
|
||||
#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 */
|
||||
|
||||
|
||||
/* Version 4 superblock definition */
|
||||
@@ -126,4 +133,46 @@ Superblock quota flags - sb_qflags
|
||||
#define XFS_SB_VERSION2_PROJID32BIT 0x0008 /* 32-bit project id */
|
||||
#define XFS_SB_VERSION2_CRCBIT 0x0010 /* Metadata checksumming */
|
||||
#define XFS_SB_VERSION2_FTYPE 0x0020
|
||||
#endif
|
||||
|
||||
|
||||
/* 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:
|
||||
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
|
||||
|
||||
@@ -38,4 +38,4 @@ typedef int64 xfs_fsize_t; // byte size of a file
|
||||
|
||||
// typedef unsigned char uuid_t[16];
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user