From cb94280c6b8450b48764df889cdf0a8fd19af64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 16 Sep 2003 21:49:22 +0000 Subject: [PATCH] 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 --- .../kernel/file_systems/bfs/BPlusTree.cpp | 312 +++++++++--------- .../kernel/file_systems/bfs/BPlusTree.h | 40 ++- .../file_systems/bfs/BlockAllocator.cpp | 105 +++--- src/add-ons/kernel/file_systems/bfs/Inode.cpp | 244 +++++++------- src/add-ons/kernel/file_systems/bfs/Inode.h | 10 +- src/add-ons/kernel/file_systems/bfs/Jamfile | 1 + src/add-ons/kernel/file_systems/bfs/Stream.h | 80 ++--- .../kernel/file_systems/bfs/Volume.cpp | 69 ++-- src/add-ons/kernel/file_systems/bfs/Volume.h | 25 +- src/add-ons/kernel/file_systems/bfs/bfs.h | 2 + .../file_systems/bfs/kernel_interface.cpp | 42 +-- 11 files changed, 498 insertions(+), 432 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp b/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp index 52672f6984..b90068831e 100644 --- a/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp @@ -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 &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 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 diff --git a/src/add-ons/kernel/file_systems/bfs/BPlusTree.h b/src/add-ons/kernel/file_systems/bfs/BPlusTree.h index a34dd34724..c8251cf15b 100644 --- a/src/add-ons/kernel/file_systems/bfs/BPlusTree.h +++ b/src/add-ons/kernel/file_systems/bfs/BPlusTree.h @@ -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) { diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index 5a6c642910..41d1219b96 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -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) diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index d0bf7f1e03..daa5c1600e 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.h b/src/add-ons/kernel/file_systems/bfs/Inode.h index 75572d3d85..11d613eb20 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.h +++ b/src/add-ons/kernel/file_systems/bfs/Inode.h @@ -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; } diff --git a/src/add-ons/kernel/file_systems/bfs/Jamfile b/src/add-ons/kernel/file_systems/bfs/Jamfile index ca67a6cbf3..c4a8d7b0ab 100644 --- a/src/add-ons/kernel/file_systems/bfs/Jamfile +++ b/src/add-ons/kernel/file_systems/bfs/Jamfile @@ -7,6 +7,7 @@ oldOPTIM = $(OPTIM) ; { local defines = KEEP_WRONG_DIRENT_RECLEN + #BFS_BIG_ENDIAN_ONLY ; if $(COMPILE_FOR_R5) { diff --git a/src/add-ons/kernel/file_systems/bfs/Stream.h b/src/add-ons/kernel/file_systems/bfs/Stream.h index e97008ff73..c2226d18ec 100644 --- a/src/add-ons/kernel/file_systems/bfs/Stream.h +++ b/src/add-ons/kernel/file_systems/bfs/Stream.h @@ -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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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; diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.cpp b/src/add-ons/kernel/file_systems/bfs/Volume.cpp index 15dcd823dd..eb5b349b54 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Volume.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.h b/src/add-ons/kernel/file_systems/bfs/Volume.h index a4ece321a9..43a28d2ae1 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.h +++ b/src/add-ons/kernel/file_systems/bfs/Volume.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/bfs/bfs.h b/src/add-ons/kernel/file_systems/bfs/bfs.h index b48dd9d2ae..dfbc7014af 100644 --- a/src/add-ons/kernel/file_systems/bfs/bfs.h +++ b/src/add-ons/kernel/file_systems/bfs/bfs.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 9c35ccc77e..d32579190b 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.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; }