|
Packit Service |
cbade1 |
/*
|
|
Packit Service |
cbade1 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
cbade1 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
cbade1 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
cbade1 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
cbade1 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
cbade1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
cbade1 |
* GNU General Public License for more details.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
cbade1 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
cbade1 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
cbade1 |
* 02110-1301, USA.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/refCounts.h#7 $
|
|
Packit Service |
cbade1 |
*/
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
#ifndef REF_COUNTS_H
|
|
Packit Service |
cbade1 |
#define REF_COUNTS_H
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
#include "completion.h"
|
|
Packit Service |
cbade1 |
#include "journalPoint.h"
|
|
Packit Service |
cbade1 |
#include "slab.h"
|
|
Packit Service |
cbade1 |
#include "types.h"
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Create a reference counting object.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* A reference counting object can keep a reference count for every physical
|
|
Packit Service |
cbade1 |
* block in the VDO configuration. Since we expect the vast majority of the
|
|
Packit Service |
cbade1 |
* blocks to have 0 or 1 reference counts, the structure is optimized for that
|
|
Packit Service |
cbade1 |
* situation.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param [in] blockCount The number of physical blocks that can be
|
|
Packit Service |
cbade1 |
* referenced
|
|
Packit Service |
cbade1 |
* @param [in] slab The slab of the ref counts object
|
|
Packit Service |
cbade1 |
* @param [in] origin The layer PBN at which to save RefCounts
|
|
Packit Service |
cbade1 |
* @param [in] readOnlyNotifier The context for tracking read-only mode
|
|
Packit Service |
cbade1 |
* @param [out] refCountsPtr The pointer to hold the new ref counts object
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return a success or error code
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
int makeRefCounts(BlockCount blockCount,
|
|
Packit Service |
cbade1 |
Slab *slab,
|
|
Packit Service |
cbade1 |
PhysicalBlockNumber origin,
|
|
Packit Service |
cbade1 |
ReadOnlyNotifier *readOnlyNotifier,
|
|
Packit Service |
cbade1 |
RefCounts **refCountsPtr)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Free a reference counting object and null out the reference to it.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCountsPtr The reference to the reference counting object to free
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
void freeRefCounts(RefCounts **refCountsPtr);
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Check whether a RefCounts is active.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts to check
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
bool areRefCountsActive(RefCounts *refCounts)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Get the stored count of the number of blocks that are currently free.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts object
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return the number of blocks with a reference count of zero
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
BlockCount getUnreferencedBlockCount(RefCounts *refCounts)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Determine how many times a reference count can be incremented without
|
|
Packit Service |
cbade1 |
* overflowing.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts object
|
|
Packit Service |
cbade1 |
* @param pbn The physical block number
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return the number of increments that can be performed
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
uint8_t getAvailableReferences(RefCounts *refCounts, PhysicalBlockNumber pbn)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Adjust the reference count of a block.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param [in] refCounts The refcounts object
|
|
Packit Service |
cbade1 |
* @param [in] operation The operation to perform
|
|
Packit Service |
cbade1 |
* @param [in] slabJournalPoint The slab journal entry for this adjustment
|
|
Packit Service |
cbade1 |
* @param [out] freeStatusChanged A pointer which will be set to true if the
|
|
Packit Service |
cbade1 |
* free status of the block changed
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return A success or error code, specifically:
|
|
Packit Service |
cbade1 |
* VDO_REF_COUNT_INVALID if a decrement would result in a negative
|
|
Packit Service |
cbade1 |
* reference count, or an increment in a
|
|
Packit Service |
cbade1 |
* count greater than MAXIMUM_REFS
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
int adjustReferenceCount(RefCounts *refCounts,
|
|
Packit Service |
cbade1 |
ReferenceOperation operation,
|
|
Packit Service |
cbade1 |
const JournalPoint *slabJournalPoint,
|
|
Packit Service |
cbade1 |
bool *freeStatusChanged)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Adjust the reference count of a block during rebuild.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The refcounts object
|
|
Packit Service |
cbade1 |
* @param pbn The number of the block to adjust
|
|
Packit Service |
cbade1 |
* @param operation The operation to perform on the count
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
int adjustReferenceCountForRebuild(RefCounts *refCounts,
|
|
Packit Service |
cbade1 |
PhysicalBlockNumber pbn,
|
|
Packit Service |
cbade1 |
JournalOperation operation)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Replay the reference count adjustment from a slab journal entry into the
|
|
Packit Service |
cbade1 |
* reference count for a block. The adjustment will be ignored if it was already
|
|
Packit Service |
cbade1 |
* recorded in the reference count.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The refcounts object
|
|
Packit Service |
cbade1 |
* @param entryPoint The slab journal point for the entry
|
|
Packit Service |
cbade1 |
* @param entry The slab journal entry being replayed
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return VDO_SUCCESS or an error code
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
int replayReferenceCountChange(RefCounts *refCounts,
|
|
Packit Service |
cbade1 |
const JournalPoint *entryPoint,
|
|
Packit Service |
cbade1 |
SlabJournalEntry entry)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Check whether two reference counters are equivalent. This method is
|
|
Packit Service |
cbade1 |
* used for unit testing.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param counterA The first counter to compare
|
|
Packit Service |
cbade1 |
* @param counterB The second counter to compare
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return true if the two counters are equivalent
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
bool areEquivalentReferenceCounters(RefCounts *counterA, RefCounts *counterB)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Find a block with a reference count of zero in the range of physical block
|
|
Packit Service |
cbade1 |
* numbers tracked by the reference counter. If a free block is found, that
|
|
Packit Service |
cbade1 |
* block is allocated by marking it as provisionally referenced, and the
|
|
Packit Service |
cbade1 |
* allocated block number is returned.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param [in] refCounts The reference counters to scan
|
|
Packit Service |
cbade1 |
* @param [out] allocatedPtr A pointer to hold the physical block number of
|
|
Packit Service |
cbade1 |
* the block that was found and allocated
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return VDO_SUCCESS if a free block was found and allocated;
|
|
Packit Service |
cbade1 |
* VDO_NO_SPACE if there are no unreferenced blocks;
|
|
Packit Service |
cbade1 |
* otherwise an error code
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
int allocateUnreferencedBlock(RefCounts *refCounts,
|
|
Packit Service |
cbade1 |
PhysicalBlockNumber *allocatedPtr)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Provisionally reference a block if it is unreferenced.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The reference counters
|
|
Packit Service |
cbade1 |
* @param pbn The PBN to reference
|
|
Packit Service |
cbade1 |
* @param lock The PBNLock on the block (may be NULL)
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
int provisionallyReferenceBlock(RefCounts *refCounts,
|
|
Packit Service |
cbade1 |
PhysicalBlockNumber pbn,
|
|
Packit Service |
cbade1 |
PBNLock *lock)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Count all unreferenced blocks in a range [startBlock, endBlock) of physical
|
|
Packit Service |
cbade1 |
* block numbers.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The reference counters to scan
|
|
Packit Service |
cbade1 |
* @param startPBN The physical block number at which to start
|
|
Packit Service |
cbade1 |
* scanning (included in the scan)
|
|
Packit Service |
cbade1 |
* @param endPBN The physical block number at which to stop
|
|
Packit Service |
cbade1 |
* scanning (excluded from the scan)
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return The number of unreferenced blocks
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
BlockCount countUnreferencedBlocks(RefCounts *refCounts,
|
|
Packit Service |
cbade1 |
PhysicalBlockNumber startPBN,
|
|
Packit Service |
cbade1 |
PhysicalBlockNumber endPBN)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Get the number of blocks required to save a reference counts state covering
|
|
Packit Service |
cbade1 |
* the specified number of data blocks.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param blockCount The number of physical data blocks that can be referenced
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @return The number of blocks required to save reference counts with the
|
|
Packit Service |
cbade1 |
* given block count
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
BlockCount getSavedReferenceCountSize(BlockCount blockCount)
|
|
Packit Service |
cbade1 |
__attribute__((warn_unused_result));
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Request a RefCounts save several dirty blocks asynchronously. This function
|
|
Packit Service |
cbade1 |
* currently writes 1 / flushDivisor of the dirty blocks.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts object to notify
|
|
Packit Service |
cbade1 |
* @param flushDivisor The inverse fraction of the dirty blocks to write
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
void saveSeveralReferenceBlocks(RefCounts *refCounts, size_t flushDivisor);
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Ask a RefCounts to save all its dirty blocks asynchronously.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts object to notify
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
void saveDirtyReferenceBlocks(RefCounts *refCounts);
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Mark all reference count blocks as dirty.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts of the reference blocks
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
void dirtyAllReferenceBlocks(RefCounts *refCounts);
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Drain all reference count I/O. Depending upon the type of drain being
|
|
Packit Service |
cbade1 |
* performed (as recorded in the RefCount's Slab), the reference blocks may
|
|
Packit Service |
cbade1 |
* be loaded from disk or dirty reference blocks may be written out.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The reference counts to drain
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
void drainRefCounts(RefCounts *refCounts);
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Mark all reference count blocks dirty and cause them to hold locks on slab
|
|
Packit Service |
cbade1 |
* journal block 1.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts of the reference blocks
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
void acquireDirtyBlockLocks(RefCounts *refCounts);
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
/**
|
|
Packit Service |
cbade1 |
* Dump information about this RefCounts structure.
|
|
Packit Service |
cbade1 |
*
|
|
Packit Service |
cbade1 |
* @param refCounts The RefCounts to dump
|
|
Packit Service |
cbade1 |
**/
|
|
Packit Service |
cbade1 |
void dumpRefCounts(const RefCounts *refCounts);
|
|
Packit Service |
cbade1 |
|
|
Packit Service |
cbade1 |
#endif // REF_COUNTS_H
|