blob: 44061a863794f274c5bd93c18c30b2b8b14b46dd [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.
// This file describes the structure used to allocate
// from an on-disk bitmap.
#pragma once
#include <fbl/function.h>
#include <fbl/macros.h>
#include <fbl/unique_ptr.h>
#include <fs/block-txn.h>
#include <minfs/block-txn.h>
#include <minfs/format.h>
#include <minfs/mutex.h>
#include <minfs/superblock.h>
#ifdef __Fuchsia__
#include <fuchsia/minfs/c/fidl.h>
#endif
namespace minfs {
// Forward declaration for a reference to the internal allocator.
class Allocator;
// This class represents a promise from an Allocator to save a particular number of reserved
// elements for later allocation. Allocation for reserved elements must be done through the
// AllocatorPromise class.
// This class is thread-compatible.
// This class is not assignable, copyable, or moveable.
class AllocatorPromise {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(AllocatorPromise);
AllocatorPromise() {}
~AllocatorPromise();
// Returns |ZX_OK| when |allocator| reserves |reserved| elements and |this| is successfully
// initialized. Returns an error if not enough elements are available for reservation,
// |allocator| is null, or |this| was previously initialized.
zx_status_t Initialize(WriteTxn* txn, size_t reserved, Allocator* allocator);
bool IsInitialized() const { return allocator_ != nullptr; }
// Allocate a new item in allocator_. Return the index of the newly allocated item.
// A call to Allocate() is effectively the same as a call to Swap(0) + SwapCommit(), but under
// the hood completes these operations more efficiently as additional state doesn't need to be
// stored between the two.
size_t Allocate(WriteTxn* txn);
// Unreserve all currently reserved items.
void Cancel();
#ifdef __Fuchsia__
// Swap the element currently allocated at |old_index| for a new index.
// If |old_index| is 0, a new block will still be allocated, but no blocks will be de-allocated.
// The swap will not be persisted until a call to SwapCommit is made.
size_t Swap(size_t old_index);
// Commit any pending swaps, allocating new indices and de-allocating old indices.
void SwapCommit(WriteTxn* txn);
// Remove |requested| reserved elements and give them to |other_promise|.
// The reserved count belonging to the Allocator does not change.
void GiveBlocks(size_t requested, AllocatorPromise* other_promise);
size_t GetReserved() const { return reserved_; }
#endif
private:
Allocator* allocator_ = nullptr;
size_t reserved_ = 0;
// TODO(planders): Optionally store swap info in AllocatorPromise,
// to ensure we only swap the current promise's blocks on SwapCommit.
};
} // namespace minfs