blob: 96ff782dcb1774b6f355d1cd4bf39ee6d7dbaf64 [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 <stdint.h>
#include <bitmap/rle-bitmap.h>
#include <blobfs/extent-reserver.h>
#include <blobfs/format.h>
#include <zircon/types.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