| // 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 <limits> |
| #include <stdint.h> |
| |
| #include <bitmap/rle-bitmap.h> |
| #include <blobfs/format.h> |
| #include <blobfs/node-reserver.h> |
| #include <zircon/types.h> |
| |
| namespace blobfs { |
| |
| bool NodeReserver::IsNodeReserved(uint32_t node_index) const { |
| return reserved_nodes_.Get(node_index, node_index + 1, nullptr); |
| } |
| |
| void NodeReserver::Reserve(uint32_t node_index) { |
| ZX_DEBUG_ASSERT(!reserved_nodes_.Get(node_index, node_index + 1, nullptr)); |
| |
| // Mark it as reserved so no one else can allocate it. |
| reserved_nodes_.Set(node_index, node_index + 1); |
| } |
| |
| void NodeReserver::Unreserve(uint32_t node_index) { |
| ZX_DEBUG_ASSERT(reserved_nodes_.Get(node_index, node_index + 1, nullptr)); |
| zx_status_t status = reserved_nodes_.Clear(node_index, node_index + 1); |
| ZX_DEBUG_ASSERT(status == ZX_OK); |
| |
| SetFreeNodeLowerBoundIfSmallest(node_index); |
| } |
| |
| uint32_t NodeReserver::ReservedNodeCount() const { |
| ZX_DEBUG_ASSERT(reserved_nodes_.num_bits() < std::numeric_limits<uint32_t>::max()); |
| return static_cast<uint32_t>(reserved_nodes_.num_bits()); |
| } |
| |
| void NodeReserver::SetFreeNodeLowerBoundIfSmallest(uint32_t node_index) { |
| if (free_node_lower_bound_ > node_index) { |
| SetFreeNodeLowerBound(node_index); |
| } |
| } |
| |
| void NodeReserver::SetFreeNodeLowerBound(uint32_t node_index) { |
| free_node_lower_bound_ = node_index; |
| } |
| |
| uint32_t NodeReserver::FreeNodeLowerBound() const { |
| return free_node_lower_bound_; |
| } |
| |
| ReservedNode::ReservedNode(NodeReserver* reserver, uint32_t node) |
| : reserver_(reserver), node_(node) { |
| reserver_->Reserve(node); |
| } |
| |
| ReservedNode::ReservedNode(ReservedNode&& o) : reserver_(o.reserver_), node_(o.node_) { |
| o.Release(); |
| } |
| |
| ReservedNode& ReservedNode::operator=(ReservedNode&& o) { |
| Reset(); |
| reserver_ = o.reserver_; |
| node_ = o.node_; |
| o.Release(); |
| return *this; |
| } |
| |
| ReservedNode::~ReservedNode() { |
| Reset(); |
| } |
| |
| uint32_t ReservedNode::index() const { |
| ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved node"); |
| return node_; |
| } |
| |
| void ReservedNode::Reset() { |
| if (Reserved()) { |
| reserver_->Unreserve(index()); |
| } |
| Release(); |
| } |
| |
| void ReservedNode::Release() { |
| reserver_ = nullptr; |
| } |
| |
| bool ReservedNode::Reserved() const { |
| return reserver_ != nullptr; |
| } |
| |
| } // namespace blobfs |