diff --git a/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp b/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp index f453a11468..b9dfc91964 100644 --- a/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/AttributeIterator.cpp @@ -22,9 +22,10 @@ AttributeIterator::AttributeIterator(Inode* inode) fInode(inode), fIterator(NULL) { - struct btrfs_key key; + btrfs_key key; key.SetType(BTRFS_KEY_TYPE_XATTR_ITEM); key.SetObjectID(inode->ID()); + key.SetOffset(BTREE_BEGIN); fIterator = new(std::nothrow) TreeIterator(inode->GetVolume()->FSTree(), key); } @@ -33,6 +34,7 @@ AttributeIterator::AttributeIterator(Inode* inode) AttributeIterator::~AttributeIterator() { delete fIterator; + fIterator = NULL; } @@ -46,10 +48,9 @@ AttributeIterator::InitCheck() status_t AttributeIterator::GetNext(char* name, size_t* _nameLength) { - btrfs_key key; btrfs_dir_entry* entries; uint32 entries_length; - status_t status = fIterator->GetPreviousEntry(key, (void**)&entries, + status_t status = fIterator->GetPreviousEntry((void**)&entries, &entries_length); if (status != B_OK) return status; diff --git a/src/add-ons/kernel/file_systems/btrfs/BTree.cpp b/src/add-ons/kernel/file_systems/btrfs/BTree.cpp index ce87f5a74f..bf93bf358f 100644 --- a/src/add-ons/kernel/file_systems/btrfs/BTree.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/BTree.cpp @@ -519,13 +519,16 @@ BTree::_RemoveIterator(TreeIterator* iterator) // #pragma mark - -TreeIterator::TreeIterator(BTree* tree, btrfs_key& key) +TreeIterator::TreeIterator(BTree* tree, const btrfs_key& key) : fTree(tree), - fCurrentKey(key) + fKey(key), + fIteratorStatus(B_NO_INIT) { - Rewind(); tree->_AddIterator(this); + fPath = new(std::nothrow) BTree::Path(tree); + if (fPath == NULL) + fIteratorStatus = B_NO_MEMORY; } @@ -533,26 +536,72 @@ TreeIterator::~TreeIterator() { if (fTree) fTree->_RemoveIterator(this); + + delete fPath; + fPath = NULL; +} + + +void +TreeIterator::Rewind(bool inverse) +{ + if (inverse) + fKey.SetOffset(BTREE_END); + else + fKey.SetOffset(BTREE_BEGIN); + fIteratorStatus = B_NO_INIT; } /*! Iterates through the tree in the specified direction. */ status_t -TreeIterator::Traverse(btree_traversing direction, btrfs_key& key, - void** value, uint32* size) +TreeIterator::_Traverse(btree_traversing direction) { - if (fTree == NULL) - return B_INTERRUPTED; - - fCurrentKey.SetOffset(fCurrentKey.Offset() + direction); - BTree::Path path(fTree); - status_t status = fTree->_Find(&path, fCurrentKey, value, size, direction); - if (status != B_OK) { - TRACE("TreeIterator::Traverse() Find failed\n"); - return B_ENTRY_NOT_FOUND; + status_t status = fTree->Traverse(direction, fPath, fKey); + if (status < B_OK) { + ERROR("TreeIterator::Traverse() Find failed\n"); + return status; } + return (fIteratorStatus = B_OK); +} + + +// Like GetEntry in BTree::Path but here we check the type and moving. +status_t +TreeIterator::_GetEntry(btree_traversing type, void** _value, uint32* _size, + uint32* _offset) +{ + status_t status; + if (fIteratorStatus == B_NO_INIT) { + status = _Traverse(type); + if (status != B_OK) + return status; + type = BTREE_EXACT; + } + + if (fIteratorStatus != B_OK) + return fIteratorStatus; + + int move = fPath->Move(0, type); + if (move > 0) + status = fTree->NextLeaf(fPath); + else if (move < 0) + status = fTree->PreviousLeaf(fPath); + if (status != B_OK) + return status; + + btrfs_key found; + status = fPath->GetCurrentEntry(&found, _value, _size, _offset); + if (status != B_OK) + return status; + + fKey.SetObjectID(found.ObjectID()); + fKey.SetOffset(found.Offset()); + if (fKey.Type() != found.Type() && fKey.Type() != BTRFS_KEY_TYPE_ANY) + return B_ENTRY_NOT_FOUND; + return B_OK; } @@ -560,11 +609,13 @@ TreeIterator::Traverse(btree_traversing direction, btrfs_key& key, /*! just sets the current key in the iterator. */ status_t -TreeIterator::Find(btrfs_key& key) +TreeIterator::Find(const btrfs_key& key) { - if (fTree == NULL) - return B_INTERRUPTED; - fCurrentKey = key; + if (fIteratorStatus == B_INTERRUPTED) + return fIteratorStatus; + + fKey = key; + fIteratorStatus = B_NO_INIT; return B_OK; } @@ -573,4 +624,5 @@ void TreeIterator::Stop() { fTree = NULL; + fIteratorStatus = B_INTERRUPTED; } diff --git a/src/add-ons/kernel/file_systems/btrfs/BTree.h b/src/add-ons/kernel/file_systems/btrfs/BTree.h index 30afcaf790..d44a40102f 100644 --- a/src/add-ons/kernel/file_systems/btrfs/BTree.h +++ b/src/add-ons/kernel/file_systems/btrfs/BTree.h @@ -176,31 +176,37 @@ public: class TreeIterator : public SinglyLinkedListLinkImpl { public: - TreeIterator(BTree* tree, btrfs_key& key); + TreeIterator(BTree* tree, const btrfs_key& key); ~TreeIterator(); - status_t Traverse(btree_traversing direction, - btrfs_key& key, void** value, - uint32* size = NULL); - status_t Find(btrfs_key& key); + void Rewind(bool inverse = false); + status_t Find(const btrfs_key& key); + status_t GetNextEntry(void** _value, + uint32* _size = NULL, + uint32* _offset = NULL); + status_t GetPreviousEntry(void** _value, + uint32* _size = NULL, + uint32* _offset = NULL); - status_t Rewind(); - status_t GetNextEntry(btrfs_key& key, void** value, - uint32* size = NULL); - status_t GetPreviousEntry(btrfs_key& key, void** value, - uint32* size = NULL); - - BTree* Tree() const { return fTree; } + BTree* Tree() const { return fTree; } + btrfs_key Key() const { return fKey; } private: friend class BTree; + status_t _Traverse(btree_traversing direction); + status_t _Find(btree_traversing type, btrfs_key& key, + void** _value); + status_t _GetEntry(btree_traversing type, void** _value, + uint32* _size, uint32* _offset); // called by BTree void Stop(); private: BTree* fTree; - btrfs_key fCurrentKey; + BTree::Path* fPath; + btrfs_key fKey; + status_t fIteratorStatus; }; @@ -219,25 +225,16 @@ BTree::Path::GetCurrentEntry(btrfs_key* _key, void** _value, uint32* _size, inline status_t -TreeIterator::Rewind() +TreeIterator::GetNextEntry(void** _value, uint32* _size, uint32* _offset) { - fCurrentKey.SetOffset(BTREE_BEGIN); - return B_OK; + return _GetEntry(BTREE_FORWARD, _value, _size, _offset); } inline status_t -TreeIterator::GetNextEntry(btrfs_key& key, void** value, uint32* size) +TreeIterator::GetPreviousEntry(void** _value, uint32* _size, uint32* _offset) { - return Traverse(BTREE_FORWARD, key, value, size); -} - - -inline status_t -TreeIterator::GetPreviousEntry(btrfs_key& key, void** value, - uint32* size) -{ - return Traverse(BTREE_BACKWARD, key, value, size); + return _GetEntry(BTREE_BACKWARD, _value, _size, _offset); } diff --git a/src/add-ons/kernel/file_systems/btrfs/DirectoryIterator.cpp b/src/add-ons/kernel/file_systems/btrfs/DirectoryIterator.cpp index ccfd1b225b..0be81a4829 100644 --- a/src/add-ons/kernel/file_systems/btrfs/DirectoryIterator.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/DirectoryIterator.cpp @@ -26,6 +26,7 @@ DirectoryIterator::DirectoryIterator(Inode* inode) btrfs_key key; key.SetType(BTRFS_KEY_TYPE_DIR_INDEX); key.SetObjectID(inode->ID()); + key.SetOffset(BTREE_BEGIN); fIterator = new(std::nothrow) TreeIterator(inode->GetVolume()->FSTree(), key); } @@ -33,8 +34,8 @@ DirectoryIterator::DirectoryIterator(Inode* inode) DirectoryIterator::~DirectoryIterator() { - if (fIterator != NULL) - delete fIterator; + delete fIterator; + fIterator = NULL; } @@ -69,11 +70,9 @@ DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id) return fInode->FindParent(_id); } - btrfs_key key; btrfs_dir_entry* entries; uint32 entries_length; - status_t status = fIterator->GetNextEntry(key, (void**)&entries, - &entries_length); + status_t status = fIterator->GetNextEntry((void**)&entries, &entries_length); if (status != B_OK) return status;