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 <limits>
6 #include <stdint.h>
7 
8 #include <bitmap/rle-bitmap.h>
9 #include <blobfs/format.h>
10 #include <blobfs/node-reserver.h>
11 #include <zircon/types.h>
12 
13 namespace blobfs {
14 
IsNodeReserved(uint32_t node_index) const15 bool NodeReserver::IsNodeReserved(uint32_t node_index) const {
16     return reserved_nodes_.Get(node_index, node_index + 1, nullptr);
17 }
18 
Reserve(uint32_t node_index)19 void NodeReserver::Reserve(uint32_t node_index) {
20     ZX_DEBUG_ASSERT(!reserved_nodes_.Get(node_index, node_index + 1, nullptr));
21 
22     // Mark it as reserved so no one else can allocate it.
23     reserved_nodes_.Set(node_index, node_index + 1);
24 }
25 
Unreserve(uint32_t node_index)26 void NodeReserver::Unreserve(uint32_t node_index) {
27     ZX_DEBUG_ASSERT(reserved_nodes_.Get(node_index, node_index + 1, nullptr));
28     zx_status_t status = reserved_nodes_.Clear(node_index, node_index + 1);
29     ZX_DEBUG_ASSERT(status == ZX_OK);
30 
31     SetFreeNodeLowerBoundIfSmallest(node_index);
32 }
33 
ReservedNodeCount() const34 uint32_t NodeReserver::ReservedNodeCount() const {
35     ZX_DEBUG_ASSERT(reserved_nodes_.num_bits() < std::numeric_limits<uint32_t>::max());
36     return static_cast<uint32_t>(reserved_nodes_.num_bits());
37 }
38 
SetFreeNodeLowerBoundIfSmallest(uint32_t node_index)39 void NodeReserver::SetFreeNodeLowerBoundIfSmallest(uint32_t node_index) {
40     if (free_node_lower_bound_ > node_index) {
41         SetFreeNodeLowerBound(node_index);
42     }
43 }
44 
SetFreeNodeLowerBound(uint32_t node_index)45 void NodeReserver::SetFreeNodeLowerBound(uint32_t node_index) {
46     free_node_lower_bound_ = node_index;
47 }
48 
FreeNodeLowerBound() const49 uint32_t NodeReserver::FreeNodeLowerBound() const {
50     return free_node_lower_bound_;
51 }
52 
ReservedNode(NodeReserver * reserver,uint32_t node)53 ReservedNode::ReservedNode(NodeReserver* reserver, uint32_t node)
54     : reserver_(reserver), node_(node) {
55     reserver_->Reserve(node);
56 }
57 
ReservedNode(ReservedNode && o)58 ReservedNode::ReservedNode(ReservedNode&& o) : reserver_(o.reserver_), node_(o.node_) {
59     o.Release();
60 }
61 
operator =(ReservedNode && o)62 ReservedNode& ReservedNode::operator=(ReservedNode&& o) {
63     Reset();
64     reserver_ = o.reserver_;
65     node_ = o.node_;
66     o.Release();
67     return *this;
68 }
69 
~ReservedNode()70 ReservedNode::~ReservedNode() {
71     Reset();
72 }
73 
index() const74 uint32_t ReservedNode::index() const {
75     ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved node");
76     return node_;
77 }
78 
Reset()79 void ReservedNode::Reset() {
80     if (Reserved()) {
81         reserver_->Unreserve(index());
82     }
83     Release();
84 }
85 
Release()86 void ReservedNode::Release() {
87     reserver_ = nullptr;
88 }
89 
Reserved() const90 bool ReservedNode::Reserved() const {
91     return reserver_ != nullptr;
92 }
93 
94 } // namespace blobfs
95