1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdint.h> 6 7 #include <blobfs/format.h> 8 #include <blobfs/iterator/allocated-extent-iterator.h> 9 #include <blobfs/iterator/extent-iterator.h> 10 #include <zircon/types.h> 11 12 namespace blobfs { 13 AllocatedExtentIterator(NodeFinder * finder,uint32_t node_index)14AllocatedExtentIterator::AllocatedExtentIterator(NodeFinder* finder, uint32_t node_index) 15 : finder_(finder), inode_(finder_->GetNode(node_index)), node_index_(node_index), 16 extent_node_(nullptr) {} 17 Done() const18bool AllocatedExtentIterator::Done() const { 19 return extent_index_ == inode_->extent_count; 20 } 21 Next(const Extent ** out)22zx_status_t AllocatedExtentIterator::Next(const Extent** out) { 23 ZX_DEBUG_ASSERT(!Done()); 24 zx_status_t status = ValidateExtentCount(); 25 if (status != ZX_OK) { 26 return status; 27 } 28 29 const Extent* extent = GetExtent(); 30 UpdateIndices(*extent); 31 if (!Done() && local_index_ == (IsInode() ? kInlineMaxExtents : extent_node_->extent_count)) { 32 zx_status_t status = NextContainer(); 33 if (status != ZX_OK) { 34 return status; 35 } 36 } 37 38 *out = extent; 39 return ZX_OK; 40 } 41 BlockIndex() const42uint64_t AllocatedExtentIterator::BlockIndex() const { 43 return block_index_; 44 } 45 ExtentIndex() const46uint32_t AllocatedExtentIterator::ExtentIndex() const { 47 return extent_index_; 48 } 49 NodeIndex() const50uint32_t AllocatedExtentIterator::NodeIndex() const { 51 ZX_DEBUG_ASSERT(!Done()); 52 return node_index_; 53 } 54 IsInode() const55bool AllocatedExtentIterator::IsInode() const { 56 return extent_node_ == nullptr; 57 } 58 ValidateExtentCount() const59zx_status_t AllocatedExtentIterator::ValidateExtentCount() const { 60 ZX_DEBUG_ASSERT(local_index_ < (IsInode() ? kInlineMaxExtents : kContainerMaxExtents)); 61 if (!IsInode() && local_index_ > extent_node_->extent_count) { 62 // This container doesn't recognize this extent as valid. 63 return ZX_ERR_IO_DATA_INTEGRITY; 64 } 65 return ZX_OK; 66 } 67 UpdateIndices(const Extent & extent)68void AllocatedExtentIterator::UpdateIndices(const Extent& extent) { 69 block_index_ += extent.Length(); 70 local_index_++; 71 extent_index_++; 72 } 73 GetExtent() const74const Extent* AllocatedExtentIterator::GetExtent() const { 75 if (IsInode()) { 76 return &inode_->extents[local_index_]; 77 } else { 78 return &extent_node_->extents[local_index_]; 79 } 80 } 81 GetNextNode() const82uint32_t AllocatedExtentIterator::GetNextNode() const { 83 if (IsInode()) { 84 return inode_->header.next_node; 85 } else { 86 return extent_node_->header.next_node; 87 } 88 } 89 NextContainer()90zx_status_t AllocatedExtentIterator::NextContainer() { 91 ZX_DEBUG_ASSERT(!Done()); 92 uint32_t node_index = GetNextNode(); 93 94 local_index_ = 0; 95 extent_node_ = finder_->GetNode(node_index)->AsExtentContainer(); 96 node_index_ = node_index; 97 98 ZX_DEBUG_ASSERT(extent_node_ != nullptr); 99 bool is_container = extent_node_->header.IsAllocated() && 100 extent_node_->header.IsExtentContainer(); 101 if (!is_container) { 102 return ZX_ERR_IO_DATA_INTEGRITY; 103 } 104 return ZX_OK; 105 } 106 107 } // namespace blobfs 108