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
// even access the b+tree header with this method (use SetToHeader()
// instead)
if (offset > fTree->fHeader->maximum_size - fTree->fNodeSize
if (offset > fTree->fHeader->MaximumSize() - fTree->fNodeSize
|| offset <= 0
|| (offset % fTree->fNodeSize) != 0)
return NULL;
@@ -91,10 +91,10 @@ CachedNode::SetTo(off_t offset,bool check)
if (InternalSetTo(offset) != NULL && check) {
// sanity checks (links, all_key_count)
bplustree_header *header = fTree->fHeader;
if (!header->IsValidLink(fNode->left_link)
|| !header->IsValidLink(fNode->right_link)
|| !header->IsValidLink(fNode->overflow_link)
|| (int8 *)fNode->Values() + fNode->all_key_count * sizeof(off_t) >
if (!header->IsValidLink(fNode->LeftLink())
|| !header->IsValidLink(fNode->RightLink())
|| !header->IsValidLink(fNode->OverflowLink())
|| (int8 *)fNode->Values() + fNode->NumKeys() * sizeof(off_t) >
(int8 *)fNode + fTree->fNodeSize) {
FATAL(("invalid node read from offset %Ld, inode at %Ld\n",
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
// 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) {
fTree->fHeader->maximum_size = lastOffset;
fTree->fHeader->maximum_size = HOST_ENDIAN_TO_BFS_INT64(lastOffset);
status_t status = fTree->fStream->SetFileSize(transaction,lastOffset);
if (status < B_OK)
@@ -173,10 +173,10 @@ CachedNode::Free(Transaction *transaction,off_t offset)
// add the node to the free nodes list
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) {
fTree->fHeader->free_node_pointer = offset;
fTree->fHeader->free_node_pointer = HOST_ENDIAN_TO_BFS_INT64(offset);
return fTree->fCachedHeader.WriteBack(transaction);
}
return B_ERROR;
@@ -194,8 +194,8 @@ CachedNode::Allocate(Transaction *transaction, bplustree_node **_node, off_t *_o
status_t status;
// if there are any free nodes, recycle them
if (SetTo(fTree->fHeader->free_node_pointer,false) != NULL) {
*_offset = fTree->fHeader->free_node_pointer;
if (SetTo(fTree->fHeader->FreeNode(), false) != NULL) {
*_offset = fTree->fHeader->FreeNode();
// set new free node pointer
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
Inode *stream = fTree->fStream;
if ((status = stream->Append(transaction,fTree->fNodeSize)) < B_OK)
if ((status = stream->Append(transaction, fTree->fNodeSize)) < B_OK)
return status;
// 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
off_t offset = fTree->fHeader->maximum_size;
fTree->fHeader->maximum_size += fTree->fNodeSize;
off_t offset = fTree->fHeader->MaximumSize();
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;
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)
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;
// initialize b+tree header
fHeader->magic = BPLUSTREE_MAGIC;
fHeader->node_size = fNodeSize;
fHeader->max_number_of_levels = 1;
fHeader->data_type = ModeToKeyType(stream->Mode());
fHeader->root_node_pointer = nodeSize;
fHeader->free_node_pointer = BPLUSTREE_NULL;
fHeader->maximum_size = nodeSize * 2;
fHeader->magic = HOST_ENDIAN_TO_BFS_INT32(BPLUSTREE_MAGIC);
fHeader->node_size = HOST_ENDIAN_TO_BFS_INT32(fNodeSize);
fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
fHeader->data_type = HOST_ENDIAN_TO_BFS_INT32(ModeToKeyType(stream->Mode()));
fHeader->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(nodeSize);
fHeader->free_node_pointer = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
fHeader->maximum_size = HOST_ENDIAN_TO_BFS_INT64(nodeSize * 2);
if (fCachedHeader.WriteBack(transaction) < B_OK)
RETURN_ERROR(fStatus = B_ERROR);
// initialize b+tree root node
CachedNode cached(this,fHeader->root_node_pointer,false);
CachedNode cached(this, fHeader->RootNode(), false);
if (cached.Node() == NULL)
RETURN_ERROR(B_ERROR);
@@ -357,14 +357,14 @@ BPlusTree::SetTo(Inode *stream)
// is header valid?
if (fHeader->magic != BPLUSTREE_MAGIC
|| fHeader->maximum_size != stream->Size()
|| (fHeader->root_node_pointer % fHeader->node_size) != 0
|| !fHeader->IsValidLink(fHeader->root_node_pointer)
|| !fHeader->IsValidLink(fHeader->free_node_pointer))
if (fHeader->Magic() != BPLUSTREE_MAGIC
|| fHeader->MaximumSize() != stream->Size()
|| (fHeader->RootNode() % fHeader->NodeSize()) != 0
|| !fHeader->IsValidLink(fHeader->RootNode())
|| !fHeader->IsValidLink(fHeader->FreeNode()))
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,
@@ -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
| S_ULONG_LONG_INDEX | S_FLOAT_INDEX | S_DOUBLE_INDEX);
if (fHeader->data_type > BPLUSTREE_DOUBLE_TYPE
|| (stream->Mode() & S_INDEX_DIR) && toMode[fHeader->data_type] != mode
if (fHeader->DataType() > BPLUSTREE_DOUBLE_TYPE
|| (stream->Mode() & S_INDEX_DIR) && toMode[fHeader->DataType()] != mode
|| !stream->IsContainer()) {
D( dump_bplustree_header(fHeader);
dump_inode(stream->Node());
@@ -388,7 +388,7 @@ BPlusTree::SetTo(Inode *stream)
|| (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);
}
@@ -406,10 +406,13 @@ BPlusTree::TypeCodeToKeyType(type_code code)
switch (code) {
case B_STRING_TYPE:
return BPLUSTREE_STRING_TYPE;
case B_SSIZE_T_TYPE:
case B_INT32_TYPE:
return BPLUSTREE_INT32_TYPE;
case B_SIZE_T_TYPE:
case B_UINT32_TYPE:
return BPLUSTREE_UINT32_TYPE;
case B_OFF_T_TYPE:
case B_INT64_TYPE:
return BPLUSTREE_INT64_TYPE;
case B_UINT64_TYPE:
@@ -533,7 +536,7 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
if (index)
*index = 0;
if (next)
*next = node->overflow_link;
*next = node->OverflowLink();
return B_ENTRY_NOT_FOUND;
}
@@ -541,11 +544,11 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
int16 saveIndex = -1;
// 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 searchLength;
uint8 *searchKey = node->KeyAt(i,&searchLength);
uint8 *searchKey = node->KeyAt(i, &searchLength);
if (searchKey + searchLength + sizeof(off_t) + sizeof(uint16) > (uint8 *)node + fNodeSize
|| searchLength > BPLUSTREE_MAX_KEY_LENGTH) {
fStream->GetVolume()->Panic();
@@ -562,7 +565,7 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
if (index)
*index = i;
if (next)
*next = values[i];
*next = BFS_ENDIAN_TO_HOST_INT64(values[i]);
return B_OK;
}
}
@@ -570,10 +573,10 @@ BPlusTree::FindKey(bplustree_node *node, const uint8 *key, uint16 keyLength, uin
if (index)
*index = saveIndex;
if (next) {
if (saveIndex == node->all_key_count)
*next = node->overflow_link;
if (saveIndex == node->NumKeys())
*next = node->OverflowLink();
else
*next = values[saveIndex];
*next = BFS_ENDIAN_TO_HOST_INT64(values[saveIndex]);
}
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
node_and_key nodeAndKey;
nodeAndKey.nodeOffset = fHeader->root_node_pointer;
nodeAndKey.nodeOffset = fHeader->RootNode();
CachedNode cached(this);
bplustree_node *node;
while ((node = cached.SetTo(nodeAndKey.nodeOffset)) != NULL) {
// 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
// needed in the calling functions anyway)!
nodeAndKey.keyIndex = 0;
@@ -623,7 +626,7 @@ BPlusTree::FindFreeDuplicateFragment(bplustree_node *node, CachedNode *cached, o
bplustree_node **_fragment, uint32 *_index)
{
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?
if (bplustree_node::LinkType(values[i]) != BPLUSTREE_DUPLICATE_FRAGMENT)
continue;
@@ -687,8 +690,8 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
// reuse it as a duplicate node
offset = bplustree_node::FragmentOffset(oldValue);
memmove(duplicate->DuplicateArray(),array,(NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
duplicate->left_link = duplicate->right_link = BPLUSTREE_NULL;
memmove(duplicate->DuplicateArray(), array, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
duplicate->left_link = duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
array = duplicate->DuplicateArray();
array->Insert(value);
@@ -696,13 +699,13 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
// create a new duplicate node
CachedNode cachedNewDuplicate(this);
bplustree_node *newDuplicate;
status = cachedNewDuplicate.Allocate(transaction,&newDuplicate,&offset);
status = cachedNewDuplicate.Allocate(transaction, &newDuplicate, &offset);
if (status < B_OK)
return status;
// copy the array from the fragment node to the duplicate node
// 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],
array->count * 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;
}
} while (array->count >= NUM_DUPLICATE_VALUES
&& (oldValue = duplicate->right_link) != BPLUSTREE_NULL);
&& (oldValue = duplicate->RightLink()) != BPLUSTREE_NULL);
if (array->count < NUM_DUPLICATE_VALUES) {
array->Insert(value);
@@ -761,8 +764,8 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
return status;
// link the two nodes together
duplicate->right_link = offset;
newDuplicate->left_link = duplicateOffset;
duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(offset);
newDuplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(duplicateOffset);
array = newDuplicate->DuplicateArray();
array->count = 0;
@@ -807,27 +810,27 @@ BPlusTree::InsertKey(bplustree_node *node, uint16 index, uint8 *key, uint16 keyL
off_t value)
{
// should never happen, but who knows?
if (index > node->all_key_count)
if (index > node->NumKeys())
return;
off_t *values = node->Values();
uint16 *keyLengths = node->KeyLengths();
uint8 *keys = node->Keys();
node->all_key_count++;
node->all_key_length += keyLength;
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() + 1);
node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(node->AllKeyLength() + keyLength);
off_t *newValues = node->Values();
uint16 *newKeyLengths = node->KeyLengths();
// 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,values,sizeof(off_t) * index);
memmove(newValues + index + 1, values + index, sizeof(off_t) * (node->NumKeys() - 1 - index));
memmove(newValues, values, sizeof(off_t) * index);
newValues[index] = value;
// 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;
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);
// 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)
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,
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;
uint16 *inKeyLengths = node->KeyLengths();
@@ -867,7 +870,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
size_t size = fNodeSize >> 1;
int32 out,in;
for (in = out = 0;in < node->all_key_count + 1;) {
for (in = out = 0; in < node->NumKeys() + 1;) {
if (!bytes)
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;
other->left_link = node->left_link;
other->right_link = nodeOffset;
other->all_key_length = bytes + bytesBefore + bytesAfter;
other->all_key_count = out;
other->right_link = HOST_ENDIAN_TO_BFS_INT64(nodeOffset);
other->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore + bytesAfter);
other->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out);
uint16 *outKeyLengths = other->KeyLengths();
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).
// The dropped key is also the one which has to be inserted in
// 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) {
newKey = key;
newLength = *_keyLength;
other->overflow_link = *_value;
other->overflow_link = HOST_ENDIAN_TO_BFS_INT64(*_value);
keyIndex--;
} else {
// 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);
if (newKey == NULL)
return B_NO_MEMORY;
memcpy(newKey,droppedKey,newLength);
memcpy(newKey, droppedKey, newLength);
other->overflow_link = inKeyValues[in];
total = inKeyLengths[in++];
@@ -975,7 +978,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
bytesBefore = bytesAfter = bytes = 0;
out = 0;
int32 skip = in;
while (in < node->all_key_count + 1) {
while (in < node->NumKeys() + 1) {
if (in == keyIndex && !bytes) {
// it's enough to set bytesBefore once here, because we do
// 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;
bytes = *_keyLength;
} else {
if (in < node->all_key_count) {
if (in < node->NumKeys()) {
inKeyLengths[in] -= total;
if (bytes) {
inKeyLengths[in] += bytes;
@@ -996,7 +999,7 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
out++;
// break out when all keys are done
if (in > node->all_key_count && keyIndex < in)
if (in > node->NumKeys() && keyIndex < in)
break;
}
@@ -1004,15 +1007,15 @@ BPlusTree::SplitNode(bplustree_node *node,off_t nodeOffset,bplustree_node *other
if (keyIndex >= in && keyIndex - skip < out)
bytesAfter = inKeyLengths[in] - bytesBefore - total;
else if (keyIndex < skip)
bytesBefore = node->all_key_length - total;
bytesBefore = node->AllKeyLength() - total;
if (bytesBefore < 0 || bytesAfter < 0)
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
node->all_key_length = bytes + bytesBefore + bytesAfter;
node->all_key_count = out - 1;
node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore + bytesAfter);
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out - 1);
// array positions have changed
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 (newKey == NULL)
newKey = other->KeyAt(other->all_key_count - 1, &newLength);
newKey = other->KeyAt(other->NumKeys() - 1, &newLength);
memcpy(key,newKey,newLength);
*_keyLength = newLength;
@@ -1075,12 +1078,12 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
WriteLocked locked(fStream->Lock());
Stack<node_and_key> stack;
if (SeekDown(stack,key,keyLength) != B_OK)
if (SeekDown(stack, key, keyLength) != B_OK)
RETURN_ERROR(B_ERROR);
uint8 keyBuffer[BPLUSTREE_MAX_KEY_LENGTH + 1];
memcpy(keyBuffer,key,keyLength);
memcpy(keyBuffer, key, keyLength);
keyBuffer[keyLength] = 0;
node_and_key nodeAndKey;
@@ -1093,7 +1096,7 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
#endif
if (node->IsLeaf()) {
// 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?
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?
if (int32(round_up(sizeof(bplustree_node) + node->all_key_length + keyLength)
+ (node->all_key_count + 1) * (sizeof(uint16) + sizeof(off_t))) < fNodeSize)
if (int32(round_up(sizeof(bplustree_node) + node->AllKeyLength() + keyLength)
+ (node->NumKeys() + 1) * (sizeof(uint16) + sizeof(off_t))) < fNodeSize)
{
InsertKey(node, nodeAndKey.keyIndex, keyBuffer, keyLength, value);
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
// it now
off_t newRoot = BPLUSTREE_NULL;
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer) {
if (nodeAndKey.nodeOffset == fHeader->RootNode()) {
bplustree_node *root;
status_t status = cachedNewRoot.Allocate(transaction, &root, &newRoot);
if (status < B_OK) {
@@ -1158,11 +1161,11 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
RETURN_ERROR(B_ERROR);
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
if ((other = cachedOther.SetTo(other->left_link)) != NULL) {
other->right_link = otherOffset;
if ((other = cachedOther.SetTo(other->LeftLink())) != NULL) {
other->right_link = HOST_ENDIAN_TO_BFS_INT64(otherOffset);
if (cachedOther.WriteBack(transaction) < B_OK)
RETURN_ERROR(B_ERROR);
}
@@ -1171,15 +1174,15 @@ BPlusTree::Insert(Transaction *transaction, const uint8 *key, uint16 keyLength,
if (newRoot != BPLUSTREE_NULL) {
bplustree_node *root = cachedNewRoot.Node();
InsertKey(root, 0, keyBuffer, keyLength, node->left_link);
root->overflow_link = nodeAndKey.nodeOffset;
InsertKey(root, 0, keyBuffer, keyLength, node->LeftLink());
root->overflow_link = HOST_ENDIAN_TO_BFS_INT64(nodeAndKey.nodeOffset);
if (cachedNewRoot.WriteBack(transaction) < B_OK)
RETURN_ERROR(B_ERROR);
// finally, update header to point to the new root
fHeader->root_node_pointer = newRoot;
fHeader->max_number_of_levels++;
fHeader->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(newRoot);
fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(fHeader->MaxNumberOfLevels() + 1);
return fCachedHeader.WriteBack(transaction);
}
@@ -1242,8 +1245,8 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
duplicate_array *array;
if (duplicate->left_link != BPLUSTREE_NULL) {
FATAL(("invalid duplicate node: first left link points to %Ld!\n",duplicate->left_link));
if (duplicate->LeftLink() != BPLUSTREE_NULL) {
FATAL(("invalid duplicate node: first left link points to %Ld!\n", duplicate->LeftLink()));
return B_BAD_DATA;
}
@@ -1259,7 +1262,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
if (array->Remove(value))
break;
if ((duplicateOffset = duplicate->right_link) == BPLUSTREE_NULL)
if ((duplicateOffset = duplicate->RightLink()) == BPLUSTREE_NULL)
RETURN_ERROR(B_ENTRY_NOT_FOUND);
duplicate = cachedDuplicate.SetTo(duplicateOffset,false);
@@ -1268,8 +1271,8 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
RETURN_ERROR(B_IO_ERROR);
while (true) {
off_t left = duplicate->left_link;
off_t right = duplicate->right_link;
off_t left = duplicate->LeftLink();
off_t right = duplicate->RightLink();
bool isLast = left == BPLUSTREE_NULL && right == BPLUSTREE_NULL;
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)
return status;
}
if ((status = cachedDuplicate.Free(transaction,duplicateOffset)) < B_OK)
return status;
if (left != BPLUSTREE_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
// 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) {
duplicateOffset = left;
continue;
@@ -1310,12 +1313,12 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
return status;
}
if (right != BPLUSTREE_NULL
&& (duplicate = cachedDuplicate.SetTo(right,false)) != NULL) {
duplicate->left_link = left;
&& (duplicate = cachedDuplicate.SetTo(right, false)) != NULL) {
duplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(left);
// Again, we may need to turn the duplicate entry back into a normal entry
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) {
duplicateOffset = right;
continue;
@@ -1368,7 +1371,7 @@ void
BPlusTree::RemoveKey(bplustree_node *node,uint16 index)
{
// 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));
return;
}
@@ -1378,7 +1381,7 @@ BPlusTree::RemoveKey(bplustree_node *node,uint16 index)
// if we would have to drop the overflow link, drop
// the last key instead and update the overflow link
// 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];
uint16 length;
@@ -1393,26 +1396,26 @@ BPlusTree::RemoveKey(bplustree_node *node,uint16 index)
uint16 *keyLengths = node->KeyLengths();
uint8 *keys = node->Keys();
node->all_key_count--;
node->all_key_length -= length;
node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() - 1);
node->all_key_length = HOST_ENDIAN_TO_BFS_INT64(node->AllKeyLength() - length);
off_t *newValues = node->Values();
uint16 *newKeyLengths = node->KeyLengths();
// 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
if (index > 0 && newKeyLengths != keyLengths)
memmove(newKeyLengths,keyLengths,index * sizeof(uint16));
for (uint16 i = index;i < node->all_key_count;i++)
memmove(newKeyLengths, keyLengths, index * sizeof(uint16));
for (uint16 i = index; i < node->NumKeys(); i++)
newKeyLengths[i] = keyLengths[i + 1] - length;
// move values
if (index > 0)
memmove(newValues,values,index * sizeof(off_t));
if (node->all_key_count > index)
memmove(newValues + index,values + index + 1,(node->all_key_count - index) * sizeof(off_t));
if (node->NumKeys() > index)
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
// more nodes, we need a way to prevent the TreeIterators to
// touch the old node again, we use BPLUSTREE_FREE for this
off_t next = node->right_link == BPLUSTREE_NULL ? BPLUSTREE_FREE : node->right_link;
UpdateIterators(nodeAndKey.nodeOffset,node->all_key_count == 1 ?
next : BPLUSTREE_NULL,nodeAndKey.keyIndex,0,-1);
off_t next = node->RightLink() == BPLUSTREE_NULL ? BPLUSTREE_FREE : node->RightLink();
UpdateIterators(nodeAndKey.nodeOffset, node->NumKeys() == 1 ?
next : BPLUSTREE_NULL,nodeAndKey.keyIndex,0 , -1);
// is this a duplicate entry?
if (bplustree_node::IsDuplicate(node->Values()[nodeAndKey.keyIndex])) {
if (fAllowDuplicates)
return RemoveDuplicate(transaction,node,&cached,nodeAndKey.keyIndex,value);
return RemoveDuplicate(transaction, node, &cached, nodeAndKey.keyIndex, value);
else
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
// to a leaf node by dropping the overflow link, or,
// if it's a leaf node, just empty it
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer
&& node->all_key_count == 0
|| node->all_key_count == 1 && node->IsLeaf()) {
node->overflow_link = BPLUSTREE_NULL;
if (nodeAndKey.nodeOffset == fHeader->RootNode()
&& node->NumKeys() == 0
|| node->NumKeys() == 1 && node->IsLeaf()) {
node->overflow_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL);
node->all_key_count = 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
// number of levels in the header
if (nodeAndKey.nodeOffset == fHeader->root_node_pointer) {
fHeader->max_number_of_levels = 1;
if (nodeAndKey.nodeOffset == fHeader->RootNode()) {
fHeader->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1);
return fCachedHeader.WriteBack(transaction);
}
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
// it, we can just dump the node (index nodes still have
// the overflow link, so we have to drop the last key)
if (node->all_key_count > 1
|| !node->IsLeaf() && node->all_key_count == 1) {
if (node->NumKeys() > 1
|| !node->IsLeaf() && node->NumKeys() == 1) {
RemoveKey(node,nodeAndKey.keyIndex);
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
// siblings first
CachedNode otherCached(this);
bplustree_node *other = otherCached.SetTo(node->left_link);
bplustree_node *other = otherCached.SetTo(node->LeftLink());
if (other != NULL) {
other->right_link = node->right_link;
if (otherCached.WriteBack(transaction) < B_OK)
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;
if (otherCached.WriteBack(transaction) < B_OK)
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)
ReadLocked locked(fStream->Lock());
off_t nodeOffset = fHeader->root_node_pointer;
off_t nodeOffset = fHeader->RootNode();
CachedNode cached(this);
bplustree_node *node;
@@ -1551,7 +1554,7 @@ BPlusTree::Replace(Transaction *transaction, const uint8 *key, uint16 keyLength,
off_t 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) {
node->Values()[keyIndex] = value;
return cached.WriteBack(transaction);
@@ -1592,7 +1595,7 @@ BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
// lock access to stream
ReadLocked locked(fStream->Lock());
off_t nodeOffset = fHeader->root_node_pointer;
off_t nodeOffset = fHeader->RootNode();
CachedNode cached(this);
bplustree_node *node;
@@ -1608,12 +1611,12 @@ BPlusTree::Find(const uint8 *key, uint16 keyLength, off_t *_value)
#ifdef DEBUG
levels++;
#endif
if (node->overflow_link == BPLUSTREE_NULL) {
if (node->OverflowLink() == BPLUSTREE_NULL) {
if (status == B_OK && _value != NULL)
*_value = node->Values()[keyIndex];
*_value = BFS_ENDIAN_TO_HOST_INT64(node->Values()[keyIndex]);
#ifdef DEBUG
if (levels != (int32)fHeader->max_number_of_levels)
if (levels != (int32)fHeader->MaxNumberOfLevels())
DEBUGGER(("levels don't match"));
#endif
return status;
@@ -1656,15 +1659,15 @@ TreeIterator::Goto(int8 to)
// lock access to stream
ReadLocked locked(fTree->fStream->Lock());
off_t nodeOffset = fTree->fHeader->root_node_pointer;
off_t nodeOffset = fTree->fHeader->RootNode();
CachedNode cached(fTree);
bplustree_node *node;
while ((node = cached.SetTo(nodeOffset)) != NULL) {
// is the node a leaf node?
if (node->overflow_link == BPLUSTREE_NULL) {
if (node->OverflowLink() == BPLUSTREE_NULL) {
fCurrentNodeOffset = nodeOffset;
fCurrentKey = to == BPLUSTREE_BEGIN ? -1 : node->all_key_count;
fCurrentKey = to == BPLUSTREE_BEGIN ? -1 : node->NumKeys();
fDuplicateNode = BPLUSTREE_NULL;
return B_OK;
@@ -1674,13 +1677,13 @@ TreeIterator::Goto(int8 to)
// are any keys in that node at all)
off_t nextOffset;
if (to == BPLUSTREE_END || node->all_key_count == 0)
nextOffset = node->overflow_link;
nextOffset = node->OverflowLink();
else {
if (node->all_key_length > fTree->fNodeSize
|| (uint32)node->Values() > (uint32)node + fTree->fNodeSize - 8 * node->all_key_count)
if (node->AllKeyLength() > fTree->fNodeSize
|| (uint32)node->Values() > (uint32)node + fTree->fNodeSize - 8 * node->NumKeys())
RETURN_ERROR(B_ERROR);
nextOffset = node->Values()[0];
nextOffset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[0]);
}
if (nextOffset == nodeOffset)
break;
@@ -1740,7 +1743,7 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
if (!fIsFragment && fDuplicate >= fNumDuplicates)
{
// 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
&& (node = cached.SetTo(fDuplicateNode, false)) != NULL)
{
@@ -1769,10 +1772,10 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
fCurrentKey += direction;
// 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))
{
fCurrentNodeOffset = direction == BPLUSTREE_FORWARD ? node->right_link : node->left_link;
fCurrentNodeOffset = direction == BPLUSTREE_FORWARD ? node->RightLink() : node->LeftLink();
// are there any more nodes?
if (fCurrentNodeOffset != BPLUSTREE_NULL)
@@ -1782,13 +1785,13 @@ TreeIterator::Traverse(int8 direction, void *key, uint16 *keyLength, uint16 maxL
RETURN_ERROR(B_ERROR);
// reset current key
fCurrentKey = direction == BPLUSTREE_FORWARD ? 0 : node->all_key_count;
fCurrentKey = direction == BPLUSTREE_FORWARD ? 0 : node->NumKeys();
}
else
{
// there are no nodes left, so turn back to the last key
fCurrentNodeOffset = savedNodeOffset;
fCurrentKey = direction == BPLUSTREE_FORWARD ? node->all_key_count : -1;
fCurrentKey = direction == BPLUSTREE_FORWARD ? node->NumKeys() : -1;
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 ?
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
|| length > BPLUSTREE_MAX_KEY_LENGTH) {
fTree->fStream->GetVolume()->Panic();
RETURN_ERROR(B_BAD_DATA);
}
length = min_c(length,maxLength);
memcpy(key,keyStart,length);
length = min_c(length, maxLength);
memcpy(key, keyStart, length);
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;
off_t offset = node->Values()[fCurrentKey];
off_t offset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[fCurrentKey]);
// duplicate fragments?
uint8 type = bplustree_node::LinkType(offset);
@@ -1868,7 +1871,7 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
// lock access to stream
ReadLocked locked(fTree->fStream->Lock());
off_t nodeOffset = fTree->fHeader->root_node_pointer;
off_t nodeOffset = fTree->fHeader->RootNode();
CachedNode cached(fTree);
bplustree_node *node;
@@ -1877,7 +1880,7 @@ TreeIterator::Find(const uint8 *key, uint16 keyLength)
off_t nextOffset;
status_t status = fTree->FindKey(node, key, keyLength, &keyIndex, &nextOffset);
if (node->overflow_link == BPLUSTREE_NULL) {
if (node->OverflowLink() == BPLUSTREE_NULL) {
fCurrentNodeOffset = nodeOffset;
fCurrentKey = keyIndex - 1;
fDuplicateNode = BPLUSTREE_NULL;
@@ -1952,7 +1955,7 @@ TreeIterator::Dump()
void
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_length = 0;
}
@@ -1961,15 +1964,16 @@ bplustree_node::Initialize()
uint8 *
bplustree_node::KeyAt(int32 index, uint16 *keyLength) const
{
if (index < 0 || index > all_key_count)
if (index < 0 || index > NumKeys())
return NULL;
uint8 *keyStart = Keys();
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)
keyStart += keyLengths[index - 1];
keyStart += BFS_ENDIAN_TO_HOST_INT16(keyLengths[index - 1]);
return keyStart;
}
@@ -1986,7 +1990,7 @@ bplustree_node::CountDuplicates(off_t offset, bool isFragment) const
return ((off_t *)this)[fragment];
}
return overflow_link;
return OverflowLink();
}
@@ -2026,10 +2030,10 @@ bplustree_node::FragmentsUsed(uint32 nodeSize)
void
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"));
for (int32 i = 0; i < all_key_count; i++) {
for (int32 i = 0; i < NumKeys(); i++) {
uint16 length;
uint8 *key = KeyAt(i, &length);
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 free_node_pointer;
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);
};
@@ -56,13 +64,19 @@ struct bplustree_node {
off_t overflow_link;
uint16 all_key_count;
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 off_t *Values() const;
inline uint8 *Keys() const;
inline int32 Used() const;
uint8 *KeyAt(int32 index,uint16 *keyLength) const;
uint8 *KeyAt(int32 index, uint16 *keyLength) const;
inline bool IsLeaf() const;
void Initialize();
@@ -381,7 +395,7 @@ TreeIterator::GetPreviousEntry(void *key, uint16 *keyLength, uint16 maxLength,
inline bool
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 *
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 *
bplustree_node::Values() const
{
return (off_t *)((char *)KeyLengths() + all_key_count * sizeof(uint16));
return (off_t *)((char *)KeyLengths() + NumKeys() * sizeof(uint16));
}
inline uint8 *
bplustree_node::Keys() const
{
return (uint8 *)this + sizeof(bplustree_node);
}
inline int32
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
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;
}
inline off_t
bplustree_node::MakeLink(uint8 type, off_t link, uint32 fragmentIndex)
{
return ((off_t)type << 62) | (link & 0x3ffffffffffffc00LL) | (fragmentIndex & 0x3ff);
}
inline bool
bplustree_node::IsDuplicate(off_t link)
{
return (LinkType(link) & (BPLUSTREE_DUPLICATE_NODE | BPLUSTREE_DUPLICATE_FRAGMENT)) > 0;
}
inline off_t
bplustree_node::FragmentOffset(off_t link)
{
return link & 0x3ffffffffffffc00LL;
}
inline uint32
bplustree_node::FragmentIndex(off_t link)
{
@@ -112,7 +112,7 @@ AllocationBlock::IsUsed(uint16 block)
if (block > fNumBits)
return true;
// 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
// 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));
DEBUGGER(("blocks already set!"));
}
#endif
Block(block++) |= mask;
Block(block++) |= HOST_ENDIAN_TO_BFS_INT32(mask);
start = 0;
}
}
@@ -165,7 +165,7 @@ AllocationBlock::Free(uint16 start, uint16 numBlocks)
for (int32 i = start % 32; i < 32 && numBlocks; i++, numBlocks--)
mask |= 1UL << (i % 32);
Block(block++) &= ~mask;
Block(block++) &= HOST_ENDIAN_TO_BFS_INT32(~mask);
start = 0;
}
}
@@ -332,7 +332,7 @@ BlockAllocator::Initialize()
return B_ERROR;
fNumGroups = fVolume->AllocationGroups();
fBlocksPerGroup = fVolume->SuperBlock().blocks_per_ag;
fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
fGroups = new AllocationGroup[fNumGroups];
if (fGroups == NULL)
return B_NO_MEMORY;
@@ -397,7 +397,7 @@ BlockAllocator::initialize(BlockAllocator *allocator)
free(buffer);
// 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) {
Transaction transaction(volume, 0);
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
// normal that the values don't match
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;
@@ -502,11 +502,12 @@ BlockAllocator::AllocateBlocks(Transaction *transaction, int32 group, uint16 sta
if (fGroups[group].Allocate(transaction, rangeStart, numBlocks) < B_OK)
RETURN_ERROR(B_IO_ERROR);
run.allocation_group = group;
run.start = rangeStart;
run.length = numBlocks;
run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(group);
run.start = HOST_ENDIAN_TO_BFS_INT16(rangeStart);
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
// either done by the journaling code, or when the disk
// 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
// 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)
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
// if necessary)
uint16 group = inode->BlockRun().allocation_group;
uint16 group = inode->BlockRun().AllocationGroup();
uint16 start = 0;
// 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) {
// Since size > 0, there must be a valid block run in this stream
int32 last = 0;
for (;last < NUM_DIRECT_BLOCKS - 1;last++)
for (; last < NUM_DIRECT_BLOCKS - 1; last++)
if (data->direct[last + 1].IsZero())
break;
group = data->direct[last].allocation_group;
start = data->direct[last].start + data->direct[last].length;
group = data->direct[last].AllocationGroup();
start = data->direct[last].Start() + data->direct[last].Length();
}
} else if (inode->IsContainer() || inode->IsSymLink()) {
// directory and symbolic link data will go in the same allocation
// group as the inode is in but after the inode data
start = inode->BlockRun().start;
start = inode->BlockRun().Start();
} else {
// 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);
@@ -604,9 +605,9 @@ BlockAllocator::Free(Transaction *transaction, block_run run)
{
Locker lock(fLock);
int32 group = run.allocation_group;
uint16 start = run.start;
uint16 length = run.length;
int32 group = run.AllocationGroup();
uint16 start = run.Start();
uint16 length = run.Length();
// doesn't use Volume::IsValidBlockRun() here because it can check better
// 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;
}
// 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));
DEBUGGER(("tried to free reserved block"));
return B_BAD_VALUE;
@@ -632,7 +633,8 @@ BlockAllocator::Free(Transaction *transaction, block_run run)
if (fGroups[group].Free(transaction, start, length) < B_OK)
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;
}
@@ -683,7 +685,7 @@ BlockAllocator::StartChecking(check_control *control)
// initialize bitmap
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);
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
// transactions, so that we don't blow the maximum log size
// 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 blockSize = fVolume->BlockSize();
for (int32 i = 0; i < blocksInBitmap; i += 512) {
Transaction transaction(fVolume, 1 + i);
int32 blocksToWrite = 512;
if (blocksToWrite + i > blocksInBitmap)
blocksToWrite = blocksInBitmap - i;
@@ -943,7 +945,7 @@ BlockAllocator::CheckBitmapIsUsedAt(off_t block) const
if (index > size / 4)
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)
return;
fCheckBitmap[index] |= (1UL << (block & 0x1f));
fCheckBitmap[index] |= HOST_ENDIAN_TO_BFS_INT32(1UL << (block & 0x1f));
}
status_t
BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *control)
{
if (run.allocation_group < 0 || run.allocation_group >= fNumGroups
|| run.start > fGroups[run.allocation_group].fNumBits
|| uint32(run.start + run.length) > fGroups[run.allocation_group].fNumBits
if (run.AllocationGroup() < 0 || run.AllocationGroup() >= fNumGroups
|| run.Start() > fGroups[run.allocation_group].fNumBits
|| uint32(run.Start() + run.Length()) > fGroups[run.AllocationGroup()].fNumBits
|| 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)
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 block = run.start / bitsPerBlock;
uint32 pos = run.start % bitsPerBlock;
uint32 block = run.Start() / bitsPerBlock;
uint32 pos = run.Start() % bitsPerBlock;
int32 length = 0;
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);
for (; block < fBlocksPerGroup && length < run.length; block++, pos = 0) {
if (cached.SetTo(fGroups[run.allocation_group], block) < B_OK)
for (; block < fBlocksPerGroup && length < run.Length(); block++, pos = 0) {
if (cached.SetTo(fGroups[run.AllocationGroup()], block) < B_OK)
RETURN_ERROR(B_IO_ERROR);
if (pos >= cached.NumBlockBits()) {
@@ -992,10 +994,10 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
RETURN_ERROR(B_ERROR);
}
while (length < run.length && pos < cached.NumBlockBits()) {
while (length < run.Length() && pos < cached.NumBlockBits()) {
if (!cached.IsUsed(pos)) {
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;
}
if (firstMissing == -1) {
@@ -1004,7 +1006,8 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
}
control->stats.missing++;
} 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;
}
@@ -1020,7 +1023,8 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
control->stats.already_set++;
} else {
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;
}
SetCheckBitmapAt(firstGroupBlock + offset);
@@ -1030,11 +1034,11 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
pos++;
}
if (block + 1 >= fBlocksPerGroup || length >= run.length) {
if (block + 1 >= fBlocksPerGroup || length >= run.Length()) {
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)
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
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())
break;
status = CheckBlockRun(data->direct[i], "direct", control);
if (status < B_OK)
return status;
@@ -1080,7 +1084,7 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
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);
if (runs == NULL)
RETURN_ERROR(B_IO_ERROR);
@@ -1111,7 +1115,8 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
int32 runsPerArray = runsPerBlock << ARRAY_BLOCKS_SHIFT;
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++) {
// get the indirect array block
@@ -1129,7 +1134,7 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
if (status < B_OK)
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; ) {
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();
node->magic1 = INODE_MAGIC1;
node->magic1 = HOST_ENDIAN_TO_BFS_INT32(INODE_MAGIC1);
node->inode_num = run;
node->mode = mode;
node->flags = INODE_IN_USE | INODE_NOT_READY;
node->mode = HOST_ENDIAN_TO_BFS_INT32(mode);
node->flags = HOST_ENDIAN_TO_BFS_INT32(INODE_IN_USE | INODE_NOT_READY);
// INODE_NOT_READY prevents the inode from being opened - it is
// cleared in InodeAllocator::Keep()
node->etc = (uint32)fInode;
// this is temporarily set along INODE_NOT_READY and lets bfs_read_vnode()
// find the associated Inode object
node->create_time = (bigtime_t)time(NULL) << INODE_TIME_SHIFT;
node->last_modified_time = node->create_time | (volume->GetUniqueID() & INODE_TIME_MASK);
node->create_time = HOST_ENDIAN_TO_BFS_INT64((bigtime_t)time(NULL) << INODE_TIME_SHIFT);
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
// last_modified index
node->inode_size = volume->InodeSize();
node->inode_size = HOST_ENDIAN_TO_BFS_INT32(volume->InodeSize());
*_inode = fInode;
return B_OK;
@@ -105,7 +106,7 @@ InodeAllocator::CreateTree()
// force S_STR_INDEX to be set, if no type is set
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);
if (tree == NULL || tree->InitCheck() < B_OK)
@@ -146,20 +147,20 @@ bfs_inode::InitCheck(Volume *volume)
return B_BUSY;
}
if (magic1 != INODE_MAGIC1
|| !(flags & INODE_IN_USE)
|| inode_num.length != 1
if (Magic1() != INODE_MAGIC1
|| !(Flags() & INODE_IN_USE)
|| inode_num.Length() != 1
// matches inode size?
|| (uint32)inode_size != volume->InodeSize()
|| (uint32)InodeSize() != volume->InodeSize()
// parent resides on disk?
|| parent.allocation_group > int32(volume->AllocationGroups())
|| parent.allocation_group < 0
|| parent.start > (1L << volume->AllocationGroupShift())
|| parent.length != 1
|| parent.AllocationGroup() > int32(volume->AllocationGroups())
|| parent.AllocationGroup() < 0
|| parent.Start() > (1L << volume->AllocationGroupShift())
|| parent.Length() != 1
// attributes, too?
|| attributes.allocation_group > int32(volume->AllocationGroups())
|| attributes.allocation_group < 0
|| attributes.start > (1L << volume->AllocationGroupShift()))
|| attributes.AllocationGroup() > int32(volume->AllocationGroups())
|| attributes.AllocationGroup() < 0
|| attributes.Start() > (1L << volume->AllocationGroupShift()))
RETURN_ERROR(B_BAD_DATA);
// ToDo: Add some tests to check the integrity of the other stuff here,
@@ -200,10 +201,10 @@ void
Inode::Initialize()
{
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);
Node()->flags &= INODE_PERMANENT_FLAGS;
Node()->flags &= HOST_ENDIAN_TO_BFS_INT32(INODE_PERMANENT_FLAGS);
// these two will help to maintain the indices
fOldSize = Size();
@@ -251,9 +252,9 @@ Inode::CheckPermissions(int accessMode) const
// shift mode bits, to check directly against accessMode
mode_t mode = Mode();
if (user == (uid_t)Node()->uid)
if (user == (uid_t)Node()->UserID())
mode >>= 6;
else if (group == (gid_t)Node()->gid)
else if (group == (gid_t)Node()->GroupID())
mode >>= 3;
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
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)
RETURN_ERROR(status);
size_t length = item->data_size;
size_t length = item->DataSize();
status = attribute->WriteAt(transaction, 0, item->Data(), &length);
ReleaseAttribute(attribute);
@@ -466,18 +467,18 @@ Inode::AddSmallData(Transaction *transaction, const char *name, uint32 type,
// try to change the attributes value
if (item->data_size > length
|| 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)
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
// 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);
if (MakeSpaceForSmallData(transaction, name, needed) < B_OK)
return B_ERROR;
// reset our pointers
item = Node()->small_data_start;
index = 0;
@@ -502,8 +503,8 @@ Inode::AddSmallData(Transaction *transaction, const char *name, uint32 type,
if ((uint8 *)last < (uint8 *)Node() + fVolume->BlockSize())
memset(last, 0, (uint8 *)Node() + fVolume->BlockSize() - (uint8 *)last);
item->type = type;
item->data_size = length;
item->type = HOST_ENDIAN_TO_BFS_INT32(type);
item->data_size = HOST_ENDIAN_TO_BFS_INT16(length);
memcpy(item->Data(), data, length);
item->Data()[length] = '\0';
@@ -539,9 +540,9 @@ Inode::AddSmallData(Transaction *transaction, const char *name, uint32 type,
}
memset(item, 0, spaceNeeded);
item->type = type;
item->name_size = nameLength;
item->data_size = length;
item->type = HOST_ENDIAN_TO_BFS_INT32(type);
item->name_size = HOST_ENDIAN_TO_BFS_INT16(nameLength);
item->data_size = HOST_ENDIAN_TO_BFS_INT16(length);
strcpy(item->Name(), name);
memcpy(item->Data(), data, length);
@@ -628,7 +629,7 @@ Inode::Name() const
small_data *smallData = NULL;
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 NULL;
@@ -694,8 +695,8 @@ Inode::ReadAttribute(const char *name, int32 type, off_t pos, uint8 *buffer, siz
*_length = 0;
return B_OK;
}
if (length + pos > smallData->data_size)
length = smallData->data_size - pos;
if (length + pos > smallData->DataSize())
length = smallData->DataSize() - pos;
memcpy(buffer, smallData->Data() + pos, length);
*_length = length;
@@ -749,7 +750,7 @@ Inode::WriteAttribute(Transaction *transaction, const char *name, int32 type, of
small_data *smallData = FindSmallData(name);
if (smallData != NULL) {
oldLength = smallData->data_size;
oldLength = smallData->DataSize();
if (oldLength > BPLUSTREE_MAX_KEY_LENGTH)
oldLength = BPLUSTREE_MAX_KEY_LENGTH;
memcpy(oldData = oldBuffer, smallData->Data(), oldLength);
@@ -820,10 +821,10 @@ Inode::RemoveAttribute(Transaction *transaction, const char *name)
small_data *smallData = FindSmallData(name);
if (smallData != NULL) {
uint32 length = smallData->data_size;
uint32 length = smallData->DataSize();
if (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();
}
@@ -857,7 +858,7 @@ Inode::RemoveAttribute(Transaction *transaction, const char *name)
// remove attribute directory (don't fail if that can't be done)
if (remove_vnode(fVolume->ID(), attributes->ID()) == B_OK) {
// 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) {
Attributes().SetTo(0, 0, 0);
WriteBack(transaction);
@@ -1103,12 +1104,12 @@ Inode::FillGapWithZeros(off_t pos, off_t newSize)
while (length > 0) {
// offset is the offset to the current pos in the block_run
run.start += (pos - offset) >> blockShift;
run.length -= (pos - offset) >> blockShift;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
CachedBlock cached(fVolume);
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)
RETURN_ERROR(B_IO_ERROR);
@@ -1116,7 +1117,7 @@ Inode::FillGapWithZeros(off_t pos, off_t newSize)
RETURN_ERROR(B_IO_ERROR);
}
int32 bytes = run.length << blockShift;
int32 bytes = run.Length() << blockShift;
length -= bytes;
bytesWritten += bytes;
@@ -1152,7 +1153,7 @@ Inode::AllocateBlockArray(Transaction *transaction, block_run &run)
CachedBlock cached(fVolume);
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);
if (runs == NULL)
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?
// (can be the case with preallocated blocks)
if (size < data->max_direct_range
|| size < data->max_indirect_range
|| size < data->max_double_indirect_range) {
data->size = size;
if (size < data->MaxDirectRange()
|| size < data->MaxIndirectRange()
|| size < data->MaxDoubleIndirectRange()) {
data->size = HOST_ENDIAN_TO_BFS_INT64(size);
return B_OK;
}
// how many bytes are still needed? (unused ranges are always zero)
uint16 minimum = 1;
off_t bytes;
if (data->size < data->max_double_indirect_range) {
bytes = size - data->max_double_indirect_range;
if (data->Size() < data->MaxDoubleIndirectRange()) {
bytes = size - data->MaxDoubleIndirectRange();
// the double indirect range can only handle multiple of NUM_ARRAY_BLOCKS
minimum = NUM_ARRAY_BLOCKS;
} else if (data->size < data->max_indirect_range)
bytes = size - data->max_indirect_range;
else if (data->size < data->max_direct_range)
bytes = size - data->max_direct_range;
} else if (data->Size() < data->MaxIndirectRange())
bytes = size - data->MaxIndirectRange();
else if (data->Size() < data->MaxDirectRange())
bytes = size - data->MaxDirectRange();
else
bytes = size - data->size;
bytes = size - data->Size();
// do we have enough free blocks on the disk?
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
// 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
blocksRequested = blocksNeeded;
if (minimum > 1) {
@@ -1231,10 +1232,10 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// 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
int32 free = 0;
for (;free < NUM_DIRECT_BLOCKS;free++)
for (; free < NUM_DIRECT_BLOCKS; free++)
if (data->direct[free].IsZero())
break;
@@ -1242,19 +1243,19 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// can we merge the last allocated run with the new one?
int32 last = free - 1;
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
data->direct[free] = run;
data->max_direct_range += run.length * fVolume->BlockSize();
data->size = blocksNeeded > 0 ? data->max_direct_range : size;
data->max_direct_range = HOST_ENDIAN_TO_BFS_INT64(data->MaxDirectRange() + run.Length() * fVolume->BlockSize());
data->size = HOST_ENDIAN_TO_BFS_INT64(blocksNeeded > 0 ? data->max_direct_range : size);
continue;
}
}
// Indirect block range
if (data->size <= data->max_indirect_range || !data->max_indirect_range) {
if (data->Size() <= data->MaxIndirectRange() || !data->MaxIndirectRange()) {
CachedBlock cached(fVolume);
block_run *runs = NULL;
uint32 free = 0;
@@ -1266,7 +1267,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
if (status < B_OK)
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
runs = (block_run *)cached.SetTo(data->indirect);
} else {
@@ -1275,7 +1276,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// search first empty entry
int32 i = 0;
for (; i < data->indirect.length; i++) {
for (; i < data->indirect.Length(); i++) {
if ((runs = (block_run *)cached.SetTo(block + i)) == NULL)
return B_IO_ERROR;
@@ -1286,7 +1287,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
if (free < numberOfRuns)
break;
}
if (i == data->indirect.length)
if (i == data->indirect.Length())
runs = NULL;
}
@@ -1295,12 +1296,12 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// take block borders into account, so it could be further optimized
int32 last = free - 1;
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
runs[free] = run;
data->max_indirect_range += run.length << fVolume->BlockShift();
data->size = blocksNeeded > 0 ? data->max_indirect_range : size;
data->max_indirect_range = HOST_ENDIAN_TO_BFS_INT64(data->MaxIndirectRange() + (run.Length() << fVolume->BlockShift()));
data->size = HOST_ENDIAN_TO_BFS_INT64(blocksNeeded > 0 ? data->MaxIndirectRange() : size);
cached.WriteBack(transaction);
continue;
@@ -1309,18 +1310,18 @@ Inode::GrowStream(Transaction *transaction, off_t size)
// Double indirect block range
if (data->size <= data->max_double_indirect_range || !data->max_double_indirect_range) {
while ((run.length % NUM_ARRAY_BLOCKS) != 0) {
if (data->Size() <= data->MaxDoubleIndirectRange() || !data->max_double_indirect_range) {
while ((run.Length() % NUM_ARRAY_BLOCKS) != 0) {
// 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
// grows into the double indirect range.
// First, free the remaining blocks that don't fit into a multiple
// of NUM_ARRAY_BLOCKS
int32 rest = run.length % NUM_ARRAY_BLOCKS;
run.length -= rest;
int32 rest = run.Length() % NUM_ARRAY_BLOCKS;
run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - rest);
status = fVolume->Free(transaction, block_run::Run(run.allocation_group,
run.start + run.length, rest));
status = fVolume->Free(transaction, block_run::Run(run.AllocationGroup(),
run.Start() + run.Length(), rest));
if (status < B_OK)
return status;
@@ -1352,7 +1353,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
int32 directSize = NUM_ARRAY_BLOCKS << fVolume->BlockShift();
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 index = start / directSize;
@@ -1362,7 +1363,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
CachedBlock cached(fVolume);
CachedBlock cachedDirect(fVolume);
block_run *array = NULL;
uint32 runLength = run.length;
uint32 runLength = run.Length();
// ToDo: the following code is commented - it could be used to
// 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
if (array == NULL) {
if (cached.Block() != NULL
&& cached.WriteBack(transaction) < B_OK)
return B_IO_ERROR;
array = (block_run *)cached.SetTo(fVolume->ToBlock(data->double_indirect) +
indirectIndex / runsPerBlock);
array = (block_run *)cached.SetTo(fVolume->ToBlock(data->double_indirect)
+ indirectIndex / runsPerBlock);
if (array == NULL)
return B_IO_ERROR;
}
@@ -1424,11 +1425,11 @@ Inode::GrowStream(Transaction *transaction, off_t size)
do {
// insert the block_run into the array
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
run.start += NUM_ARRAY_BLOCKS;
run.length -= NUM_ARRAY_BLOCKS;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + NUM_ARRAY_BLOCKS);
run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - NUM_ARRAY_BLOCKS);
} while ((++index % runsPerBlock) != 0 && run.length);
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->size = blocksNeeded > 0 ? data->max_double_indirect_range : size;
data->max_double_indirect_range = HOST_ENDIAN_TO_BFS_INT64(data->MaxDoubleIndirectRange() + (runLength << fVolume->BlockShift()));
data->size = blocksNeeded > 0 ? HOST_ENDIAN_TO_BFS_INT64(data->max_double_indirect_range) : size;
continue;
}
@@ -1450,7 +1451,7 @@ Inode::GrowStream(Transaction *transaction, off_t size)
RETURN_ERROR(EFBIG);
}
// update the size of the data stream
data->size = size;
data->size = HOST_ENDIAN_TO_BFS_INT64(size);
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
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);
if (array == NULL)
RETURN_ERROR(B_ERROR);
@@ -1490,7 +1491,7 @@ Inode::FreeStaticStreamArray(Transaction *transaction, int32 level, block_run ru
for (index = index % runsPerBlock; index < runsPerBlock; index++) {
if (array[index].IsZero()) {
// we also want to break out of the outer loop
i = run.length;
i = run.Length();
break;
}
@@ -1500,7 +1501,7 @@ Inode::FreeStaticStreamArray(Transaction *transaction, int32 level, block_run ru
else if (offset >= size)
status = fVolume->Free(transaction, array[index]);
else
max = offset + indirectSize;
max = HOST_ENDIAN_TO_BFS_INT64(offset + indirectSize);
if (status < B_OK)
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
* have to be freed - after this, the values won't be correct anymore, but
* will still assure correct function for all subsequent calls.
* "max" is considered to be in file system byte order.
*/
status_t
@@ -1535,7 +1537,7 @@ Inode::FreeStreamArray(Transaction *transaction, block_run *array, uint32 arrayL
if (array[i].IsZero())
break;
newOffset += (off_t)array[i].length << fVolume->BlockShift();
newOffset += (off_t)array[i].Length() << fVolume->BlockShift();
if (newOffset <= size)
continue;
@@ -1545,20 +1547,20 @@ Inode::FreeStreamArray(Transaction *transaction, block_run *array, uint32 arrayL
if (newOffset > size && offset < size) {
// free partial block_run (and update the original block_run)
run.start = array[i].start + ((size - offset) >> fVolume->BlockShift()) + 1;
array[i].length = run.start - array[i].start;
run.length -= array[i].length;
array[i].length = HOST_ENDIAN_TO_BFS_INT16(run.Start() - array[i].Start());
run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - array[i].Length());
if (run.length == 0)
continue;
// 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 {
// free the whole block_run
array[i].SetTo(0, 0, 0);
if (max > offset)
max = offset;
if ((off_t)BFS_ENDIAN_TO_HOST_INT64(max) > offset)
max = HOST_ENDIAN_TO_BFS_INT64(offset);
}
if (fVolume->Free(transaction, run) < B_OK)
@@ -1573,22 +1575,22 @@ Inode::ShrinkStream(Transaction *transaction, off_t size)
{
data_stream *data = &Node()->data;
if (data->max_double_indirect_range > size) {
if (data->MaxDoubleIndirectRange() > 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);
data->double_indirect.SetTo(0, 0, 0);
data->max_double_indirect_range = 0;
}
}
if (data->max_indirect_range > size) {
if (data->MaxIndirectRange() > size) {
CachedBlock cached(fVolume);
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);
if (array == NULL)
break;
@@ -1603,13 +1605,13 @@ Inode::ShrinkStream(Transaction *transaction, off_t size)
data->max_indirect_range = 0;
}
}
if (data->max_direct_range > size) {
if (data->MaxDirectRange() > size) {
off_t offset = 0;
FreeStreamArray(transaction, data->direct, NUM_DIRECT_BLOCKS, size, offset,
data->max_direct_range);
}
data->size = size;
data->size = HOST_ENDIAN_TO_BFS_INT64(size);
return B_OK;
}
@@ -1624,7 +1626,7 @@ Inode::SetFileSize(Transaction *transaction, off_t size)
|| Flags() & INODE_NO_CACHE)
return B_BAD_VALUE;
off_t oldSize = Node()->data.size;
off_t oldSize = Size();
if (size == oldSize)
return B_OK;
@@ -1709,12 +1711,12 @@ Inode::Sync()
// 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())
return B_OK;
status = flush_blocks(fVolume->Device(), fVolume->ToBlock(data->direct[i]),
data->direct[i].length);
data->direct[i].Length());
if (status != B_OK)
return status;
}
@@ -1728,7 +1730,7 @@ Inode::Sync()
off_t block = fVolume->ToBlock(data->indirect);
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);
if (runs == NULL)
break;
@@ -1737,7 +1739,7 @@ Inode::Sync()
if (runs[i].IsZero())
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)
return status;
}
@@ -1750,7 +1752,7 @@ Inode::Sync()
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);
if (indirectRuns == NULL)
return B_FILE_ERROR;
@@ -1762,7 +1764,7 @@ Inode::Sync()
return B_OK;
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);
if (runs == NULL)
return B_FILE_ERROR;
@@ -1774,7 +1776,7 @@ Inode::Sync()
// ToDo: combine single block_runs to bigger ones when
// they are adjacent
status = flush_blocks(fVolume->Device(), fVolume->ToBlock(runs[i]),
runs[i].length);
runs[i].Length());
if (status != B_OK)
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 :-)
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
// 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->uid = geteuid();
node->gid = parent ? parent->Node()->gid : getegid();
node->uid = HOST_ENDIAN_TO_BFS_INT32(geteuid());
node->gid = HOST_ENDIAN_TO_BFS_INT32(parent ? parent->Node()->gid : getegid());
// 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
// 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()))
break;
if (item->name_size == FILE_NAME_NAME_LENGTH
if (item->NameSize() == FILE_NAME_NAME_LENGTH
&& *item->Name() == FILE_NAME_NAME)
continue;
@@ -2108,8 +2110,8 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type, vnode_id
if (!item->IsLast(fInode->Node())) {
strncpy(name, item->Name(), B_FILE_NAME_LENGTH);
*_type = item->type;
*_length = item->name_size;
*_type = item->Type();
*_length = item->NameSize();
*_id = (vnode_id)fCurrentSmallData;
fCurrentSmallData = i;
@@ -2158,8 +2160,8 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type, vnode_id
Vnode vnode(volume,id);
Inode *attribute;
if ((status = vnode.Get(&attribute)) == B_OK) {
*_type = attribute->Node()->type;
*_length = attribute->Node()->data.size;
*_type = attribute->Type();
*_length = attribute->Size();
*_id = id;
}
+5 -5
View File
@@ -97,9 +97,9 @@ class Inode : public CachedBlock {
ReadWriteLock &Lock() { return fLock; }
SimpleLock &SmallDataLock() { return fSmallDataLock; }
mode_t Mode() const { return Node()->mode; }
uint32 Type() const { return Node()->type; }
int32 Flags() const { return Node()->flags; }
mode_t Mode() const { return Node()->Mode(); }
uint32 Type() const { return Node()->Type(); }
int32 Flags() const { return Node()->Flags(); }
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 :)
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()); }
// 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; }
block_run &BlockRun() const { return Node()->inode_num; }
@@ -173,7 +173,7 @@ class Inode : public CachedBlock {
// index maintaining helper
void UpdateOldSize() { fOldSize = Size(); }
void UpdateOldLastModified() { fOldLastModified = Node()->last_modified_time; }
void UpdateOldLastModified() { fOldLastModified = Node()->LastModifiedTime(); }
off_t OldSize() { return fOldSize; }
off_t OldLastModified() { return fOldLastModified; }
@@ -7,6 +7,7 @@ oldOPTIM = $(OPTIM) ;
{
local defines =
KEEP_WRONG_DIRENT_RECLEN
#BFS_BIG_ENDIAN_ONLY
;
if $(COMPILE_FOR_R5) {
+40 -40
View File
@@ -146,14 +146,14 @@ Uncached::WriteBack(Transaction *transaction)
status_t
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
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
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
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
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
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
@@ -271,13 +271,13 @@ Stream<Cache>::FindBlockRun(off_t pos, block_run &run, off_t &offset)
// find matching block run
if (data->max_direct_range > 0 && pos >= data->max_direct_range) {
if (data->max_double_indirect_range > 0 && pos >= data->max_indirect_range) {
if (data->MaxDirectRange() > 0 && pos >= data->MaxDirectRange()) {
if (data->MaxDoubleIndirectRange() > 0 && pos >= data->MaxIndirectRange()) {
// access to double indirect blocks
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()))
* (fVolume->BlockSize() / sizeof(block_run));
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);
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);
} else {
// access to indirect blocks
int32 runsPerBlock = fVolume->BlockSize() / sizeof(block_run);
off_t runBlockEnd = data->max_direct_range;
off_t runBlockEnd = data->MaxDirectRange();
Cache cached(fVolume);
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);
if (indirect == NULL)
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())
break;
runBlockEnd += indirect[current].length << cached.BlockShift();
runBlockEnd += indirect[current].Length() << cached.BlockShift();
if (runBlockEnd > pos) {
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("### 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);
}
}
@@ -343,11 +343,11 @@ Stream<Cache>::FindBlockRun(off_t pos, block_run &run, off_t &offset)
if (data->direct[current].IsZero())
break;
runBlockEnd += data->direct[current].length << fVolume->BlockShift();
runBlockEnd += data->direct[current].Length() << fVolume->BlockShift();
if (runBlockEnd > pos) {
run = data->direct[current];
offset = runBlockEnd - (run.length << fVolume->BlockShift());
//printf("### run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset);
offset = runBlockEnd - (run.Length() << fVolume->BlockShift());
//printf("### run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.Length(),fRunFileOffset);
return fVolume->ValidateBlockRun(run);
}
}
@@ -366,15 +366,15 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
if (pos < 0)
return B_BAD_VALUE;
if (pos >= Node()->data.size) {
if (pos >= Node()->data.Size()) {
*_length = 0;
return B_NO_ERROR;
}
size_t length = *_length;
if (pos + length > Node()->data.size)
length = Node()->data.size - pos;
if (pos + length > Node()->data.Size())
length = Node()->data.Size() - pos;
block_run run;
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
if (pos % blockSize != 0) {
run.start += (pos - offset) / blockSize;
run.length -= (pos - offset) / blockSize;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
Cache cached(fVolume,run);
if ((block = cached.Block()) == NULL) {
@@ -429,10 +429,10 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
while (length > 0) {
// offset is the offset to the current pos in the block_run
run.start += (pos - offset) >> blockShift;
run.length -= (pos - offset) >> blockShift;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((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) {
Cache cached(fVolume, run);
if ((block = cached.Block()) == NULL) {
@@ -443,7 +443,7 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
bytesRead += length;
break;
}
run.length = length >> blockShift;
run.length = HOST_ENDIAN_TO_BFS_INT16(length >> blockShift);
partial = true;
}
@@ -452,7 +452,7 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
RETURN_ERROR(B_BAD_VALUE);
}
int32 bytes = run.length << blockShift;
int32 bytes = run.Length() << blockShift;
#ifdef DEBUG
if ((uint32)bytes > length)
DEBUGGER(("bytes greater than length"));
@@ -467,8 +467,8 @@ Stream<Cache>::ReadAt(off_t pos, uint8 *buffer, size_t *_length)
if (partial) {
// if the last block was read only partially, point block_run
// to the remaining part
run.start += run.length;
run.length = 1;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + run.Length());
run.length = HOST_ENDIAN_TO_BFS_INT16(1);
offset = pos;
} else if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = bytesRead;
@@ -490,7 +490,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
// set/check boundaries for pos/length
if (pos < 0)
return B_BAD_VALUE;
if (pos + length > Node()->data.size) {
if (pos + length > Size()) {
off_t oldSize = Size();
// 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
if (pos % blockSize != 0) {
run.start += (pos - offset) / blockSize;
run.length -= (pos - offset) / blockSize;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift));
run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift));
Cache cached(fVolume, run);
if ((block = cached.Block()) == NULL) {
@@ -578,10 +578,10 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
while (length > 0) {
// offset is the offset to the current pos in the block_run
run.start += (pos - offset) >> blockShift;
run.length -= (pos - offset) >> blockShift;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((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) {
Cache cached(fVolume,run);
if ((block = cached.Block()) == NULL) {
@@ -595,7 +595,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
bytesWritten += length;
break;
}
run.length = length >> blockShift;
run.length = HOST_ENDIAN_TO_BFS_INT16(length >> blockShift);
partial = true;
}
@@ -604,7 +604,7 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
RETURN_ERROR(B_BAD_VALUE);
}
int32 bytes = run.length << blockShift;
int32 bytes = run.Length() << blockShift;
length -= bytes;
bytesWritten += bytes;
if (length == 0)
@@ -615,8 +615,8 @@ Stream<Cache>::WriteAt(Transaction *transaction, off_t pos, const uint8 *buffer,
if (partial) {
// if the last block was written only partially, point block_run
// to the remaining part
run.start += run.length;
run.length = 1;
run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + run.Length());
run.length = HOST_ENDIAN_TO_BFS_INT16(1);
offset = pos;
} else if (FindBlockRun(pos, run, offset) < B_OK) {
*_length = bytesWritten;
+47 -22
View File
@@ -41,17 +41,18 @@ Volume::~Volume()
bool
Volume::IsValidSuperBlock()
{
if (fSuperBlock.magic1 != (int32)SUPER_BLOCK_MAGIC1
|| fSuperBlock.magic2 != (int32)SUPER_BLOCK_MAGIC2
|| fSuperBlock.magic3 != (int32)SUPER_BLOCK_MAGIC3
if (fSuperBlock.Magic1() != (int32)SUPER_BLOCK_MAGIC1
|| fSuperBlock.Magic2() != (int32)SUPER_BLOCK_MAGIC2
|| fSuperBlock.Magic3() != (int32)SUPER_BLOCK_MAGIC3
|| (int32)fSuperBlock.block_size != fSuperBlock.inode_size
|| fSuperBlock.fs_byte_order != SUPER_BLOCK_FS_LENDIAN
|| (1UL << fSuperBlock.block_shift) != fSuperBlock.block_size
|| fSuperBlock.num_ags < 1
|| fSuperBlock.ag_shift < 1
|| fSuperBlock.blocks_per_ag < 1
|| fSuperBlock.num_blocks < 10
|| fSuperBlock.num_ags != divide_roundup(fSuperBlock.num_blocks,1L << fSuperBlock.ag_shift))
|| fSuperBlock.ByteOrder() != SUPER_BLOCK_FS_LENDIAN
|| (1UL << fSuperBlock.BlockShift()) != fSuperBlock.BlockSize()
|| fSuperBlock.AllocationGroups() < 1
|| fSuperBlock.AllocationGroupShift() < 1
|| fSuperBlock.BlocksPerAllocationGroup() < 1
|| fSuperBlock.NumBlocks() < 10
|| fSuperBlock.AllocationGroups() != divide_roundup(fSuperBlock.NumBlocks(),
1L << fSuperBlock.AllocationGroupShift()))
return false;
return true;
@@ -77,8 +78,15 @@ Volume::Mount(const char *deviceName, uint32 flags)
if (flags & B_MOUNT_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 (fDevice < B_OK && (flags & B_MOUNT_READ_ONLY) == 0) {
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
// is located at offset 0!
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()) {
// set the current log pointers, so that journaling will work correctly
fLogStart = fSuperBlock.log_start;
fLogEnd = fSuperBlock.log_end;
fLogStart = fSuperBlock.LogStart();
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) {
fJournal = new Journal(this);
@@ -130,7 +155,7 @@ Volume::Mount(const char *deviceName, uint32 flags)
fRootNode = new Inode(this, ToVnode(Root()));
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
// question: why doesn't get_vnode() work here??
@@ -208,12 +233,12 @@ Volume::Sync()
status_t
Volume::ValidateBlockRun(block_run run)
{
if (run.allocation_group < 0 || run.allocation_group > (int32)AllocationGroups()
|| run.start > (1UL << AllocationGroupShift())
if (run.AllocationGroup() < 0 || run.AllocationGroup() > (int32)AllocationGroups()
|| run.Start() > (1UL << AllocationGroupShift())
|| run.length == 0
|| uint32(run.length + run.start) > (1UL << AllocationGroupShift())) {
|| uint32(run.Length() + run.Start()) > (1UL << AllocationGroupShift())) {
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_OK;
@@ -224,9 +249,9 @@ block_run
Volume::ToBlockRun(off_t block) const
{
block_run run;
run.allocation_group = block >> fSuperBlock.ag_shift;
run.start = block & ~((1LL << fSuperBlock.ag_shift) - 1);
run.length = 1;
run.allocation_group = HOST_ENDIAN_TO_BFS_INT32(block >> AllocationGroupShift());
run.start = HOST_ENDIAN_TO_BFS_INT16(block & ~((1LL << AllocationGroupShift()) - 1));
run.length = HOST_ENDIAN_TO_BFS_INT16(1);
return run;
}
+15 -10
View File
@@ -57,19 +57,19 @@ class Volume {
nspace_id ID() const { return fID; }
const char *Name() const { return fSuperBlock.name; }
off_t NumBlocks() const { return fSuperBlock.num_blocks; }
off_t UsedBlocks() const { return fSuperBlock.used_blocks; }
off_t FreeBlocks() const { return fSuperBlock.num_blocks - fSuperBlock.used_blocks; }
off_t NumBlocks() const { return fSuperBlock.NumBlocks(); }
off_t UsedBlocks() const { return fSuperBlock.UsedBlocks(); }
off_t FreeBlocks() const { return NumBlocks() - UsedBlocks(); }
uint32 BlockSize() const { return fSuperBlock.block_size; }
uint32 BlockShift() const { return fSuperBlock.block_shift; }
uint32 InodeSize() const { return fSuperBlock.inode_size; }
uint32 AllocationGroups() const { return fSuperBlock.num_ags; }
uint32 AllocationGroupShift() const { return fSuperBlock.ag_shift; }
uint32 BlockSize() const { return fBlockSize; }
uint32 BlockShift() const { return fBlockShift; }
uint32 InodeSize() const { return fSuperBlock.InodeSize(); }
uint32 AllocationGroups() const { return fSuperBlock.AllocationGroups(); }
uint32 AllocationGroupShift() const { return fAllocationGroupShift; }
disk_super_block &SuperBlock() { return fSuperBlock; }
off_t ToOffset(block_run run) const { return ToBlock(run) << fSuperBlock.block_shift; }
off_t ToBlock(block_run run) const { return ((((off_t)run.allocation_group) << fSuperBlock.ag_shift) | (off_t)run.start); }
off_t ToOffset(block_run run) const { return ToBlock(run) << BlockShift(); }
off_t ToBlock(block_run run) const { return ((((off_t)run.AllocationGroup()) << AllocationGroupShift()) | (off_t)run.Start()); }
block_run ToBlockRun(off_t block) const;
status_t ValidateBlockRun(block_run run);
@@ -114,6 +114,11 @@ class Volume {
nspace_id fID;
int fDevice;
disk_super_block fSuperBlock;
uint32 fBlockSize;
uint32 fBlockShift;
uint32 fAllocationGroupShift;
BlockAllocator fBlockAllocator;
RecursiveLock fLock;
Journal *fJournal;
@@ -188,6 +188,8 @@ struct bfs_inode {
int32 Flags() const { return BFS_ENDIAN_TO_HOST_INT32(flags); }
int32 Type() const { return BFS_ENDIAN_TO_HOST_INT32(type); }
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);
// 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
if (inode->Flags() & INODE_LONG_SYMLINK) {
size_t readBytes = inode->Node()->data.size;
size_t readBytes = inode->Size();
char *data = (char *)malloc(readBytes);
if (data != NULL) {
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);
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
status_t status = volume->Pool().RequestBuffers(volume->BlockSize());
if (status == B_OK)
inode->Node()->flags |= INODE_NO_CACHE;
inode->Node()->flags |= HOST_ENDIAN_TO_BFS_INT32(INODE_NO_CACHE);
return status;
}
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;
off_t *creationTime = (off_t *)buffer;
*creationTime = inode->Node()->create_time;
*creationTime = inode->Node()->CreateTime();
return B_OK;
}
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);
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;
}
@@ -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);
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;
}
@@ -758,14 +758,14 @@ bfs_read_stat(void *_ns, void *_node, struct stat *st)
st->st_nlink = 1;
st->st_blksize = BFS_IO_SIZE;
st->st_uid = node->uid;
st->st_gid = node->gid;
st->st_mode = node->mode;
st->st_size = node->data.size;
st->st_uid = node->UserID();
st->st_gid = node->GroupID();
st->st_mode = node->Mode();
st->st_size = node->data.Size();
st->st_atime = time(NULL);
st->st_mtime = st->st_ctime = (time_t)(node->last_modified_time >> INODE_TIME_SHIFT);
st->st_crtime = (time_t)(node->create_time >> INODE_TIME_SHIFT);
st->st_mtime = st->st_ctime = (time_t)(node->LastModifiedTime() >> INODE_TIME_SHIFT);
st->st_crtime = (time_t)(node->CreateTime() >> INODE_TIME_SHIFT);
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);
status = link->WriteBack(&transaction);
} 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
// we don't have to do that here...
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) {
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
// non-permanent flag which will be removed when the inode is loaded
// 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 ((smallData = inode->FindSmallData((const char *)name)) != NULL) {
attrInfo->type = smallData->type;
attrInfo->size = smallData->data_size;
attrInfo->type = smallData->Type();
attrInfo->size = smallData->DataSize();
}
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();
indexInfo->type = index.Type();
indexInfo->size = node->data.size;
indexInfo->modification_time = (time_t)(node->last_modified_time >> INODE_TIME_SHIFT);
indexInfo->creation_time = (time_t)(node->create_time >> INODE_TIME_SHIFT);
indexInfo->uid = node->uid;
indexInfo->gid = node->gid;
indexInfo->size = node->data.Size();
indexInfo->modification_time = (time_t)(node->LastModifiedTime() >> INODE_TIME_SHIFT);
indexInfo->creation_time = (time_t)(node->CreateTime() >> INODE_TIME_SHIFT);
indexInfo->uid = node->UserID();
indexInfo->gid = node->GroupID();
return B_OK;
}