/*
* Copyright (c) 2020 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/blockAllocator.h#12 $
*/
#ifndef BLOCK_ALLOCATOR_H
#define BLOCK_ALLOCATOR_H
#include "completion.h"
#include "fixedLayout.h"
#include "statistics.h"
#include "types.h"
#include "vioPool.h"
#include "waitQueue.h"
/**
* Create a block allocator.
*
* @param [in] depot The slab depot for this allocator
* @param [in] zoneNumber The physical zone number for this allocator
* @param [in] threadID The thread ID for this allocator's zone
* @param [in] nonce The nonce of the VDO
* @param [in] vioPoolSize The size of the VIO pool
* @param [in] layer The physical layer below this allocator
* @param [in] readOnlyNotifier The context for entering read-only mode
* @param [out] allocatorPtr A pointer to hold the allocator
*
* @return A success or error code
**/
int makeBlockAllocator(SlabDepot *depot,
ZoneCount zoneNumber,
ThreadID threadID,
Nonce nonce,
BlockCount vioPoolSize,
PhysicalLayer *layer,
ReadOnlyNotifier *readOnlyNotifier,
BlockAllocator **allocatorPtr)
__attribute__((warn_unused_result));
/**
* Destroy a block allocator and null out the reference to it.
*
* @param blockAllocatorPtr The reference to the allocator to destroy
**/
void freeBlockAllocator(BlockAllocator **blockAllocatorPtr);
/**
* Queue a slab for allocation or scrubbing.
*
* @param slab The slab to queue
**/
void queueSlab(Slab *slab);
/**
* Update the block allocator to reflect an increment or decrement of the free
* block count in a slab. This adjusts the allocated block count and
* reprioritizes the slab when appropriate.
*
* @param slab The slab whose free block count changed
* @param increment True if the free block count went up by one,
* false if it went down by one
**/
void adjustFreeBlockCount(Slab *slab, bool increment);
/**
* Allocate a physical block.
*
* The block allocated will have a provisional reference and the
* reference must be either confirmed with a subsequent call to
* incrementReferenceCount() or vacated with a subsequent call to
* decrementReferenceCount().
*
* @param [in] allocator The block allocator
* @param [out] blockNumberPtr A pointer to receive the allocated block number
*
* @return UDS_SUCCESS or an error code
**/
int allocateBlock(BlockAllocator *allocator,
PhysicalBlockNumber *blockNumberPtr)
__attribute__((warn_unused_result));
/**
* Release an unused provisional reference.
*
* @param allocator The block allocator
* @param pbn The block to dereference
* @param why Why the block was referenced (for logging)
**/
void releaseBlockReference(BlockAllocator *allocator,
PhysicalBlockNumber pbn,
const char *why);
/**
* Get the number of allocated blocks, which is the total number of
* blocks in all slabs that have a non-zero reference count.
*
* @param allocator The block allocator
*
* @return The number of blocks with a non-zero reference count
**/
BlockCount getAllocatedBlocks(const BlockAllocator *allocator)
__attribute__((warn_unused_result));
/**
* Get the number of unrecovered slabs.
*
* @param allocator The block allocator
*
* @return The number of slabs that are unrecovered
**/
BlockCount getUnrecoveredSlabCount(const BlockAllocator *allocator)
__attribute__((warn_unused_result));
/**
* Load the state of an allocator from disk.
*
* <p>Implements ZoneAction.
**/
void loadBlockAllocator(void *context,
ZoneCount zoneNumber,
VDOCompletion *parent);
/**
* Inform a block allocator that its slab journals have been recovered from the
* recovery journal.
*
* @param allocator The allocator to inform
* @param result The result of the recovery operation
**/
void notifySlabJournalsAreRecovered(BlockAllocator *allocator, int result);
/**
* Prepare the block allocator to come online and start allocating blocks.
*
* <p>Implements ZoneAction.
**/
void prepareAllocatorToAllocate(void *context,
ZoneCount zoneNumber,
VDOCompletion *parent);
/**
* Register a slab with the allocator, ready for use.
*
* @param allocator The allocator to use
* @param slab The slab in question
**/
void registerSlabWithAllocator(BlockAllocator *allocator, Slab *slab);
/**
* Register the new slabs belonging to this allocator.
*
* <p>Implements ZoneAction.
**/
void registerNewSlabsForAllocator(void *context,
ZoneCount zoneNumber,
VDOCompletion *parent);
/**
* Drain all allocator I/O. Depending upon the type of drain, some or all
* dirty metadata may be written to disk. The type of drain will be determined
* from the state of the allocator's depot.
*
* <p>Implements ZoneAction.
**/
void drainBlockAllocator(void *context,
ZoneCount zoneNumber,
VDOCompletion *parent);
/**
* Resume a quiescent allocator.
*
* <p>Implements ZoneAction.
**/
void resumeBlockAllocator(void *context,
ZoneCount zoneNumber,
VDOCompletion *parent);
/**
* Request a commit of all dirty tail blocks which are locking a given recovery
* journal block.
*
* <p>Implements ZoneAction.
**/
void releaseTailBlockLocks(void *context,
ZoneCount zoneNumber,
VDOCompletion *parent);
/**
* Get the slab summary zone for an allocator.
*
* @param allocator The allocator
*
* @return The SlabSummaryZone for that allocator
**/
SlabSummaryZone *getSlabSummaryZone(const BlockAllocator *allocator)
__attribute__((warn_unused_result));
/**
* Acquire a VIO from a block allocator's VIO pool (asynchronous).
*
* @param allocator The allocator from which to get a VIO
* @param waiter The object requesting the VIO
*
* @return VDO_SUCCESS or an error
**/
int acquireVIO(BlockAllocator *allocator, Waiter *waiter)
__attribute__((warn_unused_result));
/**
* Return a VIO to a block allocator's VIO pool
*
* @param allocator The block allocator which owns the VIO
* @param entry The VIO being returned
**/
void returnVIO(BlockAllocator *allocator, VIOPoolEntry *entry);
/**
* Initiate scrubbing all unrecovered slabs.
*
* <p>Implements ZoneAction.
**/
void scrubAllUnrecoveredSlabsInZone(void *context,
ZoneCount zoneNumber,
VDOCompletion *parent);
/**
* Queue a waiter for a clean slab.
*
* @param allocator The allocator to wait on
* @param waiter The waiter
*
* @return VDO_SUCCESS if the waiter was queued, VDO_NO_SPACE if there are no
* slabs to scrub, and some other error otherwise
**/
int enqueueForCleanSlab(BlockAllocator *allocator, Waiter *waiter)
__attribute__((warn_unused_result));
/**
* Increase the scrubbing priority of a slab.
*
* @param slab The slab
**/
void increaseScrubbingPriority(Slab *slab);
/**
* Get the statistics for this allocator.
*
* @param allocator The allocator to query
*
* @return A copy of the current statistics for the allocator
**/
BlockAllocatorStatistics
getBlockAllocatorStatistics(const BlockAllocator *allocator)
__attribute__((warn_unused_result));
/**
* Get the aggregated slab journal statistics for the slabs in this allocator.
*
* @param allocator The allocator to query
*
* @return A copy of the current statistics for the allocator
**/
SlabJournalStatistics getSlabJournalStatistics(const BlockAllocator *allocator)
__attribute__((warn_unused_result));
/**
* Get the cumulative RefCounts statistics for the slabs in this allocator.
*
* @param allocator The allocator to query
*
* @return A copy of the current statistics for the allocator
**/
RefCountsStatistics getRefCountsStatistics(const BlockAllocator *allocator)
__attribute__((warn_unused_result));
/**
* Dump information about a block allocator to the log for debugging.
*
* @param allocator The allocator to dump
**/
void dumpBlockAllocator(const BlockAllocator *allocator);
#endif // BLOCK_ALLOCATOR_H