Blame source/vdo/base/refCounts.h

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