The file system is now almost endian-aware.

Used lazy unreadable conversion: ==, !=, == 0, != 0 are endian-safe
and don't need byte swapping.
If the platform endian differs from the one selected at compile time,
it will mount all volumes read-only for now.
Uncomment BFS_BIG_ENDIAN_ONLY in the Jamfile to build the big endian
version under x86.
No matter on what platform, the compilation defaults to build BFS as
little endian file system (see bfs_endian.h for details).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4715 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2003-09-16 21:49:22 +00:00
parent fd5b021f86
commit cb94280c6b
11 changed files with 498 additions and 432 deletions
+158 -154
View File
@@ -83,7 +83,7 @@ CachedNode::SetTo(off_t offset,bool check)
// You can only ask for nodes at valid positions - you can't // You can only ask for nodes at valid positions - you can't
// even access the b+tree header with this method (use SetToHeader() // even access the b+tree header with this method (use SetToHeader()
// instead) // instead)
if (offset > fTree->fHeader->maximum_size - fTree->fNodeSize if (offset > fTree->fHeader->MaximumSize() - fTree->fNodeSize
|| offset <= 0 || offset <= 0
|| (offset % fTree->fNodeSize) != 0) || (offset % fTree->fNodeSize) != 0)
return NULL; return NULL;
@@ -91,10 +91,10 @@ CachedNode::SetTo(off_t offset,bool check)
if (InternalSetTo(offset) != NULL && check) { if (InternalSetTo(offset) != NULL && check) {
// sanity checks (links, all_key_count) // sanity checks (links, all_key_count)
bplustree_header *header = fTree->fHeader; bplustree_header *header = fTree->fHeader;
if (!header->IsValidLink(fNode->left_link) if (!header->IsValidLink(fNode->LeftLink())
|| !header->IsValidLink(fNode->right_link) || !header->IsValidLink(fNode->RightLink())
|| !header->IsValidLink(fNode->overflow_link) || !header->IsValidLink(fNode->OverflowLink())
|| (int8 *)fNode->Values() + fNode->all_key_count * sizeof(off_t) > || (int8 *)fNode->Values() + fNode->NumKeys() * sizeof(off_t) >
(int8 *)fNode + fTree->fNodeSize) { (int8 *)fNode + fTree->fNodeSize) {
FATAL(("invalid node read from offset %Ld, inode at %Ld\n", FATAL(("invalid node read from offset %Ld, inode at %Ld\n",
offset,fTree->fStream->ID())); offset,fTree->fStream->ID()));
@@ -160,9 +160,9 @@ CachedNode::Free(Transaction *transaction,off_t offset)
// if the node is the last one in the tree, we shrink // if the node is the last one in the tree, we shrink
// the tree and file size by one node // the tree and file size by one node
off_t lastOffset = fTree->fHeader->maximum_size - fTree->fNodeSize; off_t lastOffset = fTree->fHeader->MaximumSize() - fTree->fNodeSize;
if (offset == lastOffset) { if (offset == lastOffset) {
fTree->fHeader->maximum_size = lastOffset; fTree->fHeader->maximum_size = HOST_ENDIAN_TO_BFS_INT64(lastOffset);
status_t status = fTree->fStream->SetFileSize(transaction,lastOffset); status_t status = fTree->fStream->SetFileSize(transaction,lastOffset);
if (status < B_OK) if (status < B_OK)
@@ -173,10 +173,10 @@ CachedNode::Free(Transaction *transaction,off_t offset)
// add the node to the free nodes list // add the node to the free nodes list
fNode->left_link = fTree->fHeader->free_node_pointer; fNode->left_link = fTree->fHeader->free_node_pointer;
fNode->overflow_link = BPLUSTREE_FREE; fNode->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_FREE);
if (WriteBack(transaction) == B_OK) { if (WriteBack(transaction) == B_OK) {
fTree->fHeader->free_node_pointer = offset; fTree->fHeader->free_node_pointer = HOST_ENDIAN_TO_BFS_INT64(offset);
return fTree->fCachedHeader.WriteBack(transaction); return fTree->fCachedHeader.WriteBack(transaction);
} }
return B_ERROR; return B_ERROR;
@@ -194,8 +194,8 @@ CachedNode::Allocate(Transaction *transaction, bplustree_node **_node, off_t *_o
status_t status; status_t status;
// if there are any free nodes, recycle them // if there are any free nodes, recycle them
if (SetTo(fTree->fHeader->free_node_pointer,false) != NULL) { if (SetTo(fTree->fHeader->FreeNode(), false) != NULL) {
*_offset = fTree->fHeader->free_node_pointer; *_offset = fTree->fHeader->FreeNode();
// set new free node pointer // set new free node pointer
fTree->fHeader->free_node_pointer = fNode->left_link; fTree->fHeader->free_node_pointer = fNode->left_link;
@@ -208,15 +208,15 @@ CachedNode::Allocate(Transaction *transaction, bplustree_node **_node, off_t *_o
} }
// allocate space for a new node // allocate space for a new node
Inode *stream = fTree->fStream; Inode *stream = fTree->fStream;
if ((status = stream->Append(transaction,fTree->fNodeSize)) < B_OK) if ((status = stream->Append(transaction, fTree->fNodeSize)) < B_OK)
return status; return status;
// the maximum_size has to be changed before the call to SetTo() - or // the maximum_size has to be changed before the call to SetTo() - or
// else it will fail because the requested node is out of bounds // else it will fail because the requested node is out of bounds
off_t offset = fTree->fHeader->maximum_size; off_t offset = fTree->fHeader->MaximumSize();
fTree->fHeader->maximum_size += fTree->fNodeSize; fTree->fHeader->maximum_size = HOST_ENDIAN_TO_BFS_INT64(fTree->fHeader->MaximumSize() + fTree->fNodeSize);
if (SetTo(offset,false) != NULL) { if (SetTo(offset, false) != NULL) {
*_offset = offset; *_offset = offset;
if (fTree->fCachedHeader.WriteBack(transaction) >= B_OK) { if (fTree->fCachedHeader.WriteBack(transaction) >= B_OK) {
@@ -235,7 +235,7 @@ CachedNode::WriteBack(Transaction *transaction)
if (transaction == NULL || fTree == NULL || fTree->fStream == NULL || fNode == NULL) if (transaction == NULL || fTree == NULL || fTree->fStream == NULL || fNode == NULL)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
return transaction->WriteBlocks(fBlockNumber,fBlock); return transaction->WriteBlocks(fBlockNumber, fBlock);
} }
@@ -319,19 +319,19 @@ BPlusTree::SetTo(Transaction *transaction, Inode *stream, int32 nodeSize)
fNodeSize = nodeSize; fNodeSize = nodeSize;
// initialize b+tree header // initialize b+tree header
fHeader->magic = BPLUSTREE_MAGIC; fHeader->magic = HOST_ENDIAN_TO_BFS_INT32(BPLUSTREE_MAGIC);
fHeader->node_size = fNodeSize; fHeader->node_size = HOST_ENDIAN_TO_BFS_INT32(fNodeSize);
fHeader->max_number_of_levels = 1; fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
fHeader->data_type = ModeToKeyType(stream->Mode()); fHeader->data_type = HOST_ENDIAN_TO_BFS_INT32(ModeToKeyType(stream->Mode()));
fHeader->root_node_pointer = nodeSize; fHeader->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(nodeSize);
fHeader->free_node_pointer = BPLUSTREE_NULL; fHeader->free_node_pointer = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
fHeader->maximum_size = nodeSize * 2; fHeader->maximum_size = HOST_ENDIAN_TO_BFS_INT64(nodeSize * 2);
if (fCachedHeader.WriteBack(transaction) < B_OK) if (fCachedHeader.WriteBack(transaction) < B_OK)
RETURN_ERROR(fStatus = B_ERROR); RETURN_ERROR(fStatus = B_ERROR);
// initialize b+tree root node // initialize b+tree root node
CachedNode cached(this,fHeader->root_node_pointer,false); CachedNode cached(this, fHeader->RootNode(), false);
if (cached.Node() == NULL) if (cached.Node() == NULL)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
@@ -357,14 +357,14 @@ BPlusTree::SetTo(Inode *stream)
// is header valid? // is header valid?
if (fHeader->magic != BPLUSTREE_MAGIC if (fHeader->Magic() != BPLUSTREE_MAGIC
|| fHeader->maximum_size != stream->Size() || fHeader->MaximumSize() != stream->Size()
|| (fHeader->root_node_pointer % fHeader->node_size) != 0 || (fHeader->RootNode() % fHeader->NodeSize()) != 0
|| !fHeader->IsValidLink(fHeader->root_node_pointer) || !fHeader->IsValidLink(fHeader->RootNode())
|| !fHeader->IsValidLink(fHeader->free_node_pointer)) || !fHeader->IsValidLink(fHeader->FreeNode()))
RETURN_ERROR(fStatus = B_BAD_DATA); RETURN_ERROR(fStatus = B_BAD_DATA);
fNodeSize = fHeader->node_size; fNodeSize = fHeader->NodeSize();
{ {
uint32 toMode[] = {S_STR_INDEX, S_INT_INDEX, S_UINT_INDEX, S_LONG_LONG_INDEX, uint32 toMode[] = {S_STR_INDEX, S_INT_INDEX, S_UINT_INDEX, S_LONG_LONG_INDEX,
@@ -372,8 +372,8 @@ BPlusTree::SetTo(Inode *stream)
uint32 mode = stream->Mode() & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX | S_LONG_LONG_INDEX uint32 mode = stream->Mode() & (S_STR_INDEX | S_INT_INDEX | S_UINT_INDEX | S_LONG_LONG_INDEX
| S_ULONG_LONG_INDEX | S_FLOAT_INDEX | S_DOUBLE_INDEX); | S_ULONG_LONG_INDEX | S_FLOAT_INDEX | S_DOUBLE_INDEX);
if (fHeader->data_type > BPLUSTREE_DOUBLE_TYPE if (fHeader->DataType() > BPLUSTREE_DOUBLE_TYPE
|| (stream->Mode() & S_INDEX_DIR) && toMode[fHeader->data_type] != mode || (stream->Mode() & S_INDEX_DIR) && toMode[fHeader->DataType()] != mode
|| !stream->IsContainer()) { || !stream->IsContainer()) {
D( dump_bplustree_header(fHeader); D( dump_bplustree_header(fHeader);
dump_inode(stream->Node()); dump_inode(stream->Node());
@@ -388,7 +388,7 @@ BPlusTree::SetTo(Inode *stream)
|| (stream->Mode() & S_ALLOW_DUPS) != 0; || (stream->Mode() & S_ALLOW_DUPS) != 0;
} }
CachedNode cached(this,fHeader->root_node_pointer); CachedNode cached(this, fHeader->RootNode());
RETURN_ERROR(fStatus = cached.Node() ? B_OK : B_BAD_DATA); RETURN_ERROR(fStatus = cached.Node() ? B_OK : B_BAD_DATA);
} }
@@ -406,10 +406,13 @@ BPlusTree::TypeCodeToKeyType(type_code code)
switch (code) { switch (code) {
case B_STRING_TYPE: case B_STRING_TYPE:
return BPLUSTREE_STRING_TYPE; return BPLUSTREE_STRING_TYPE;
case B_SSIZE_T_TYPE:
case B_INT32_TYPE: case B_INT32_TYPE:
return BPLUSTREE_INT32_TYPE; return BPLUSTREE_INT32_TYPE;
case B_SIZE_T_TYPE:
case B_UINT32_TYPE: case B_UINT32_TYPE:
return BPLUSTREE_UINT32_TYPE; return BPLUSTREE_UINT32_TYPE;
case B_OFF_T_TYPE:
case B_INT64_TYPE: case B_INT64_TYPE:
return BPLUSTREE_INT64_TYPE; return BPLUSTREE_INT64_TYPE;
case B_UINT64_TYPE: case B_UINT64_TYPE:
@@ -533,7 +536,7 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
if (index) if (index)
*index = 0; *index = 0;
if (next) if (next)
*next = node->overflow_link; *next = node->OverflowLink();
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
@@ -541,11 +544,11 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
int16 saveIndex = -1; int16 saveIndex = -1;
// binary search in the key array // binary search in the key array
for (int16 first = 0, last = node->all_key_count - 1; first <= last;) { for (int16 first = 0, last = node->NumKeys() - 1; first <= last;) {
uint16 i = (first + last) >> 1; uint16 i = (first + last) >> 1;
uint16 searchLength; uint16 searchLength;
uint8 *searchKey = node->KeyAt(i,&searchLength); uint8 *searchKey = node->KeyAt(i, &searchLength);
if (searchKey + searchLength + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fNodeSize if (searchKey + searchLength + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fNodeSize
|| searchLength > BPLUSTREE_MAX_KEY_LENGTH) { || searchLength > BPLUSTREE_MAX_KEY_LENGTH) {
fStream->GetVolume()->Panic(); fStream->GetVolume()->Panic();
@@ -562,7 +565,7 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
if (index) if (index)
*index = i; *index = i;
if (next) if (next)
*next = values[i]; *next = BFS_ENDIAN_TO_HOST_INT64(values[i]);
return B_OK; return B_OK;
} }
} }
@@ -570,10 +573,10 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
if (index) if (index)
*index = saveIndex; *index = saveIndex;
if (next) { if (next) {
if (saveIndex == node->all_key_count) if (saveIndex == node->NumKeys())
*next = node->overflow_link; *next = node->OverflowLink();
else else
*next = values[saveIndex]; *next = BFS_ENDIAN_TO_HOST_INT64(values[saveIndex]);
} }
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
@@ -589,13 +592,13 @@ BPlusTree::SeekDown(Stack<node_and_key> &stack, const uint8 *key, uint16 keyLeng
{ {
// set the root node to begin with // set the root node to begin with
node_and_key nodeAndKey; node_and_key nodeAndKey;
nodeAndKey.nodeOffset = fHeader->root_node_pointer; nodeAndKey.nodeOffset = fHeader->RootNode();
CachedNode cached(this); CachedNode cached(this);
bplustree_node *node; bplustree_node *node;
while ((node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) { while ((node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) {
// if we are already on leaf level, we're done // if we are already on leaf level, we're done
if (node->overflow_link == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
// node that the keyIndex is not properly set here (but it's not // node that the keyIndex is not properly set here (but it's not
// needed in the calling functions anyway)! // needed in the calling functions anyway)!
nodeAndKey.keyIndex = 0; nodeAndKey.keyIndex = 0;
@@ -623,7 +626,7 @@ BPlusTree::FindFreeDuplicateFragment(bplustree_node *node, CachedNode *cached, o
bplustree_node **_fragment, uint32 *_index) bplustree_node **_fragment, uint32 *_index)
{ {
off_t *values = node->Values(); off_t *values = node->Values();
for (int32 i = 0;i < node->all_key_count;i++) { for (int32 i = 0; i < node->NumKeys(); i++) {
// does the value link to a duplicate fragment? // does the value link to a duplicate fragment?
if (bplustree_node::LinkType(values[i]) != BPLUSTREE_DUPLICATE_FRAGMENT) if (bplustree_node::LinkType(values[i]) != BPLUSTREE_DUPLICATE_FRAGMENT)
continue; continue;
@@ -687,8 +690,8 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
// reuse it as a duplicate node // reuse it as a duplicate node
offset = bplustree_node::FragmentOffset(oldValue); offset = bplustree_node::FragmentOffset(oldValue);
memmove(duplicate->DuplicateArray(),array,(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); memmove(duplicate->DuplicateArray(), array, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
duplicate->left_link = duplicate->right_link = BPLUSTREE_NULL; duplicate->left_link = duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
array->Insert(value); array->Insert(value);
@@ -696,13 +699,13 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
// create a new duplicate node // create a new duplicate node
CachedNode cachedNewDuplicate(this); CachedNode cachedNewDuplicate(this);
bplustree_node *newDuplicate; bplustree_node *newDuplicate;
status = cachedNewDuplicate.Allocate(transaction,&newDuplicate,&offset); status = cachedNewDuplicate.Allocate(transaction, &newDuplicate, &offset);
if (status < B_OK) if (status < B_OK)
return status; return status;
// copy the array from the fragment node to the duplicate node // copy the array from the fragment node to the duplicate node
// and free the old entry (by zero'ing all values) // and free the old entry (by zero'ing all values)
newDuplicate->overflow_link = array->count; newDuplicate->overflow_link = HOST_ENDIAN_TO_BFS_INT64(array->count);
memcpy(&newDuplicate->all_key_count, &array->values[0], memcpy(&newDuplicate->all_key_count, &array->values[0],
array->count * sizeof(off_t)); array->count * sizeof(off_t));
memset(array,0,(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); memset(array,0,(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
@@ -747,7 +750,7 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
return B_BAD_DATA; return B_BAD_DATA;
} }
} while (array->count >= NUM_DUPLICATE_VALUES } while (array->count >= NUM_DUPLICATE_VALUES
&& (oldValue = duplicate->right_link) != BPLUSTREE_NULL); && (oldValue = duplicate->RightLink()) != BPLUSTREE_NULL);
if (array->count < NUM_DUPLICATE_VALUES) { if (array->count < NUM_DUPLICATE_VALUES) {
array->Insert(value); array->Insert(value);
@@ -761,8 +764,8 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
return status; return status;
// link the two nodes together // link the two nodes together
duplicate->right_link = offset; duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(offset);
newDuplicate->left_link = duplicateOffset; newDuplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(duplicateOffset);
array = newDuplicate->DuplicateArray(); array = newDuplicate->DuplicateArray();
array->count = 0; array->count = 0;
@@ -807,27 +810,27 @@ BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyL
off_t value) off_t value)
{ {
// should never happen, but who knows? // should never happen, but who knows?
if (index > node->all_key_count) if (index > node->NumKeys())
return; return;
off_t *values = node->Values(); off_t *values = node->Values();
uint16 *keyLengths = node->KeyLengths(); uint16 *keyLengths = node->KeyLengths();
uint8 *keys = node->Keys(); uint8 *keys = node->Keys();
node->all_key_count++; node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() + 1);
node->all_key_length += keyLength; node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(node->AllKeyLength() + keyLength);
off_t *newValues = node->Values(); off_t *newValues = node->Values();
uint16 *newKeyLengths = node->KeyLengths(); uint16 *newKeyLengths = node->KeyLengths();
// move values and copy new value into them // move values and copy new value into them
memmove(newValues + index + 1,values + index,sizeof(off_t) * (node->all_key_count - 1 - index)); memmove(newValues + index + 1, values + index, sizeof(off_t) * (node->NumKeys() - 1 - index));
memmove(newValues,values,sizeof(off_t) * index); memmove(newValues, values, sizeof(off_t) * index);
newValues[index] = value; newValues[index] = value;
// move and update key length index // move and update key length index
for (uint16 i = node->all_key_count;i-- > index + 1;) for (uint16 i = node->NumKeys(); i-- > index + 1;)
newKeyLengths[i] = keyLengths[i - 1] + keyLength; newKeyLengths[i] = keyLengths[i - 1] + keyLength;
memmove(newKeyLengths,keyLengths,sizeof(uint16) * index); memmove(newKeyLengths,keyLengths,sizeof(uint16) * index);
@@ -835,7 +838,7 @@ BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyL
newKeyLengths[index] = keyLength + (keyStart = index > 0 ? newKeyLengths[index - 1] : 0); newKeyLengths[index] = keyLength + (keyStart = index > 0 ? newKeyLengths[index - 1] : 0);
// move keys and copy new key into them // move keys and copy new key into them
int32 size = node->all_key_length - newKeyLengths[index]; int32 size = node->AllKeyLength() - newKeyLengths[index];
if (size > 0) if (size > 0)
memmove(keys + newKeyLengths[index],keys + newKeyLengths[index] - keyLength,size); memmove(keys + newKeyLengths[index],keys + newKeyLengths[index] - keyLength,size);
@@ -847,7 +850,7 @@ status_t
BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other, BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other,
off_t otherOffset, uint16 *_keyIndex, uint8 *key, uint16 *_keyLength, off_t *_value) off_t otherOffset, uint16 *_keyIndex, uint8 *key, uint16 *_keyLength, off_t *_value)
{ {
if (*_keyIndex > node->all_key_count + 1) if (*_keyIndex > node->NumKeys() + 1)
return B_BAD_VALUE; return B_BAD_VALUE;
uint16 *inKeyLengths = node->KeyLengths(); uint16 *inKeyLengths = node->KeyLengths();
@@ -867,7 +870,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
size_t size = fNodeSize >> 1; size_t size = fNodeSize >> 1;
int32 out,in; int32 out,in;
for (in = out = 0;in < node->all_key_count + 1;) { for (in = out = 0; in < node->NumKeys() + 1;) {
if (!bytes) if (!bytes)
bytesBefore = in > 0 ? inKeyLengths[in - 1] : 0; bytesBefore = in > 0 ? inKeyLengths[in - 1] : 0;
@@ -897,9 +900,9 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
return B_BAD_DATA; return B_BAD_DATA;
other->left_link = node->left_link; other->left_link = node->left_link;
other->right_link = nodeOffset; other->right_link = HOST_ENDIAN_TO_BFS_INT64(nodeOffset);
other->all_key_length = bytes + bytesBefore + bytesAfter; other->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore + bytesAfter);
other->all_key_count = out; other->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out);
uint16 *outKeyLengths = other->KeyLengths(); uint16 *outKeyLengths = other->KeyLengths();
off_t *outKeyValues = other->Values(); off_t *outKeyValues = other->Values();
@@ -943,12 +946,12 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
// of the next node (which can also be the new key to insert). // of the next node (which can also be the new key to insert).
// The dropped key is also the one which has to be inserted in // The dropped key is also the one which has to be inserted in
// the parent node, so we will set the "newKey" already here. // the parent node, so we will set the "newKey" already here.
if (node->overflow_link != BPLUSTREE_NULL) { if (node->OverflowLink() != BPLUSTREE_NULL) {
if (in == keyIndex) { if (in == keyIndex) {
newKey = key; newKey = key;
newLength = *_keyLength; newLength = *_keyLength;
other->overflow_link = *_value; other->overflow_link = HOST_ENDIAN_TO_BFS_INT64(*_value);
keyIndex--; keyIndex--;
} else { } else {
// If a key is dropped (is not the new key), we have to copy // If a key is dropped (is not the new key), we have to copy
@@ -962,7 +965,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
newKey = (uint8 *)malloc(newLength); newKey = (uint8 *)malloc(newLength);
if (newKey == NULL) if (newKey == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
memcpy(newKey,droppedKey,newLength); memcpy(newKey, droppedKey, newLength);
other->overflow_link = inKeyValues[in]; other->overflow_link = inKeyValues[in];
total = inKeyLengths[in++]; total = inKeyLengths[in++];
@@ -975,7 +978,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
bytesBefore = bytesAfter = bytes = 0; bytesBefore = bytesAfter = bytes = 0;
out = 0; out = 0;
int32 skip = in; int32 skip = in;
while (in < node->all_key_count + 1) { while (in < node->NumKeys() + 1) {
if (in == keyIndex && !bytes) { if (in == keyIndex && !bytes) {
// it's enough to set bytesBefore once here, because we do // it's enough to set bytesBefore once here, because we do
// not need to know the exact length of all keys in this // not need to know the exact length of all keys in this
@@ -983,7 +986,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
bytesBefore = in > skip ? inKeyLengths[in - 1] : 0; bytesBefore = in > skip ? inKeyLengths[in - 1] : 0;
bytes = *_keyLength; bytes = *_keyLength;
} else { } else {
if (in < node->all_key_count) { if (in < node->NumKeys()) {
inKeyLengths[in] -= total; inKeyLengths[in] -= total;
if (bytes) { if (bytes) {
inKeyLengths[in] += bytes; inKeyLengths[in] += bytes;
@@ -996,7 +999,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
out++; out++;
// break out when all keys are done // break out when all keys are done
if (in > node->all_key_count && keyIndex < in) if (in > node->NumKeys() && keyIndex < in)
break; break;
} }
@@ -1004,15 +1007,15 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
if (keyIndex >= in && keyIndex - skip < out) if (keyIndex >= in && keyIndex - skip < out)
bytesAfter = inKeyLengths[in] - bytesBefore - total; bytesAfter = inKeyLengths[in] - bytesBefore - total;
else if (keyIndex < skip) else if (keyIndex < skip)
bytesBefore = node->all_key_length - total; bytesBefore = node->AllKeyLength() - total;
if (bytesBefore < 0 || bytesAfter < 0) if (bytesBefore < 0 || bytesAfter < 0)
return B_BAD_DATA; return B_BAD_DATA;
node->left_link = otherOffset; node->left_link = HOST_ENDIAN_TO_BFS_INT64(otherOffset);
// right link, and overflow link can stay the same // right link, and overflow link can stay the same
node->all_key_length = bytes + bytesBefore + bytesAfter; node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore + bytesAfter);
node->all_key_count = out - 1; node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out - 1);
// array positions have changed // array positions have changed
outKeyLengths = node->KeyLengths(); outKeyLengths = node->KeyLengths();
@@ -1052,7 +1055,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
// If it's the dropped key, "newKey" was already set earlier. // If it's the dropped key, "newKey" was already set earlier.
if (newKey == NULL) if (newKey == NULL)
newKey = other->KeyAt(other->all_key_count - 1, &newLength); newKey = other->KeyAt(other->NumKeys() - 1, &newLength);
memcpy(key,newKey,newLength); memcpy(key,newKey,newLength);
*_keyLength = newLength; *_keyLength = newLength;
@@ -1075,12 +1078,12 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
WriteLocked locked(fStream->Lock()); WriteLocked locked(fStream->Lock());
Stack<node_and_key> stack; Stack<node_and_key> stack;
if (SeekDown(stack,key,keyLength) != B_OK) if (SeekDown(stack, key, keyLength) != B_OK)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
uint8 keyBuffer[BPLUSTREE_MAX_KEY_LENGTH + 1]; uint8 keyBuffer[BPLUSTREE_MAX_KEY_LENGTH + 1];
memcpy(keyBuffer,key,keyLength); memcpy(keyBuffer, key, keyLength);
keyBuffer[keyLength] = 0; keyBuffer[keyLength] = 0;
node_and_key nodeAndKey; node_and_key nodeAndKey;
@@ -1093,7 +1096,7 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
#endif #endif
if (node->IsLeaf()) { if (node->IsLeaf()) {
// first round, check for duplicate entries // first round, check for duplicate entries
status_t status = FindKey(node,key,keyLength,&nodeAndKey.keyIndex); status_t status = FindKey(node, key, keyLength, &nodeAndKey.keyIndex);
// is this a duplicate entry? // is this a duplicate entry?
if (status == B_OK) { if (status == B_OK) {
@@ -1105,8 +1108,8 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
} }
// is the node big enough to hold the pair? // is the node big enough to hold the pair?
if (int32(round_up(sizeof(bplustree_node) + node->all_key_length + keyLength) if (int32(round_up(sizeof(bplustree_node) + node->AllKeyLength() + keyLength)
+ (node->all_key_count + 1) * (sizeof(uint16) + sizeof(off_t))) < fNodeSize) + (node->NumKeys() + 1) * (sizeof(uint16) + sizeof(off_t))) < fNodeSize)
{ {
InsertKey(node, nodeAndKey.keyIndex, keyBuffer, keyLength, value); InsertKey(node, nodeAndKey.keyIndex, keyBuffer, keyLength, value);
UpdateIterators(nodeAndKey.nodeOffset, BPLUSTREE_NULL, nodeAndKey.keyIndex, 0, 1); UpdateIterators(nodeAndKey.nodeOffset, BPLUSTREE_NULL, nodeAndKey.keyIndex, 0, 1);
@@ -1119,7 +1122,7 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
// do we need to allocate a new root node? if so, then do // do we need to allocate a new root node? if so, then do
// it now // it now
off_t newRoot = BPLUSTREE_NULL; off_t newRoot = BPLUSTREE_NULL;
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer) { if (nodeAndKey.nodeOffset == fHeader->RootNode()) {
bplustree_node *root; bplustree_node *root;
status_t status = cachedNewRoot.Allocate(transaction, &root, &newRoot); status_t status = cachedNewRoot.Allocate(transaction, &root, &newRoot);
if (status < B_OK) { if (status < B_OK) {
@@ -1158,11 +1161,11 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
UpdateIterators(nodeAndKey.nodeOffset, otherOffset, nodeAndKey.keyIndex, UpdateIterators(nodeAndKey.nodeOffset, otherOffset, nodeAndKey.keyIndex,
node->all_key_count, 1); node->NumKeys(), 1);
// update the right link of the node in the left of the new node // update the right link of the node in the left of the new node
if ((other = cachedOther.SetTo(other->left_link)) != NULL) { if ((other = cachedOther.SetTo(other->LeftLink())) != NULL) {
other->right_link = otherOffset; other->right_link = HOST_ENDIAN_TO_BFS_INT64(otherOffset);
if (cachedOther.WriteBack(transaction) < B_OK) if (cachedOther.WriteBack(transaction) < B_OK)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
} }
@@ -1171,15 +1174,15 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
if (newRoot != BPLUSTREE_NULL) { if (newRoot != BPLUSTREE_NULL) {
bplustree_node *root = cachedNewRoot.Node(); bplustree_node *root = cachedNewRoot.Node();
InsertKey(root, 0, keyBuffer, keyLength, node->left_link); InsertKey(root, 0, keyBuffer, keyLength, node->LeftLink());
root->overflow_link = nodeAndKey.nodeOffset; root->overflow_link = HOST_ENDIAN_TO_BFS_INT64(nodeAndKey.nodeOffset);
if (cachedNewRoot.WriteBack(transaction) < B_OK) if (cachedNewRoot.WriteBack(transaction) < B_OK)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
// finally, update header to point to the new root // finally, update header to point to the new root
fHeader->root_node_pointer = newRoot; fHeader->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(newRoot);
fHeader->max_number_of_levels++; fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(fHeader->MaxNumberOfLevels() + 1);
return fCachedHeader.WriteBack(transaction); return fCachedHeader.WriteBack(transaction);
} }
@@ -1242,8 +1245,8 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
duplicate_array *array; duplicate_array *array;
if (duplicate->left_link != BPLUSTREE_NULL) { if (duplicate->LeftLink() != BPLUSTREE_NULL) {
FATAL(("invalid duplicate node: first left link points to %Ld!\n",duplicate->left_link)); FATAL(("invalid duplicate node: first left link points to %Ld!\n", duplicate->LeftLink()));
return B_BAD_DATA; return B_BAD_DATA;
} }
@@ -1259,7 +1262,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
if (array->Remove(value)) if (array->Remove(value))
break; break;
if ((duplicateOffset = duplicate->right_link) == BPLUSTREE_NULL) if ((duplicateOffset = duplicate->RightLink()) == BPLUSTREE_NULL)
RETURN_ERROR(B_ENTRY_NOT_FOUND); RETURN_ERROR(B_ENTRY_NOT_FOUND);
duplicate = cachedDuplicate.SetTo(duplicateOffset,false); duplicate = cachedDuplicate.SetTo(duplicateOffset,false);
@@ -1268,8 +1271,8 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
while (true) { while (true) {
off_t left = duplicate->left_link; off_t left = duplicate->LeftLink();
off_t right = duplicate->right_link; off_t right = duplicate->RightLink();
bool isLast = left == BPLUSTREE_NULL && right == BPLUSTREE_NULL; bool isLast = left == BPLUSTREE_NULL && right == BPLUSTREE_NULL;
if (isLast && array->count == 1 || array->count == 0) { if (isLast && array->count == 1 || array->count == 0) {
@@ -1289,17 +1292,17 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
if ((status = cached->WriteBack(transaction)) < B_OK) if ((status = cached->WriteBack(transaction)) < B_OK)
return status; return status;
} }
if ((status = cachedDuplicate.Free(transaction,duplicateOffset)) < B_OK) if ((status = cachedDuplicate.Free(transaction,duplicateOffset)) < B_OK)
return status; return status;
if (left != BPLUSTREE_NULL if (left != BPLUSTREE_NULL
&& (duplicate = cachedDuplicate.SetTo(left,false)) != NULL) { && (duplicate = cachedDuplicate.SetTo(left,false)) != NULL) {
duplicate->right_link = right; duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(right);
// If the next node is the last node, we need to free that node // If the next node is the last node, we need to free that node
// and convert the duplicate entry back into a normal entry // and convert the duplicate entry back into a normal entry
if (right == BPLUSTREE_NULL && duplicate->left_link == BPLUSTREE_NULL if (right == BPLUSTREE_NULL && duplicate->LeftLink() == BPLUSTREE_NULL
&& duplicate->DuplicateArray()->count <= NUM_FRAGMENT_VALUES) { && duplicate->DuplicateArray()->count <= NUM_FRAGMENT_VALUES) {
duplicateOffset = left; duplicateOffset = left;
continue; continue;
@@ -1310,12 +1313,12 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
return status; return status;
} }
if (right != BPLUSTREE_NULL if (right != BPLUSTREE_NULL
&& (duplicate = cachedDuplicate.SetTo(right,false)) != NULL) { && (duplicate = cachedDuplicate.SetTo(right, false)) != NULL) {
duplicate->left_link = left; duplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(left);
// Again, we may need to turn the duplicate entry back into a normal entry // Again, we may need to turn the duplicate entry back into a normal entry
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (left == BPLUSTREE_NULL && duplicate->right_link == BPLUSTREE_NULL if (left == BPLUSTREE_NULL && duplicate->RightLink() == BPLUSTREE_NULL
&& duplicate->DuplicateArray()->count <= NUM_FRAGMENT_VALUES) { && duplicate->DuplicateArray()->count <= NUM_FRAGMENT_VALUES) {
duplicateOffset = right; duplicateOffset = right;
continue; continue;
@@ -1368,7 +1371,7 @@ void
BPlusTree::RemoveKey(bplustree_node *node,uint16 index) BPlusTree::RemoveKey(bplustree_node *node,uint16 index)
{ {
// should never happen, but who knows? // should never happen, but who knows?
if (index > node->all_key_count && node->all_key_count > 0) { if (index > node->NumKeys() && node->NumKeys() > 0) {
FATAL(("Asked me to remove key outer limits: %u\n",index)); FATAL(("Asked me to remove key outer limits: %u\n",index));
return; return;
} }
@@ -1378,7 +1381,7 @@ BPlusTree::RemoveKey(bplustree_node *node,uint16 index)
// if we would have to drop the overflow link, drop // if we would have to drop the overflow link, drop
// the last key instead and update the overflow link // the last key instead and update the overflow link
// to the value of that one // to the value of that one
if (!node->IsLeaf() && index == node->all_key_count) if (!node->IsLeaf() && index == node->NumKeys())
node->overflow_link = values[--index]; node->overflow_link = values[--index];
uint16 length; uint16 length;
@@ -1393,26 +1396,26 @@ BPlusTree::RemoveKey(bplustree_node *node,uint16 index)
uint16 *keyLengths = node->KeyLengths(); uint16 *keyLengths = node->KeyLengths();
uint8 *keys = node->Keys(); uint8 *keys = node->Keys();
node->all_key_count--; node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() - 1);
node->all_key_length -= length; node->all_key_length = HOST_ENDIAN_TO_BFS_INT64(node->AllKeyLength() - length);
off_t *newValues = node->Values(); off_t *newValues = node->Values();
uint16 *newKeyLengths = node->KeyLengths(); uint16 *newKeyLengths = node->KeyLengths();
// move key data // move key data
memmove(key,key + length,node->all_key_length - (key - keys)); memmove(key, key + length, node->AllKeyLength() - (key - keys));
// move and update key lengths // move and update key lengths
if (index > 0 && newKeyLengths != keyLengths) if (index > 0 && newKeyLengths != keyLengths)
memmove(newKeyLengths,keyLengths,index * sizeof(uint16)); memmove(newKeyLengths, keyLengths, index * sizeof(uint16));
for (uint16 i = index;i < node->all_key_count;i++) for (uint16 i = index; i < node->NumKeys(); i++)
newKeyLengths[i] = keyLengths[i + 1] - length; newKeyLengths[i] = keyLengths[i + 1] - length;
// move values // move values
if (index > 0) if (index > 0)
memmove(newValues,values,index * sizeof(off_t)); memmove(newValues,values,index * sizeof(off_t));
if (node->all_key_count > index) if (node->NumKeys() > index)
memmove(newValues + index,values + index + 1,(node->all_key_count - index) * sizeof(off_t)); memmove(newValues + index, values + index + 1, (node->NumKeys() - index) * sizeof(off_t));
} }
@@ -1453,14 +1456,14 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
// to the next node after the current - if there aren't any // to the next node after the current - if there aren't any
// more nodes, we need a way to prevent the TreeIterators to // more nodes, we need a way to prevent the TreeIterators to
// touch the old node again, we use BPLUSTREE_FREE for this // touch the old node again, we use BPLUSTREE_FREE for this
off_t next = node->right_link == BPLUSTREE_NULL ? BPLUSTREE_FREE : node->right_link; off_t next = node->RightLink() == BPLUSTREE_NULL ? BPLUSTREE_FREE : node->RightLink();
UpdateIterators(nodeAndKey.nodeOffset,node->all_key_count == 1 ? UpdateIterators(nodeAndKey.nodeOffset, node->NumKeys() == 1 ?
next : BPLUSTREE_NULL,nodeAndKey.keyIndex,0,-1); next : BPLUSTREE_NULL,nodeAndKey.keyIndex,0 , -1);
// is this a duplicate entry? // is this a duplicate entry?
if (bplustree_node::IsDuplicate(node->Values()[nodeAndKey.keyIndex])) { if (bplustree_node::IsDuplicate(node->Values()[nodeAndKey.keyIndex])) {
if (fAllowDuplicates) if (fAllowDuplicates)
return RemoveDuplicate(transaction,node,&cached,nodeAndKey.keyIndex,value); return RemoveDuplicate(transaction, node, &cached, nodeAndKey.keyIndex, value);
else else
RETURN_ERROR(B_NAME_IN_USE); RETURN_ERROR(B_NAME_IN_USE);
} }
@@ -1469,10 +1472,10 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
// if it's an empty root node, we have to convert it // if it's an empty root node, we have to convert it
// to a leaf node by dropping the overflow link, or, // to a leaf node by dropping the overflow link, or,
// if it's a leaf node, just empty it // if it's a leaf node, just empty it
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer if (nodeAndKey.nodeOffset == fHeader->RootNode()
&& node->all_key_count == 0 && node->NumKeys() == 0
|| node->all_key_count == 1 && node->IsLeaf()) { || node->NumKeys() == 1 && node->IsLeaf()) {
node->overflow_link = BPLUSTREE_NULL; node->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
node->all_key_count = 0; node->all_key_count = 0;
node->all_key_length = 0; node->all_key_length = 0;
@@ -1481,8 +1484,8 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
// if we've cleared the root node, reset the maximum // if we've cleared the root node, reset the maximum
// number of levels in the header // number of levels in the header
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer) { if (nodeAndKey.nodeOffset == fHeader->RootNode()) {
fHeader->max_number_of_levels = 1; fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
return fCachedHeader.WriteBack(transaction); return fCachedHeader.WriteBack(transaction);
} }
return B_OK; return B_OK;
@@ -1491,8 +1494,8 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
// if there is only one key left, we don't have to remove // if there is only one key left, we don't have to remove
// it, we can just dump the node (index nodes still have // it, we can just dump the node (index nodes still have
// the overflow link, so we have to drop the last key) // the overflow link, so we have to drop the last key)
if (node->all_key_count > 1 if (node->NumKeys() > 1
|| !node->IsLeaf() && node->all_key_count == 1) { || !node->IsLeaf() && node->NumKeys() == 1) {
RemoveKey(node,nodeAndKey.keyIndex); RemoveKey(node,nodeAndKey.keyIndex);
return cached.WriteBack(transaction); return cached.WriteBack(transaction);
} }
@@ -1501,14 +1504,14 @@ BPlusTree::Remove(Transaction *transaction, const uint8 *key, uint16 keyLength,
// we have to update the right/left link of the // we have to update the right/left link of the
// siblings first // siblings first
CachedNode otherCached(this); CachedNode otherCached(this);
bplustree_node *other = otherCached.SetTo(node->left_link); bplustree_node *other = otherCached.SetTo(node->LeftLink());
if (other != NULL) { if (other != NULL) {
other->right_link = node->right_link; other->right_link = node->right_link;
if (otherCached.WriteBack(transaction) < B_OK) if (otherCached.WriteBack(transaction) < B_OK)
return B_IO_ERROR; return B_IO_ERROR;
} }
if ((other = otherCached.SetTo(node->right_link)) != NULL) { if ((other = otherCached.SetTo(node->RightLink())) != NULL) {
other->left_link = node->left_link; other->left_link = node->left_link;
if (otherCached.WriteBack(transaction) < B_OK) if (otherCached.WriteBack(transaction) < B_OK)
return B_IO_ERROR; return B_IO_ERROR;
@@ -1542,7 +1545,7 @@ BPlusTree::Replace(Transaction *transaction, const uint8 *key, uint16 keyLength,
// lock access to stream (a read lock is okay for this purpose) // lock access to stream (a read lock is okay for this purpose)
ReadLocked locked(fStream->Lock()); ReadLocked locked(fStream->Lock());
off_t nodeOffset = fHeader->root_node_pointer; off_t nodeOffset = fHeader->RootNode();
CachedNode cached(this); CachedNode cached(this);
bplustree_node *node; bplustree_node *node;
@@ -1551,7 +1554,7 @@ BPlusTree::Replace(Transaction *transaction, const uint8 *key, uint16 keyLength,
off_t nextOffset; off_t nextOffset;
status_t status = FindKey(node, key, keyLength, &keyIndex, &nextOffset); status_t status = FindKey(node, key, keyLength, &keyIndex, &nextOffset);
if (node->overflow_link == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
if (status == B_OK) { if (status == B_OK) {
node->Values()[keyIndex] = value; node->Values()[keyIndex] = value;
return cached.WriteBack(transaction); return cached.WriteBack(transaction);
@@ -1592,7 +1595,7 @@ BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
// lock access to stream // lock access to stream
ReadLocked locked(fStream->Lock()); ReadLocked locked(fStream->Lock());
off_t nodeOffset = fHeader->root_node_pointer; off_t nodeOffset = fHeader->RootNode();
CachedNode cached(this); CachedNode cached(this);
bplustree_node *node; bplustree_node *node;
@@ -1608,12 +1611,12 @@ BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
#ifdef DEBUG #ifdef DEBUG
levels++; levels++;
#endif #endif
if (node->overflow_link == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
if (status == B_OK && _value != NULL) if (status == B_OK && _value != NULL)
*_value = node->Values()[keyIndex]; *_value = BFS_ENDIAN_TO_HOST_INT64(node->Values()[keyIndex]);
#ifdef DEBUG #ifdef DEBUG
if (levels != (int32)fHeader->max_number_of_levels) if (levels != (int32)fHeader->MaxNumberOfLevels())
DEBUGGER(("levels don't match")); DEBUGGER(("levels don't match"));
#endif #endif
return status; return status;
@@ -1656,15 +1659,15 @@ TreeIterator::Goto(int8 to)
// lock access to stream // lock access to stream
ReadLocked locked(fTree->fStream->Lock()); ReadLocked locked(fTree->fStream->Lock());
off_t nodeOffset = fTree->fHeader->root_node_pointer; off_t nodeOffset = fTree->fHeader->RootNode();
CachedNode cached(fTree); CachedNode cached(fTree);
bplustree_node *node; bplustree_node *node;
while ((node = cached.SetTo(nodeOffset)) != NULL) { while ((node = cached.SetTo(nodeOffset)) != NULL) {
// is the node a leaf node? // is the node a leaf node?
if (node->overflow_link == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
fCurrentNodeOffset = nodeOffset; fCurrentNodeOffset = nodeOffset;
fCurrentKey = to == BPLUSTREE_BEGIN ? -1 : node->all_key_count; fCurrentKey = to == BPLUSTREE_BEGIN ? -1 : node->NumKeys();
fDuplicateNode = BPLUSTREE_NULL; fDuplicateNode = BPLUSTREE_NULL;
return B_OK; return B_OK;
@@ -1674,13 +1677,13 @@ TreeIterator::Goto(int8 to)
// are any keys in that node at all) // are any keys in that node at all)
off_t nextOffset; off_t nextOffset;
if (to == BPLUSTREE_END || node->all_key_count == 0) if (to == BPLUSTREE_END || node->all_key_count == 0)
nextOffset = node->overflow_link; nextOffset = node->OverflowLink();
else { else {
if (node->all_key_length > fTree->fNodeSize if (node->AllKeyLength() > fTree->fNodeSize
|| (uint32)node->Values() > (uint32)node + fTree->fNodeSize - 8 * node->all_key_count) || (uint32)node->Values() > (uint32)node + fTree->fNodeSize - 8 * node->NumKeys())
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
nextOffset = node->Values()[0]; nextOffset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[0]);
} }
if (nextOffset == nodeOffset) if (nextOffset == nodeOffset)
break; break;
@@ -1740,7 +1743,7 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
if (!fIsFragment && fDuplicate >= fNumDuplicates) if (!fIsFragment && fDuplicate >= fNumDuplicates)
{ {
// if the node is out of duplicates, we go directly to the next one // if the node is out of duplicates, we go directly to the next one
fDuplicateNode = node->right_link; fDuplicateNode = node->RightLink();
if (fDuplicateNode != BPLUSTREE_NULL if (fDuplicateNode != BPLUSTREE_NULL
&& (node = cached.SetTo(fDuplicateNode, false)) != NULL) && (node = cached.SetTo(fDuplicateNode, false)) != NULL)
{ {
@@ -1769,10 +1772,10 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
fCurrentKey += direction; fCurrentKey += direction;
// is the current key in the current node? // is the current key in the current node?
while ((direction == BPLUSTREE_FORWARD && fCurrentKey >= node->all_key_count) while ((direction == BPLUSTREE_FORWARD && fCurrentKey >= node->NumKeys())
|| (direction == BPLUSTREE_BACKWARD && fCurrentKey < 0)) || (direction == BPLUSTREE_BACKWARD && fCurrentKey < 0))
{ {
fCurrentNodeOffset = direction == BPLUSTREE_FORWARD ? node->right_link : node->left_link; fCurrentNodeOffset = direction == BPLUSTREE_FORWARD ? node->RightLink() : node->LeftLink();
// are there any more nodes? // are there any more nodes?
if (fCurrentNodeOffset != BPLUSTREE_NULL) if (fCurrentNodeOffset != BPLUSTREE_NULL)
@@ -1782,13 +1785,13 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
// reset current key // reset current key
fCurrentKey = direction == BPLUSTREE_FORWARD ? 0 : node->all_key_count; fCurrentKey = direction == BPLUSTREE_FORWARD ? 0 : node->NumKeys();
} }
else else
{ {
// there are no nodes left, so turn back to the last key // there are no nodes left, so turn back to the last key
fCurrentNodeOffset = savedNodeOffset; fCurrentNodeOffset = savedNodeOffset;
fCurrentKey = direction == BPLUSTREE_FORWARD ? node->all_key_count : -1; fCurrentKey = direction == BPLUSTREE_FORWARD ? node->NumKeys() : -1;
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
@@ -1798,15 +1801,15 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
RETURN_ERROR(B_ERROR); // B_ENTRY_NOT_FOUND ? RETURN_ERROR(B_ERROR); // B_ENTRY_NOT_FOUND ?
uint16 length; uint16 length;
uint8 *keyStart = node->KeyAt(fCurrentKey,&length); uint8 *keyStart = node->KeyAt(fCurrentKey, &length);
if (keyStart + length + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fTree->fNodeSize if (keyStart + length + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fTree->fNodeSize
|| length > BPLUSTREE_MAX_KEY_LENGTH) { || length > BPLUSTREE_MAX_KEY_LENGTH) {
fTree->fStream->GetVolume()->Panic(); fTree->fStream->GetVolume()->Panic();
RETURN_ERROR(B_BAD_DATA); RETURN_ERROR(B_BAD_DATA);
} }
length = min_c(length,maxLength); length = min_c(length, maxLength);
memcpy(key,keyStart,length); memcpy(key, keyStart, length);
if (fTree->fHeader->data_type == BPLUSTREE_STRING_TYPE) // terminate string type if (fTree->fHeader->data_type == BPLUSTREE_STRING_TYPE) // terminate string type
{ {
@@ -1816,7 +1819,7 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
} }
*keyLength = length; *keyLength = length;
off_t offset = node->Values()[fCurrentKey]; off_t offset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[fCurrentKey]);
// duplicate fragments? // duplicate fragments?
uint8 type = bplustree_node::LinkType(offset); uint8 type = bplustree_node::LinkType(offset);
@@ -1868,7 +1871,7 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
// lock access to stream // lock access to stream
ReadLocked locked(fTree->fStream->Lock()); ReadLocked locked(fTree->fStream->Lock());
off_t nodeOffset = fTree->fHeader->root_node_pointer; off_t nodeOffset = fTree->fHeader->RootNode();
CachedNode cached(fTree); CachedNode cached(fTree);
bplustree_node *node; bplustree_node *node;
@@ -1877,7 +1880,7 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
off_t nextOffset; off_t nextOffset;
status_t status = fTree->FindKey(node, key, keyLength, &keyIndex, &nextOffset); status_t status = fTree->FindKey(node, key, keyLength, &keyIndex, &nextOffset);
if (node->overflow_link == BPLUSTREE_NULL) { if (node->OverflowLink() == BPLUSTREE_NULL) {
fCurrentNodeOffset = nodeOffset; fCurrentNodeOffset = nodeOffset;
fCurrentKey = keyIndex - 1; fCurrentKey = keyIndex - 1;
fDuplicateNode = BPLUSTREE_NULL; fDuplicateNode = BPLUSTREE_NULL;
@@ -1952,7 +1955,7 @@ TreeIterator::Dump()
void void
bplustree_node::Initialize() bplustree_node::Initialize()
{ {
left_link = right_link = overflow_link = BPLUSTREE_NULL; left_link = right_link = overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
all_key_count = 0; all_key_count = 0;
all_key_length = 0; all_key_length = 0;
} }
@@ -1961,15 +1964,16 @@ bplustree_node::Initialize()
uint8 * uint8 *
bplustree_node::KeyAt(int32 index, uint16 *keyLength) const bplustree_node::KeyAt(int32 index, uint16 *keyLength) const
{ {
if (index < 0 || index > all_key_count) if (index < 0 || index > NumKeys())
return NULL; return NULL;
uint8 *keyStart = Keys(); uint8 *keyStart = Keys();
uint16 *keyLengths = KeyLengths(); uint16 *keyLengths = KeyLengths();
*keyLength = keyLengths[index] - (index != 0 ? keyLengths[index - 1] : 0); *keyLength = BFS_ENDIAN_TO_HOST_INT16(keyLengths[index])
- (index != 0 ? BFS_ENDIAN_TO_HOST_INT16(keyLengths[index - 1]) : 0);
if (index > 0) if (index > 0)
keyStart += keyLengths[index - 1]; keyStart += BFS_ENDIAN_TO_HOST_INT16(keyLengths[index - 1]);
return keyStart; return keyStart;
} }
@@ -1986,7 +1990,7 @@ bplustree_node::CountDuplicates(off_t offset, bool isFragment) const
return ((off_t *)this)[fragment]; return ((off_t *)this)[fragment];
} }
return overflow_link; return OverflowLink();
} }
@@ -2026,10 +2030,10 @@ bplustree_node::FragmentsUsed(uint32 nodeSize)
void void
bplustree_node::CheckIntegrity(uint32 nodeSize) bplustree_node::CheckIntegrity(uint32 nodeSize)
{ {
if (all_key_count > nodeSize || all_key_length > nodeSize) if (NumKeys() > nodeSize || AllKeyLength() > nodeSize)
DEBUGGER(("invalid node: key/length count")); DEBUGGER(("invalid node: key/length count"));
for (int32 i = 0; i < all_key_count; i++) { for (int32 i = 0; i < NumKeys(); i++) {
uint16 length; uint16 length;
uint8 *key = KeyAt(i, &length); uint8 *key = KeyAt(i, &length);
if (key + length + sizeof(off_t) + sizeof(uint16) > (uint8 *)this + nodeSize if (key + length + sizeof(off_t) + sizeof(uint16) > (uint8 *)this + nodeSize
@@ -28,7 +28,15 @@ struct bplustree_header {
off_t root_node_pointer; off_t root_node_pointer;
off_t free_node_pointer; off_t free_node_pointer;
off_t maximum_size; off_t maximum_size;
uint32 Magic() const { return BFS_ENDIAN_TO_HOST_INT32(magic); }
uint32 NodeSize() const { return BFS_ENDIAN_TO_HOST_INT32(node_size); }
uint32 DataType() const { return BFS_ENDIAN_TO_HOST_INT32(data_type); }
off_t RootNode() const { return BFS_ENDIAN_TO_HOST_INT64(root_node_pointer); }
off_t FreeNode() const { return BFS_ENDIAN_TO_HOST_INT64(free_node_pointer); }
off_t MaximumSize() const { return BFS_ENDIAN_TO_HOST_INT64(maximum_size); }
uint32 MaxNumberOfLevels() const { return BFS_ENDIAN_TO_HOST_INT32(max_number_of_levels); }
inline bool IsValidLink(off_t link); inline bool IsValidLink(off_t link);
}; };
@@ -56,13 +64,19 @@ struct bplustree_node {
off_t overflow_link; off_t overflow_link;
uint16 all_key_count; uint16 all_key_count;
uint16 all_key_length; uint16 all_key_length;
off_t LeftLink() const { return BFS_ENDIAN_TO_HOST_INT64(left_link); }
off_t RightLink() const { return BFS_ENDIAN_TO_HOST_INT64(right_link); }
off_t OverflowLink() const { return BFS_ENDIAN_TO_HOST_INT64(overflow_link); }
uint16 NumKeys() const { return BFS_ENDIAN_TO_HOST_INT16(all_key_count); }
uint16 AllKeyLength() const { return BFS_ENDIAN_TO_HOST_INT16(all_key_length); }
inline uint16 *KeyLengths() const; inline uint16 *KeyLengths() const;
inline off_t *Values() const; inline off_t *Values() const;
inline uint8 *Keys() const; inline uint8 *Keys() const;
inline int32 Used() const; inline int32 Used() const;
uint8 *KeyAt(int32 index,uint16 *keyLength) const; uint8 *KeyAt(int32 index, uint16 *keyLength) const;
inline bool IsLeaf() const; inline bool IsLeaf() const;
void Initialize(); void Initialize();
@@ -381,7 +395,7 @@ TreeIterator::GetPreviousEntry(void *key, uint16 *keyLength, uint16 maxLength,
inline bool inline bool
bplustree_header::IsValidLink(off_t link) bplustree_header::IsValidLink(off_t link)
{ {
return link == BPLUSTREE_NULL || (link > 0 && link <= maximum_size - node_size); return link == BPLUSTREE_NULL || (link > 0 && link <= MaximumSize() - NodeSize());
} }
@@ -392,31 +406,35 @@ bplustree_header::IsValidLink(off_t link)
inline uint16 * inline uint16 *
bplustree_node::KeyLengths() const bplustree_node::KeyLengths() const
{ {
return (uint16 *)(((char *)this) + round_up(sizeof(bplustree_node) + all_key_length)); return (uint16 *)(((char *)this) + round_up(sizeof(bplustree_node) + AllKeyLength()));
} }
inline off_t * inline off_t *
bplustree_node::Values() const bplustree_node::Values() const
{ {
return (off_t *)((char *)KeyLengths() + all_key_count * sizeof(uint16)); return (off_t *)((char *)KeyLengths() + NumKeys() * sizeof(uint16));
} }
inline uint8 * inline uint8 *
bplustree_node::Keys() const bplustree_node::Keys() const
{ {
return (uint8 *)this + sizeof(bplustree_node); return (uint8 *)this + sizeof(bplustree_node);
} }
inline int32 inline int32
bplustree_node::Used() const bplustree_node::Used() const
{ {
return round_up(sizeof(bplustree_node) + all_key_length) + all_key_count * (sizeof(uint16) + sizeof(off_t)); return round_up(sizeof(bplustree_node) + AllKeyLength()) + NumKeys() * (sizeof(uint16) + sizeof(off_t));
} }
inline bool inline bool
bplustree_node::IsLeaf() const bplustree_node::IsLeaf() const
{ {
return overflow_link == BPLUSTREE_NULL; return OverflowLink() == BPLUSTREE_NULL;
} }
@@ -440,24 +458,28 @@ bplustree_node::LinkType(off_t link)
return *(uint64 *)&link >> 62; return *(uint64 *)&link >> 62;
} }
inline off_t inline off_t
bplustree_node::MakeLink(uint8 type, off_t link, uint32 fragmentIndex) bplustree_node::MakeLink(uint8 type, off_t link, uint32 fragmentIndex)
{ {
return ((off_t)type << 62) | (link & 0x3ffffffffffffc00LL) | (fragmentIndex & 0x3ff); return ((off_t)type << 62) | (link & 0x3ffffffffffffc00LL) | (fragmentIndex & 0x3ff);
} }
inline bool inline bool
bplustree_node::IsDuplicate(off_t link) bplustree_node::IsDuplicate(off_t link)
{ {
return (LinkType(link) & (BPLUSTREE_DUPLICATE_NODE | BPLUSTREE_DUPLICATE_FRAGMENT)) > 0; return (LinkType(link) & (BPLUSTREE_DUPLICATE_NODE | BPLUSTREE_DUPLICATE_FRAGMENT)) > 0;
} }
inline off_t inline off_t
bplustree_node::FragmentOffset(off_t link) bplustree_node::FragmentOffset(off_t link)
{ {
return link & 0x3ffffffffffffc00LL; return link & 0x3ffffffffffffc00LL;
} }
inline uint32 inline uint32
bplustree_node::FragmentIndex(off_t link) bplustree_node::FragmentIndex(off_t link)
{ {
@@ -112,7 +112,7 @@ AllocationBlock::IsUsed(uint16 block)
if (block > fNumBits) if (block > fNumBits)
return true; return true;
// the block bitmap is accessed in 32-bit blocks // the block bitmap is accessed in 32-bit blocks
return Block(block >> 5) & (1UL << (block % 32)); return Block(block >> 5) & HOST_ENDIAN_TO_BFS_INT32(1UL << (block % 32));
} }
@@ -136,12 +136,12 @@ AllocationBlock::Allocate(uint16 start, uint16 numBlocks)
#ifdef DEBUG #ifdef DEBUG
// check for already set blocks // check for already set blocks
if (mask & ((uint32 *)fBlock)[block]) { if (HOST_ENDIAN_TO_BFS_INT32(mask) & ((uint32 *)fBlock)[block]) {
FATAL(("AllocationBlock::Allocate(): some blocks are already allocated, start = %u, numBlocks = %u\n", start, numBlocks)); FATAL(("AllocationBlock::Allocate(): some blocks are already allocated, start = %u, numBlocks = %u\n", start, numBlocks));
DEBUGGER(("blocks already set!")); DEBUGGER(("blocks already set!"));
} }
#endif #endif
Block(block++) |= mask; Block(block++) |= HOST_ENDIAN_TO_BFS_INT32(mask);
start = 0; start = 0;
} }
} }
@@ -165,7 +165,7 @@ AllocationBlock::Free(uint16 start, uint16 numBlocks)
for (int32 i = start % 32; i < 32 && numBlocks; i++, numBlocks--) for (int32 i = start % 32; i < 32 && numBlocks; i++, numBlocks--)
mask |= 1UL << (i % 32); mask |= 1UL << (i % 32);
Block(block++) &= ~mask; Block(block++) &= HOST_ENDIAN_TO_BFS_INT32(~mask);
start = 0; start = 0;
} }
} }
@@ -332,7 +332,7 @@ BlockAllocator::Initialize()
return B_ERROR; return B_ERROR;
fNumGroups = fVolume->AllocationGroups(); fNumGroups = fVolume->AllocationGroups();
fBlocksPerGroup = fVolume->SuperBlock().blocks_per_ag; fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
fGroups = new AllocationGroup[fNumGroups]; fGroups = new AllocationGroup[fNumGroups];
if (fGroups == NULL) if (fGroups == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -397,7 +397,7 @@ BlockAllocator::initialize(BlockAllocator *allocator)
free(buffer); free(buffer);
// check if block bitmap and log area are reserved // check if block bitmap and log area are reserved
uint32 reservedBlocks = volume->Log().start + volume->Log().length; uint32 reservedBlocks = volume->Log().Start() + volume->Log().Length();
if (allocator->CheckBlockRun(block_run::Run(0, 0, reservedBlocks)) < B_OK) { if (allocator->CheckBlockRun(block_run::Run(0, 0, reservedBlocks)) < B_OK) {
Transaction transaction(volume, 0); Transaction transaction(volume, 0);
if (groups[0].Allocate(&transaction, 0, reservedBlocks) < B_OK) { if (groups[0].Allocate(&transaction, 0, reservedBlocks) < B_OK) {
@@ -415,7 +415,7 @@ BlockAllocator::initialize(BlockAllocator *allocator)
// If the disk in a dirty state at mount time, it's // If the disk in a dirty state at mount time, it's
// normal that the values don't match // normal that the values don't match
INFORM(("volume reports %Ld used blocks, correct is %Ld\n", volume->UsedBlocks(), usedBlocks)); INFORM(("volume reports %Ld used blocks, correct is %Ld\n", volume->UsedBlocks(), usedBlocks));
volume->SuperBlock().used_blocks = usedBlocks; volume->SuperBlock().used_blocks = HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
} }
return B_OK; return B_OK;
@@ -502,11 +502,12 @@ BlockAllocator::AllocateBlocks(Transaction *transaction, int32 group, uint16 sta
if (fGroups[group].Allocate(transaction, rangeStart, numBlocks) < B_OK) if (fGroups[group].Allocate(transaction, rangeStart, numBlocks) < B_OK)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
run.allocation_group = group; run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(group);
run.start = rangeStart; run.start = HOST_ENDIAN_TO_BFS_INT16(rangeStart);
run.length = numBlocks; run.length = HOST_ENDIAN_TO_BFS_INT16(numBlocks);
fVolume->SuperBlock().used_blocks += numBlocks; fVolume->SuperBlock().used_blocks =
HOST_ENDIAN_TO_BFS_INT64(fVolume->UsedBlocks() + numBlocks);
// We are not writing back the disk's super block - it's // We are not writing back the disk's super block - it's
// either done by the journaling code, or when the disk // either done by the journaling code, or when the disk
// is unmounted. // is unmounted.
@@ -534,7 +535,7 @@ BlockAllocator::AllocateForInode(Transaction *transaction, const block_run *pare
// files are going in the same allocation group as its parent, sub-directories // files are going in the same allocation group as its parent, sub-directories
// will be inserted 8 allocation groups after the one of the parent // will be inserted 8 allocation groups after the one of the parent
uint16 group = parent->allocation_group; uint16 group = parent->AllocationGroup();
if ((type & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR)) == S_DIRECTORY) if ((type & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR)) == S_DIRECTORY)
group += 8; group += 8;
@@ -567,7 +568,7 @@ BlockAllocator::Allocate(Transaction *transaction, const Inode *inode, off_t num
// apply some allocation policies here (AllocateBlocks() will break them // apply some allocation policies here (AllocateBlocks() will break them
// if necessary) // if necessary)
uint16 group = inode->BlockRun().allocation_group; uint16 group = inode->BlockRun().AllocationGroup();
uint16 start = 0; uint16 start = 0;
// are there already allocated blocks? (then just try to allocate near the last one) // are there already allocated blocks? (then just try to allocate near the last one)
@@ -579,20 +580,20 @@ BlockAllocator::Allocate(Transaction *transaction, const Inode *inode, off_t num
&& data->max_indirect_range == 0) { && data->max_indirect_range == 0) {
// Since size > 0, there must be a valid block run in this stream // Since size > 0, there must be a valid block run in this stream
int32 last = 0; int32 last = 0;
for (;last < NUM_DIRECT_BLOCKS - 1;last++) for (; last < NUM_DIRECT_BLOCKS - 1; last++)
if (data->direct[last + 1].IsZero()) if (data->direct[last + 1].IsZero())
break; break;
group = data->direct[last].allocation_group; group = data->direct[last].AllocationGroup();
start = data->direct[last].start + data->direct[last].length; start = data->direct[last].Start() + data->direct[last].Length();
} }
} else if (inode->IsContainer() || inode->IsSymLink()) { } else if (inode->IsContainer() || inode->IsSymLink()) {
// directory and symbolic link data will go in the same allocation // directory and symbolic link data will go in the same allocation
// group as the inode is in but after the inode data // group as the inode is in but after the inode data
start = inode->BlockRun().start; start = inode->BlockRun().Start();
} else { } else {
// file data will start in the next allocation group // file data will start in the next allocation group
group = inode->BlockRun().allocation_group + 1; group = inode->BlockRun().AllocationGroup() + 1;
} }
return AllocateBlocks(transaction, group, start, numBlocks, minimum, run); return AllocateBlocks(transaction, group, start, numBlocks, minimum, run);
@@ -604,9 +605,9 @@ BlockAllocator::Free(Transaction *transaction, block_run run)
{ {
Locker lock(fLock); Locker lock(fLock);
int32 group = run.allocation_group; int32 group = run.AllocationGroup();
uint16 start = run.start; uint16 start = run.Start();
uint16 length = run.length; uint16 length = run.Length();
// doesn't use Volume::IsValidBlockRun() here because it can check better // doesn't use Volume::IsValidBlockRun() here because it can check better
// against the group size (the last group may have a different length) // against the group size (the last group may have a different length)
@@ -619,7 +620,7 @@ BlockAllocator::Free(Transaction *transaction, block_run run)
return B_BAD_VALUE; return B_BAD_VALUE;
} }
// check if someone tries to free reserved areas at the beginning of the drive // check if someone tries to free reserved areas at the beginning of the drive
if (group == 0 && start < uint32(fVolume->Log().start + fVolume->Log().length)) { if (group == 0 && start < uint32(fVolume->Log().Start() + fVolume->Log().Length())) {
FATAL(("tried to free a reserved block_run (%ld, %u, %u)\n", group, start, length)); FATAL(("tried to free a reserved block_run (%ld, %u, %u)\n", group, start, length));
DEBUGGER(("tried to free reserved block")); DEBUGGER(("tried to free reserved block"));
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -632,7 +633,8 @@ BlockAllocator::Free(Transaction *transaction, block_run run)
if (fGroups[group].Free(transaction, start, length) < B_OK) if (fGroups[group].Free(transaction, start, length) < B_OK)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
fVolume->SuperBlock().used_blocks -= run.length; fVolume->SuperBlock().used_blocks =
HOST_ENDIAN_TO_BFS_INT64(fVolume->UsedBlocks() - run.Length());
return B_OK; return B_OK;
} }
@@ -683,7 +685,7 @@ BlockAllocator::StartChecking(check_control *control)
// initialize bitmap // initialize bitmap
memset(fCheckBitmap, 0, size); memset(fCheckBitmap, 0, size);
for (int32 block = fVolume->Log().start + fVolume->Log().length; block-- > 0;) for (int32 block = fVolume->Log().Start() + fVolume->Log().Length(); block-- > 0;)
SetCheckBitmapAt(block); SetCheckBitmapAt(block);
cookie->stack.Push(fVolume->Root()); cookie->stack.Push(fVolume->Root());
@@ -747,14 +749,14 @@ BlockAllocator::StopChecking(check_control *control)
// and use transactions here to play safe - we even use several // and use transactions here to play safe - we even use several
// transactions, so that we don't blow the maximum log size // transactions, so that we don't blow the maximum log size
// on large disks; since we don't need to make this atomic // on large disks; since we don't need to make this atomic
fVolume->SuperBlock().used_blocks = usedBlocks; fVolume->SuperBlock().used_blocks = HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
int32 blocksInBitmap = fNumGroups * fBlocksPerGroup; int32 blocksInBitmap = fNumGroups * fBlocksPerGroup;
int32 blockSize = fVolume->BlockSize(); int32 blockSize = fVolume->BlockSize();
for (int32 i = 0; i < blocksInBitmap; i += 512) { for (int32 i = 0; i < blocksInBitmap; i += 512) {
Transaction transaction(fVolume, 1 + i); Transaction transaction(fVolume, 1 + i);
int32 blocksToWrite = 512; int32 blocksToWrite = 512;
if (blocksToWrite + i > blocksInBitmap) if (blocksToWrite + i > blocksInBitmap)
blocksToWrite = blocksInBitmap - i; blocksToWrite = blocksInBitmap - i;
@@ -943,7 +945,7 @@ BlockAllocator::CheckBitmapIsUsedAt(off_t block) const
if (index > size / 4) if (index > size / 4)
return false; return false;
return fCheckBitmap[index] & (1UL << (block & 0x1f)); return BFS_ENDIAN_TO_HOST_INT32(fCheckBitmap[index]) & (1UL << (block & 0x1f));
} }
@@ -955,18 +957,18 @@ BlockAllocator::SetCheckBitmapAt(off_t block)
if (index > size / 4) if (index > size / 4)
return; return;
fCheckBitmap[index] |= (1UL << (block & 0x1f)); fCheckBitmap[index] |= HOST_ENDIAN_TO_BFS_INT32(1UL << (block & 0x1f));
} }
status_t status_t
BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *control) BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *control)
{ {
if (run.allocation_group < 0 || run.allocation_group >= fNumGroups if (run.AllocationGroup() < 0 || run.AllocationGroup() >= fNumGroups
|| run.start > fGroups[run.allocation_group].fNumBits || run.Start() > fGroups[run.allocation_group].fNumBits
|| uint32(run.start + run.length) > fGroups[run.allocation_group].fNumBits || uint32(run.Start() + run.Length()) > fGroups[run.AllocationGroup()].fNumBits
|| run.length == 0) { || run.length == 0) {
PRINT(("%s: block_run(%ld, %u, %u) is invalid!\n", type, run.allocation_group, run.start, run.length)); PRINT(("%s: block_run(%ld, %u, %u) is invalid!\n", type, run.AllocationGroup(), run.Start(), run.Length()));
if (control == NULL) if (control == NULL)
return B_BAD_DATA; return B_BAD_DATA;
@@ -975,16 +977,16 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
} }
uint32 bitsPerBlock = fVolume->BlockSize() << 3; uint32 bitsPerBlock = fVolume->BlockSize() << 3;
uint32 block = run.start / bitsPerBlock; uint32 block = run.Start() / bitsPerBlock;
uint32 pos = run.start % bitsPerBlock; uint32 pos = run.Start() % bitsPerBlock;
int32 length = 0; int32 length = 0;
off_t firstMissing = -1, firstSet = -1; off_t firstMissing = -1, firstSet = -1;
off_t firstGroupBlock = (off_t)run.allocation_group << fVolume->AllocationGroupShift(); off_t firstGroupBlock = (off_t)run.AllocationGroup() << fVolume->AllocationGroupShift();
AllocationBlock cached(fVolume); AllocationBlock cached(fVolume);
for (; block < fBlocksPerGroup && length < run.length; block++, pos = 0) { for (; block < fBlocksPerGroup && length < run.Length(); block++, pos = 0) {
if (cached.SetTo(fGroups[run.allocation_group], block) < B_OK) if (cached.SetTo(fGroups[run.AllocationGroup()], block) < B_OK)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
if (pos >= cached.NumBlockBits()) { if (pos >= cached.NumBlockBits()) {
@@ -992,10 +994,10 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
} }
while (length < run.length && pos < cached.NumBlockBits()) { while (length < run.Length() && pos < cached.NumBlockBits()) {
if (!cached.IsUsed(pos)) { if (!cached.IsUsed(pos)) {
if (control == NULL) { if (control == NULL) {
PRINT(("%s: block_run(%ld, %u, %u) is only partially allocated!\n", type, run.allocation_group, run.start, run.length)); PRINT(("%s: block_run(%ld, %u, %u) is only partially allocated!\n", type, run.AllocationGroup(), run.Start(), run.Length()));
return B_BAD_DATA; return B_BAD_DATA;
} }
if (firstMissing == -1) { if (firstMissing == -1) {
@@ -1004,7 +1006,8 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
} }
control->stats.missing++; control->stats.missing++;
} else if (firstMissing != -1) { } else if (firstMissing != -1) {
PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are not allocated!\n", type, run.allocation_group, run.start, run.length, firstMissing, firstGroupBlock + pos + block * bitsPerBlock - 1)); PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are not allocated!\n",
type, run.allocation_group, run.start, run.length, firstMissing, firstGroupBlock + pos + block * bitsPerBlock - 1));
firstMissing = -1; firstMissing = -1;
} }
@@ -1020,7 +1023,8 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
control->stats.already_set++; control->stats.already_set++;
} else { } else {
if (firstSet != -1) { if (firstSet != -1) {
FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are already set!\n", type, run.allocation_group, run.start, run.length, firstSet, firstGroupBlock + offset - 1)); FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are already set!\n",
type, run.AllocationGroup(), run.Start(), run.Length(), firstSet, firstGroupBlock + offset - 1));
firstSet = -1; firstSet = -1;
} }
SetCheckBitmapAt(firstGroupBlock + offset); SetCheckBitmapAt(firstGroupBlock + offset);
@@ -1030,11 +1034,11 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
pos++; pos++;
} }
if (block + 1 >= fBlocksPerGroup || length >= run.length) { if (block + 1 >= fBlocksPerGroup || length >= run.Length()) {
if (firstMissing != -1) if (firstMissing != -1)
PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are not allocated!\n", type, run.allocation_group, run.start, run.length, firstMissing, firstGroupBlock + pos + block * bitsPerBlock - 1)); PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are not allocated!\n", type, run.AllocationGroup(), run.Start(), run.Length(), firstMissing, firstGroupBlock + pos + block * bitsPerBlock - 1));
if (firstSet != -1) if (firstSet != -1)
FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are already set!\n", type, run.allocation_group, run.start, run.length, firstSet, firstGroupBlock + pos + block * bitsPerBlock - 1)); FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are already set!\n", type, run.AllocationGroup(), run.Start(), run.Length(), firstSet, firstGroupBlock + pos + block * bitsPerBlock - 1));
} }
} }
@@ -1059,10 +1063,10 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
// check the direct range // check the direct range
if (data->max_direct_range) { if (data->max_direct_range) {
for (int32 i = 0;i < NUM_DIRECT_BLOCKS;i++) { for (int32 i = 0; i < NUM_DIRECT_BLOCKS; i++) {
if (data->direct[i].IsZero()) if (data->direct[i].IsZero())
break; break;
status = CheckBlockRun(data->direct[i], "direct", control); status = CheckBlockRun(data->direct[i], "direct", control);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -1080,7 +1084,7 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
off_t block = fVolume->ToBlock(data->indirect); off_t block = fVolume->ToBlock(data->indirect);
for (int32 i = 0; i < data->indirect.length; i++) { for (int32 i = 0; i < data->indirect.Length(); i++) {
block_run *runs = (block_run *)cached.SetTo(block + i); block_run *runs = (block_run *)cached.SetTo(block + i);
if (runs == NULL) if (runs == NULL)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
@@ -1111,7 +1115,8 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
int32 runsPerArray = runsPerBlock << ARRAY_BLOCKS_SHIFT; int32 runsPerArray = runsPerBlock << ARRAY_BLOCKS_SHIFT;
CachedBlock cachedDirect(fVolume); CachedBlock cachedDirect(fVolume);
int32 maxIndirectIndex = (data->double_indirect.length << fVolume->BlockShift()) / sizeof(block_run); int32 maxIndirectIndex = (data->double_indirect.Length() << fVolume->BlockShift())
/ sizeof(block_run);
for (int32 indirectIndex = 0; indirectIndex < maxIndirectIndex; indirectIndex++) { for (int32 indirectIndex = 0; indirectIndex < maxIndirectIndex; indirectIndex++) {
// get the indirect array block // get the indirect array block
@@ -1129,7 +1134,7 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
if (status < B_OK) if (status < B_OK)
return status; return status;
int32 maxIndex = (indirect.length << fVolume->BlockShift()) / sizeof(block_run); int32 maxIndex = (indirect.Length() << fVolume->BlockShift()) / sizeof(block_run);
for (int32 index = 0; index < maxIndex; ) { for (int32 index = 0; index < maxIndex; ) {
block_run *runs = (block_run *)cachedDirect.SetTo(fVolume->ToBlock(indirect) block_run *runs = (block_run *)cachedDirect.SetTo(fVolume->ToBlock(indirect)
+123 -121
View File
@@ -76,22 +76,23 @@ InodeAllocator::New(block_run *parentRun, mode_t mode, block_run &run, Inode **_
bfs_inode *node = fInode->Node(); bfs_inode *node = fInode->Node();
node->magic1 = INODE_MAGIC1; node->magic1 = HOST_ENDIAN_TO_BFS_INT32(INODE_MAGIC1);
node->inode_num = run; node->inode_num = run;
node->mode = mode; node->mode = HOST_ENDIAN_TO_BFS_INT32(mode);
node->flags = INODE_IN_USE | INODE_NOT_READY; node->flags = HOST_ENDIAN_TO_BFS_INT32(INODE_IN_USE | INODE_NOT_READY);
// INODE_NOT_READY prevents the inode from being opened - it is // INODE_NOT_READY prevents the inode from being opened - it is
// cleared in InodeAllocator::Keep() // cleared in InodeAllocator::Keep()
node->etc = (uint32)fInode; node->etc = (uint32)fInode;
// this is temporarily set along INODE_NOT_READY and lets bfs_read_vnode() // this is temporarily set along INODE_NOT_READY and lets bfs_read_vnode()
// find the associated Inode object // find the associated Inode object
node->create_time = (bigtime_t)time(NULL) << INODE_TIME_SHIFT; node->create_time = HOST_ENDIAN_TO_BFS_INT64((bigtime_t)time(NULL) << INODE_TIME_SHIFT);
node->last_modified_time = node->create_time | (volume->GetUniqueID() & INODE_TIME_MASK); node->last_modified_time = HOST_ENDIAN_TO_BFS_INT64(node->create_time
| (volume->GetUniqueID() & INODE_TIME_MASK));
// we use Volume::GetUniqueID() to avoid having too many duplicates in the // we use Volume::GetUniqueID() to avoid having too many duplicates in the
// last_modified index // last_modified index
node->inode_size = volume->InodeSize(); node->inode_size = HOST_ENDIAN_TO_BFS_INT32(volume->InodeSize());
*_inode = fInode; *_inode = fInode;
return B_OK; return B_OK;
@@ -105,7 +106,7 @@ InodeAllocator::CreateTree()
// force S_STR_INDEX to be set, if no type is set // force S_STR_INDEX to be set, if no type is set
if ((fInode->Mode() & S_INDEX_TYPES) == 0) if ((fInode->Mode() & S_INDEX_TYPES) == 0)
fInode->Node()->mode |= S_STR_INDEX; fInode->Node()->mode |= HOST_ENDIAN_TO_BFS_INT32(S_STR_INDEX);
BPlusTree *tree = fInode->fTree = new BPlusTree(fTransaction, fInode); BPlusTree *tree = fInode->fTree = new BPlusTree(fTransaction, fInode);
if (tree == NULL || tree->InitCheck() < B_OK) if (tree == NULL || tree->InitCheck() < B_OK)
@@ -146,20 +147,20 @@ bfs_inode::InitCheck(Volume *volume)
return B_BUSY; return B_BUSY;
} }
if (magic1 != INODE_MAGIC1 if (Magic1() != INODE_MAGIC1
|| !(flags & INODE_IN_USE) || !(Flags() & INODE_IN_USE)
|| inode_num.length != 1 || inode_num.Length() != 1
// matches inode size? // matches inode size?
|| (uint32)inode_size != volume->InodeSize() || (uint32)InodeSize() != volume->InodeSize()
// parent resides on disk? // parent resides on disk?
|| parent.allocation_group > int32(volume->AllocationGroups()) || parent.AllocationGroup() > int32(volume->AllocationGroups())
|| parent.allocation_group < 0 || parent.AllocationGroup() < 0
|| parent.start > (1L << volume->AllocationGroupShift()) || parent.Start() > (1L << volume->AllocationGroupShift())
|| parent.length != 1 || parent.Length() != 1
// attributes, too? // attributes, too?
|| attributes.allocation_group > int32(volume->AllocationGroups()) || attributes.AllocationGroup() > int32(volume->AllocationGroups())
|| attributes.allocation_group < 0 || attributes.AllocationGroup() < 0
|| attributes.start > (1L << volume->AllocationGroupShift())) || attributes.Start() > (1L << volume->AllocationGroupShift()))
RETURN_ERROR(B_BAD_DATA); RETURN_ERROR(B_BAD_DATA);
// ToDo: Add some tests to check the integrity of the other stuff here, // ToDo: Add some tests to check the integrity of the other stuff here,
@@ -200,10 +201,10 @@ void
Inode::Initialize() Inode::Initialize()
{ {
char lockName[32]; char lockName[32];
sprintf(lockName, "bfs inode %ld.%d", BlockRun().allocation_group, BlockRun().start); sprintf(lockName, "bfs inode %ld.%d", BlockRun().AllocationGroup(), BlockRun().Start());
fLock.Initialize(lockName); fLock.Initialize(lockName);
Node()->flags &= INODE_PERMANENT_FLAGS; Node()->flags &= HOST_ENDIAN_TO_BFS_INT32(INODE_PERMANENT_FLAGS);
// these two will help to maintain the indices // these two will help to maintain the indices
fOldSize = Size(); fOldSize = Size();
@@ -251,9 +252,9 @@ Inode::CheckPermissions(int accessMode) const
// shift mode bits, to check directly against accessMode // shift mode bits, to check directly against accessMode
mode_t mode = Mode(); mode_t mode = Mode();
if (user == (uid_t)Node()->uid) if (user == (uid_t)Node()->UserID())
mode >>= 6; mode >>= 6;
else if (group == (gid_t)Node()->gid) else if (group == (gid_t)Node()->GroupID())
mode >>= 3; mode >>= 3;
if (accessMode & ~(mode & S_IRWXO)) if (accessMode & ~(mode & S_IRWXO))
@@ -327,11 +328,11 @@ Inode::MakeSpaceForSmallData(Transaction *transaction, const char *name, int32 b
// Luckily, this doesn't cause any index updates // Luckily, this doesn't cause any index updates
Inode *attribute; Inode *attribute;
status_t status = CreateAttribute(transaction, item->Name(), item->type, &attribute); status_t status = CreateAttribute(transaction, item->Name(), item->Type(), &attribute);
if (status < B_OK) if (status < B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
size_t length = item->data_size; size_t length = item->DataSize();
status = attribute->WriteAt(transaction, 0, item->Data(), &length); status = attribute->WriteAt(transaction, 0, item->Data(), &length);
ReleaseAttribute(attribute); ReleaseAttribute(attribute);
@@ -466,18 +467,18 @@ Inode::AddSmallData(Transaction *transaction, const char *name, uint32 type,
// try to change the attributes value // try to change the attributes value
if (item->data_size > length if (item->data_size > length
|| force || force
|| ((uint8 *)last + length - item->data_size) <= ((uint8 *)Node() + fVolume->InodeSize())) { || ((uint8 *)last + length - item->DataSize()) <= ((uint8 *)Node() + fVolume->InodeSize())) {
// make room for the new attribute if needed (and we are forced to do so) // make room for the new attribute if needed (and we are forced to do so)
if (force if (force
&& ((uint8 *)last + length - item->data_size) > ((uint8 *)Node() + fVolume->InodeSize())) { && ((uint8 *)last + length - item->DataSize()) > ((uint8 *)Node() + fVolume->InodeSize())) {
// We also take the free space at the end of the small_data section // We also take the free space at the end of the small_data section
// into account, and request only what's really needed // into account, and request only what's really needed
uint32 needed = length - item->data_size - uint32 needed = length - item->DataSize() -
(uint32)((uint8 *)Node() + fVolume->InodeSize() - (uint8 *)last); (uint32)((uint8 *)Node() + fVolume->InodeSize() - (uint8 *)last);
if (MakeSpaceForSmallData(transaction, name, needed) < B_OK) if (MakeSpaceForSmallData(transaction, name, needed) < B_OK)
return B_ERROR; return B_ERROR;
// reset our pointers // reset our pointers
item = Node()->small_data_start; item = Node()->small_data_start;
index = 0; index = 0;
@@ -502,8 +503,8 @@ Inode::AddSmallData(Transaction *transaction, const char *name, uint32 type,
if ((uint8 *)last < (uint8 *)Node() + fVolume->BlockSize()) if ((uint8 *)last < (uint8 *)Node() + fVolume->BlockSize())
memset(last, 0, (uint8 *)Node() + fVolume->BlockSize() - (uint8 *)last); memset(last, 0, (uint8 *)Node() + fVolume->BlockSize() - (uint8 *)last);
item->type = type; item->type = HOST_ENDIAN_TO_BFS_INT32(type);
item->data_size = length; item->data_size = HOST_ENDIAN_TO_BFS_INT16(length);
memcpy(item->Data(), data, length); memcpy(item->Data(), data, length);
item->Data()[length] = '\0'; item->Data()[length] = '\0';
@@ -539,9 +540,9 @@ Inode::AddSmallData(Transaction *transaction, const char *name, uint32 type,
} }
memset(item, 0, spaceNeeded); memset(item, 0, spaceNeeded);
item->type = type; item->type = HOST_ENDIAN_TO_BFS_INT32(type);
item->name_size = nameLength; item->name_size = HOST_ENDIAN_TO_BFS_INT16(nameLength);
item->data_size = length; item->data_size = HOST_ENDIAN_TO_BFS_INT16(length);
strcpy(item->Name(), name); strcpy(item->Name(), name);
memcpy(item->Data(), data, length); memcpy(item->Data(), data, length);
@@ -628,7 +629,7 @@ Inode::Name() const
small_data *smallData = NULL; small_data *smallData = NULL;
while (GetNextSmallData(&smallData) == B_OK) { while (GetNextSmallData(&smallData) == B_OK) {
if (*smallData->Name() == FILE_NAME_NAME && smallData->name_size == FILE_NAME_NAME_LENGTH) if (*smallData->Name() == FILE_NAME_NAME && smallData->NameSize() == FILE_NAME_NAME_LENGTH)
return (const char *)smallData->Data(); return (const char *)smallData->Data();
} }
return NULL; return NULL;
@@ -694,8 +695,8 @@ Inode::ReadAttribute(const char *name, int32 type, off_t pos, uint8 *buffer, siz
*_length = 0; *_length = 0;
return B_OK; return B_OK;
} }
if (length + pos > smallData->data_size) if (length + pos > smallData->DataSize())
length = smallData->data_size - pos; length = smallData->DataSize() - pos;
memcpy(buffer, smallData->Data() + pos, length); memcpy(buffer, smallData->Data() + pos, length);
*_length = length; *_length = length;
@@ -749,7 +750,7 @@ Inode::WriteAttribute(Transaction *transaction, const char *name, int32 type, of
small_data *smallData = FindSmallData(name); small_data *smallData = FindSmallData(name);
if (smallData != NULL) { if (smallData != NULL) {
oldLength = smallData->data_size; oldLength = smallData->DataSize();
if (oldLength > BPLUSTREE_MAX_KEY_LENGTH) if (oldLength > BPLUSTREE_MAX_KEY_LENGTH)
oldLength = BPLUSTREE_MAX_KEY_LENGTH; oldLength = BPLUSTREE_MAX_KEY_LENGTH;
memcpy(oldData = oldBuffer, smallData->Data(), oldLength); memcpy(oldData = oldBuffer, smallData->Data(), oldLength);
@@ -820,10 +821,10 @@ Inode::RemoveAttribute(Transaction *transaction, const char *name)
small_data *smallData = FindSmallData(name); small_data *smallData = FindSmallData(name);
if (smallData != NULL) { if (smallData != NULL) {
uint32 length = smallData->data_size; uint32 length = smallData->DataSize();
if (length > BPLUSTREE_MAX_KEY_LENGTH) if (length > BPLUSTREE_MAX_KEY_LENGTH)
length = BPLUSTREE_MAX_KEY_LENGTH; length = BPLUSTREE_MAX_KEY_LENGTH;
index.Update(transaction, name, smallData->type, smallData->Data(), length, NULL, 0, this); index.Update(transaction, name, smallData->Type(), smallData->Data(), length, NULL, 0, this);
} }
fSmallDataLock.Unlock(); fSmallDataLock.Unlock();
} }
@@ -857,7 +858,7 @@ Inode::RemoveAttribute(Transaction *transaction, const char *name)
// remove attribute directory (don't fail if that can't be done) // remove attribute directory (don't fail if that can't be done)
if (remove_vnode(fVolume->ID(), attributes->ID()) == B_OK) { if (remove_vnode(fVolume->ID(), attributes->ID()) == B_OK) {
// update the inode, so that no one will ever doubt it's deleted :-) // update the inode, so that no one will ever doubt it's deleted :-)
attributes->Node()->flags |= INODE_DELETED; attributes->Node()->flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_DELETED);
if (attributes->WriteBack(transaction) == B_OK) { if (attributes->WriteBack(transaction) == B_OK) {
Attributes().SetTo(0, 0, 0); Attributes().SetTo(0, 0, 0);
WriteBack(transaction); WriteBack(transaction);
@@ -1103,12 +1104,12 @@ Inode::FillGapWithZeros(off_t pos, off_t newSize)
while (length > 0) { while (length > 0) {
// offset is the offset to the current pos in the block_run // offset is the offset to the current pos in the block_run
run.start += (pos - offset) >> blockShift; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length -= (pos - offset) >> blockShift; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
off_t blockNumber = fVolume->ToBlock(run); off_t blockNumber = fVolume->ToBlock(run);
for (int32 i = 0; i < run.length; i++) { for (int32 i = 0; i < run.Length(); i++) {
if ((block = cached.SetTo(blockNumber + i, true)) == NULL) if ((block = cached.SetTo(blockNumber + i, true)) == NULL)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
@@ -1116,7 +1117,7 @@ Inode::FillGapWithZeros(off_t pos, off_t newSize)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
} }
int32 bytes = run.length << blockShift; int32 bytes = run.Length() << blockShift;
length -= bytes; length -= bytes;
bytesWritten += bytes; bytesWritten += bytes;
@@ -1152,7 +1153,7 @@ Inode::AllocateBlockArray(Transaction *transaction, block_run &run)
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
off_t block = fVolume->ToBlock(run); off_t block = fVolume->ToBlock(run);
for (int32 i = 0;i < run.length;i++) { for (int32 i = 0; i < run.Length(); i++) {
block_run *runs = (block_run *)cached.SetTo(block + i, true); block_run *runs = (block_run *)cached.SetTo(block + i, true);
if (runs == NULL) if (runs == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -1171,26 +1172,26 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// is the data stream already large enough to hold the new size? // is the data stream already large enough to hold the new size?
// (can be the case with preallocated blocks) // (can be the case with preallocated blocks)
if (size < data->max_direct_range if (size < data->MaxDirectRange()
|| size < data->max_indirect_range || size < data->MaxIndirectRange()
|| size < data->max_double_indirect_range) { || size < data->MaxDoubleIndirectRange()) {
data->size = size; data->size = HOST_ENDIAN_TO_BFS_INT64(size);
return B_OK; return B_OK;
} }
// how many bytes are still needed? (unused ranges are always zero) // how many bytes are still needed? (unused ranges are always zero)
uint16 minimum = 1; uint16 minimum = 1;
off_t bytes; off_t bytes;
if (data->size < data->max_double_indirect_range) { if (data->Size() < data->MaxDoubleIndirectRange()) {
bytes = size - data->max_double_indirect_range; bytes = size - data->MaxDoubleIndirectRange();
// the double indirect range can only handle multiple of NUM_ARRAY_BLOCKS // the double indirect range can only handle multiple of NUM_ARRAY_BLOCKS
minimum = NUM_ARRAY_BLOCKS; minimum = NUM_ARRAY_BLOCKS;
} else if (data->size < data->max_indirect_range) } else if (data->Size() < data->MaxIndirectRange())
bytes = size - data->max_indirect_range; bytes = size - data->MaxIndirectRange();
else if (data->size < data->max_direct_range) else if (data->Size() < data->MaxDirectRange())
bytes = size - data->max_direct_range; bytes = size - data->MaxDirectRange();
else else
bytes = size - data->size; bytes = size - data->Size();
// do we have enough free blocks on the disk? // do we have enough free blocks on the disk?
off_t blocksRequested = (bytes + fVolume->BlockSize() - 1) >> fVolume->BlockShift(); off_t blocksRequested = (bytes + fVolume->BlockSize() - 1) >> fVolume->BlockShift();
@@ -1221,7 +1222,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// ToDo: if anything goes wrong here, we probably want to free the // ToDo: if anything goes wrong here, we probably want to free the
// blocks that couldn't be distributed into the stream! // blocks that couldn't be distributed into the stream!
blocksNeeded -= run.length; blocksNeeded -= run.Length();
// don't preallocate if the first allocation was already too small // don't preallocate if the first allocation was already too small
blocksRequested = blocksNeeded; blocksRequested = blocksNeeded;
if (minimum > 1) { if (minimum > 1) {
@@ -1231,10 +1232,10 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// Direct block range // Direct block range
if (data->size <= data->max_direct_range) { if (data->Size() <= data->MaxDirectRange()) {
// let's try to put them into the direct block range // let's try to put them into the direct block range
int32 free = 0; int32 free = 0;
for (;free < NUM_DIRECT_BLOCKS;free++) for (; free < NUM_DIRECT_BLOCKS; free++)
if (data->direct[free].IsZero()) if (data->direct[free].IsZero())
break; break;
@@ -1242,19 +1243,19 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// can we merge the last allocated run with the new one? // can we merge the last allocated run with the new one?
int32 last = free - 1; int32 last = free - 1;
if (free > 0 && data->direct[last].MergeableWith(run)) if (free > 0 && data->direct[last].MergeableWith(run))
data->direct[last].length += run.length; data->direct[last].length = HOST_ENDIAN_TO_BFS_INT16(data->direct[last].Length() + run.Length());
else else
data->direct[free] = run; data->direct[free] = run;
data->max_direct_range += run.length * fVolume->BlockSize(); data->max_direct_range = HOST_ENDIAN_TO_BFS_INT64(data->MaxDirectRange() + run.Length() * fVolume->BlockSize());
data->size = blocksNeeded > 0 ? data->max_direct_range : size; data->size = HOST_ENDIAN_TO_BFS_INT64(blocksNeeded > 0 ? data->max_direct_range : size);
continue; continue;
} }
} }
// Indirect block range // Indirect block range
if (data->size <= data->max_indirect_range || !data->max_indirect_range) { if (data->Size() <= data->MaxIndirectRange() || !data->MaxIndirectRange()) {
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
block_run *runs = NULL; block_run *runs = NULL;
uint32 free = 0; uint32 free = 0;
@@ -1266,7 +1267,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
if (status < B_OK) if (status < B_OK)
return status; return status;
data->max_indirect_range = data->max_direct_range; data->max_indirect_range = HOST_ENDIAN_TO_BFS_INT64(data->MaxDirectRange());
// insert the block_run in the first block // insert the block_run in the first block
runs = (block_run *)cached.SetTo(data->indirect); runs = (block_run *)cached.SetTo(data->indirect);
} else { } else {
@@ -1275,7 +1276,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// search first empty entry // search first empty entry
int32 i = 0; int32 i = 0;
for (; i < data->indirect.length; i++) { for (; i < data->indirect.Length(); i++) {
if ((runs = (block_run *)cached.SetTo(block + i)) == NULL) if ((runs = (block_run *)cached.SetTo(block + i)) == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -1286,7 +1287,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
if (free < numberOfRuns) if (free < numberOfRuns)
break; break;
} }
if (i == data->indirect.length) if (i == data->indirect.Length())
runs = NULL; runs = NULL;
} }
@@ -1295,12 +1296,12 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// take block borders into account, so it could be further optimized // take block borders into account, so it could be further optimized
int32 last = free - 1; int32 last = free - 1;
if (free > 0 && runs[last].MergeableWith(run)) if (free > 0 && runs[last].MergeableWith(run))
runs[last].length += run.length; runs[last].length = HOST_ENDIAN_TO_BFS_INT16(runs[last].Length() + run.Length());
else else
runs[free] = run; runs[free] = run;
data->max_indirect_range += run.length << fVolume->BlockShift(); data->max_indirect_range = HOST_ENDIAN_TO_BFS_INT64(data->MaxIndirectRange() + (run.Length() << fVolume->BlockShift()));
data->size = blocksNeeded > 0 ? data->max_indirect_range : size; data->size = HOST_ENDIAN_TO_BFS_INT64(blocksNeeded > 0 ? data->MaxIndirectRange() : size);
cached.WriteBack(transaction); cached.WriteBack(transaction);
continue; continue;
@@ -1309,18 +1310,18 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// Double indirect block range // Double indirect block range
if (data->size <= data->max_double_indirect_range || !data->max_double_indirect_range) { if (data->Size() <= data->MaxDoubleIndirectRange() || !data->max_double_indirect_range) {
while ((run.length % NUM_ARRAY_BLOCKS) != 0) { while ((run.Length() % NUM_ARRAY_BLOCKS) != 0) {
// The number of allocated blocks isn't a multiple of NUM_ARRAY_BLOCKS, // The number of allocated blocks isn't a multiple of NUM_ARRAY_BLOCKS,
// so we have to change this. This can happen the first time the stream // so we have to change this. This can happen the first time the stream
// grows into the double indirect range. // grows into the double indirect range.
// First, free the remaining blocks that don't fit into a multiple // First, free the remaining blocks that don't fit into a multiple
// of NUM_ARRAY_BLOCKS // of NUM_ARRAY_BLOCKS
int32 rest = run.length % NUM_ARRAY_BLOCKS; int32 rest = run.Length() % NUM_ARRAY_BLOCKS;
run.length -= rest; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - rest);
status = fVolume->Free(transaction, block_run::Run(run.allocation_group, status = fVolume->Free(transaction, block_run::Run(run.AllocationGroup(),
run.start + run.length, rest)); run.Start() + run.Length(), rest));
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -1352,7 +1353,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
int32 directSize = NUM_ARRAY_BLOCKS << fVolume->BlockShift(); int32 directSize = NUM_ARRAY_BLOCKS << fVolume->BlockShift();
int32 runsPerArray = runsPerBlock << ARRAY_BLOCKS_SHIFT; int32 runsPerArray = runsPerBlock << ARRAY_BLOCKS_SHIFT;
off_t start = data->max_double_indirect_range - data->max_indirect_range; off_t start = data->MaxDoubleIndirectRange() - data->MaxIndirectRange();
int32 indirectIndex = start / indirectSize; int32 indirectIndex = start / indirectSize;
int32 index = start / directSize; int32 index = start / directSize;
@@ -1362,7 +1363,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
CachedBlock cachedDirect(fVolume); CachedBlock cachedDirect(fVolume);
block_run *array = NULL; block_run *array = NULL;
uint32 runLength = run.length; uint32 runLength = run.Length();
// ToDo: the following code is commented - it could be used to // ToDo: the following code is commented - it could be used to
// preallocate all needed block arrays to see in advance if the // preallocate all needed block arrays to see in advance if the
@@ -1394,15 +1395,15 @@ Inode::GrowStream(Transaction *transaction, off_t size)
} }
*/ */
while (run.length) { while (run.length != 0) {
// get the indirect array block // get the indirect array block
if (array == NULL) { if (array == NULL) {
if (cached.Block() != NULL if (cached.Block() != NULL
&& cached.WriteBack(transaction) < B_OK) && cached.WriteBack(transaction) < B_OK)
return B_IO_ERROR; return B_IO_ERROR;
array = (block_run *)cached.SetTo(fVolume->ToBlock(data->double_indirect) + array = (block_run *)cached.SetTo(fVolume->ToBlock(data->double_indirect)
indirectIndex / runsPerBlock); + indirectIndex / runsPerBlock);
if (array == NULL) if (array == NULL)
return B_IO_ERROR; return B_IO_ERROR;
} }
@@ -1424,11 +1425,11 @@ Inode::GrowStream(Transaction *transaction, off_t size)
do { do {
// insert the block_run into the array // insert the block_run into the array
runs[index % runsPerBlock] = run; runs[index % runsPerBlock] = run;
runs[index % runsPerBlock].length = NUM_ARRAY_BLOCKS; runs[index % runsPerBlock].length = HOST_ENDIAN_TO_BFS_INT16(NUM_ARRAY_BLOCKS);
// alter the remaining block_run // alter the remaining block_run
run.start += NUM_ARRAY_BLOCKS; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + NUM_ARRAY_BLOCKS);
run.length -= NUM_ARRAY_BLOCKS; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - NUM_ARRAY_BLOCKS);
} while ((++index % runsPerBlock) != 0 && run.length); } while ((++index % runsPerBlock) != 0 && run.length);
if (cachedDirect.WriteBack(transaction) < B_OK) if (cachedDirect.WriteBack(transaction) < B_OK)
@@ -1441,8 +1442,8 @@ Inode::GrowStream(Transaction *transaction, off_t size)
} }
} }
data->max_double_indirect_range += runLength << fVolume->BlockShift(); data->max_double_indirect_range = HOST_ENDIAN_TO_BFS_INT64(data->MaxDoubleIndirectRange() + (runLength << fVolume->BlockShift()));
data->size = blocksNeeded > 0 ? data->max_double_indirect_range : size; data->size = blocksNeeded > 0 ? HOST_ENDIAN_TO_BFS_INT64(data->max_double_indirect_range) : size;
continue; continue;
} }
@@ -1450,7 +1451,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
RETURN_ERROR(EFBIG); RETURN_ERROR(EFBIG);
} }
// update the size of the data stream // update the size of the data stream
data->size = size; data->size = HOST_ENDIAN_TO_BFS_INT64(size);
return B_OK; return B_OK;
} }
@@ -1482,7 +1483,7 @@ Inode::FreeStaticStreamArray(Transaction *transaction, int32 level, block_run ru
// set the file offset to the current block run // set the file offset to the current block run
offset += (off_t)index * indirectSize; offset += (off_t)index * indirectSize;
for (int32 i = index / runsPerBlock; i < run.length; i++) { for (int32 i = index / runsPerBlock; i < run.Length(); i++) {
block_run *array = (block_run *)cached.SetTo(blockNumber + i); block_run *array = (block_run *)cached.SetTo(blockNumber + i);
if (array == NULL) if (array == NULL)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
@@ -1490,7 +1491,7 @@ Inode::FreeStaticStreamArray(Transaction *transaction, int32 level, block_run ru
for (index = index % runsPerBlock; index < runsPerBlock; index++) { for (index = index % runsPerBlock; index < runsPerBlock; index++) {
if (array[index].IsZero()) { if (array[index].IsZero()) {
// we also want to break out of the outer loop // we also want to break out of the outer loop
i = run.length; i = run.Length();
break; break;
} }
@@ -1500,7 +1501,7 @@ Inode::FreeStaticStreamArray(Transaction *transaction, int32 level, block_run ru
else if (offset >= size) else if (offset >= size)
status = fVolume->Free(transaction, array[index]); status = fVolume->Free(transaction, array[index]);
else else
max = offset + indirectSize; max = HOST_ENDIAN_TO_BFS_INT64(offset + indirectSize);
if (status < B_OK) if (status < B_OK)
RETURN_ERROR(status); RETURN_ERROR(status);
@@ -1523,6 +1524,7 @@ Inode::FreeStaticStreamArray(Transaction *transaction, int32 level, block_run ru
* "offset" and "max" are maintained until the last block_run that doesn't * "offset" and "max" are maintained until the last block_run that doesn't
* have to be freed - after this, the values won't be correct anymore, but * have to be freed - after this, the values won't be correct anymore, but
* will still assure correct function for all subsequent calls. * will still assure correct function for all subsequent calls.
* "max" is considered to be in file system byte order.
*/ */
status_t status_t
@@ -1535,7 +1537,7 @@ Inode::FreeStreamArray(Transaction *transaction, block_run *array, uint32 arrayL
if (array[i].IsZero()) if (array[i].IsZero())
break; break;
newOffset += (off_t)array[i].length << fVolume->BlockShift(); newOffset += (off_t)array[i].Length() << fVolume->BlockShift();
if (newOffset <= size) if (newOffset <= size)
continue; continue;
@@ -1545,20 +1547,20 @@ Inode::FreeStreamArray(Transaction *transaction, block_run *array, uint32 arrayL
if (newOffset > size && offset < size) { if (newOffset > size && offset < size) {
// free partial block_run (and update the original block_run) // free partial block_run (and update the original block_run)
run.start = array[i].start + ((size - offset) >> fVolume->BlockShift()) + 1; run.start = array[i].start + ((size - offset) >> fVolume->BlockShift()) + 1;
array[i].length = run.start - array[i].start; array[i].length = HOST_ENDIAN_TO_BFS_INT16(run.Start() - array[i].Start());
run.length -= array[i].length; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - array[i].Length());
if (run.length == 0) if (run.length == 0)
continue; continue;
// update maximum range // update maximum range
max = offset + ((off_t)array[i].length << fVolume->BlockShift()); max = HOST_ENDIAN_TO_BFS_INT64(offset + ((off_t)array[i].Length() << fVolume->BlockShift()));
} else { } else {
// free the whole block_run // free the whole block_run
array[i].SetTo(0, 0, 0); array[i].SetTo(0, 0, 0);
if (max > offset) if ((off_t)BFS_ENDIAN_TO_HOST_INT64(max) > offset)
max = offset; max = HOST_ENDIAN_TO_BFS_INT64(offset);
} }
if (fVolume->Free(transaction, run) < B_OK) if (fVolume->Free(transaction, run) < B_OK)
@@ -1573,22 +1575,22 @@ Inode::ShrinkStream(Transaction *transaction, off_t size)
{ {
data_stream *data = &Node()->data; data_stream *data = &Node()->data;
if (data->max_double_indirect_range > size) { if (data->MaxDoubleIndirectRange() > size) {
FreeStaticStreamArray(transaction, 0, data->double_indirect, size, FreeStaticStreamArray(transaction, 0, data->double_indirect, size,
data->max_indirect_range, data->max_double_indirect_range); data->MaxIndirectRange(), data->max_double_indirect_range);
if (size <= data->max_indirect_range) { if (size <= data->MaxIndirectRange()) {
fVolume->Free(transaction, data->double_indirect); fVolume->Free(transaction, data->double_indirect);
data->double_indirect.SetTo(0, 0, 0); data->double_indirect.SetTo(0, 0, 0);
data->max_double_indirect_range = 0; data->max_double_indirect_range = 0;
} }
} }
if (data->max_indirect_range > size) { if (data->MaxIndirectRange() > size) {
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
off_t block = fVolume->ToBlock(data->indirect); off_t block = fVolume->ToBlock(data->indirect);
off_t offset = data->max_direct_range; off_t offset = data->MaxDirectRange();
for (int32 i = 0; i < data->indirect.length; i++) { for (int32 i = 0; i < data->indirect.Length(); i++) {
block_run *array = (block_run *)cached.SetTo(block + i); block_run *array = (block_run *)cached.SetTo(block + i);
if (array == NULL) if (array == NULL)
break; break;
@@ -1603,13 +1605,13 @@ Inode::ShrinkStream(Transaction *transaction, off_t size)
data->max_indirect_range = 0; data->max_indirect_range = 0;
} }
} }
if (data->max_direct_range > size) { if (data->MaxDirectRange() > size) {
off_t offset = 0; off_t offset = 0;
FreeStreamArray(transaction, data->direct, NUM_DIRECT_BLOCKS, size, offset, FreeStreamArray(transaction, data->direct, NUM_DIRECT_BLOCKS, size, offset,
data->max_direct_range); data->max_direct_range);
} }
data->size = size; data->size = HOST_ENDIAN_TO_BFS_INT64(size);
return B_OK; return B_OK;
} }
@@ -1624,7 +1626,7 @@ Inode::SetFileSize(Transaction *transaction, off_t size)
|| Flags() & INODE_NO_CACHE) || Flags() & INODE_NO_CACHE)
return B_BAD_VALUE; return B_BAD_VALUE;
off_t oldSize = Node()->data.size; off_t oldSize = Size();
if (size == oldSize) if (size == oldSize)
return B_OK; return B_OK;
@@ -1709,12 +1711,12 @@ Inode::Sync()
// flush direct range // flush direct range
for (int32 i = 0;i < NUM_DIRECT_BLOCKS;i++) { for (int32 i = 0; i < NUM_DIRECT_BLOCKS; i++) {
if (data->direct[i].IsZero()) if (data->direct[i].IsZero())
return B_OK; return B_OK;
status = flush_blocks(fVolume->Device(), fVolume->ToBlock(data->direct[i]), status = flush_blocks(fVolume->Device(), fVolume->ToBlock(data->direct[i]),
data->direct[i].length); data->direct[i].Length());
if (status != B_OK) if (status != B_OK)
return status; return status;
} }
@@ -1728,7 +1730,7 @@ Inode::Sync()
off_t block = fVolume->ToBlock(data->indirect); off_t block = fVolume->ToBlock(data->indirect);
int32 count = fVolume->BlockSize() / sizeof(block_run); int32 count = fVolume->BlockSize() / sizeof(block_run);
for (int32 j = 0; j < data->indirect.length; j++) { for (int32 j = 0; j < data->indirect.Length(); j++) {
block_run *runs = (block_run *)cached.SetTo(block + j); block_run *runs = (block_run *)cached.SetTo(block + j);
if (runs == NULL) if (runs == NULL)
break; break;
@@ -1737,7 +1739,7 @@ Inode::Sync()
if (runs[i].IsZero()) if (runs[i].IsZero())
return B_OK; return B_OK;
status = flush_blocks(fVolume->Device(), fVolume->ToBlock(runs[i]), runs[i].length); status = flush_blocks(fVolume->Device(), fVolume->ToBlock(runs[i]), runs[i].Length());
if (status != B_OK) if (status != B_OK)
return status; return status;
} }
@@ -1750,7 +1752,7 @@ Inode::Sync()
off_t indirectBlock = fVolume->ToBlock(data->double_indirect); off_t indirectBlock = fVolume->ToBlock(data->double_indirect);
for (int32 l = 0; l < data->double_indirect.length; l++) { for (int32 l = 0; l < data->double_indirect.Length(); l++) {
block_run *indirectRuns = (block_run *)cached.SetTo(indirectBlock + l); block_run *indirectRuns = (block_run *)cached.SetTo(indirectBlock + l);
if (indirectRuns == NULL) if (indirectRuns == NULL)
return B_FILE_ERROR; return B_FILE_ERROR;
@@ -1762,7 +1764,7 @@ Inode::Sync()
return B_OK; return B_OK;
block = fVolume->ToBlock(indirectRuns[k]); block = fVolume->ToBlock(indirectRuns[k]);
for (int32 j = 0; j < indirectRuns[k].length; j++) { for (int32 j = 0; j < indirectRuns[k].Length(); j++) {
block_run *runs = (block_run *)directCached.SetTo(block + j); block_run *runs = (block_run *)directCached.SetTo(block + j);
if (runs == NULL) if (runs == NULL)
return B_FILE_ERROR; return B_FILE_ERROR;
@@ -1774,7 +1776,7 @@ Inode::Sync()
// ToDo: combine single block_runs to bigger ones when // ToDo: combine single block_runs to bigger ones when
// they are adjacent // they are adjacent
status = flush_blocks(fVolume->Device(), fVolume->ToBlock(runs[i]), status = flush_blocks(fVolume->Device(), fVolume->ToBlock(runs[i]),
runs[i].length); runs[i].Length());
if (status != B_OK) if (status != B_OK)
return status; return status;
} }
@@ -1840,7 +1842,7 @@ Inode::Remove(Transaction *transaction, const char *name, off_t *_id, bool isDir
} }
// update the inode, so that no one will ever doubt it's deleted :-) // update the inode, so that no one will ever doubt it's deleted :-)
inode->Node()->flags |= INODE_DELETED; inode->Node()->flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_DELETED);
// In balance to the Inode::Create() method, the main indices // In balance to the Inode::Create() method, the main indices
// are updated here (name, size, & last_modified) // are updated here (name, size, & last_modified)
@@ -1957,11 +1959,11 @@ Inode::Create(Transaction *transaction, Inode *parent, const char *name, int32 m
node->parent = parentRun; node->parent = parentRun;
node->uid = geteuid(); node->uid = HOST_ENDIAN_TO_BFS_INT32(geteuid());
node->gid = parent ? parent->Node()->gid : getegid(); node->gid = HOST_ENDIAN_TO_BFS_INT32(parent ? parent->Node()->gid : getegid());
// the group ID is inherited from the parent, if available // the group ID is inherited from the parent, if available
node->type = type; node->type = HOST_ENDIAN_TO_BFS_INT32(type);
// only add the name to regular files, directories, or symlinks // only add the name to regular files, directories, or symlinks
// don't add it to attributes, or indices // don't add it to attributes, or indices
@@ -2098,7 +2100,7 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type, vnode_id
if (item->IsLast(fInode->Node())) if (item->IsLast(fInode->Node()))
break; break;
if (item->name_size == FILE_NAME_NAME_LENGTH if (item->NameSize() == FILE_NAME_NAME_LENGTH
&& *item->Name() == FILE_NAME_NAME) && *item->Name() == FILE_NAME_NAME)
continue; continue;
@@ -2108,8 +2110,8 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type, vnode_id
if (!item->IsLast(fInode->Node())) { if (!item->IsLast(fInode->Node())) {
strncpy(name, item->Name(), B_FILE_NAME_LENGTH); strncpy(name, item->Name(), B_FILE_NAME_LENGTH);
*_type = item->type; *_type = item->Type();
*_length = item->name_size; *_length = item->NameSize();
*_id = (vnode_id)fCurrentSmallData; *_id = (vnode_id)fCurrentSmallData;
fCurrentSmallData = i; fCurrentSmallData = i;
@@ -2158,8 +2160,8 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type, vnode_id
Vnode vnode(volume,id); Vnode vnode(volume,id);
Inode *attribute; Inode *attribute;
if ((status = vnode.Get(&attribute)) == B_OK) { if ((status = vnode.Get(&attribute)) == B_OK) {
*_type = attribute->Node()->type; *_type = attribute->Type();
*_length = attribute->Node()->data.size; *_length = attribute->Size();
*_id = id; *_id = id;
} }
+5 -5
View File
@@ -97,9 +97,9 @@ class Inode : public CachedBlock {
ReadWriteLock &Lock() { return fLock; } ReadWriteLock &Lock() { return fLock; }
SimpleLock &SmallDataLock() { return fSmallDataLock; } SimpleLock &SmallDataLock() { return fSmallDataLock; }
mode_t Mode() const { return Node()->mode; } mode_t Mode() const { return Node()->Mode(); }
uint32 Type() const { return Node()->type; } uint32 Type() const { return Node()->Type(); }
int32 Flags() const { return Node()->flags; } int32 Flags() const { return Node()->Flags(); }
bool IsContainer() const { return Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR); } bool IsContainer() const { return Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR); }
// note, that this test will also be true for S_IFBLK (not that it's used in the fs :) // note, that this test will also be true for S_IFBLK (not that it's used in the fs :)
bool IsDirectory() const { return (Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR)) == S_DIRECTORY; } bool IsDirectory() const { return (Mode() & (S_DIRECTORY | S_INDEX_DIR | S_ATTR_DIR)) == S_DIRECTORY; }
@@ -114,7 +114,7 @@ class Inode : public CachedBlock {
bool HasUserAccessableStream() const { return S_ISREG(Mode()); } bool HasUserAccessableStream() const { return S_ISREG(Mode()); }
// currently only files can be accessed with bfs_read()/bfs_write() // currently only files can be accessed with bfs_read()/bfs_write()
off_t Size() const { return Node()->data.size; } off_t Size() const { return Node()->data.Size(); }
off_t LastModified() const { return Node()->last_modified_time; } off_t LastModified() const { return Node()->last_modified_time; }
block_run &BlockRun() const { return Node()->inode_num; } block_run &BlockRun() const { return Node()->inode_num; }
@@ -173,7 +173,7 @@ class Inode : public CachedBlock {
// index maintaining helper // index maintaining helper
void UpdateOldSize() { fOldSize = Size(); } void UpdateOldSize() { fOldSize = Size(); }
void UpdateOldLastModified() { fOldLastModified = Node()->last_modified_time; } void UpdateOldLastModified() { fOldLastModified = Node()->LastModifiedTime(); }
off_t OldSize() { return fOldSize; } off_t OldSize() { return fOldSize; }
off_t OldLastModified() { return fOldLastModified; } off_t OldLastModified() { return fOldLastModified; }
@@ -7,6 +7,7 @@ oldOPTIM = $(OPTIM) ;
{ {
local defines = local defines =
KEEP_WRONG_DIRENT_RECLEN KEEP_WRONG_DIRENT_RECLEN
#BFS_BIG_ENDIAN_ONLY
; ;
if $(COMPILE_FOR_R5) { if $(COMPILE_FOR_R5) {
+40 -40
View File
@@ -146,14 +146,14 @@ Uncached::WriteBack(Transaction *transaction)
status_t status_t
Uncached::Read(Volume *volume, block_run run, uint8 *buffer) Uncached::Read(Volume *volume, block_run run, uint8 *buffer)
{ {
return read_pos(volume->Device(), volume->ToBlock(run) << volume->BlockShift(), buffer, run.length << volume->BlockShift()); return read_pos(volume->Device(), volume->ToBlock(run) << volume->BlockShift(), buffer, run.Length() << volume->BlockShift());
} }
status_t status_t
Uncached::Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer) Uncached::Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer)
{ {
return write_pos(volume->Device(), volume->ToBlock(run) << volume->BlockShift(), buffer, run.length << volume->BlockShift()); return write_pos(volume->Device(), volume->ToBlock(run) << volume->BlockShift(), buffer, run.Length() << volume->BlockShift());
} }
@@ -191,14 +191,14 @@ Cached::WriteBack(Transaction *transaction)
status_t status_t
Cached::Read(Volume *volume, block_run run, uint8 *buffer) Cached::Read(Volume *volume, block_run run, uint8 *buffer)
{ {
return cached_read(volume->Device(), volume->ToBlock(run), buffer, run.length, volume->BlockSize()); return cached_read(volume->Device(), volume->ToBlock(run), buffer, run.Length(), volume->BlockSize());
} }
status_t status_t
Cached::Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer) Cached::Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer)
{ {
return volume->WriteBlocks(volume->ToBlock(run), buffer, run.length); return volume->WriteBlocks(volume->ToBlock(run), buffer, run.Length());
} }
@@ -226,14 +226,14 @@ Logged::Logged(Volume *volume, block_run run, bool empty = false)
status_t status_t
Logged::Read(Volume *volume, block_run run, uint8 *buffer) Logged::Read(Volume *volume, block_run run, uint8 *buffer)
{ {
return cached_read(volume->Device(), volume->ToBlock(run), buffer, run.length, volume->BlockSize()); return cached_read(volume->Device(), volume->ToBlock(run), buffer, run.Length(), volume->BlockSize());
} }
status_t status_t
Logged::Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer) Logged::Write(Transaction *transaction, Volume *volume, block_run run, const uint8 *buffer)
{ {
return transaction->WriteBlocks(volume->ToBlock(run), buffer, run.length); return transaction->WriteBlocks(volume->ToBlock(run), buffer, run.Length());
} }
}; // namespace Access }; // namespace Access
@@ -271,13 +271,13 @@ Stream<Cache>::FindBlockRun(off_t pos, block_run &run, off_t &offset)
// find matching block run // find matching block run
if (data->max_direct_range > 0 && pos >= data->max_direct_range) { if (data->MaxDirectRange() > 0 && pos >= data->MaxDirectRange()) {
if (data->max_double_indirect_range > 0 && pos >= data->max_indirect_range) { if (data->MaxDoubleIndirectRange() > 0 && pos >= data->MaxIndirectRange()) {
// access to double indirect blocks // access to double indirect blocks
Cache cached(fVolume); Cache cached(fVolume);
off_t start = pos - data->max_indirect_range; off_t start = pos - data->MaxIndirectRange();
int32 indirectSize = (1L << (INDIRECT_BLOCKS_SHIFT + cached.BlockShift())) int32 indirectSize = (1L << (INDIRECT_BLOCKS_SHIFT + cached.BlockShift()))
* (fVolume->BlockSize() / sizeof(block_run)); * (fVolume->BlockSize() / sizeof(block_run));
int32 directSize = NUM_ARRAY_BLOCKS << cached.BlockShift(); int32 directSize = NUM_ARRAY_BLOCKS << cached.BlockShift();
@@ -300,18 +300,18 @@ Stream<Cache>::FindBlockRun(off_t pos, block_run &run, off_t &offset)
RETURN_ERROR(B_ERROR); RETURN_ERROR(B_ERROR);
run = indirect[current % runsPerBlock]; run = indirect[current % runsPerBlock];
offset = data->max_indirect_range + (index * indirectSize) + (current * directSize); offset = data->MaxIndirectRange() + (index * indirectSize) + (current * directSize);
//printf("\tfCurrent = %ld, fRunFileOffset = %Ld, fRunBlockEnd = %Ld, fRun = %ld,%d\n",fCurrent,fRunFileOffset,fRunBlockEnd,fRun.allocation_group,fRun.start); //printf("\tfCurrent = %ld, fRunFileOffset = %Ld, fRunBlockEnd = %Ld, fRun = %ld,%d\n",fCurrent,fRunFileOffset,fRunBlockEnd,fRun.allocation_group,fRun.start);
} else { } else {
// access to indirect blocks // access to indirect blocks
int32 runsPerBlock = fVolume->BlockSize() / sizeof(block_run); int32 runsPerBlock = fVolume->BlockSize() / sizeof(block_run);
off_t runBlockEnd = data->max_direct_range; off_t runBlockEnd = data->MaxDirectRange();
Cache cached(fVolume); Cache cached(fVolume);
off_t block = fVolume->ToBlock(data->indirect); off_t block = fVolume->ToBlock(data->indirect);
for (int32 i = 0;i < data->indirect.length;i++) { for (int32 i = 0; i < data->indirect.Length(); i++) {
block_run *indirect = (block_run *)cached.SetTo(block + i); block_run *indirect = (block_run *)cached.SetTo(block + i);
if (indirect == NULL) if (indirect == NULL)
RETURN_ERROR(B_IO_ERROR); RETURN_ERROR(B_IO_ERROR);
@@ -321,12 +321,12 @@ Stream<Cache>::FindBlockRun(off_t pos, block_run &run, off_t &offset)
if (indirect[current].IsZero()) if (indirect[current].IsZero())
break; break;
runBlockEnd += indirect[current].length << cached.BlockShift(); runBlockEnd += indirect[current].Length() << cached.BlockShift();
if (runBlockEnd > pos) { if (runBlockEnd > pos) {
run = indirect[current]; run = indirect[current];
offset = runBlockEnd - (run.length << cached.BlockShift()); offset = runBlockEnd - (run.Length() << cached.BlockShift());
//printf("reading from indirect block: %ld,%d\n",fRun.allocation_group,fRun.start); //printf("reading from indirect block: %ld,%d\n",fRun.allocation_group,fRun.start);
//printf("### indirect-run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset); //printf("### indirect-run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.Length(),fRunFileOffset);
return fVolume->ValidateBlockRun(run); return fVolume->ValidateBlockRun(run);
} }
} }
@@ -343,11 +343,11 @@ Stream<Cache>::FindBlockRun(off_t pos, block_run &run, off_t &offset)
if (data->direct[current].IsZero()) if (data->direct[current].IsZero())
break; break;
runBlockEnd += data->direct[current].length << fVolume->BlockShift(); runBlockEnd += data->direct[current].Length() << fVolume->BlockShift();
if (runBlockEnd > pos) { if (runBlockEnd > pos) {
run = data->direct[current]; run = data->direct[current];
offset = runBlockEnd - (run.length << fVolume->BlockShift()); offset = runBlockEnd - (run.Length() << fVolume->BlockShift());
//printf("### run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset); //printf("### run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.Length(),fRunFileOffset);
return fVolume->ValidateBlockRun(run); return fVolume->ValidateBlockRun(run);
} }
} }
@@ -366,15 +366,15 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
if (pos < 0) if (pos < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
if (pos >= Node()->data.size) { if (pos >= Node()->data.Size()) {
*_length = 0; *_length = 0;
return B_NO_ERROR; return B_NO_ERROR;
} }
size_t length = *_length; size_t length = *_length;
if (pos + length > Node()->data.size) if (pos + length > Node()->data.Size())
length = Node()->data.size - pos; length = Node()->data.Size() - pos;
block_run run; block_run run;
off_t offset; off_t offset;
@@ -393,8 +393,8 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
// pos % block_size == (pos - offset) % block_size, offset % block_size == 0 // pos % block_size == (pos - offset) % block_size, offset % block_size == 0
if (pos % blockSize != 0) { if (pos % blockSize != 0) {
run.start += (pos - offset) / blockSize; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length -= (pos - offset) / blockSize; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
Cache cached(fVolume,run); Cache cached(fVolume,run);
if ((block = cached.Block()) == NULL) { if ((block = cached.Block()) == NULL) {
@@ -429,10 +429,10 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
while (length > 0) { while (length > 0) {
// offset is the offset to the current pos in the block_run // offset is the offset to the current pos in the block_run
run.start += (pos - offset) >> blockShift; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length -= (pos - offset) >> blockShift; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
if (uint32(run.length << blockShift) > length) { if (uint32(run.Length() << blockShift) > length) {
if (length < blockSize) { if (length < blockSize) {
Cache cached(fVolume, run); Cache cached(fVolume, run);
if ((block = cached.Block()) == NULL) { if ((block = cached.Block()) == NULL) {
@@ -443,7 +443,7 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
bytesRead += length; bytesRead += length;
break; break;
} }
run.length = length >> blockShift; run.length = HOST_ENDIAN_TO_BFS_INT16(length >> blockShift);
partial = true; partial = true;
} }
@@ -452,7 +452,7 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
int32 bytes = run.length << blockShift; int32 bytes = run.Length() << blockShift;
#ifdef DEBUG #ifdef DEBUG
if ((uint32)bytes > length) if ((uint32)bytes > length)
DEBUGGER(("bytes greater than length")); DEBUGGER(("bytes greater than length"));
@@ -467,8 +467,8 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
if (partial) { if (partial) {
// if the last block was read only partially, point block_run // if the last block was read only partially, point block_run
// to the remaining part // to the remaining part
run.start += run.length; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + run.Length());
run.length = 1; run.length = HOST_ENDIAN_TO_BFS_INT16(1);
offset = pos; offset = pos;
} else if (FindBlockRun(pos, run, offset) < B_OK) { } else if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = bytesRead; *_length = bytesRead;
@@ -490,7 +490,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
// set/check boundaries for pos/length // set/check boundaries for pos/length
if (pos < 0) if (pos < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
if (pos + length > Node()->data.size) { if (pos + length > Size()) {
off_t oldSize = Size(); off_t oldSize = Size();
// uncached files can't be resized (Inode::SetFileSize() also // uncached files can't be resized (Inode::SetFileSize() also
@@ -539,8 +539,8 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
// pos % block_size == (pos - offset) % block_size, offset % block_size == 0 // pos % block_size == (pos - offset) % block_size, offset % block_size == 0
if (pos % blockSize != 0) { if (pos % blockSize != 0) {
run.start += (pos - offset) / blockSize; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length -= (pos - offset) / blockSize; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
Cache cached(fVolume, run); Cache cached(fVolume, run);
if ((block = cached.Block()) == NULL) { if ((block = cached.Block()) == NULL) {
@@ -578,10 +578,10 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
while (length > 0) { while (length > 0) {
// offset is the offset to the current pos in the block_run // offset is the offset to the current pos in the block_run
run.start += (pos - offset) >> blockShift; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length -= (pos - offset) >> blockShift; run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
if (uint32(run.length << blockShift) > length) { if (uint32(run.Length() << blockShift) > length) {
if (length < blockSize) { if (length < blockSize) {
Cache cached(fVolume,run); Cache cached(fVolume,run);
if ((block = cached.Block()) == NULL) { if ((block = cached.Block()) == NULL) {
@@ -595,7 +595,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
bytesWritten += length; bytesWritten += length;
break; break;
} }
run.length = length >> blockShift; run.length = HOST_ENDIAN_TO_BFS_INT16(length >> blockShift);
partial = true; partial = true;
} }
@@ -604,7 +604,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
int32 bytes = run.length << blockShift; int32 bytes = run.Length() << blockShift;
length -= bytes; length -= bytes;
bytesWritten += bytes; bytesWritten += bytes;
if (length == 0) if (length == 0)
@@ -615,8 +615,8 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
if (partial) { if (partial) {
// if the last block was written only partially, point block_run // if the last block was written only partially, point block_run
// to the remaining part // to the remaining part
run.start += run.length; run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + run.Length());
run.length = 1; run.length = HOST_ENDIAN_TO_BFS_INT16(1);
offset = pos; offset = pos;
} else if (FindBlockRun(pos, run, offset) < B_OK) { } else if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = bytesWritten; *_length = bytesWritten;
+47 -22
View File
@@ -41,17 +41,18 @@ Volume::~Volume()
bool bool
Volume::IsValidSuperBlock() Volume::IsValidSuperBlock()
{ {
if (fSuperBlock.magic1 != (int32)SUPER_BLOCK_MAGIC1 if (fSuperBlock.Magic1() != (int32)SUPER_BLOCK_MAGIC1
|| fSuperBlock.magic2 != (int32)SUPER_BLOCK_MAGIC2 || fSuperBlock.Magic2() != (int32)SUPER_BLOCK_MAGIC2
|| fSuperBlock.magic3 != (int32)SUPER_BLOCK_MAGIC3 || fSuperBlock.Magic3() != (int32)SUPER_BLOCK_MAGIC3
|| (int32)fSuperBlock.block_size != fSuperBlock.inode_size || (int32)fSuperBlock.block_size != fSuperBlock.inode_size
|| fSuperBlock.fs_byte_order != SUPER_BLOCK_FS_LENDIAN || fSuperBlock.ByteOrder() != SUPER_BLOCK_FS_LENDIAN
|| (1UL << fSuperBlock.block_shift) != fSuperBlock.block_size || (1UL << fSuperBlock.BlockShift()) != fSuperBlock.BlockSize()
|| fSuperBlock.num_ags < 1 || fSuperBlock.AllocationGroups() < 1
|| fSuperBlock.ag_shift < 1 || fSuperBlock.AllocationGroupShift() < 1
|| fSuperBlock.blocks_per_ag < 1 || fSuperBlock.BlocksPerAllocationGroup() < 1
|| fSuperBlock.num_blocks < 10 || fSuperBlock.NumBlocks() < 10
|| fSuperBlock.num_ags != divide_roundup(fSuperBlock.num_blocks,1L << fSuperBlock.ag_shift)) || fSuperBlock.AllocationGroups() != divide_roundup(fSuperBlock.NumBlocks(),
1L << fSuperBlock.AllocationGroupShift()))
return false; return false;
return true; return true;
@@ -77,8 +78,15 @@ Volume::Mount(const char *deviceName, uint32 flags)
if (flags & B_MOUNT_READ_ONLY) if (flags & B_MOUNT_READ_ONLY)
fFlags |= VOLUME_READ_ONLY; fFlags |= VOLUME_READ_ONLY;
fDevice = open(deviceName,flags & B_MOUNT_READ_ONLY ? O_RDONLY : O_RDWR); // ToDo: validate the FS in write mode as well!
#if (B_HOST_IS_LENDIAN && defined(BFS_BIG_ENDIAN_ONLY)) \
|| (B_HOST_IS_BENDIAN && defined(BFS_LITTLE_ENDIAN_ONLY))
// in big endian mode, we only mount read-only for now
flags |= B_MOUNT_READ_ONLY;
#endif
fDevice = open(deviceName, flags & B_MOUNT_READ_ONLY ? O_RDONLY : O_RDWR);
// if we couldn't open the device, try read-only (don't rely on a specific error code) // if we couldn't open the device, try read-only (don't rely on a specific error code)
if (fDevice < B_OK && (flags & B_MOUNT_READ_ONLY) == 0) { if (fDevice < B_OK && (flags & B_MOUNT_READ_ONLY) == 0) {
fDevice = open(deviceName, O_RDONLY); fDevice = open(deviceName, O_RDONLY);
@@ -116,11 +124,28 @@ Volume::Mount(const char *deviceName, uint32 flags)
// Note: that does work only for x86, for PowerPC, the super block // Note: that does work only for x86, for PowerPC, the super block
// is located at offset 0! // is located at offset 0!
memcpy(&fSuperBlock, buffer + 512, sizeof(disk_super_block)); memcpy(&fSuperBlock, buffer + 512, sizeof(disk_super_block));
if (!IsValidSuperBlock()) {
#ifndef BFS_LITTLE_ENDIAN_ONLY
memcpy(&fSuperBlock, buffer, sizeof(disk_super_block));
if (!IsValidSuperBlock()) {
close(fDevice);
return B_BAD_VALUE;
}
#else
close(fDevice);
return B_BAD_VALUE;
#endif
}
if (IsValidSuperBlock()) { if (IsValidSuperBlock()) {
// set the current log pointers, so that journaling will work correctly // set the current log pointers, so that journaling will work correctly
fLogStart = fSuperBlock.log_start; fLogStart = fSuperBlock.LogStart();
fLogEnd = fSuperBlock.log_end; fLogEnd = fSuperBlock.LogEnd();
// initialize short hands to the super block (to save byte swapping)
fBlockSize = fSuperBlock.BlockSize();
fBlockShift = fSuperBlock.BlockShift();
fAllocationGroupShift = fSuperBlock.AllocationGroupShift();
if (init_cache_for_device(fDevice, NumBlocks()) == B_OK) { if (init_cache_for_device(fDevice, NumBlocks()) == B_OK) {
fJournal = new Journal(this); fJournal = new Journal(this);
@@ -130,7 +155,7 @@ Volume::Mount(const char *deviceName, uint32 flags)
fRootNode = new Inode(this, ToVnode(Root())); fRootNode = new Inode(this, ToVnode(Root()));
if (fRootNode && fRootNode->InitCheck() == B_OK) { if (fRootNode && fRootNode->InitCheck() == B_OK) {
if (new_vnode(fID, ToVnode(Root()),(void *)fRootNode) == B_OK) { if (new_vnode(fID, ToVnode(Root()), (void *)fRootNode) == B_OK) {
// try to get indices root dir // try to get indices root dir
// question: why doesn't get_vnode() work here?? // question: why doesn't get_vnode() work here??
@@ -208,12 +233,12 @@ Volume::Sync()
status_t status_t
Volume::ValidateBlockRun(block_run run) Volume::ValidateBlockRun(block_run run)
{ {
if (run.allocation_group < 0 || run.allocation_group > (int32)AllocationGroups() if (run.AllocationGroup() < 0 || run.AllocationGroup() > (int32)AllocationGroups()
|| run.start > (1UL << AllocationGroupShift()) || run.Start() > (1UL << AllocationGroupShift())
|| run.length == 0 || run.length == 0
|| uint32(run.length + run.start) > (1UL << AllocationGroupShift())) { || uint32(run.Length() + run.Start()) > (1UL << AllocationGroupShift())) {
Panic(); Panic();
FATAL(("*** invalid run(%ld,%d,%d)\n", run.allocation_group, run.start, run.length)); FATAL(("*** invalid run(%ld,%d,%d)\n", run.AllocationGroup(), run.Start(), run.Length()));
return B_BAD_DATA; return B_BAD_DATA;
} }
return B_OK; return B_OK;
@@ -224,9 +249,9 @@ block_run
Volume::ToBlockRun(off_t block) const Volume::ToBlockRun(off_t block) const
{ {
block_run run; block_run run;
run.allocation_group = block >> fSuperBlock.ag_shift; run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(block >> AllocationGroupShift());
run.start = block & ~((1LL << fSuperBlock.ag_shift) - 1); run.start = HOST_ENDIAN_TO_BFS_INT16(block & ~((1LL << AllocationGroupShift()) - 1));
run.length = 1; run.length = HOST_ENDIAN_TO_BFS_INT16(1);
return run; return run;
} }
+15 -10
View File
@@ -57,19 +57,19 @@ class Volume {
nspace_id ID() const { return fID; } nspace_id ID() const { return fID; }
const char *Name() const { return fSuperBlock.name; } const char *Name() const { return fSuperBlock.name; }
off_t NumBlocks() const { return fSuperBlock.num_blocks; } off_t NumBlocks() const { return fSuperBlock.NumBlocks(); }
off_t UsedBlocks() const { return fSuperBlock.used_blocks; } off_t UsedBlocks() const { return fSuperBlock.UsedBlocks(); }
off_t FreeBlocks() const { return fSuperBlock.num_blocks - fSuperBlock.used_blocks; } off_t FreeBlocks() const { return NumBlocks() - UsedBlocks(); }
uint32 BlockSize() const { return fSuperBlock.block_size; } uint32 BlockSize() const { return fBlockSize; }
uint32 BlockShift() const { return fSuperBlock.block_shift; } uint32 BlockShift() const { return fBlockShift; }
uint32 InodeSize() const { return fSuperBlock.inode_size; } uint32 InodeSize() const { return fSuperBlock.InodeSize(); }
uint32 AllocationGroups() const { return fSuperBlock.num_ags; } uint32 AllocationGroups() const { return fSuperBlock.AllocationGroups(); }
uint32 AllocationGroupShift() const { return fSuperBlock.ag_shift; } uint32 AllocationGroupShift() const { return fAllocationGroupShift; }
disk_super_block &SuperBlock() { return fSuperBlock; } disk_super_block &SuperBlock() { return fSuperBlock; }
off_t ToOffset(block_run run) const { return ToBlock(run) << fSuperBlock.block_shift; } off_t ToOffset(block_run run) const { return ToBlock(run) << BlockShift(); }
off_t ToBlock(block_run run) const { return ((((off_t)run.allocation_group) << fSuperBlock.ag_shift) | (off_t)run.start); } off_t ToBlock(block_run run) const { return ((((off_t)run.AllocationGroup()) << AllocationGroupShift()) | (off_t)run.Start()); }
block_run ToBlockRun(off_t block) const; block_run ToBlockRun(off_t block) const;
status_t ValidateBlockRun(block_run run); status_t ValidateBlockRun(block_run run);
@@ -114,6 +114,11 @@ class Volume {
nspace_id fID; nspace_id fID;
int fDevice; int fDevice;
disk_super_block fSuperBlock; disk_super_block fSuperBlock;
uint32 fBlockSize;
uint32 fBlockShift;
uint32 fAllocationGroupShift;
BlockAllocator fBlockAllocator; BlockAllocator fBlockAllocator;
RecursiveLock fLock; RecursiveLock fLock;
Journal *fJournal; Journal *fJournal;
@@ -188,6 +188,8 @@ struct bfs_inode {
int32 Flags() const { return BFS_ENDIAN_TO_HOST_INT32(flags); } int32 Flags() const { return BFS_ENDIAN_TO_HOST_INT32(flags); }
int32 Type() const { return BFS_ENDIAN_TO_HOST_INT32(type); } int32 Type() const { return BFS_ENDIAN_TO_HOST_INT32(type); }
int32 InodeSize() const { return BFS_ENDIAN_TO_HOST_INT32(inode_size); } int32 InodeSize() const { return BFS_ENDIAN_TO_HOST_INT32(inode_size); }
bigtime_t LastModifiedTime() const { return BFS_ENDIAN_TO_HOST_INT64(last_modified_time); }
bigtime_t CreateTime() const { return BFS_ENDIAN_TO_HOST_INT64(create_time); }
status_t InitCheck(Volume *volume); status_t InitCheck(Volume *volume);
// defined in Inode.cpp // defined in Inode.cpp
@@ -539,11 +539,11 @@ bfs_walk(void *_ns, void *_directory, const char *file, char **_resolvedPath, vn
// for the path, so we're not going to do that // for the path, so we're not going to do that
if (inode->Flags() & INODE_LONG_SYMLINK) { if (inode->Flags() & INODE_LONG_SYMLINK) {
size_t readBytes = inode->Node()->data.size; size_t readBytes = inode->Size();
char *data = (char *)malloc(readBytes); char *data = (char *)malloc(readBytes);
if (data != NULL) { if (data != NULL) {
status = inode->ReadAt(0, (uint8 *)data, &readBytes); status = inode->ReadAt(0, (uint8 *)data, &readBytes);
if (status == B_OK && readBytes == inode->Node()->data.size) if (status == B_OK && readBytes == inode->Size())
status = new_path(data, &newPath); status = new_path(data, &newPath);
free(data); free(data);
@@ -597,7 +597,7 @@ bfs_ioctl(void *_ns, void *_node, void *_cookie, int cmd, void *buffer, size_t b
// using the cache or allocating memory // using the cache or allocating memory
status_t status = volume->Pool().RequestBuffers(volume->BlockSize()); status_t status = volume->Pool().RequestBuffers(volume->BlockSize());
if (status == B_OK) if (status == B_OK)
inode->Node()->flags |= INODE_NO_CACHE; inode->Node()->flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_NO_CACHE);
return status; return status;
} }
case IOCTL_CREATE_TIME: case IOCTL_CREATE_TIME:
@@ -606,7 +606,7 @@ bfs_ioctl(void *_ns, void *_node, void *_cookie, int cmd, void *buffer, size_t b
return B_BAD_VALUE; return B_BAD_VALUE;
off_t *creationTime = (off_t *)buffer; off_t *creationTime = (off_t *)buffer;
*creationTime = inode->Node()->create_time; *creationTime = inode->Node()->CreateTime();
return B_OK; return B_OK;
} }
case IOCTL_MODIFIED_TIME: case IOCTL_MODIFIED_TIME:
@@ -633,7 +633,7 @@ bfs_ioctl(void *_ns, void *_node, void *_cookie, int cmd, void *buffer, size_t b
status_t status = allocator.StartChecking(control); status_t status = allocator.StartChecking(control);
if (status == B_OK && inode != NULL) if (status == B_OK && inode != NULL)
inode->Node()->flags |= INODE_CHKBFS_RUNNING; inode->Node()->flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_CHKBFS_RUNNING);
return status; return status;
} }
@@ -645,7 +645,7 @@ bfs_ioctl(void *_ns, void *_node, void *_cookie, int cmd, void *buffer, size_t b
status_t status = allocator.StopChecking(control); status_t status = allocator.StopChecking(control);
if (status == B_OK && inode != NULL) if (status == B_OK && inode != NULL)
inode->Node()->flags &= ~INODE_CHKBFS_RUNNING; inode->Node()->flags &= HOST_ENDIAN_TO_BFS_INT32(~INODE_CHKBFS_RUNNING);
return status; return status;
} }
@@ -758,14 +758,14 @@ bfs_read_stat(void *_ns, void *_node, struct stat *st)
st->st_nlink = 1; st->st_nlink = 1;
st->st_blksize = BFS_IO_SIZE; st->st_blksize = BFS_IO_SIZE;
st->st_uid = node->uid; st->st_uid = node->UserID();
st->st_gid = node->gid; st->st_gid = node->GroupID();
st->st_mode = node->mode; st->st_mode = node->Mode();
st->st_size = node->data.size; st->st_size = node->data.Size();
st->st_atime = time(NULL); st->st_atime = time(NULL);
st->st_mtime = st->st_ctime = (time_t)(node->last_modified_time >> INODE_TIME_SHIFT); st->st_mtime = st->st_ctime = (time_t)(node->LastModifiedTime() >> INODE_TIME_SHIFT);
st->st_crtime = (time_t)(node->create_time >> INODE_TIME_SHIFT); st->st_crtime = (time_t)(node->CreateTime() >> INODE_TIME_SHIFT);
return B_NO_ERROR; return B_NO_ERROR;
} }
@@ -931,7 +931,7 @@ bfs_symlink(void *_ns, void *_directory, const char *name, const char *path)
strcpy(link->Node()->short_symlink, path); strcpy(link->Node()->short_symlink, path);
status = link->WriteBack(&transaction); status = link->WriteBack(&transaction);
} else { } else {
link->Node()->flags |= INODE_LONG_SYMLINK | INODE_LOGGED; link->Node()->flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_LONG_SYMLINK | INODE_LOGGED);
// The following call will have to write the inode back, so // The following call will have to write the inode back, so
// we don't have to do that here... // we don't have to do that here...
status = link->WriteAt(&transaction, 0, (const uint8 *)path, &length); status = link->WriteAt(&transaction, 0, (const uint8 *)path, &length);
@@ -1376,7 +1376,7 @@ bfs_free_cookie(void *_ns, void *_node, void *_cookie)
if (inode->Flags() & INODE_NO_CACHE) { if (inode->Flags() & INODE_NO_CACHE) {
volume->Pool().ReleaseBuffers(); volume->Pool().ReleaseBuffers();
inode->Node()->flags &= ~INODE_NO_CACHE; inode->Node()->flags &= HOST_ENDIAN_TO_BFS_INT32(~INODE_NO_CACHE);
// We don't need to save the inode, because INODE_NO_CACHE is a // We don't need to save the inode, because INODE_NO_CACHE is a
// non-permanent flag which will be removed when the inode is loaded // non-permanent flag which will be removed when the inode is loaded
// into memory. // into memory.
@@ -1758,8 +1758,8 @@ bfs_stat_attr(void *ns, void *_node, const char *name, struct attr_info *attrInf
if (inode->SmallDataLock().Lock() == B_OK) if (inode->SmallDataLock().Lock() == B_OK)
{ {
if ((smallData = inode->FindSmallData((const char *)name)) != NULL) { if ((smallData = inode->FindSmallData((const char *)name)) != NULL) {
attrInfo->type = smallData->type; attrInfo->type = smallData->Type();
attrInfo->size = smallData->data_size; attrInfo->size = smallData->DataSize();
} }
inode->SmallDataLock().Unlock(); inode->SmallDataLock().Unlock();
} }
@@ -2004,11 +2004,11 @@ bfs_stat_index(void *_ns, const char *name, struct index_info *indexInfo)
bfs_inode *node = index.Node()->Node(); bfs_inode *node = index.Node()->Node();
indexInfo->type = index.Type(); indexInfo->type = index.Type();
indexInfo->size = node->data.size; indexInfo->size = node->data.Size();
indexInfo->modification_time = (time_t)(node->last_modified_time >> INODE_TIME_SHIFT); indexInfo->modification_time = (time_t)(node->LastModifiedTime() >> INODE_TIME_SHIFT);
indexInfo->creation_time = (time_t)(node->create_time >> INODE_TIME_SHIFT); indexInfo->creation_time = (time_t)(node->CreateTime() >> INODE_TIME_SHIFT);
indexInfo->uid = node->uid; indexInfo->uid = node->UserID();
indexInfo->gid = node->gid; indexInfo->gid = node->GroupID();
return B_OK; return B_OK;
} }