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 <bitmap/rle-bitmap.h>
8 #include <blobfs/extent-reserver.h>
9 #include <blobfs/format.h>
10 #include <zircon/types.h>
11
12 namespace blobfs {
13
Reserve(const Extent & extent)14 void ExtentReserver::Reserve(const Extent& extent) {
15 ZX_DEBUG_ASSERT_MSG(extent.Length() > 0, "Reserving empty extents is disallowed");
16 zx_status_t status = reserved_blocks_.Set(extent.Start(),
17 extent.Start() + extent.Length());
18 ZX_DEBUG_ASSERT(status == ZX_OK);
19 }
20
Unreserve(const Extent & extent)21 void ExtentReserver::Unreserve(const Extent& extent) {
22 // Ensure the blocks are already reserved.
23 size_t blkno_out;
24 ZX_DEBUG_ASSERT(reserved_blocks_.Find(true,
25 extent.Start(),
26 extent.Start() + extent.Length(),
27 extent.Length(), &blkno_out) == ZX_OK);
28
29 zx_status_t status = reserved_blocks_.Clear(extent.Start(),
30 extent.Start() + extent.Length());
31 ZX_DEBUG_ASSERT(status == ZX_OK);
32 }
33
ReservedBlockCount() const34 uint64_t ExtentReserver::ReservedBlockCount() const {
35 return reserved_blocks_.num_bits();
36 }
37
ReservedExtent(ExtentReserver * reserver,Extent extent)38 ReservedExtent::ReservedExtent(ExtentReserver* reserver, Extent extent)
39 : reserver_(reserver), extent_(extent) {
40 reserver_->Reserve(extent_);
41 }
42
~ReservedExtent()43 ReservedExtent::~ReservedExtent() {
44 Reset();
45 }
46
ReservedExtent(ReservedExtent && o)47 ReservedExtent::ReservedExtent(ReservedExtent&& o) : reserver_(o.reserver_), extent_(o.extent_) {
48 o.Release();
49 }
50
operator =(ReservedExtent && o)51 ReservedExtent& ReservedExtent::operator=(ReservedExtent&& o) {
52 Reset();
53 reserver_ = o.reserver_;
54 extent_ = o.extent_;
55 o.Release();
56 return *this;
57 }
58
extent() const59 const Extent& ReservedExtent::extent() const {
60 ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved extent");
61 return extent_;
62 }
63
SplitAt(BlockCountType block_split)64 ReservedExtent ReservedExtent::SplitAt(BlockCountType block_split) {
65 ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved extent");
66 ZX_DEBUG_ASSERT(block_split < extent_.Length());
67 Extent latter(extent_.Start() + block_split,
68 static_cast<BlockCountType>(extent_.Length() - block_split));
69
70 extent_.SetLength(block_split);
71 return ReservedExtent(reserver_, std::move(latter));
72 }
73
Reset()74 void ReservedExtent::Reset() {
75 if (Reserved()) {
76 reserver_->Unreserve(extent());
77 }
78 Release();
79 }
80
Release()81 void ReservedExtent::Release() {
82 reserver_ = nullptr;
83 }
84
Reserved() const85 bool ReservedExtent::Reserved() const {
86 return reserver_ != nullptr;
87 }
88
89 } // namespace blobfs
90