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