| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/storage/blobfs/iterator/allocated_node_iterator.h" |
| |
| #include <lib/syslog/cpp/macros.h> |
| #include <lib/zx/result.h> |
| #include <stdint.h> |
| #include <zircon/errors.h> |
| #include <zircon/types.h> |
| |
| #include "src/storage/blobfs/format.h" |
| #include "src/storage/blobfs/node_finder.h" |
| |
| namespace blobfs { |
| |
| AllocatedNodeIterator::AllocatedNodeIterator(NodeFinder* finder, uint32_t node_index, Inode* inode) |
| : finder_(finder), current_node_index_(node_index), inode_(inode) { |
| ZX_ASSERT(finder_ && inode_); |
| } |
| |
| bool AllocatedNodeIterator::Done() const { |
| return extent_index_ + NodeExtentCount() >= inode_->extent_count; |
| } |
| |
| zx::result<ExtentContainer*> AllocatedNodeIterator::Next() { |
| ZX_DEBUG_ASSERT(!Done()); |
| |
| const uint32_t next_node_index = NextNodeIndex(); |
| auto next_node = finder_->GetNode(next_node_index); |
| if (next_node.is_error()) { |
| FX_LOGS(ERROR) << "GetNode(" << next_node_index << ") failed: " << next_node.status_value(); |
| if (inode_) { |
| FX_LOGS(ERROR) << "Inode: " << *inode_; |
| } |
| return zx::error(ZX_ERR_IO_DATA_INTEGRITY); |
| } |
| ExtentContainer* next = next_node->AsExtentContainer(); |
| |
| ZX_DEBUG_ASSERT(next != nullptr); |
| if (!next->header.IsAllocated() || !next->header.IsExtentContainer() || |
| next->previous_node != current_node_index_ || next->extent_count > kContainerMaxExtents) { |
| FX_LOGS(ERROR) << "Next node " << next_node_index << " invalid: " << *next; |
| return zx::error(ZX_ERR_IO_DATA_INTEGRITY); |
| } |
| extent_index_ += NodeExtentCount(); |
| extent_node_ = next; |
| current_node_index_ = next_node_index; |
| |
| return zx::ok(extent_node_); |
| } |
| |
| uint32_t AllocatedNodeIterator::ExtentIndex() const { return extent_index_; } |
| |
| uint32_t AllocatedNodeIterator::NextNodeIndex() const { |
| ZX_DEBUG_ASSERT(!Done()); |
| return IsInode() ? inode_->header.next_node : extent_node_->header.next_node; |
| } |
| |
| uint32_t AllocatedNodeIterator::NodeExtentCount() const { |
| if (IsInode()) { |
| return inode_->extent_count > 0 ? 1 : 0; |
| } |
| return extent_node_->extent_count; |
| } |
| |
| bool AllocatedNodeIterator::IsInode() const { return extent_node_ == nullptr; } |
| |
| } // namespace blobfs |