blob: d3230054bf2f690d3ce216fae4c90c76dc66a08d [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 SRC_STORAGE_BLOBFS_ALLOCATOR_ALLOCATOR_H_
#define SRC_STORAGE_BLOBFS_ALLOCATOR_ALLOCATOR_H_
#include <lib/fzl/resizeable-vmo-mapper.h>
#include <lib/zx/vmo.h>
#include <zircon/types.h>
#include <cstdint>
#include <memory>
#include <shared_mutex>
#include <vector>
#include <bitmap/raw-bitmap.h>
#include <id_allocator/id_allocator.h>
#include <storage/buffer/vmoid_registry.h>
#include "src/storage/blobfs/allocator/base_allocator.h"
#include "src/storage/blobfs/allocator/extent_reserver.h"
#include "src/storage/blobfs/allocator/node_reserver.h"
#include "src/storage/blobfs/common.h"
#include "src/storage/blobfs/node_finder.h"
#include "src/storage/lib/vfs/cpp/transaction/device_transaction_handler.h"
namespace blobfs {
class Allocator;
// An interface which controls actual access to the underlying storage.
class SpaceManager : public storage::VmoidRegistry {
public:
~SpaceManager() override = default;
virtual const Superblock& Info() const = 0;
// Adds any number of nodes to |allocator|'s node map, extending the volume if necessary.
virtual zx_status_t AddInodes(Allocator* allocator) = 0;
// Adds space for |nblocks| blocks to |map|, extending the volume if necessary.
virtual zx_status_t AddBlocks(uint64_t nblocks, RawBitmap* map) = 0;
};
// Allocates and frees both block and node entries.
//
// Also maintains reservation mappings, to help in-progress allocations avoid from being persisted
// too early.
class Allocator : public BaseAllocator {
public:
Allocator(SpaceManager* space_manager, RawBitmap block_map, fzl::ResizeableVmoMapper node_map,
std::unique_ptr<id_allocator::IdAllocator> node_bitmap);
~Allocator() override = default;
// blobfs::NodeFinder interface.
zx::result<InodePtr> GetNode(uint32_t node_index) final;
void SetLogging(bool enable) { log_allocation_failure_ = enable; }
// Reads the block map and node map from underlying storage, using a blocking read transaction.
//
// It is unsafe to call this method while any nodes or blocks are reserved.
zx_status_t ResetFromStorage(fs::DeviceTransactionHandler& transaction_handler);
// Provides a read-only view into the block map.
const zx::vmo& GetBlockMapVmo() const;
// Provides a read-only view into the node map.
const zx::vmo& GetNodeMapVmo() const;
// blobfs::NodeReserverInterface interface.
zx::result<ReservedNode> ReserveNode() final;
// Called when InodePtr goes out of scope.
void DropInodePtr() final;
// Grows node map to |size|. The caller takes responsibility for initializing the new entries.
[[nodiscard]] zx_status_t GrowNodeMap(size_t size);
// Decommits unused memory.
void Decommit();
protected:
// blobfs::BaseAllocator interface.
zx::result<> AddBlocks(uint64_t block_count) final;
zx::result<> AddNodes() final;
private:
// Resets the size of the block map based on |Info().data_block_count|.
//
// It is unsafe to call this method while any blocks are reserved.
zx_status_t ResetBlockMapSize();
// Resets the size of the node map based on |Info().inode_count|.
//
// It is unsafe to call this method while any nodes are reserved.
zx_status_t ResetNodeMapSize();
void LogAllocationFailure(uint64_t num_blocks) const;
SpaceManager* space_manager_;
fzl::ResizeableVmoMapper node_map_;
// Guards growing node_map_, which will invalidate outstanding pointers.
std::shared_mutex node_map_grow_mutex_;
bool log_allocation_failure_ = true;
};
} // namespace blobfs
#endif // SRC_STORAGE_BLOBFS_ALLOCATOR_ALLOCATOR_H_