BTRFS: Implement InsertEntries() that will insert consecutive items and its data.

Signed-off-by: Augustin Cavalier <waddlesplash@gmail.com>
This commit is contained in:
hyche 2017-08-29 02:07:52 +07:00 committed by Augustin Cavalier
parent 02bce792d8
commit 84bc447cae
2 changed files with 85 additions and 0 deletions

View File

@ -420,6 +420,18 @@ BTree::Path::GetEntry(int slot, btrfs_key* _key, void** _value, uint32* _size,
}
status_t
BTree::Path::SetEntry(int slot, const btrfs_entry& entry, void* value)
{
if (slot < 0)
return B_ENTRY_NOT_FOUND;
memcpy(fNodes[0]->Item(slot), &entry, sizeof(btrfs_entry));
memcpy(fNodes[0]->ItemData(slot), value, entry.Size());
return B_OK;
}
/*
* Allocate and copy block and do all the changes that it can.
* for now, we only copy-on-write tree block,
@ -702,6 +714,72 @@ BTree::FindExact(Path* path, btrfs_key& key, void** _value, uint32* _size,
}
/*
* Insert "num" of consecutive empty entries start with slot of "startKey"
* if successful return the starting slot, otherwise return error code.
*/
status_t
BTree::MakeEntries(Transaction& transaction, Path* path,
const btrfs_key& startKey, int num, int length)
{
TRACE("BTree::MakeEntries() num %i key (% " B_PRIu64 " %" B_PRIu8 " %"
B_PRIu64 ")\n", num, startKey.ObjectID(), startKey.Type(),
startKey.Offset());
status_t status = Traverse(BTREE_FORWARD, path, startKey);
if (status < B_OK)
return status;
int slot = status;
status = path->InternalCopy(transaction, 1);
if (status != B_OK)
return status;
status = path->CopyOnWrite(transaction, 0, slot, num, length);
if (status == B_DEVICE_FULL) {
// TODO: push data or split node
return status;
}
if (status != B_OK)
return status;
return slot;
}
/* MakeEntries and then fill in them.
*/
status_t
BTree::InsertEntries(Transaction& transaction, Path* path,
btrfs_entry* entries, void** data, int num)
{
int totalLength = sizeof(btrfs_entry) * num;
for (int i = 0; i < num; i++)
totalLength += entries[i].Size();
status_t slot = MakeEntries(transaction, path, entries[0].key, num,
totalLength);
if (slot < B_OK)
return slot;
uint32 upperLimit;
if (slot > 0) {
path->GetEntry(slot - 1, NULL, NULL, NULL, &upperLimit);
} else
upperLimit = fVolume->BlockSize() - sizeof(btrfs_header);
TRACE("BTree::InsertEntries() num: %i upper limit %" B_PRIu32 "\n", num,
upperLimit);
for (int i = 0; i < num; i++) {
upperLimit -= entries[i].Size();
entries[i].SetOffset(upperLimit);
path->SetEntry(slot + i, entries[i], data[i]);
}
return B_OK;
}
status_t
BTree::PreviousLeaf(Path* path) const
{

View File

@ -72,6 +72,12 @@ public:
status_t PreviousLeaf(Path* path) const;
status_t NextLeaf(Path* path) const;
status_t MakeEntries(Transaction& transaction,
Path* path, const btrfs_key& startKey,
int num, int length);
status_t InsertEntries(Transaction& transaction,
Path* path, btrfs_entry* entries,
void** data, int num);
Volume* SystemVolume() const { return fVolume; }
status_t SetRoot(off_t logical, fsblock_t* block);
@ -181,6 +187,7 @@ public:
uint32* _size = NULL, uint32* _offset = NULL);
status_t GetEntry(int slot, btrfs_key* _key, void** _value,
uint32* _size = NULL, uint32* _offset = NULL);
status_t SetEntry(int slot, const btrfs_entry& entry, void* value);
int Move(int level, int step);