bonefish + mmlr + axeld:

* Fixed a bug that could easily corrupt your disks (yeah, one of those
  again): bfs_get_file_map() truncated the last vec incorrectly and
  would potentially return a too large file size -- which was later
  happily overwritten with file data, but could have belonged to
  anything but that file (like inodes, B+trees, etc.).
* Renamed previous round_up() function to key_align().
* Added round_up() template function, and used it where appropriate.
* The latter actually fixed two bugs where the and mask was computed in
  32 bit where it should have been in 64 bit.
* Inode::FindBlockRun() should have checked the max indirect size
  instead of the direct size - this didn't cause any problems, though.
* White space cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26531 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-07-20 23:59:32 +00:00
parent a0a18e64f0
commit 9083840f34
6 changed files with 37 additions and 30 deletions
@@ -1036,7 +1036,7 @@ BPlusTree::_SplitNode(bplustree_node *node, off_t nodeOffset,
} }
out++; out++;
if (round_up(sizeof(bplustree_node) + bytesBefore + bytesAfter + bytes) if (key_align(sizeof(bplustree_node) + bytesBefore + bytesAfter + bytes)
+ out * (sizeof(uint16) + sizeof(off_t)) >= size) { + out * (sizeof(uint16) + sizeof(off_t)) >= size) {
// we have found the number of keys in the new node! // we have found the number of keys in the new node!
break; break;
@@ -1303,7 +1303,7 @@ BPlusTree::Insert(Transaction &transaction, const uint8 *key, uint16 keyLength,
return B_IO_ERROR; return B_IO_ERROR;
// is the node big enough to hold the pair? // is the node big enough to hold the pair?
if (int32(round_up(sizeof(bplustree_node) if (int32(key_align(sizeof(bplustree_node)
+ writableNode->AllKeyLength() + keyLength) + writableNode->AllKeyLength() + keyLength)
+ (writableNode->NumKeys() + 1) * (sizeof(uint16) + (writableNode->NumKeys() + 1) * (sizeof(uint16)
+ sizeof(off_t))) < fNodeSize) { + sizeof(off_t))) < fNodeSize) {
@@ -450,7 +450,7 @@ bplustree_header::IsValidLink(off_t link) const
inline uint16 * inline uint16 *
bplustree_node::KeyLengths() const bplustree_node::KeyLengths() const
{ {
return (uint16 *)(((char *)this) + round_up(sizeof(bplustree_node) return (uint16 *)(((char *)this) + key_align(sizeof(bplustree_node)
+ AllKeyLength())); + AllKeyLength()));
} }
@@ -472,7 +472,7 @@ bplustree_node::Keys() const
inline int32 inline int32
bplustree_node::Used() const bplustree_node::Used() const
{ {
return round_up(sizeof(bplustree_node) + AllKeyLength()) + NumKeys() return key_align(sizeof(bplustree_node) + AllKeyLength()) + NumKeys()
* (sizeof(uint16) + sizeof(off_t)); * (sizeof(uint16) + sizeof(off_t));
} }
@@ -1280,7 +1280,7 @@ Inode::FindBlockRun(off_t pos, block_run &run, off_t &offset)
// find matching block run // find matching block run
if (data->MaxDirectRange() > 0 && pos >= data->MaxDirectRange()) { if (data->MaxIndirectRange() > 0 && pos >= data->MaxDirectRange()) {
if (data->MaxDoubleIndirectRange() > 0 if (data->MaxDoubleIndirectRange() > 0
&& pos >= data->MaxIndirectRange()) { && pos >= data->MaxIndirectRange()) {
// access to double indirect blocks // access to double indirect blocks
@@ -1581,7 +1581,7 @@ Inode::_GrowStream(Transaction &transaction, off_t size)
blocksRequested = blocksNeeded; blocksRequested = blocksNeeded;
if (minimum > 1) { if (minimum > 1) {
// make sure that "blocks" is a multiple of minimum // make sure that "blocks" is a multiple of minimum
blocksRequested = (blocksRequested + minimum - 1) & ~(minimum - 1); blocksRequested = round_up(blocksRequested, minimum);
} }
// Direct block range // Direct block range
@@ -1694,8 +1694,7 @@ Inode::_GrowStream(Transaction &transaction, off_t size)
return status; return status;
blocksNeeded += rest; blocksNeeded += rest;
blocksRequested = (blocksNeeded + NUM_ARRAY_BLOCKS - 1) blocksRequested = round_up(blocksNeeded, NUM_ARRAY_BLOCKS);
& ~(NUM_ARRAY_BLOCKS - 1);
minimum = NUM_ARRAY_BLOCKS; minimum = NUM_ARRAY_BLOCKS;
// we make sure here that we have at minimum // we make sure here that we have at minimum
// NUM_ARRAY_BLOCKS allocated, so if the allocation // NUM_ARRAY_BLOCKS allocated, so if the allocation
@@ -2042,8 +2041,7 @@ Inode::NeedsTrimming()
if (IsIndex() || IsDeleted()) if (IsIndex() || IsDeleted())
return false; return false;
off_t roundedSize = (Size() + fVolume->BlockSize() - 1) off_t roundedSize = round_up(Size(), fVolume->BlockSize());
& ~(fVolume->BlockSize() - 1);
return Node().data.MaxDirectRange() > roundedSize return Node().data.MaxDirectRange() > roundedSize
|| Node().data.MaxIndirectRange() > roundedSize || Node().data.MaxIndirectRange() > roundedSize
@@ -33,4 +33,14 @@ sorted_array::Find(off_t value) const
return _FindInternal(value, i) ? i : -1; return _FindInternal(value, i) ? i : -1;
} }
/*! \a to must be a power of 2.
*/
template<typename IntType, typename RoundType>
inline IntType
round_up(const IntType& value, const RoundType& to)
{
return (value + (to - 1)) & ~((IntType)to - 1);
}
#endif /* UTILITY_H */ #endif /* UTILITY_H */
+2 -2
View File
@@ -267,8 +267,8 @@ get_shift(uint64 i)
return c; return c;
} }
inline int32 inline uint32
round_up(uint32 data) key_align(uint32 data)
{ {
// rounds up to the next off_t boundary // rounds up to the next off_t boundary
return (data + sizeof(off_t) - 1) & ~(sizeof(off_t) - 1); return (data + sizeof(off_t) - 1) & ~(sizeof(off_t) - 1);
@@ -431,7 +431,7 @@ bfs_get_file_map(fs_volume *_volume, fs_vnode *_node, off_t offset, size_t size,
Inode *inode = (Inode *)_node->private_node; Inode *inode = (Inode *)_node->private_node;
int32 blockShift = volume->BlockShift(); int32 blockShift = volume->BlockShift();
size_t index = 0, max = *_count; uint32 index = 0, max = *_count;
block_run run; block_run run;
off_t fileOffset; off_t fileOffset;
@@ -445,21 +445,20 @@ bfs_get_file_map(fs_volume *_volume, fs_vnode *_node, off_t offset, size_t size,
vecs[index].offset = volume->ToOffset(run) + offset - fileOffset; vecs[index].offset = volume->ToOffset(run) + offset - fileOffset;
vecs[index].length = (run.Length() << blockShift) - offset + fileOffset; vecs[index].length = (run.Length() << blockShift) - offset + fileOffset;
offset += vecs[index].length;
// are we already done? // are we already done?
if (size <= vecs[index].length if (size <= vecs[index].length
|| offset >= inode->Size()) { || offset + vecs[index].length >= inode->Size()) {
if (offset > inode->Size()) { if (offset + vecs[index].length > inode->Size()) {
// make sure the extent ends with the last official file // make sure the extent ends with the last official file
// block (without taking any preallocations into account) // block (without taking any preallocations into account)
vecs[index].length = (inode->Size() - fileOffset vecs[index].length = round_up(inode->Size() - offset,
+ volume->BlockSize() - 1) & ~(volume->BlockSize() - 1); volume->BlockSize());
} }
*_count = index + 1; *_count = index + 1;
return B_OK; return B_OK;
} }
offset += vecs[index].length;
size -= vecs[index].length; size -= vecs[index].length;
index++; index++;