BTRFS: Implement some copy relevant helpers.
Copy() copys data from other node, MoveEntries() changes data on the current node. Signed-off-by: Augustin Cavalier <waddlesplash@gmail.com>
This commit is contained in:
parent
27ffe0583b
commit
89484dc08d
@ -185,6 +185,30 @@ BTree::Node::SpaceLeft() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BTree::Node::_Copy(const Node* origin, uint32 at, uint32 from, uint32 to,
|
||||||
|
int length) const
|
||||||
|
{
|
||||||
|
TRACE("Node::_Copy() at: %d from: %d to: %d length: %d\n",
|
||||||
|
at, from, to, length);
|
||||||
|
|
||||||
|
if (Level() == 0) {
|
||||||
|
memcpy(Item(at), origin->Item(from), origin->_CalculateSpace(from, to));
|
||||||
|
// Item offset of copied node must be changed to get the
|
||||||
|
// item data offset correctly. length can be zero
|
||||||
|
// but let it there doesn't harm anything.
|
||||||
|
for (uint32 i = at; i - at <= to - from; ++i)
|
||||||
|
Item(i)->SetOffset(Item(i)->Offset() - length);
|
||||||
|
|
||||||
|
memcpy(ItemData(at + to - from), origin->ItemData(to),
|
||||||
|
origin->_CalculateSpace(from, to, 2));
|
||||||
|
} else {
|
||||||
|
memcpy(Index(at), origin->Index(from),
|
||||||
|
origin->_CalculateSpace(from, to));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BTree::Node::_SpaceCheck(int length) const
|
BTree::Node::_SpaceCheck(int length) const
|
||||||
{
|
{
|
||||||
@ -198,6 +222,101 @@ BTree::Node::_SpaceCheck(int length) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* copy node header, items and items data
|
||||||
|
* length is size to insert/remove
|
||||||
|
* if node is a internal node, length isnt used
|
||||||
|
* length = 0: Copy a whole
|
||||||
|
* length < 0: removing
|
||||||
|
* length > 0: inserting
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
BTree::Node::Copy(const Node* origin, uint32 start, uint32 end, int length)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
status_t status = origin->_SpaceCheck(length);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
memcpy(fNode, origin->fNode, sizeof(btrfs_header));
|
||||||
|
if (length == 0) {
|
||||||
|
// like removing [0, start - 1] and keeping [start, end]
|
||||||
|
length = -origin->_CalculateSpace(0, start - 1, 2);
|
||||||
|
_Copy(origin, 0, start, end, length);
|
||||||
|
} else if (length < 0) {
|
||||||
|
//removing all items in [start, end]
|
||||||
|
if (start > 0)
|
||||||
|
_Copy(origin, 0, 0, start - 1, 0); // <-- [start,...
|
||||||
|
if (end + 1 < origin->ItemCount()) {
|
||||||
|
// ..., end] -->
|
||||||
|
// we only care data size
|
||||||
|
length += origin->_CalculateSpace(start, end);
|
||||||
|
_Copy(origin, start, end + 1, origin->ItemCount() - 1, length);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//inserting in [start, end] - make a hole for later
|
||||||
|
if (start > 0)
|
||||||
|
_Copy(origin, 0, 0, start - 1, 0);
|
||||||
|
if (start < origin->ItemCount()) {
|
||||||
|
length -= origin->_CalculateSpace(start, end);
|
||||||
|
_Copy(origin, end + 1, start, origin->ItemCount() - 1, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Like copy but here we use memmove on current node.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
BTree::Node::MoveEntries(uint32 start, uint32 end, int length) const
|
||||||
|
{
|
||||||
|
status_t status = _SpaceCheck(length);
|
||||||
|
if (status != B_OK || length == 0/*B_OK*/)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
int entrySize = sizeof(btrfs_entry);
|
||||||
|
if (Level() != 0)
|
||||||
|
entrySize = sizeof(btrfs_index);
|
||||||
|
|
||||||
|
uint8* base = (uint8*)fNode + sizeof(btrfs_header);
|
||||||
|
end++;
|
||||||
|
if (length < 0) {
|
||||||
|
// removing [start, end]
|
||||||
|
TRACE("Node::MoveEntries() removing ... start %" B_PRIu32 " end %"
|
||||||
|
B_PRIu32 " length %i\n", start, end, length);
|
||||||
|
length += _CalculateSpace(start, end - 1);
|
||||||
|
} else {
|
||||||
|
// length > 0
|
||||||
|
// inserting into [start, end] - make room for later
|
||||||
|
TRACE("Node::MoveEntries() inserting ... start %" B_PRIu32 " end %"
|
||||||
|
B_PRIu32 " length %i\n", start, end, length);
|
||||||
|
length -= _CalculateSpace(start, end - 1);
|
||||||
|
std::swap(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end >= ItemCount())
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
int dataSize = _CalculateSpace(end, ItemCount() - 1, 2);
|
||||||
|
// moving items/block pointers
|
||||||
|
memmove(base + start * entrySize, base + end * entrySize,
|
||||||
|
_CalculateSpace(end, ItemCount() - 1));
|
||||||
|
if (Level() == 0) {
|
||||||
|
// moving item data
|
||||||
|
int num = start - end;
|
||||||
|
for(uint32 i = start; i < ItemCount() + num; ++i)
|
||||||
|
Item(i)->SetOffset(Item(i)->Offset() - length);
|
||||||
|
|
||||||
|
memmove(ItemData(ItemCount() - 1) - length, ItemData(ItemCount() - 1),
|
||||||
|
dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BTree::Path implementation
|
// #pragma mark - BTree::Path implementation
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,6 +133,9 @@ public:
|
|||||||
|
|
||||||
off_t BlockNum() const { return fBlockNumber;}
|
off_t BlockNum() const { return fBlockNumber;}
|
||||||
bool IsWritable() const { return fWritable; }
|
bool IsWritable() const { return fWritable; }
|
||||||
|
status_t Copy(const Node* origin, uint32 start, uint32 end,
|
||||||
|
int length) const;
|
||||||
|
status_t MoveEntries(uint32 start, uint32 end, int length) const;
|
||||||
|
|
||||||
status_t SearchSlot(const btrfs_key& key, int* slot,
|
status_t SearchSlot(const btrfs_key& key, int* slot,
|
||||||
btree_traversing type) const;
|
btree_traversing type) const;
|
||||||
@ -141,6 +144,8 @@ public:
|
|||||||
Node& operator=(const Node&);
|
Node& operator=(const Node&);
|
||||||
//no implementation
|
//no implementation
|
||||||
|
|
||||||
|
void _Copy(const Node* origin, uint32 at, uint32 from, uint32 to,
|
||||||
|
int length) const;
|
||||||
status_t _SpaceCheck(int length) const;
|
status_t _SpaceCheck(int length) const;
|
||||||
int _CalculateSpace(uint32 from, uint32 to, uint8 type = 1) const;
|
int _CalculateSpace(uint32 from, uint32 to, uint8 type = 1) const;
|
||||||
|
|
||||||
|
@ -132,6 +132,7 @@ struct btrfs_entry {
|
|||||||
{ return B_LENDIAN_TO_HOST_INT32(offset); }
|
{ return B_LENDIAN_TO_HOST_INT32(offset); }
|
||||||
uint32 Size() const
|
uint32 Size() const
|
||||||
{ return B_LENDIAN_TO_HOST_INT32(size); }
|
{ return B_LENDIAN_TO_HOST_INT32(size); }
|
||||||
|
void SetOffset(uint32 off) { offset = B_HOST_TO_LENDIAN_INT32(off); }
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user