blob: b13f02494ffc022be9dcf8bfb2b8d3abcc72c353 [file] [log] [blame]
// 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 "allocator/extent-reserver.h"
#include <stdint.h>
#include <zircon/types.h>
#include <bitmap/rle-bitmap.h>
#include <blobfs/format.h>
namespace blobfs {
void ExtentReserver::Reserve(const Extent& extent) {
ZX_DEBUG_ASSERT_MSG(extent.Length() > 0, "Reserving empty extents is disallowed");
zx_status_t status = reserved_blocks_.Set(extent.Start(), extent.Start() + extent.Length());
ZX_DEBUG_ASSERT(status == ZX_OK);
}
void ExtentReserver::Unreserve(const Extent& extent) {
// Ensure the blocks are already reserved.
size_t blkno_out;
ZX_DEBUG_ASSERT(reserved_blocks_.Find(true, extent.Start(), extent.Start() + extent.Length(),
extent.Length(), &blkno_out) == ZX_OK);
zx_status_t status = reserved_blocks_.Clear(extent.Start(), extent.Start() + extent.Length());
ZX_DEBUG_ASSERT(status == ZX_OK);
}
uint64_t ExtentReserver::ReservedBlockCount() const { return reserved_blocks_.num_bits(); }
ReservedExtent::ReservedExtent(ExtentReserver* reserver, Extent extent)
: reserver_(reserver), extent_(extent) {
reserver_->Reserve(extent_);
}
ReservedExtent::~ReservedExtent() { Reset(); }
ReservedExtent::ReservedExtent(ReservedExtent&& o) : reserver_(o.reserver_), extent_(o.extent_) {
o.Release();
}
ReservedExtent& ReservedExtent::operator=(ReservedExtent&& o) {
Reset();
reserver_ = o.reserver_;
extent_ = o.extent_;
o.Release();
return *this;
}
const Extent& ReservedExtent::extent() const {
ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved extent");
return extent_;
}
ReservedExtent ReservedExtent::SplitAt(BlockCountType block_split) {
ZX_DEBUG_ASSERT_MSG(Reserved(), "Accessing unreserved extent");
ZX_DEBUG_ASSERT(block_split < extent_.Length());
Extent latter(extent_.Start() + block_split,
static_cast<BlockCountType>(extent_.Length() - block_split));
extent_.SetLength(block_split);
return ReservedExtent(reserver_, std::move(latter));
}
void ReservedExtent::Reset() {
if (Reserved()) {
reserver_->Unreserve(extent());
}
Release();
}
void ReservedExtent::Release() { reserver_ = nullptr; }
bool ReservedExtent::Reserved() const { return reserver_ != nullptr; }
} // namespace blobfs