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