xfs: B+Tree ExtentMap reading
We can now read all the extent maps from the leaves. This will be needed to implement the GetNext() functionality. Change-Id: Ie10b453c33bec6e6d3109743d695f86a90de45cd Reviewed-on: https://review.haiku-os.org/c/haiku/+/3119 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
parent
d9b9a94c4f
commit
b4763972bd
@ -7,122 +7,219 @@
|
||||
#include "BPlusTree.h"
|
||||
|
||||
|
||||
void
|
||||
bplustree_short_block::SwapEndian()
|
||||
TreeDirectory::TreeDirectory(Inode* inode)
|
||||
:
|
||||
fInode(inode),
|
||||
fInitStatus(B_OK),
|
||||
fRoot(NULL),
|
||||
fExtents(NULL),
|
||||
fSingleDirBlock(NULL),
|
||||
fCountOfFilledExtents(0)
|
||||
{
|
||||
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;
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
fRoot = new(std::nothrow) BlockInDataFork;
|
||||
if (fRoot == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
fSingleDirBlock = new(std::nothrow) char[fInode->DirBlockSize()];
|
||||
if (fSingleDirBlock == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy((void*)fRoot,
|
||||
DIR_DFORK_PTR(fInode->Buffer()), sizeof(BlockInDataFork));
|
||||
}
|
||||
|
||||
|
||||
TreeDirectory::~TreeDirectory()
|
||||
{
|
||||
delete fRoot;
|
||||
delete[] fExtents;
|
||||
delete fSingleDirBlock;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TreeDirectory::InitCheck()
|
||||
{
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BPlusTree::KeyLen()
|
||||
TreeDirectory::BlockLen()
|
||||
{
|
||||
if (fKeyType == ALLOC_FLAG)
|
||||
return XFS_ALLOC_REC_SIZE;
|
||||
return B_BAD_VALUE;
|
||||
return XFS_BTREE_LBLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BPlusTree::BlockLen()
|
||||
TreeKey
|
||||
TreeDirectory::GetKey(int pos)
|
||||
{
|
||||
if (fPtrType == LONG_BLOCK_FLAG)
|
||||
return XFS_BTREE_LBLOCK_SIZE;
|
||||
if (fPtrType == SHORT_BLOCK_FLAG)
|
||||
return XFS_BTREE_SBLOCK_SIZE;
|
||||
return B_BAD_VALUE;
|
||||
return BlockLen() + (pos - 1) * XFS_KEY_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BPlusTree::PtrLen()
|
||||
size_t
|
||||
TreeDirectory::KeySize()
|
||||
{
|
||||
if (fPtrType == LONG_BLOCK_FLAG)
|
||||
return sizeof(uint64);
|
||||
return XFS_KEY_SIZE;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
TreeDirectory::PtrSize()
|
||||
{
|
||||
return XFS_PTR_SIZE;
|
||||
}
|
||||
|
||||
|
||||
TreePointer*
|
||||
TreeDirectory::GetPtr(int pos, LongBlock* curLongBlock)
|
||||
{
|
||||
size_t availableSpace = fInode->GetVolume()->BlockSize() - BlockLen();
|
||||
size_t maxRecords = availableSpace / (KeySize() + PtrSize());
|
||||
size_t offsetIntoNode =
|
||||
BlockLen() + maxRecords * KeySize() + (pos - 1) * PtrSize();
|
||||
return (TreePointer*)((char*)curLongBlock + offsetIntoNode);
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
TreeDirectory::MaxRecordsPossible(size_t len)
|
||||
{
|
||||
len -= sizeof(BlockInDataFork);
|
||||
return len / (KeySize() + PtrSize());
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TreeDirectory::GetAllExtents()
|
||||
{
|
||||
xfs_extnum_t noOfExtents = fInode->DataExtentsCount();
|
||||
ExtentMapUnwrap* extentsWrapped
|
||||
= new(std::nothrow) ExtentMapUnwrap[noOfExtents];
|
||||
if (extentsWrapped == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
Volume* volume = fInode->GetVolume();
|
||||
uint16 levelsInTree = fRoot->Levels();
|
||||
|
||||
size_t lengthOfDataFork;
|
||||
if (fInode->ForkOffset() != 0)
|
||||
lengthOfDataFork = fInode->ForkOffset() << 3;
|
||||
else
|
||||
return sizeof(uint32);
|
||||
lengthOfDataFork = volume->InodeSize() - INODE_CORE_UNLINKED_SIZE;
|
||||
|
||||
TRACE("Length Of Data Fork: (%d)\n", lengthOfDataFork);
|
||||
size_t maxRecords = MaxRecordsPossible(lengthOfDataFork);
|
||||
TRACE("Maxrecords: (%d)\n", maxRecords);
|
||||
TreePointer* ptrToNode = (TreePointer*)
|
||||
((char*)DIR_DFORK_PTR(fInode->Buffer())
|
||||
+ sizeof(BlockInDataFork) + maxRecords*KeySize());
|
||||
|
||||
size_t len = volume->BlockSize();
|
||||
char node[len];
|
||||
// This isn't for a directory block but for one of the tree nodes
|
||||
|
||||
TRACE("levels:(%d)\n", levelsInTree);
|
||||
TRACE("Numrecs:(%d)\n", fRoot->NumRecords());
|
||||
|
||||
// Go down the tree by taking the leftest pointer to go to the first leaf
|
||||
uint64 fileSystemBlockNo = B_BENDIAN_TO_HOST_INT64(*ptrToNode);
|
||||
uint64 readPos = fInode->FileSystemBlockToAddr(fileSystemBlockNo);
|
||||
while (levelsInTree != 1) {
|
||||
fileSystemBlockNo = B_BENDIAN_TO_HOST_INT64(*ptrToNode);
|
||||
// The fs block that contains node at next lower level. Now read.
|
||||
readPos = fInode->FileSystemBlockToAddr(fileSystemBlockNo);
|
||||
if (read_pos(volume->Device(), readPos, node, len) != len) {
|
||||
ERROR("Extent::FillBlockBuffer(): IO Error");
|
||||
|
||||
delete[] extentsWrapped;
|
||||
extentsWrapped = NULL;
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
LongBlock* curLongBlock = (LongBlock*)node;
|
||||
ASSERT(curLongBlock->Magic() == XFS_BMAP_MAGIC);
|
||||
ptrToNode = GetPtr(1, curLongBlock);
|
||||
// Get's the first pointer. This points to next node.
|
||||
levelsInTree--;
|
||||
}
|
||||
|
||||
// Next level wil contain leaf nodes. Now Read Directory Buffer
|
||||
len = fInode->DirBlockSize();
|
||||
if (read_pos(volume->Device(), readPos, fSingleDirBlock, len)
|
||||
!= len) {
|
||||
ERROR("Extent::FillBlockBuffer(): IO Error");
|
||||
|
||||
delete[] extentsWrapped;
|
||||
extentsWrapped = NULL;
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
levelsInTree--;
|
||||
ASSERT(levelsInTree == 0);
|
||||
|
||||
// We should be at the left most leaf node.
|
||||
// This could be a multilevel node type directory
|
||||
while (1) {
|
||||
// Run till you have leaf blocks to checkout
|
||||
char* leafBuffer = fSingleDirBlock;
|
||||
ASSERT(((LongBlock*)leafBuffer)->Magic() == XFS_BMAP_MAGIC);
|
||||
uint32 offset = sizeof(LongBlock);
|
||||
int numRecs = ((LongBlock*)leafBuffer)->NumRecs();
|
||||
|
||||
for (int i = 0; i < numRecs; i++) {
|
||||
extentsWrapped[fCountOfFilledExtents].first =
|
||||
*(uint64*)(leafBuffer + offset);
|
||||
extentsWrapped[fCountOfFilledExtents].second =
|
||||
*(uint64*)(leafBuffer + offset + sizeof(uint64));
|
||||
offset += sizeof(ExtentMapUnwrap);
|
||||
fCountOfFilledExtents++;
|
||||
}
|
||||
|
||||
fileSystemBlockNo = ((LongBlock*)leafBuffer)->Right();
|
||||
TRACE("Next leaf is at: (%d)\n", fileSystemBlockNo);
|
||||
if (fileSystemBlockNo == -1)
|
||||
break;
|
||||
uint64 readPos = fInode->FileSystemBlockToAddr(fileSystemBlockNo);
|
||||
if (read_pos(volume->Device(), readPos, fSingleDirBlock, len)
|
||||
!= len) {
|
||||
ERROR("Extent::FillBlockBuffer(): IO Error");
|
||||
|
||||
delete[] extentsWrapped;
|
||||
extentsWrapped = NULL;
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
}
|
||||
TRACE("Total covered: (%d)\n", fCountOfFilledExtents);
|
||||
|
||||
status_t status = UnWrapExtents(extentsWrapped);
|
||||
|
||||
delete[] extentsWrapped;
|
||||
extentsWrapped = NULL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BPlusTree::RecordOffset(int pos)
|
||||
status_t
|
||||
TreeDirectory::UnWrapExtents(ExtentMapUnwrap* extentsWrapped)
|
||||
{
|
||||
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();
|
||||
fExtents = new(std::nothrow) ExtentMapEntry[fCountOfFilledExtents];
|
||||
if (fExtents == NULL)
|
||||
return B_NO_MEMORY;
|
||||
uint64 first, second;
|
||||
|
||||
for (int i = 0; i < fCountOfFilledExtents; i++) {
|
||||
first = B_BENDIAN_TO_HOST_INT64(extentsWrapped[i].first);
|
||||
second = B_BENDIAN_TO_HOST_INT64(extentsWrapped[i].second);
|
||||
fExtents[i].br_state = first >> 63;
|
||||
fExtents[i].br_startoff = (first & MASK(63)) >> 9;
|
||||
fExtents[i].br_startblock = ((first & MASK(9)) << 43) | (second >> 21);
|
||||
fExtents[i].br_blockcount = second & MASK(21);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -5,136 +5,115 @@
|
||||
#ifndef _BPLUS_TREE_H_
|
||||
#define _BPLUS_TREE_H_
|
||||
|
||||
|
||||
#include "Extent.h"
|
||||
#include "Inode.h"
|
||||
#include "LeafDirectory.h"
|
||||
#include "Node.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
|
||||
#define XFS_BTREE_SBLOCK_SIZE 18
|
||||
// Header for Short Format btree
|
||||
#define XFS_BTREE_LBLOCK_SIZE 24
|
||||
// Header for Long Format btree
|
||||
#define XFS_KEY_SIZE sizeof(xfs_fileoff_t)
|
||||
#define XFS_PTR_SIZE sizeof(xfs_fsblock_t)
|
||||
#define XFS_BMAP_MAGIC 0x424d4150
|
||||
|
||||
|
||||
typedef xfs_fileoff_t TreeKey;
|
||||
typedef xfs_fsblock_t TreePointer;
|
||||
|
||||
|
||||
/*
|
||||
* Headers are the "nodes" really and are called "blocks". The records, keys
|
||||
* and ptrs are calculated using helpers
|
||||
* Headers(here, the LongBlock) are the "nodes" really and are called "blocks".
|
||||
* The records, keys and ptrs are calculated using helpers
|
||||
*/
|
||||
struct bplustree_short_block {
|
||||
void SwapEndian();
|
||||
struct LongBlock {
|
||||
|
||||
uint32 Magic()
|
||||
{ return bb_magic; }
|
||||
{ return B_BENDIAN_TO_HOST_INT32(bb_magic); }
|
||||
|
||||
uint16 Level()
|
||||
{ return bb_level; }
|
||||
{ return B_BENDIAN_TO_HOST_INT16(bb_level); }
|
||||
|
||||
uint16 NumRecs()
|
||||
{ return bb_numrecs; }
|
||||
{ return B_BENDIAN_TO_HOST_INT16(bb_numrecs); }
|
||||
|
||||
xfs_alloc_ptr_t Left()
|
||||
{ return bb_leftsib; }
|
||||
TreePointer Left()
|
||||
{ return B_BENDIAN_TO_HOST_INT64(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; }
|
||||
|
||||
uint16 NumRecs()
|
||||
{ return bb_numrecs; }
|
||||
|
||||
xfs_alloc_ptr_t Left()
|
||||
{ return bb_leftsib; }
|
||||
|
||||
xfs_alloc_ptr_t Right()
|
||||
{ return bb_rightsib;}
|
||||
TreePointer Right()
|
||||
{ return B_BENDIAN_TO_HOST_INT64(bb_rightsib); }
|
||||
|
||||
uint32 bb_magic;
|
||||
uint16 bb_level;
|
||||
uint16 bb_numrecs;
|
||||
uint64 bb_leftsib;
|
||||
uint64 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 {
|
||||
void SwapEndian();
|
||||
|
||||
uint32 StartBlock()
|
||||
{ return ar_startblock; }
|
||||
|
||||
uint32 BlockCount()
|
||||
{ return ar_blockcount; }
|
||||
|
||||
uint32 ar_startblock;
|
||||
uint32 ar_blockcount;
|
||||
|
||||
} xfs_alloc_rec_t, xfs_alloc_key_t;
|
||||
/* We have an array of extent records in
|
||||
* the leaf node along with above headers
|
||||
* The behaviour is very much like node directories.
|
||||
*/
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
//xfs_bmdr_block
|
||||
struct BlockInDataFork {
|
||||
uint16 Levels()
|
||||
{ return
|
||||
B_BENDIAN_TO_HOST_INT16(bb_level); }
|
||||
uint16 NumRecords()
|
||||
{ return
|
||||
B_BENDIAN_TO_HOST_INT16(bb_numrecs); }
|
||||
uint16 bb_level;
|
||||
uint16 bb_numrecs;
|
||||
};
|
||||
|
||||
|
||||
union btree_key {
|
||||
xfs_alloc_key_t fAlloc;
|
||||
}
|
||||
struct ExtentMapUnwrap {
|
||||
uint64 first;
|
||||
uint64 second;
|
||||
};
|
||||
|
||||
|
||||
union btree_rec {
|
||||
xfs_alloc_rec_t fAlloc;
|
||||
}
|
||||
|
||||
|
||||
class BPlusTree {
|
||||
/*
|
||||
* This class should handle B+Tree based directories
|
||||
*/
|
||||
class TreeDirectory {
|
||||
public:
|
||||
uint32 BlockSize();
|
||||
int RecordSize();
|
||||
int MaxRecords(bool leaf);
|
||||
int KeyLen();
|
||||
TreeDirectory(Inode* inode);
|
||||
~TreeDirectory();
|
||||
status_t InitCheck();
|
||||
status_t GetNext(char* name, size_t* length,
|
||||
xfs_ino_t* ino);
|
||||
status_t Lookup(const char* name, size_t length,
|
||||
xfs_ino_t* id);
|
||||
int EntrySize(int len) const;
|
||||
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
|
||||
size_t PtrSize();
|
||||
size_t KeySize();
|
||||
TreeKey GetKey(int pos);
|
||||
// get the pos'th key
|
||||
TreePointer* GetPtr(int pos, LongBlock* pointer);
|
||||
// get the pos'th pointer
|
||||
status_t GetAllExtents();
|
||||
size_t MaxRecordsPossible(size_t len);
|
||||
|
||||
private:
|
||||
Volume* fVolume;
|
||||
xfs_agnumber_t fAgnumber;
|
||||
btree_ptr* fRoot;
|
||||
int fRecType;
|
||||
int fKeyType;
|
||||
int fPtrType;
|
||||
}
|
||||
inline status_t UnWrapExtents(ExtentMapUnwrap* extentsWrapped);
|
||||
|
||||
private:
|
||||
Inode* fInode;
|
||||
status_t fInitStatus;
|
||||
BlockInDataFork* fRoot;
|
||||
ExtentMapEntry* fExtents;
|
||||
uint32 fCountOfFilledExtents;
|
||||
char* fSingleDirBlock;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -13,7 +13,8 @@ DirectoryIterator::DirectoryIterator(Inode* inode)
|
||||
fShortDir(NULL),
|
||||
fExtentDir(NULL),
|
||||
fLeafDir(NULL),
|
||||
fNodeDir(NULL)
|
||||
fNodeDir(NULL),
|
||||
fTreeDir(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -24,6 +25,7 @@ DirectoryIterator::~DirectoryIterator()
|
||||
delete fLeafDir;
|
||||
delete fExtentDir;
|
||||
delete fNodeDir;
|
||||
delete fTreeDir;
|
||||
}
|
||||
|
||||
|
||||
@ -75,16 +77,13 @@ DirectoryIterator::Init()
|
||||
* we can atleast still list the shortform directory
|
||||
*/
|
||||
|
||||
//TODO: Reading from extent based directories
|
||||
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
|
||||
TRACE("Iterator:GetNext: EXTENTS");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//TODO: Reading from B+Trees based directories
|
||||
if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
|
||||
TRACE("Iterator:GetNext: B+TREE");
|
||||
return B_OK;
|
||||
fTreeDir = new(std::nothrow) TreeDirectory(fInode);
|
||||
if (fTreeDir == NULL)
|
||||
return B_NO_MEMORY;
|
||||
return fTreeDir->InitCheck();
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define _DIRECTORY_H_
|
||||
|
||||
|
||||
#include "BPlusTree.h"
|
||||
#include "Extent.h"
|
||||
#include "Inode.h"
|
||||
#include "LeafDirectory.h"
|
||||
@ -38,6 +39,7 @@ private:
|
||||
LeafDirectory* fLeafDir;
|
||||
// Extent based leaf directory
|
||||
NodeDirectory* fNodeDir;
|
||||
TreeDirectory* fTreeDir;
|
||||
};
|
||||
|
||||
|
||||
|
@ -20,6 +20,7 @@ DEFINES += DEBUG_APP="\\\"xfs\\\"" ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
||||
|
||||
local xfsSources =
|
||||
BPlusTree.cpp
|
||||
DeviceOpener.cpp
|
||||
Directory.cpp
|
||||
Extent.cpp
|
||||
|
@ -39,6 +39,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||
|
||||
local xfsSource =
|
||||
BPlusTree.cpp
|
||||
DeviceOpener.cpp
|
||||
Directory.cpp
|
||||
Extent.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user