blob: 18f54136a33ded6d153daa0e256b52ec77ba1b7a [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.
#ifndef ZIRCON_SYSTEM_ULIB_BLOBFS_ALLOCATOR_EXTENT_RESERVER_H_
#define ZIRCON_SYSTEM_ULIB_BLOBFS_ALLOCATOR_EXTENT_RESERVER_H_
#include <stdbool.h>
#include <stdint.h>
#include <zircon/types.h>
#include <bitmap/rle-bitmap.h>
#include <blobfs/format.h>
namespace blobfs {
// Allows extents to be reserved and unreserved. The purpose of reservation is to allow allocation
// of extents to occur without yet allocating structures which could be written out to durable
// storage.
//
// These extents may be observed by derived classes of ExtentReserver
class ExtentReserver {
public:
// Reserves space for blocks in memory. Does not update disk.
//
// |extent.Length()| must be > 0.
void Reserve(const Extent& extent);
// Unreserves space for blocks in memory. Does not update disk.
void Unreserve(const Extent& extent);
// Returns the total number of reserved blocks.
uint64_t ReservedBlockCount() const;
protected:
// Returns an iterator to the underlying reserved blocks.
//
// This iterator becomes invalid on the next call to either |ReserveExtent| or
// |UnreserveExtent|.
bitmap::RleBitmap::const_iterator ReservedBlocksCbegin() const {
return reserved_blocks_.cbegin();
}
bitmap::RleBitmap::const_iterator ReservedBlocksCend() const { return reserved_blocks_.end(); }
private:
bitmap::RleBitmap reserved_blocks_ = {};
};
// Wraps an extent reservation in RAII to hold the reservation active, and release it when it goes
// out of scope.
class ReservedExtent {
public:
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ReservedExtent);
// Creates a reserved extent.
//
// |extent.Length()| must be > 0.
ReservedExtent(ExtentReserver* reserver, Extent extent);
ReservedExtent(ReservedExtent&& o);
ReservedExtent& operator=(ReservedExtent&& o);
~ReservedExtent();
// Access the underlying extent which has been reserved.
//
// Unsafe to call if this extent has not actually been reserved.
const Extent& extent() const;
// Split a reserved extent from [start, start + length) such that:
// This retains [start, start + block_split),
// and returns [start + block_split, start + length)
//
// This function requires that |block_split| < |extent.block_count|.
ReservedExtent SplitAt(BlockCountType block_split);
// Releases the underlying reservation, unreserving the extent and preventing continued access
// to |extent()|.
void Reset();
private:
// Update internal state such that future calls to |Reserved| return false.
void Release();
// Identify if the underlying extent is reserved, and able to be accessed.
bool Reserved() const;
ExtentReserver* reserver_;
Extent extent_;
};
} // namespace blobfs
#endif // ZIRCON_SYSTEM_ULIB_BLOBFS_ALLOCATOR_EXTENT_RESERVER_H_