blob: 17559004b19bfa0bc5d39a85a01e19895befb282 [file] [log] [blame]
// Copyright 2018 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 <stdint.h>
#include <blobfs/format.h>
#include <blobfs/iterator/allocated-extent-iterator.h>
#include <blobfs/iterator/extent-iterator.h>
#include <zircon/types.h>
namespace blobfs {
AllocatedExtentIterator::AllocatedExtentIterator(NodeFinder* finder, uint32_t node_index)
: finder_(finder), inode_(finder_->GetNode(node_index)), node_index_(node_index),
extent_node_(nullptr) {}
bool AllocatedExtentIterator::Done() const {
return extent_index_ == inode_->extent_count;
}
zx_status_t AllocatedExtentIterator::Next(const Extent** out) {
ZX_DEBUG_ASSERT(!Done());
zx_status_t status = ValidateExtentCount();
if (status != ZX_OK) {
return status;
}
const Extent* extent = GetExtent();
UpdateIndices(*extent);
if (!Done() && local_index_ == (IsInode() ? kInlineMaxExtents : extent_node_->extent_count)) {
zx_status_t status = NextContainer();
if (status != ZX_OK) {
return status;
}
}
*out = extent;
return ZX_OK;
}
uint64_t AllocatedExtentIterator::BlockIndex() const {
return block_index_;
}
uint32_t AllocatedExtentIterator::ExtentIndex() const {
return extent_index_;
}
uint32_t AllocatedExtentIterator::NodeIndex() const {
ZX_DEBUG_ASSERT(!Done());
return node_index_;
}
bool AllocatedExtentIterator::IsInode() const {
return extent_node_ == nullptr;
}
zx_status_t AllocatedExtentIterator::ValidateExtentCount() const {
ZX_DEBUG_ASSERT(local_index_ < (IsInode() ? kInlineMaxExtents : kContainerMaxExtents));
if (!IsInode() && local_index_ > extent_node_->extent_count) {
// This container doesn't recognize this extent as valid.
return ZX_ERR_IO_DATA_INTEGRITY;
}
return ZX_OK;
}
void AllocatedExtentIterator::UpdateIndices(const Extent& extent) {
block_index_ += extent.Length();
local_index_++;
extent_index_++;
}
const Extent* AllocatedExtentIterator::GetExtent() const {
if (IsInode()) {
return &inode_->extents[local_index_];
} else {
return &extent_node_->extents[local_index_];
}
}
uint32_t AllocatedExtentIterator::GetNextNode() const {
if (IsInode()) {
return inode_->header.next_node;
} else {
return extent_node_->header.next_node;
}
}
zx_status_t AllocatedExtentIterator::NextContainer() {
ZX_DEBUG_ASSERT(!Done());
uint32_t node_index = GetNextNode();
local_index_ = 0;
extent_node_ = finder_->GetNode(node_index)->AsExtentContainer();
node_index_ = node_index;
ZX_DEBUG_ASSERT(extent_node_ != nullptr);
bool is_container = extent_node_->header.IsAllocated() &&
extent_node_->header.IsExtentContainer();
if (!is_container) {
return ZX_ERR_IO_DATA_INTEGRITY;
}
return ZX_OK;
}
} // namespace blobfs