blob: e9da32cc1ec187b43836c8830d9553a8723a4e34 [file] [log] [blame]
// Copyright 2019 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 a utility for storing pending allocation state for a Minfs vnode.
#include <bitmap/rle-bitmap.h>
#include "src/storage/minfs/allocator/allocator.h"
#include "src/storage/minfs/format.h"
namespace minfs {
// PendingAllocationData stores information about data blocks which are yet to be allocated.
// This includes the relative index of each block to be processed, corresponding
// reservations, and (in the future) additional information about modifications to the inode's size
// and block count.
class PendingAllocationData {
using const_iterator = bitmap::RleBitmapBase<blk_t>::const_iterator;
PendingAllocationData() = default;
~PendingAllocationData() { ZX_DEBUG_ASSERT(IsEmpty()); }
// Clears out all allocation/reservation data.
void Reset(blk_t size);
// Returns the |start| and |count| of the first range in the block_map_.
zx_status_t GetNextRange(blk_t* start, blk_t* count) const;
// Returns true if no blocks are marked for allocation.
bool IsEmpty() const { return block_map_.num_bits() == 0 && new_blocks_ == 0; }
// Returns true if |block_num| is marked in the block_map_.
bool IsPending(blk_t block_num) const { return block_map_.GetOne(block_num); }
// Sets |block_num| in the block_map_. |allocated| indicates whether the block at |block_num|
// was previously allocated.
void SetPending(blk_t block_num, bool allocated);
// Clears |block_num| from the block_map_. |allocated| indicates whether the block at
// |block_num| was previously allocated. Returns true if the block_num was cleared from the map
// (i.e., it was set in the map initially).
bool ClearPending(blk_t block_num, bool allocated);
// Returns the count of pending blocks which are not already allocated.
blk_t GetNewPending() const { return new_blocks_; }
// Returns the total number of pending blocks.
blk_t GetTotalPending() const { return static_cast<blk_t>(block_map_.num_bits()); }
blk_t GetNodeSize() const { return node_size_; }
void SetNodeSize(blk_t size) { node_size_ = size; }
// Iterate over the ranges in the bitmap. Modifying the list while
// iterating over it may yield undefined results.
const_iterator cbegin() const { return block_map_.cbegin(); }
const_iterator cend() const { return block_map_.cend(); }
// Number of additional blocks to be allocated on behalf of the vnode.
// For example, when writing to a block which has already been allocated to a file,
// we will allocate a "different" block, but simultenously free the old data block.
// This results in a net "block change" of zero blocks.
// This size should always be less than or equal to |block_map_.size()|.
blk_t new_blocks_ = 0;
// The expected size of the vnode after all blocks in block_map_ have been allocated.
blk_t node_size_ = 0;
// Map of relative data blocks to be allocated at a later time.
bitmap::RleBitmapBase<blk_t> block_map_;
} // namespace minfs